From ec3542637200a6f004c1ae77537e65e2b4ef81b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Wed, 4 Dec 2019 10:58:13 +0000 Subject: [PATCH 1/2] Moved native version to separate folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - To have it readily available for reference. - Moved nf-interpreter submodule there too. - Update VCX projects to use new location. Signed-off-by: José Simões --- .gitmodules | 2 +- nf-interpreter | 1 - .../Tools.Li.079E1BC1.tlog/CL.command.1.tlog | Bin 2962 -> 0 bytes .../Tools.Li.079E1BC1.tlog/CL.write.1.tlog | Bin 1548 -> 0 bytes .../Lib-link.read.1.tlog | Bin 792 -> 0 bytes .../Lib-link.write.1.tlog | Bin 494 -> 0 bytes .../Tools.Li.079E1BC1.tlog/Lib.command.1.tlog | Bin 592 -> 0 bytes .../Debug/Tools.Lib.CorHelper.idb | Bin 797696 -> 0 bytes .../Tools.Parser/Debug/Tools.Lib.Parser.idb | Bin 1870848 -> 0 bytes .../Tools.Lib.Parser.tlog/CL.command.1.tlog | Bin 13344 -> 0 bytes .../Tools.Lib.Parser.tlog/CL.write.1.tlog | Bin 6326 -> 0 bytes .../Lib-link.read.1.tlog | Bin 3106 -> 0 bytes .../Lib-link.write.1.tlog | Bin 1638 -> 0 bytes .../Tools.Lib.Parser.tlog/Lib.command.1.tlog | Bin 2086 -> 0 bytes .../Tools.CorHelper/CorHelper-vs2019.vcproj | 0 .../Tools.CorHelper/CorHelper-vs2019.vcxproj | 4 +- .../CorHelper-vs2019.vcxproj.filters | 0 .../Tools.CorHelper/CorHelper.vcproj | 0 .../Tools.CorHelper/CorHelper.vcxproj | 4 +- .../Tools.CorHelper/CorHelper.vcxproj.filters | 0 .../Tools.Li.079E1BC1.tlog/CL.command.1.tlog | Bin 0 -> 2958 bytes .../Tools.Li.079E1BC1.tlog/CL.read.1.tlog | Bin 26942 -> 27054 bytes .../Tools.Li.079E1BC1.tlog/CL.write.1.tlog | Bin 0 -> 1674 bytes .../Lib-link.read.1.tlog | Bin 0 -> 848 bytes .../Lib-link.write.1.tlog | Bin 0 -> 536 bytes .../Tools.Li.079E1BC1.tlog/Lib.command.1.tlog | Bin 0 -> 634 bytes .../Tools.Lib.CorHelper.lastbuildstate | 2 +- .../Debug/Tools.Lib.CorHelper.idb | Bin 0 -> 797696 bytes .../{ => native}/Tools.CorHelper/corhlpr.cpp | 0 .../Tools.CorHelper/dotNetMF.proj | 0 .../{ => native}/Tools.CorHelper/stdafx.cpp | 0 source/{ => native}/Tools.CorHelper/stdafx.h | 0 .../Tools.MetaDataProcessor/AssemblyParser.h | 1 + .../AssemblyReparser.h | 0 .../Tools.MetaDataProcessor/HAL_Windows.h | 0 .../Tools.MetaDataProcessor/Info_Win32.cpp | 0 .../ManagedElementTypes_Win32.cpp | 0 .../ManagedElementTypes_Win32.h | 0 .../MetaDataProcessor-vs2019.vcxproj | 42 +- .../MetaDataProcessor-vs2019.vcxproj.filters | 18 +- .../MetaDataProcessor.cpp | 0 .../MetaDataProcessor.vcxproj | 42 +- .../MetaDataProcessor.vcxproj.filters | 18 +- .../ParseOptions_Win32.cpp | 0 .../Tools.MetaDataProcessor/StubWinHal.cpp | 0 .../Tools.MetaDataProcessor/Time_stubs.cpp | 0 .../Tools.MetaDataProcessor/Various.cpp | 0 .../WatchAssemblyBuilder.h | 0 .../Tools.MetaDataProcessor/XmlUtil.cpp | 0 .../Tools.MetaDataProcessor/cor.h | 0 .../Tools.MetaDataProcessor/corerror.h | 0 .../Tools.MetaDataProcessor/corhdr.h | 0 .../Tools.MetaDataProcessor/corhlpr.h | 0 .../Tools.MetaDataProcessor/corlib_native.cpp | 0 .../Tools.MetaDataProcessor/corsym.h | 0 .../Tools.MetaDataProcessor/minheap.cpp | 0 .../Tools.MetaDataProcessor/mintime.cpp | 0 .../nanoFramework.Tools.MetaDataProcessor.sln | 0 ...oFramework.Tools.MetaDataProcessor.targets | 0 .../nanoHAL_Watchdog_stubs.cpp | 0 .../Tools.MetaDataProcessor/package.nuspec | 0 .../Tools.MetaDataProcessor/packages.config | 0 .../Tools.MetaDataProcessor/stdafx.cpp | 0 .../Tools.MetaDataProcessor/stdafx.h | 0 .../Tools.MetaDataProcessor/targetver.h | 0 .../Tools.Parser/AssemblyParser.cpp | 28 +- .../Tools.Parser/AssemblyParserDump.cpp | 0 .../Tools.Parser/AssemblyReparser.cpp | 0 .../Tools.Parser/ByteCodeParser.cpp | 0 .../Tools.Parser/ByteCodeParser_Load.cpp | 0 .../Tools.Parser/ByteCodeParser_Save.cpp | 0 .../Tools.Parser/Debug/Tools.Lib.Parser.idb | Bin 0 -> 1879040 bytes .../Tools.Lib.Parser.tlog/CL.command.1.tlog | Bin 0 -> 13326 bytes .../Tools.Lib.Parser.tlog/CL.read.1.tlog | Bin 56578 -> 57890 bytes .../Tools.Lib.Parser.tlog/CL.write.1.tlog | Bin 0 -> 6872 bytes .../Lib-link.read.1.tlog | Bin 0 -> 3358 bytes .../Lib-link.write.1.tlog | Bin 0 -> 1778 bytes .../Tools.Lib.Parser.tlog/Lib.command.1.tlog | Bin 0 -> 2226 bytes .../Tools.Lib.Parser.lastbuildstate | 2 +- .../Tools.Parser/FileStore_Win32.cpp | 0 source/{ => native}/Tools.Parser/Linker.cpp | 0 .../Tools.Parser/Parser-vs2019.vcxproj | 4 +- .../Parser-vs2019.vcxproj.filters | 0 .../{ => native}/Tools.Parser/Parser.vcxproj | 4 +- .../Tools.Parser/Parser.vcxproj.filters | 0 source/{ => native}/Tools.Parser/Support.cpp | 0 .../{ => native}/Tools.Parser/dotNetMF.proj | 0 source/{ => native}/Tools.Parser/stdafx.cpp | 0 source/{ => native}/Tools.Parser/stdafx.h | 0 .../nanoFramework.Tools.MetadataProcessor.sln | 206 + .../native/nf-interpreter/.github/FUNDING.yml | 2 + .../nf-interpreter/.github/ISSUE_TEMPLATE.md | 4 + .../.github/PULL_REQUEST_TEMPLATE.md | 36 + .../native/nf-interpreter/.github/stale.yml | 19 + .../.github_changelog_generator | 14 + source/native/nf-interpreter/.gitignore | 63 + source/native/nf-interpreter/.gitmodules | 3 + .../nf-interpreter/.vs/launch.vs.SAMPLE.json | 90 + .../nf-interpreter/.vs/tasks.vs.SAMPLE.json | 76 + .../.vscode/cmake-kits.TEMPLATE-ESP32.json | 6 + .../.vscode/launch.TEMPLATE-ESP32.json | 76 + .../.vscode/launch.TEMPLATE.json | 103 + .../.vscode/settings.TEMPLATE.json | 13 + .../.vscode/tasks.TEMPLATE-ESP32.json | 47 + source/native/nf-interpreter/CHANGELOG.md | 517 ++ .../CMake/ChibiOS-Contrib.CMakeLists.cmake.in | 22 + .../CMake/ChibiOS.CMakeLists.cmake.in | 21 + .../CMake/ChibiOS_target_os.h.in | 33 + .../nf-interpreter/CMake/ESP32_target_os.h.in | 30 + .../CMake/FreeRTOS.CMakeLists.cmake.in | 21 + .../CHIBIOS_STM32F0xx_GCC_options.cmake | 47 + .../Modules/CHIBIOS_STM32F0xx_sources.cmake | 138 + .../CHIBIOS_STM32F4xx_GCC_options.cmake | 47 + .../Modules/CHIBIOS_STM32F4xx_sources.cmake | 166 + .../CHIBIOS_STM32F7xx_GCC_options.cmake | 48 + .../Modules/CHIBIOS_STM32F7xx_sources.cmake | 168 + .../CHIBIOS_STM32H7xx_GCC_options.cmake | 48 + .../Modules/CHIBIOS_STM32H7xx_sources.cmake | 165 + .../CHIBIOS_STM32L0xx_GCC_options.cmake | 51 + .../Modules/CHIBIOS_STM32L0xx_sources.cmake | 142 + .../CMake/Modules/FindBuildUtils.cmake | 91 + .../CMake/Modules/FindCHIBIOS.cmake | 181 + .../CMake/Modules/FindCHIBIOS_FATFS.cmake | 64 + .../CMake/Modules/FindCHIBIOS_LWIP.cmake | 233 + .../CMake/Modules/FindChibiOS-Contrib.cmake | 46 + .../CMake/Modules/FindChibiOSnfOverlay.cmake | 69 + .../CMake/Modules/FindMBEDOS.cmake | 389 ++ .../CMake/Modules/FindNF_CoreCLR.cmake | 256 + .../CMake/Modules/FindNF_Debugger.cmake | 53 + .../CMake/Modules/FindNF_Diagnostics.cmake | 33 + .../CMake/Modules/FindNF_Networking.cmake | 107 + .../CMake/Modules/FindRTXRTOS.cmake | 99 + .../CMake/Modules/FindRTXRTOS2.cmake | 112 + .../CMake/Modules/FindSPIFFS.cmake | 40 + .../Modules/FindSTM32F0_CubePackage.cmake | 31 + .../Modules/FindSTM32F4_CubePackage.cmake | 35 + .../Modules/FindSTM32F7_CubePackage.cmake | 34 + .../CMake/Modules/FindSTM32FREERTOS.cmake | 115 + .../Modules/FindSTM32H7_CubePackage.cmake | 34 + .../Modules/FindSTM32L0_CubePackage.cmake | 31 + .../Modules/FindSystem.Devices.Dac.cmake | 46 + .../CMake/Modules/FindSystem.Math.cmake | 38 + .../CMake/Modules/FindSystem.Net.cmake | 47 + .../CMake/Modules/FindTI_SimpleLink.cmake | 95 + .../Modules/FindWindows.Devices.Adc.cmake | 46 + .../Modules/FindWindows.Devices.Gpio.cmake | 60 + .../Modules/FindWindows.Devices.I2c.cmake | 46 + .../Modules/FindWindows.Devices.Pwm.cmake | 43 + ...dWindows.Devices.SerialCommunication.cmake | 42 + .../Modules/FindWindows.Devices.Spi.cmake | 47 + .../Modules/FindWindows.Devices.WiFi.cmake | 42 + .../FindWindows.Networking.Sockets.cmake | 45 + .../CMake/Modules/FindWindows.Storage.cmake | 52 + .../CMake/Modules/FindWireProtocol.cmake | 71 + .../CMake/Modules/FindmbedTLS.cmake | 157 + .../FindnanoFramework.Devices.Can.cmake | 42 + .../FindnanoFramework.Devices.OneWire.cmake | 42 + .../FindnanoFramework.Hardware.Esp32.cmake | 42 + .../FindnanoFramework.Hardware.Stm32.cmake | 44 + .../FindnanoFramework.Networking.Sntp.cmake | 38 + .../FindnanoFramework.ResourceManager.cmake | 38 + .../FindnanoFramework.Runtime.Events.cmake | 55 + ...FindnanoFramework.System.Collections.cmake | 42 + .../CMake/Modules/JSONParser.cmake | 289 ++ .../Modules/MBED_STM32F0_GCC_options.cmake | 16 + .../CMake/Modules/MBED_STM32F0_sources.cmake | 134 + .../CMake/Modules/MBED_STM_sources.cmake | 35 + .../CMake/Modules/NF_NativeAssemblies.cmake | 326 ++ .../CMake/Modules/STM32_CubePackage.cmake | 103 + .../TI_SimpleLink_CC32xx_GCC_options.cmake | 48 + .../TI_SimpleLink_CC32xx_sources.cmake | 245 + .../CMake/RTXRTOS.CMakeLists.cmake.in | 22 + .../CMake/SPIFFS.CMakeLists.cmake.in | 24 + .../STM32.CubePackage.CMakeLists.cmake.in | 24 + .../SimpleLinkCC32xxSdk.CMakeLists.cmake.in | 25 + .../CMake/TI_SimpleLink_target_os.h.in | 30 + .../CMake/mBedOS.CMakeLists.cmake.in | 22 + .../CMake/mbedTLS.CMakeLists.cmake.in | 24 + .../CMake/toolchain.ChibiOS.GCC.cmake | 180 + .../CMake/toolchain.FreeRtos.ESP32.GCC.cmake | 95 + .../CMake/toolchain.TI_SimpleLink.GCC.cmake | 174 + .../CMake/toolchain.mBed.GCC.cmake | 101 + source/native/nf-interpreter/CMakeLists.txt | 730 +++ .../nf-interpreter/CMakeSettings.SAMPLE.json | 519 ++ .../native/nf-interpreter/CMakeSettings.json | 460 ++ .../CLR_RT_InteropAssembliesTable.cpp.in | 23 + .../InteropAssemblies/README.md | 6 + source/native/nf-interpreter/LICENSE.md | 192 + source/native/nf-interpreter/README.md | 103 + source/native/nf-interpreter/README.zh-cn.md | 101 + source/native/nf-interpreter/RunCmd.bat | 26 + source/native/nf-interpreter/SetNFRoot.bat | 132 + .../CopyBuildOutput.cmd | 19 + .../VisualStudioDevelopment/README.md | 138 + .../VSDevDirectoryStructure.png | Bin 0 -> 29126 bytes .../build-chibios-stm32.yml | 27 + .../azure-pipelines-templates/build-esp32.yml | 68 + .../build-ti-simplelink.yml | 19 + .../download-hexdfu.yml | 27 + .../download-install-arm-gcc-toolchain.yml | 45 + ...ownload-install-esp32-build-components.yml | 93 + .../download-install-ninja.yml | 24 + .../nb-gitversioning.yml | 24 + .../pack-publish-artifacts.yml | 27 + .../pack-publish-managed-helpers.yml | 62 + .../pack-publish-ti-sl-managed-helpers.yml | 62 + .../publish-bintray.yml | 62 + .../native/nf-interpreter/azure-pipelines.yml | 416 ++ .../cmake-variants.TEMPLATE-ESP32.json | 77 + .../cmake-variants.TEMPLATE.json | 91 + .../install-scripts/Set-PathVariable.ps1 | 82 + .../install-arm-gcc-toolchain.ps1 | 35 + .../install-scripts/install-esp32-idf.ps1 | 41 + .../install-scripts/install-esp32-libs.ps1 | 38 + .../install-scripts/install-esp32-openocd.ps1 | 38 + .../install-esp32-toolchain.ps1 | 41 + .../install-scripts/install-esp32-tools.ps1 | 149 + .../install-scripts/install-nf-hex2dfu.ps1 | 21 + .../install-scripts/install-ninja.ps1 | 31 + .../install-scripts/install-stm32-tools.ps1 | 66 + source/native/nf-interpreter/nf.props | 19 + .../native/nf-interpreter/nfcore.vssettings | 74 + source/native/nf-interpreter/sd1.bat | 6 + source/native/nf-interpreter/sdkconfig | 490 ++ .../src/CLR/CorLib/CorLib-vs2019.vcxproj | 212 + .../CLR/CorLib/CorLib-vs2019.vcxproj.filters | 189 + .../nf-interpreter/src/CLR/CorLib/CorLib.h | 23 + .../src/CLR/CorLib/CorLib.vcxproj | 210 + .../src/CLR/CorLib/CorLib.vcxproj.filters | 186 + .../src/CLR/CorLib/corlib_native.cpp | 1517 ++++++ .../src/CLR/CorLib/corlib_native.h | 1064 ++++ .../CorLib/corlib_native_System_AppDomain.cpp | 313 ++ .../CLR/CorLib/corlib_native_System_Array.cpp | 190 + .../CorLib/corlib_native_System_Attribute.cpp | 8 + .../corlib_native_System_BitConverter.cpp | 600 +++ ...ib_native_System_Collections_ArrayList.cpp | 97 + .../CorLib/corlib_native_System_Console.cpp | 26 + .../CorLib/corlib_native_System_Convert.cpp | 593 +++ .../CorLib/corlib_native_System_DateTime.cpp | 270 + .../CorLib/corlib_native_System_Delegate.cpp | 184 + ...lib_native_System_Diagnostics_Debugger.cpp | 50 + .../CorLib/corlib_native_System_Double.cpp | 112 + .../CLR/CorLib/corlib_native_System_Enum.cpp | 8 + .../CorLib/corlib_native_System_Exception.cpp | 236 + .../CLR/CorLib/corlib_native_System_GC.cpp | 50 + ...ative_System_Globalization_CultureInfo.cpp | 27 + ...ve_System_Globalization_DateTimeFormat.cpp | 39 + .../CLR/CorLib/corlib_native_System_Guid.cpp | 34 + ...orlib_native_System_MarshalByRefObject.cpp | 8 + .../corlib_native_System_MathInternal.cpp | 48 + ...corlib_native_System_MulticastDelegate.cpp | 27 + .../CorLib/corlib_native_System_Number.cpp | 266 + .../CorLib/corlib_native_System_Object.cpp | 91 + .../CorLib/corlib_native_System_Random.cpp | 125 + ...rlib_native_System_Reflection_Assembly.cpp | 324 ++ ...corlib_native_System_Reflection_Binder.cpp | 8 + ...tive_System_Reflection_ConstructorInfo.cpp | 45 + ...lib_native_System_Reflection_FieldInfo.cpp | 206 + ...ib_native_System_Reflection_MemberInfo.cpp | 8 + ...ib_native_System_Reflection_MethodBase.cpp | 184 + ..._native_System_Reflection_PropertyInfo.cpp | 27 + ...ive_System_Reflection_RuntimeFieldInfo.cpp | 129 + ...ve_System_Reflection_RuntimeMethodInfo.cpp | 126 + .../corlib_native_System_RuntimeType.cpp | 325 ++ ...untime_CompilerServices_RuntimeHelpers.cpp | 217 + ...stem_Runtime_Remoting_RemotingServices.cpp | 24 + .../CorLib/corlib_native_System_String.cpp | 1182 +++++ .../corlib_native_System_Text_UTF8Decoder.cpp | 74 + ...corlib_native_System_Text_UTF8Encoding.cpp | 127 + ...native_System_Threading_AutoResetEvent.cpp | 44 + ...ib_native_System_Threading_Interlocked.cpp | 92 + ...tive_System_Threading_ManualResetEvent.cpp | 42 + ...corlib_native_System_Threading_Monitor.cpp | 65 + .../corlib_native_System_Threading_Thread.cpp | 575 +++ .../corlib_native_System_Threading_Timer.cpp | 91 + ...lib_native_System_Threading_WaitHandle.cpp | 71 + .../CorLib/corlib_native_System_TimeSpan.cpp | 193 + .../CLR/CorLib/corlib_native_System_Type.cpp | 660 +++ .../CorLib/corlib_native_System_ValueType.cpp | 17 + .../corlib_native_System_WeakReference.cpp | 181 + .../src/CLR/Core/CLR_RT_DblLinkedList.cpp | 88 + .../src/CLR/Core/CLR_RT_HeapBlock.cpp | 2003 ++++++++ .../src/CLR/Core/CLR_RT_HeapBlock_Array.cpp | 375 ++ .../CLR/Core/CLR_RT_HeapBlock_ArrayList.cpp | 209 + .../CLR/Core/CLR_RT_HeapBlock_BinaryBlob.cpp | 67 + .../CLR/Core/CLR_RT_HeapBlock_Delegate.cpp | 79 + .../Core/CLR_RT_HeapBlock_Delegate_List.cpp | 232 + .../CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp | 80 + .../src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp | 228 + .../CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp | 29 + .../src/CLR/Core/CLR_RT_HeapBlock_Node.cpp | 16 + .../src/CLR/Core/CLR_RT_HeapBlock_Queue.cpp | 173 + .../src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp | 111 + .../src/CLR/Core/CLR_RT_HeapBlock_String.cpp | 116 + .../src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp | 327 ++ .../Core/CLR_RT_HeapBlock_WaitForObject.cpp | 189 + .../src/CLR/Core/CLR_RT_HeapCluster.cpp | 340 ++ .../src/CLR/Core/CLR_RT_Interop.cpp | 813 +++ .../src/CLR/Core/CLR_RT_Memory.cpp | 208 + .../Core/CLR_RT_ObjectToEvent_Destination.cpp | 73 + .../CLR/Core/CLR_RT_ObjectToEvent_Source.cpp | 63 + .../src/CLR/Core/CLR_RT_RuntimeMemory.cpp | 136 + .../src/CLR/Core/CLR_RT_StackFrame.cpp | 1208 +++++ .../CLR/Core/CLR_RT_SystemAssembliesTable.cpp | 45 + .../src/CLR/Core/CLR_RT_UnicodeHelper.cpp | 586 +++ .../nf-interpreter/src/CLR/Core/Cache.cpp | 591 +++ .../nf-interpreter/src/CLR/Core/Checks.cpp | 83 + .../src/CLR/Core/Core-vs2019.vcxproj | 218 + .../src/CLR/Core/Core-vs2019.vcxproj.filters | 215 + .../nf-interpreter/src/CLR/Core/Core.cpp | 87 + .../native/nf-interpreter/src/CLR/Core/Core.h | 26 + .../nf-interpreter/src/CLR/Core/Core.vcxproj | 217 + .../src/CLR/Core/Core.vcxproj.filters | 215 + .../nf-interpreter/src/CLR/Core/Execution.cpp | 3573 +++++++++++++ .../src/CLR/Core/GarbageCollector.cpp | 828 +++ .../CLR/Core/GarbageCollector_Compaction.cpp | 467 ++ ...bageCollector_ComputeReachabilityGraph.cpp | 300 ++ .../src/CLR/Core/GarbageCollector_Info.cpp | 322 ++ .../CLR/Core/Hardware/Hardware-vs2019.vcxproj | 159 + .../Hardware/Hardware-vs2019.vcxproj.filters | 22 + .../src/CLR/Core/Hardware/Hardware.cpp | 175 + .../src/CLR/Core/Hardware/Hardware.vcxproj | 158 + .../Core/Hardware/Hardware.vcxproj.filters | 22 + .../src/CLR/Core/Hardware/Hardware_stub.cpp | 51 + .../CLR/Core/Hardware/Hardware_stub.vcxproj | 158 + .../Hardware/Hardware_stub.vcxproj.filters | 22 + .../src/CLR/Core/Interpreter.cpp | 3140 ++++++++++++ .../InterruptHandler-vs2019.vcxproj | 159 + .../InterruptHandler-vs2019.vcxproj.filters | 22 + .../InterruptHandler/InterruptHandler.cpp | 147 + .../InterruptHandler/InterruptHandler.vcxproj | 158 + .../InterruptHandler.vcxproj.filters | 22 + .../InterruptHandler_stub.cpp | 33 + .../InterruptHandler_stub.vcxproj | 158 + .../InterruptHandler_stub.vcxproj.filters | 22 + .../NativeEventDispatcher.cpp | 289 ++ .../NativeEventDispatcher.vcxproj | 158 + .../NativeEventDispatcher.vcxproj.filters | 22 + .../NativeEventDispatcher_stub.cpp | 106 + .../NativeEventDispatcher_stub.vcxproj | 158 + ...NativeEventDispatcher_stub.vcxproj.filters | 22 + .../Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp | 130 + .../src/CLR/Core/RPC/RPC-vs2019.vcxproj | 159 + .../CLR/Core/RPC/RPC-vs2019.vcxproj.filters | 22 + .../src/CLR/Core/RPC/RPC.vcxproj | 158 + .../src/CLR/Core/RPC/RPC.vcxproj.filters | 22 + .../src/CLR/Core/RPC/RPC_stub.cpp | 75 + .../src/CLR/Core/RPC/RPC_stub.vcxproj | 158 + .../src/CLR/Core/RPC/RPC_stub.vcxproj.filters | 22 + .../nf-interpreter/src/CLR/Core/Random.cpp | 51 + .../Core/Serialization/BinaryFormatter.cpp | 2016 ++++++++ .../Serialization/BinaryFormatter_stub.cpp | 389 ++ .../Serialization-vs2019.vcxproj | 159 + .../Serialization-vs2019.vcxproj.filters | 22 + .../Core/Serialization/Serialization.vcxproj | 158 + .../Serialization.vcxproj.filters | 22 + .../Serialization/Serialization_stub.vcxproj | 158 + .../Serialization_stub.vcxproj.filters | 22 + .../nf-interpreter/src/CLR/Core/Streams.cpp | 297 ++ .../src/CLR/Core/StringTable.cpp | 53 + .../src/CLR/Core/StringTableData.cpp | 1741 +++++++ .../nf-interpreter/src/CLR/Core/Thread.cpp | 1275 +++++ .../src/CLR/Core/TypeSystem.cpp | 4420 +++++++++++++++++ .../src/CLR/Core/TypeSystemLookup.cpp | 1774 +++++++ .../nf-interpreter/src/CLR/Core/Various.cpp | 126 + .../src/CLR/Core/corhdr_private.h | 111 + .../src/CLR/Core/nanoSupport_CRC32.c | 65 + .../src/CLR/Debugger/CMakeLists.txt | 16 + .../src/CLR/Debugger/Debugger.cpp | 3417 +++++++++++++ .../src/CLR/Debugger/Debugger.h | 101 + .../src/CLR/Debugger/Debugger.vcxproj | 169 + .../src/CLR/Debugger/Debugger.vcxproj.filters | 25 + .../src/CLR/Debugger/Debugger_full.cpp | 108 + .../src/CLR/Debugger/Debugger_minimal.cpp | 48 + .../src/CLR/Debugger/Debugger_stub.cpp | 105 + .../src/CLR/Debugger/Debugger_stub.vcxproj | 158 + .../Debugger/Debugger_stub.vcxproj.filters | 22 + .../Diagnostics/Diagnostics-vs2019.vcxproj | 162 + .../Diagnostics-vs2019.vcxproj.filters | 33 + .../src/CLR/Diagnostics/Diagnostics.h | 18 + .../src/CLR/Diagnostics/Diagnostics.vcxproj | 161 + .../Diagnostics/Diagnostics.vcxproj.filters | 33 + .../src/CLR/Diagnostics/Diagnostics_stub.cpp | 561 +++ .../CLR/Diagnostics/Diagnostics_stub.vcxproj | 161 + .../Diagnostics_stub.vcxproj.filters | 27 + .../src/CLR/Diagnostics/Info.cpp | 859 ++++ .../src/CLR/Diagnostics/Profile.cpp | 268 + .../src/CLR/Diagnostics/Profiler.cpp | 858 ++++ .../src/CLR/Helpers/Base64/base64.c | 104 + .../src/CLR/Helpers/Base64/base64.h | 46 + .../src/CLR/Helpers/TinyPrintf/printf.c | 496 ++ .../src/CLR/Helpers/TinyPrintf/printf.h | 32 + .../src/CLR/Include/WireProtocol.h | 211 + .../CLR/Include/WireProtocol_App_Interface.h | 20 + .../CLR/Include/WireProtocol_HAL_Interface.h | 17 + .../src/CLR/Include/WireProtocol_Message.h | 65 + .../Include/WireProtocol_MonitorCommands.h | 198 + .../src/CLR/Include/nanoCLR_Application.h | 40 + .../src/CLR/Include/nanoCLR_Checks.h | 68 + .../src/CLR/Include/nanoCLR_Debugging.h | 1166 +++++ .../src/CLR/Include/nanoCLR_ErrorCodes.h | 27 + .../src/CLR/Include/nanoCLR_Hardware.h | 132 + .../src/CLR/Include/nanoCLR_Interop.h | 473 ++ .../src/CLR/Include/nanoCLR_Messaging.h | 143 + .../src/CLR/Include/nanoCLR_ParseOptions.h | 136 + .../src/CLR/Include/nanoCLR_PlatformDef.h | 246 + .../src/CLR/Include/nanoCLR_Profiling.h | 219 + .../src/CLR/Include/nanoCLR_Runtime.h | 3246 ++++++++++++ .../CLR/Include/nanoCLR_Runtime__HeapBlock.h | 2443 +++++++++ .../Include/nanoCLR_Runtime__Serialization.h | 285 ++ .../src/CLR/Include/nanoCLR_Types.h | 1148 +++++ .../src/CLR/Include/nanoCLR_Win32.h | 42 + .../src/CLR/Include/nanoPackStruct.h | 21 + .../src/CLR/Include/nanoSupport.h | 19 + .../nf-interpreter/src/CLR/Include/nanoWeak.h | 21 + .../src/CLR/Include/nf_errors_exceptions.h | 171 + .../nf-interpreter/src/CLR/Include/opcode.def | 359 ++ .../nf-interpreter/src/CLR/Include/stdafx.h | 11 + .../CLR/Messaging/Messaging-vs2019.vcxproj | 164 + .../Messaging-vs2019.vcxproj.filters | 22 + .../src/CLR/Messaging/Messaging.cpp | 416 ++ .../src/CLR/Messaging/Messaging.vcxproj | 163 + .../CLR/Messaging/Messaging.vcxproj.filters | 22 + .../src/CLR/Messaging/Messaging_stub.cpp | 51 + .../src/CLR/Messaging/Messaging_stub.vcxproj | 158 + .../Messaging/Messaging_stub.vcxproj.filters | 22 + .../src/CLR/Startup/CLRStartup.cpp | 459 ++ .../src/CLR/Startup/CLRStartup.h | 28 + .../src/CLR/Startup/Startup.vcxproj | 170 + .../src/CLR/Startup/Startup.vcxproj.filters | 27 + .../CLR/System.Math/nf_native_system_math.cpp | 70 + .../CLR/System.Math/nf_native_system_math.h | 70 + .../nf_native_system_math_System_Math.cpp | 1481 ++++++ .../WireProtocol/WireProtocol-vs2019.vcxproj | 161 + .../WireProtocol-vs2019.vcxproj.filters | 34 + .../src/CLR/WireProtocol/WireProtocol.vcxproj | 160 + .../WireProtocol/WireProtocol.vcxproj.filters | 34 + .../WireProtocol/WireProtocol_App_Interface.c | 33 + .../WireProtocol/WireProtocol_HAL_Interface.c | 40 + .../CLR/WireProtocol/WireProtocol_Message.c | 395 ++ .../WireProtocol_MonitorCommands.c | 108 + .../src/CLR/WireProtocol/targetHAL_time.cpp | 22 + .../Networking.Sntp/nf_lwipopts_sntp.h | 37 + .../Networking.Sntp/nf_networking_sntp.cpp | 27 + .../Networking.Sntp/nf_networking_sntp.h | 42 + ...ing_sntp_nanoFramework_Networking_Sntp.cpp | 113 + .../System.Net/sys_net_native.cpp | 305 ++ .../System.Net/sys_net_native.h | 336 ++ ...et_NetworkInformation_NetworkInterface.cpp | 277 ++ ...Information_Wireless80211Configuration.cpp | 103 + ...orkInformation_WirelessAPConfiguration.cpp | 235 + ...System_Net_Security_CertificateManager.cpp | 51 + ...t_native_System_Net_Security_SslNative.cpp | 631 +++ ...native_System_Net_Sockets_NativeSocket.cpp | 876 ++++ ...raphy_X509Certificates_X509Certificate.cpp | 88 + ...aphy_X509Certificates_X509Certificate2.cpp | 36 + .../nf-interpreter/src/HAL/Include/nanoHAL.h | 1805 +++++++ .../Include/nanoHAL_ConfigurationManager.h | 157 + .../src/HAL/Include/nanoHAL_Network.h | 292 ++ .../src/HAL/Include/nanoHAL_Power.h | 37 + .../src/HAL/Include/nanoHAL_ReleaseInfo.h | 90 + .../src/HAL/Include/nanoHAL_Time.h | 107 + .../src/HAL/Include/nanoHAL_Types.h | 54 + .../src/HAL/Include/nanoHAL_Watchdog.h | 21 + .../src/HAL/Include/nanoHAL_Windows_Storage.h | 72 + .../src/HAL/Include/nanoHAL_v2.h | 351 ++ .../src/HAL/nanoHAL_ConfigurationManager.c | 181 + .../HAL/nanoHAL_ConfigurationManager_stubs.c | 49 + .../src/HAL/nanoHAL_SystemInformation.cpp | 60 + .../nf-interpreter/src/HAL/nanoHAL_Time.cpp | 96 + .../nf-interpreter/src/HAL/nanoHAL_Watchdog.c | 23 + .../PAL/AsyncProcCall/AsyncCompletions.cpp | 239 + .../PAL/AsyncProcCall/AsyncContinuations.cpp | 107 + .../src/PAL/AsyncProcCall/Async_stubs.cpp | 101 + .../PAL/BlockStorage/nanoPAL_BlockStorage.c | 890 ++++ .../nf-interpreter/src/PAL/COM/COM_stubs.c | 78 + .../src/PAL/COM/ComDirector.cpp | 64 + .../src/PAL/COM/GenericPort_stubs.c | 76 + .../src/PAL/COM/sockets/Sockets_debugger.cpp | 640 +++ .../src/PAL/COM/sockets/sockets_lwip.cpp | 481 ++ .../src/PAL/COM/sockets/sockets_lwip.h | 187 + .../src/PAL/COM/sockets/ssl/mbedTLS/mbedtls.h | 54 + .../sockets/ssl/mbedTLS/nf_mbedtls_config.h | 192 + .../ssl/mbedTLS/ssl_accept_internal.cpp | 64 + .../mbedTLS/ssl_add_cert_auth_internal.cpp | 50 + .../ssl/mbedTLS/ssl_close_socket_internal.cpp | 27 + .../ssl/mbedTLS/ssl_connect_internal.cpp | 72 + .../ssl_decode_private_key_internal.cpp | 40 + .../ssl/mbedTLS/ssl_exit_context_internal.cpp | 57 + .../COM/sockets/ssl/mbedTLS/ssl_generic.cpp | 232 + .../ssl/mbedTLS/ssl_generic_init_internal.cpp | 310 ++ .../ssl/mbedTLS/ssl_initialize_internal.cpp | 16 + .../ssl_parse_certificate_internal.cpp | 71 + .../ssl/mbedTLS/ssl_pending_internal.cpp | 22 + .../sockets/ssl/mbedTLS/ssl_read_internal.cpp | 30 + .../ssl/mbedTLS/ssl_uninitialize_internal.cpp | 28 + .../ssl/mbedTLS/ssl_write_internal.cpp | 48 + .../src/PAL/COM/sockets/ssl/ssl.cpp | 241 + .../src/PAL/COM/sockets/ssl/ssl.h | 30 + .../src/PAL/COM/sockets/ssl/ssl_functions.h | 85 + .../src/PAL/COM/sockets/ssl/ssl_stubs.cpp | 212 + .../src/PAL/COM/sockets/ssl/ssl_types.h | 15 + .../src/PAL/Double/nanoPAL_NativeDouble.cpp | 223 + .../src/PAL/Events/nanoPAL_Events_driver.cpp | 60 + .../PAL/Events/nanoPAL_Events_functions.cpp | 27 + .../nf-interpreter/src/PAL/Include/nanoCRT.h | 21 + .../nf-interpreter/src/PAL/Include/nanoPAL.h | 255 + .../PAL/Include/nanoPAL_AsyncProcCalls_decl.h | 134 + .../src/PAL/Include/nanoPAL_BlockStorage.h | 647 +++ .../src/PAL/Include/nanoPAL_COM.h | 56 + .../src/PAL/Include/nanoPAL_Events.h | 101 + .../src/PAL/Include/nanoPAL_GPIO.h | 25 + .../src/PAL/Include/nanoPAL_NativeDouble.h | 23 + .../src/PAL/Include/nanoPAL_Network.h | 25 + .../PAL/Include/nanoPAL_PerformanceCounters.h | 23 + .../src/PAL/Include/nanoPAL_Sockets.h | 664 +++ .../src/PAL/Include/nanoPAL_Time.h | 28 + .../src/PAL/Lwip/lwIP_Sockets.cpp | 1341 +++++ .../src/PAL/Lwip/lwIP_Sockets.h | 126 + .../src/PAL/Lwip/lwIP_Sockets_functions.cpp | 152 + .../nanoPAL_PerformanceCounters_stubs.cpp | 20 + .../src/PAL/nanoPAL_Network_stubs.cpp | 21 + .../System.Devices.Dac/sys_dev_dac_native.cpp | 53 + .../System.Devices.Dac/sys_dev_dac_native.h | 55 + .../win_dev_adc_native.cpp | 65 + .../Windows.Devices.Adc/win_dev_adc_native.h | 68 + .../win_dev_gpio_native.cpp | 103 + .../win_dev_gpio_native.h | 155 + .../win_dev_i2c_native.cpp | 66 + .../Windows.Devices.I2c/win_dev_i2c_native.h | 107 + .../win_dev_pwm_native.cpp | 65 + .../Windows.Devices.Pwm/win_dev_pwm_native.h | 64 + .../win_dev_serial_native.cpp | 87 + .../win_dev_serial_native.h | 184 + .../win_dev_spi_native.cpp | 79 + .../Windows.Devices.Spi/win_dev_spi_native.h | 108 + .../win_dev_wifi_native.cpp | 63 + .../win_dev_wifi_native.h | 87 + .../win_net_sockets_native.cpp | 119 + .../win_net_sockets_native.h | 126 + .../Windows.Storage/win_storage_native.cpp | 111 + .../src/Windows.Storage/win_storage_native.h | 114 + .../nf_devices_can_native.cpp | 70 + .../nf_devices_can_native.h | 124 + .../nf_devices_onewire_native.cpp | 29 + .../nf_devices_onewire_native.h | 32 + .../nf_system_resourcemanager.cpp | 40 + .../nf_system_resourcemanager.h | 47 + ...nager_System_Resources_ResourceManager.cpp | 218 + ...amework_Runtime_Native_ResourceUtility.cpp | 20 + .../nf_rt_events_native.cpp | 75 + .../nf_rt_events_native.h | 131 + ...nanoFramework_Runtime_Events_EventSink.cpp | 69 + ...k_Runtime_Events_NativeEventDispatcher.cpp | 183 + ...oFramework_Runtime_Events_WeakDelegate.cpp | 31 + .../nf_rt_native.cpp | 49 + .../nf_rt_native.h | 76 + ...oFramework_Runtime_Hardware_SystemInfo.cpp | 163 + ...ive_nanoFramework_Runtime_Native_Debug.cpp | 53 + ...ork_Runtime_Native_ExecutionConstraint.cpp | 70 + ...ive_nanoFramework_Runtime_Native_Power.cpp | 18 + ...nanoFramework_Runtime_Native_Rtc_stubs.cpp | 23 + .../nf_system_collections.cpp | 100 + .../nf_system_collections.h | 113 + ...m_collections_System_Collections_Queue.cpp | 80 + ...m_collections_System_Collections_Stack.cpp | 63 + source/native/nf-interpreter/startocd.bat | 48 + .../.github/ISSUE_TEMPLATE.md | 2 + .../.github/PULL_REQUEST_TEMPLATE.md | 4 + .../targets-community/.gitignore | 60 + .../ChibiOS/GHI_FEZ_CERB40_NF/CMakeLists.txt | 228 + .../ChibiOS/GHI_FEZ_CERB40_NF/README.md | 56 + .../ChibiOS/GHI_FEZ_CERB40_NF/board.c | 265 + .../ChibiOS/GHI_FEZ_CERB40_NF/board.h | 1612 ++++++ .../GHI_FEZ_CERB40_NF/common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 94 + .../common/Device_BlockStorage.c | 94 + .../ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.c | 435 ++ .../ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.h | 17 + .../managed_helpers/GHI_FEZ_CERB40_NF.Adc.cs | 48 + .../managed_helpers/GHI_FEZ_CERB40_NF.Gpio.cs | 55 + .../managed_helpers/README.md | 6 + .../nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F405xG_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F405xG_booter.ld | 80 + .../GHI_FEZ_CERB40_NF/nanoBooter/chconf.h | 616 +++ .../GHI_FEZ_CERB40_NF/nanoBooter/halconf.h | 513 ++ .../GHI_FEZ_CERB40_NF/nanoBooter/halconf_nf.h | 15 + .../GHI_FEZ_CERB40_NF/nanoBooter/main.c | 76 + .../GHI_FEZ_CERB40_NF/nanoBooter/mcuconf.h | 336 ++ .../GHI_FEZ_CERB40_NF/nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/target_board.h.in | 19 + .../GHI_FEZ_CERB40_NF/nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F405xG_CLR-DEBUG.ld | 76 + .../nanoCLR/STM32F405xG_CLR.ld | 76 + .../GHI_FEZ_CERB40_NF/nanoCLR/chconf.h | 616 +++ .../GHI_FEZ_CERB40_NF/nanoCLR/halconf.h | 525 ++ .../GHI_FEZ_CERB40_NF/nanoCLR/halconf_nf.h | 20 + .../ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/main.c | 74 + .../GHI_FEZ_CERB40_NF/nanoCLR/mcuconf.h | 336 ++ .../GHI_FEZ_CERB40_NF/nanoCLR/mcuconf_nf.h | 10 + .../GHI_FEZ_CERB40_NF/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../resources/cerb40-top.PNG | Bin 0 -> 499810 bytes .../GHI_FEZ_CERB40_NF/resources/cerb40.jpg | Bin 0 -> 289281 bytes .../GHI_FEZ_CERB40_NF/target_BlockStorage.c | 15 + .../GHI_FEZ_CERB40_NF/target_BlockStorage.h | 12 + .../ChibiOS/GHI_FEZ_CERB40_NF/target_common.c | 31 + .../GHI_FEZ_CERB40_NF/target_common.h.in | 37 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 25 + .../target_windows_devices_i2c_config.cpp | 30 + ...ows_devices_serialcommunication_config.cpp | 66 + ...ndows_devices_serialcommunication_config.h | 32 + .../target_windows_devices_spi_config.cpp | 10 + .../ChibiOS/I2M_ELECTRON_NF/CMakeLists.txt | 212 + .../ChibiOS/I2M_ELECTRON_NF/README.md | 17 + .../CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.c | 265 + .../CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.h | 1607 ++++++ .../I2M_ELECTRON_NF/common/CMakeLists.txt | 11 + .../common/Device_BlockStorage.c | 94 + .../ChibiOS/I2M_ELECTRON_NF/common/usbcfg.c | 435 ++ .../ChibiOS/I2M_ELECTRON_NF/common/usbcfg.h | 17 + .../managed_helpers/I2M_ELECTRON_NF.Adc.cs | 38 + .../managed_helpers/I2M_ELECTRON_NF.Gpio.cs | 57 + .../I2M_ELECTRON_NF/managed_helpers/README.md | 6 + .../I2M_ELECTRON_NF/nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F411xE_booter.ld | 80 + .../I2M_ELECTRON_NF/nanoBooter/chconf.h | 616 +++ .../I2M_ELECTRON_NF/nanoBooter/halconf.h | 513 ++ .../I2M_ELECTRON_NF/nanoBooter/halconf_nf.h | 19 + .../ChibiOS/I2M_ELECTRON_NF/nanoBooter/main.c | 75 + .../I2M_ELECTRON_NF/nanoBooter/mcuconf.h | 338 ++ .../I2M_ELECTRON_NF/nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/target_board.h.in | 19 + .../I2M_ELECTRON_NF/nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F411xE_CLR.ld | 76 + .../ChibiOS/I2M_ELECTRON_NF/nanoCLR/chconf.h | 616 +++ .../ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf.h | 532 ++ .../I2M_ELECTRON_NF/nanoCLR/halconf_nf.h | 19 + .../ChibiOS/I2M_ELECTRON_NF/nanoCLR/main.c | 79 + .../ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf.h | 338 ++ .../I2M_ELECTRON_NF/nanoCLR/mcuconf_nf.h | 10 + .../I2M_ELECTRON_NF/nanoCLR/nanoHAL.cpp | 12 + .../I2M_ELECTRON_NF/nanoCLR/target_board.h.in | 19 + .../resources/IngenuityMicro_Logo.svg | 128 + .../I2M_ELECTRON_NF/resources/electron.pdf | Bin 0 -> 337442 bytes .../resources/electronpins.png | Bin 0 -> 549881 bytes .../I2M_ELECTRON_NF/target_BlockStorage.c | 15 + .../I2M_ELECTRON_NF/target_BlockStorage.h | 12 + .../ChibiOS/I2M_ELECTRON_NF/target_common.c | 31 + .../I2M_ELECTRON_NF/target_common.h.in | 37 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 21 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 36 + ...ndows_devices_serialcommunication_config.h | 18 + .../target_windows_devices_spi_config.cpp | 10 + .../ChibiOS/I2M_OXYGEN_NF/CMakeLists.txt | 225 + .../CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/README.md | 9 + .../CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.c | 265 + .../CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.h | 1633 ++++++ .../I2M_OXYGEN_NF/common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 97 + .../common/Device_BlockStorage.c | 97 + .../ChibiOS/I2M_OXYGEN_NF/common/usbcfg.c | 435 ++ .../ChibiOS/I2M_OXYGEN_NF/common/usbcfg.h | 17 + .../managed_helpers/I2M_OXYGEN_NF.Adc.cs | 43 + .../managed_helpers/I2M_OXYGEN_NF.Gpio.cs | 63 + .../I2M_OXYGEN_NF/managed_helpers/README.md | 6 + .../I2M_OXYGEN_NF/nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F411xE_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F411xE_booter.ld | 80 + .../ChibiOS/I2M_OXYGEN_NF/nanoBooter/chconf.h | 616 +++ .../I2M_OXYGEN_NF/nanoBooter/halconf.h | 513 ++ .../I2M_OXYGEN_NF/nanoBooter/halconf_nf.h | 19 + .../ChibiOS/I2M_OXYGEN_NF/nanoBooter/main.c | 75 + .../I2M_OXYGEN_NF/nanoBooter/mcuconf.h | 338 ++ .../I2M_OXYGEN_NF/nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/target_board.h.in | 19 + .../I2M_OXYGEN_NF/nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F411xE_CLR-DEBUG.ld | 76 + .../I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR.ld | 76 + .../ChibiOS/I2M_OXYGEN_NF/nanoCLR/chconf.h | 621 +++ .../ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf.h | 525 ++ .../I2M_OXYGEN_NF/nanoCLR/halconf_nf.h | 19 + .../ChibiOS/I2M_OXYGEN_NF/nanoCLR/main.c | 79 + .../ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf.h | 338 ++ .../I2M_OXYGEN_NF/nanoCLR/mcuconf_nf.h | 10 + .../ChibiOS/I2M_OXYGEN_NF/nanoCLR/nanoHAL.cpp | 12 + .../I2M_OXYGEN_NF/nanoCLR/target_board.h.in | 19 + .../I2M_OXYGEN_NF/resources/oxygen-pcb.jpeg | Bin 0 -> 114109 bytes .../I2M_OXYGEN_NF/resources/oxygen.jpeg | Bin 0 -> 189405 bytes .../I2M_OXYGEN_NF/target_BlockStorage.c | 15 + .../I2M_OXYGEN_NF/target_BlockStorage.h | 12 + .../ChibiOS/I2M_OXYGEN_NF/target_common.c | 31 + .../ChibiOS/I2M_OXYGEN_NF/target_common.h.in | 37 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 22 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 66 + ...ndows_devices_serialcommunication_config.h | 32 + .../target_windows_devices_spi_config.cpp | 10 + .../ST_NUCLEO144_F412ZG_NF/CMakeLists.txt | 213 + .../ChibiOS/ST_NUCLEO144_F412ZG_NF/README.md | 25 + .../ChibiOS/ST_NUCLEO144_F412ZG_NF/board.c | 266 + .../ChibiOS/ST_NUCLEO144_F412ZG_NF/board.h | 1846 +++++++ .../common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 96 + .../common/Device_BlockStorage.c | 96 + .../ST_NUCLEO144_F412ZG_NF/common/usbcfg.c | 454 ++ .../ST_NUCLEO144_F412ZG_NF/common/usbcfg.h | 16 + .../managed_helpers/README.md | 7 + .../ST_NUCLEO144_F412ZG_NF.Adc.cs | 58 + .../ST_NUCLEO144_F412ZG_NF.Gpio.cs | 72 + .../ST_NUCLEO144_F412ZG_NF.LEDs.cs | 25 + .../nanoBooter/CMakeLists.txt | 10 + .../nanoBooter/STM32F412xG_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F412xG_booter.ld | 80 + .../nanoBooter/chconf.h | 618 +++ .../nanoBooter/halconf.h | 513 ++ .../nanoBooter/halconf_nf.h | 15 + .../ST_NUCLEO144_F412ZG_NF/nanoBooter/main.c | 87 + .../nanoBooter/mcuconf.h | 343 ++ .../nanoBooter/mcuconf_nf.h | 9 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F412xG_CLR-DEBUG.ld | 76 + .../nanoCLR/STM32F412xG_CLR.ld | 76 + .../ST_NUCLEO144_F412ZG_NF/nanoCLR/chconf.h | 621 +++ .../ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf.h | 524 ++ .../nanoCLR/halconf_nf.h | 14 + .../ST_NUCLEO144_F412ZG_NF/nanoCLR/main.c | 71 + .../ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf.h | 349 ++ .../nanoCLR/mcuconf_nf.h | 9 + .../nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../target_BlockStorage.c | 15 + .../target_BlockStorage.h | 12 + .../ST_NUCLEO144_F412ZG_NF/target_common.c | 24 + .../ST_NUCLEO144_F412ZG_NF/target_common.h.in | 37 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 24 + .../target_windows_devices_i2c_config.cpp | 30 + ...ows_devices_serialcommunication_config.cpp | 37 + ...ndows_devices_serialcommunication_config.h | 18 + .../target_windows_devices_spi_config.cpp | 10 + .../ST_NUCLEO144_F439ZI/CMakeLists.txt | 245 + .../ChibiOS/ST_NUCLEO144_F439ZI/README.md | 31 + .../ChibiOS/ST_NUCLEO144_F439ZI/board.c | 266 + .../ChibiOS/ST_NUCLEO144_F439ZI/board.h | 1837 +++++++ .../ST_NUCLEO144_F439ZI/common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 135 + .../common/Device_BlockStorage.c | 142 + .../ST_NUCLEO144_F439ZI/common/serialcfg.h | 15 + .../common/targetHAL_ConfigurationManager.cpp | 35 + .../ChibiOS/ST_NUCLEO144_F439ZI/ffconf.h | 272 + .../ChibiOS/ST_NUCLEO144_F439ZI/lwipopts.h | 2167 ++++++++ .../managed_helpers/Adc.cs | 73 + .../managed_helpers/README.md | 5 + .../ST_NUCLEO144_F439ZI/mbedtls_config.h | 53 + .../nanoBooter/CMakeLists.txt | 10 + .../nanoBooter/STM32F439xI_booter-DEBUG.ld | 97 + .../nanoBooter/STM32F439xI_booter.ld | 97 + .../ST_NUCLEO144_F439ZI/nanoBooter/chconf.h | 616 +++ .../ST_NUCLEO144_F439ZI/nanoBooter/halconf.h | 519 ++ .../nanoBooter/halconf_nf.h | 20 + .../ST_NUCLEO144_F439ZI/nanoBooter/main.c | 81 + .../ST_NUCLEO144_F439ZI/nanoBooter/mcuconf.h | 355 ++ .../nanoBooter/mcuconf_nf.h | 9 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F439xI_CLR-DEBUG.ld | 102 + .../nanoCLR/STM32F439xI_CLR.ld | 102 + .../ST_NUCLEO144_F439ZI/nanoCLR/chconf.h | 616 +++ .../ST_NUCLEO144_F439ZI/nanoCLR/halconf.h | 541 ++ .../ST_NUCLEO144_F439ZI/nanoCLR/halconf_nf.h | 19 + .../ST_NUCLEO144_F439ZI/nanoCLR/main.c | 67 + .../ST_NUCLEO144_F439ZI/nanoCLR/mcuconf.h | 355 ++ .../ST_NUCLEO144_F439ZI/nanoCLR/mcuconf_nf.h | 9 + .../ST_NUCLEO144_F439ZI/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../ST_NUCLEO144_F439ZI/nucleo144-f439zi.jpg | Bin 0 -> 35572 bytes .../ST_NUCLEO144_F439ZI/target_BlockStorage.c | 15 + .../ST_NUCLEO144_F439ZI/target_BlockStorage.h | 12 + .../ST_NUCLEO144_F439ZI/target_common.c | 24 + .../ST_NUCLEO144_F439ZI/target_common.h.in | 37 + .../target_lwip_sntp_opts.h | 18 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 32 + .../target_windows_devices_i2c_config.cpp | 31 + ...ows_devices_serialcommunication_config.cpp | 68 + ...ndows_devices_serialcommunication_config.h | 31 + .../target_windows_devices_spi_config.cpp | 10 + .../ST_NUCLEO144_F746ZG/CMakeLists.txt | 239 + .../ChibiOS/ST_NUCLEO144_F746ZG/README.md | 31 + .../ChibiOS/ST_NUCLEO144_F746ZG/board.c | 266 + .../ChibiOS/ST_NUCLEO144_F746ZG/board.h | 1833 +++++++ .../ST_NUCLEO144_F746ZG/common/CMakeLists.txt | 13 + .../common/Device_BlockStorage-DEBUG.c | 106 + .../common/Device_BlockStorage.c | 106 + .../ST_NUCLEO144_F746ZG/common/serialcfg.h | 15 + .../common/targetHAL_ConfigurationManager.cpp | 35 + .../ChibiOS/ST_NUCLEO144_F746ZG/lwipopts.h | 2167 ++++++++ .../managed_helpers/README.md | 5 + .../ST_NUCLEO144_F746ZG.Adc.cs | 73 + .../ST_NUCLEO144_F746ZG/mbedtls_config.h | 53 + .../nanoBooter/CMakeLists.txt | 10 + .../nanoBooter/STM32F746xG_booter-DEBUG.ld | 122 + .../nanoBooter/STM32F746xG_booter.ld | 122 + .../ST_NUCLEO144_F746ZG/nanoBooter/chconf.h | 707 +++ .../ST_NUCLEO144_F746ZG/nanoBooter/halconf.h | 524 ++ .../nanoBooter/halconf_nf.h | 15 + .../ST_NUCLEO144_F746ZG/nanoBooter/main.c | 84 + .../ST_NUCLEO144_F746ZG/nanoBooter/mcuconf.h | 381 ++ .../nanoBooter/mcuconf_nf.h | 9 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F746xG_CLR-DEBUG.ld | 127 + .../nanoCLR/STM32F746xG_CLR.ld | 127 + .../ST_NUCLEO144_F746ZG/nanoCLR/chconf.h | 705 +++ .../ST_NUCLEO144_F746ZG/nanoCLR/halconf.h | 535 ++ .../ST_NUCLEO144_F746ZG/nanoCLR/halconf_nf.h | 14 + .../ST_NUCLEO144_F746ZG/nanoCLR/main.c | 67 + .../ST_NUCLEO144_F746ZG/nanoCLR/mcuconf.h | 384 ++ .../ST_NUCLEO144_F746ZG/nanoCLR/mcuconf_nf.h | 9 + .../ST_NUCLEO144_F746ZG/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../ST_NUCLEO144_F746ZG/nucleo144-f746zg.jpg | Bin 0 -> 57158 bytes .../ST_NUCLEO144_F746ZG/target_BlockStorage.c | 15 + .../ST_NUCLEO144_F746ZG/target_BlockStorage.h | 12 + .../ST_NUCLEO144_F746ZG/target_common.c | 24 + .../ST_NUCLEO144_F746ZG/target_common.h.in | 41 + .../target_lwip_sntp_opts.h | 18 + .../target_nf_devices_onewire_config.cpp | 29 + .../target_nf_devices_onewire_config.h | 17 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 32 + .../target_windows_devices_i2c_config.cpp | 30 + ...ows_devices_serialcommunication_config.cpp | 69 + ...ndows_devices_serialcommunication_config.h | 31 + .../target_windows_devices_spi_config.cpp | 10 + .../ST_NUCLEO64_F401RE_NF/CMakeLists.txt | 202 + .../ChibiOS/ST_NUCLEO64_F401RE_NF/README.md | 47 + .../ChibiOS/ST_NUCLEO64_F401RE_NF/board.c | 266 + .../ChibiOS/ST_NUCLEO64_F401RE_NF/board.h | 1390 ++++++ .../common/CMakeLists.txt | 10 + .../common/Device_BlockStorage-DEBUG.c | 97 + .../common/Device_BlockStorage.c | 97 + .../ST_NUCLEO64_F401RE_NF/common/serialcfg.h | 15 + .../managed_helpers/README.md | 5 + .../managed_helpers/ST_NUCLEO64_F401RE.Adc.cs | 58 + .../nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F401xE_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F401xE_booter.ld | 80 + .../ST_NUCLEO64_F401RE_NF/nanoBooter/chconf.h | 616 +++ .../nanoBooter/halconf.h | 513 ++ .../nanoBooter/halconf_nf.h | 19 + .../ST_NUCLEO64_F401RE_NF/nanoBooter/main.c | 73 + .../nanoBooter/mcuconf.h | 338 ++ .../nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F401xE_CLR-DEBUG.ld | 76 + .../nanoCLR/STM32F401xE_CLR.ld | 76 + .../ST_NUCLEO64_F401RE_NF/nanoCLR/chconf.h | 621 +++ .../ST_NUCLEO64_F401RE_NF/nanoCLR/halconf.h | 525 ++ .../nanoCLR/halconf_nf.h | 24 + .../ST_NUCLEO64_F401RE_NF/nanoCLR/main.c | 67 + .../ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf.h | 336 ++ .../nanoCLR/mcuconf_nf.h | 10 + .../ST_NUCLEO64_F401RE_NF/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../target_BlockStorage.c | 15 + .../target_BlockStorage.h | 12 + .../ST_NUCLEO64_F401RE_NF/target_common.c | 24 + .../ST_NUCLEO64_F401RE_NF/target_common.h.in | 37 + .../target_nf_devices_onewire_config.cpp | 30 + .../target_nf_devices_onewire_config.h | 17 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 25 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 36 + ...ndows_devices_serialcommunication_config.h | 18 + .../target_windows_devices_spi_config.cpp | 10 + .../ST_NUCLEO64_F411RE_NF/CMakeLists.txt | 202 + .../ChibiOS/ST_NUCLEO64_F411RE_NF/README.md | 45 + .../ChibiOS/ST_NUCLEO64_F411RE_NF/board.c | 266 + .../ChibiOS/ST_NUCLEO64_F411RE_NF/board.h | 1375 +++++ .../common/CMakeLists.txt | 10 + .../common/Device_BlockStorage-DEBUG.c | 97 + .../common/Device_BlockStorage.c | 97 + .../ST_NUCLEO64_F411RE_NF/common/serialcfg.h | 15 + .../managed_helpers/README.md | 5 + .../ST_NUCLEO64_F411RE_NF.Adc.cs | 58 + .../nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F411xE_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F411xE_booter.ld | 80 + .../ST_NUCLEO64_F411RE_NF/nanoBooter/chconf.h | 616 +++ .../nanoBooter/halconf.h | 513 ++ .../nanoBooter/halconf_nf.h | 19 + .../ST_NUCLEO64_F411RE_NF/nanoBooter/main.c | 73 + .../nanoBooter/mcuconf.h | 337 ++ .../nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F411xE_CLR-DEBUG.ld | 76 + .../nanoCLR/STM32F411xE_CLR.ld | 76 + .../ST_NUCLEO64_F411RE_NF/nanoCLR/chconf.h | 621 +++ .../ST_NUCLEO64_F411RE_NF/nanoCLR/halconf.h | 525 ++ .../nanoCLR/halconf_nf.h | 24 + .../ST_NUCLEO64_F411RE_NF/nanoCLR/main.c | 67 + .../ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf.h | 336 ++ .../nanoCLR/mcuconf_nf.h | 10 + .../ST_NUCLEO64_F411RE_NF/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../target_BlockStorage.c | 15 + .../target_BlockStorage.h | 12 + .../ST_NUCLEO64_F411RE_NF/target_common.c | 24 + .../ST_NUCLEO64_F411RE_NF/target_common.h.in | 37 + .../target_system_devices_dac_config.cpp | 15 + .../target_windows_devices_adc_config.cpp | 24 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 36 + ...ndows_devices_serialcommunication_config.h | 18 + .../target_windows_devices_spi_config.cpp | 10 + .../ST_STM32F4_DISCOVERY/CMakeLists.txt | 205 + .../ChibiOS/ST_STM32F4_DISCOVERY/README.md | 57 + .../common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 97 + .../common/Device_BlockStorage.c | 97 + .../ST_STM32F4_DISCOVERY/common/usbcfg.c | 454 ++ .../ST_STM32F4_DISCOVERY/common/usbcfg.h | 17 + .../managed_helpers/README.md | 5 + .../ST_STM32F4_DISCOVERY.Adc.cs | 53 + .../nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F407xG_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F407xG_booter.ld | 80 + .../ST_STM32F4_DISCOVERY/nanoBooter/chconf.h | 616 +++ .../ST_STM32F4_DISCOVERY/nanoBooter/halconf.h | 513 ++ .../nanoBooter/halconf_nf.h | 15 + .../ST_STM32F4_DISCOVERY/nanoBooter/main.c | 84 + .../ST_STM32F4_DISCOVERY/nanoBooter/mcuconf.h | 336 ++ .../nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F407xG_CLR-DEBUG.ld | 76 + .../nanoCLR/STM32F407xG_CLR.ld | 76 + .../ST_STM32F4_DISCOVERY/nanoCLR/chconf.h | 616 +++ .../ST_STM32F4_DISCOVERY/nanoCLR/halconf.h | 525 ++ .../ST_STM32F4_DISCOVERY/nanoCLR/halconf_nf.h | 20 + .../ST_STM32F4_DISCOVERY/nanoCLR/main.c | 74 + .../ST_STM32F4_DISCOVERY/nanoCLR/mcuconf.h | 336 ++ .../ST_STM32F4_DISCOVERY/nanoCLR/mcuconf_nf.h | 10 + .../ST_STM32F4_DISCOVERY/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../stm32f4_discovery.jpg | Bin 0 -> 105327 bytes .../target_BlockStorage.c | 15 + .../target_BlockStorage.h | 12 + .../ST_STM32F4_DISCOVERY/target_common.c | 24 + .../ST_STM32F4_DISCOVERY/target_common.h.in | 37 + .../target_nf_devices_can_config.cpp | 44 + .../target_nf_devices_can_config.h | 25 + .../target_nf_devices_onewire_config.cpp | 29 + .../target_nf_devices_onewire_config.h | 17 + .../target_system_devices_dac_config.cpp | 17 + .../target_windows_devices_adc_config.cpp | 25 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 69 + ...ndows_devices_serialcommunication_config.h | 31 + .../target_windows_devices_spi_config.cpp | 10 + .../nf-interpreter/targets-community/LICENSE | 201 + .../targets-community/README.md | 62 + .../clone-nf-interpreter-repo.yml | 20 + .../set-build-version.yml | 24 + .../targets-community/azure-pipelines.yml | 552 ++ .../targets/CMSIS-OS/ChibiOS/CMakeLists.txt | 493 ++ .../ChibiOS/Include/CLR_Startup_Thread.h | 12 + .../CMSIS-OS/ChibiOS/Include/CMakeLists.txt | 19 + .../CMSIS-OS/ChibiOS/Include/LaunchCLR.h | 13 + .../ChibiOS/Include/TargetPAL_BlockStorage.h | 12 + .../Target_BlockStorage_STM32FlashDriver.h | 30 + .../ChibiOS/Include/Target_Windows_Storage.h | 28 + .../Include/WireProtocol_ReceiverThread.h | 13 + .../Include/platform_target_capabilities.h | 34 + .../CMSIS-OS/ChibiOS/Include/targetHAL.h | 76 + .../ChibiOS/Include/targetHAL_Power.h | 18 + .../CMSIS-OS/ChibiOS/Include/targetHAL_Time.h | 13 + .../ChibiOS/Include/targetHAL_Watchdog.h | 23 + .../CMSIS-OS/ChibiOS/Include/targetPAL.h | 22 + .../CMSIS-OS/ChibiOS/Include/targetPAL_Time.h | 12 + .../CMSIS-OS/ChibiOS/Include/vectors.h | 57 + .../CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.c | 477 ++ .../CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.h | 247 + .../CMSIS-OS/ChibiOS/Lwip/platform_sys_arch.c | 186 + .../CMSIS-OS/ChibiOS/MBN_QUAIL/CMakeLists.txt | 237 + .../CMSIS-OS/ChibiOS/MBN_QUAIL/README.md | 34 + .../CMSIS-OS/ChibiOS/MBN_QUAIL/board.c | 266 + .../CMSIS-OS/ChibiOS/MBN_QUAIL/board.h | 976 ++++ .../ChibiOS/MBN_QUAIL/common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 142 + .../MBN_QUAIL/common/Device_BlockStorage.c | 142 + .../ChibiOS/MBN_QUAIL/common/usbcfg.c | 454 ++ .../ChibiOS/MBN_QUAIL/common/usbcfg.h | 17 + .../MBN_QUAIL/nanoBooter/CMakeLists.txt | 9 + .../ChibiOS/MBN_QUAIL/nanoBooter/chconf.h | 616 +++ .../ChibiOS/MBN_QUAIL/nanoBooter/halconf.h | 513 ++ .../ChibiOS/MBN_QUAIL/nanoBooter/halconf_nf.h | 15 + .../ChibiOS/MBN_QUAIL/nanoBooter/main.c | 69 + .../nanoBooter/mbn_quail_booter-DEBUG.ld | 80 + .../MBN_QUAIL/nanoBooter/mbn_quail_booter.ld | 80 + .../ChibiOS/MBN_QUAIL/nanoBooter/mcuconf.h | 335 ++ .../ChibiOS/MBN_QUAIL/nanoBooter/mcuconf_nf.h | 10 + .../MBN_QUAIL/nanoBooter/target_board.h.in | 19 + .../ChibiOS/MBN_QUAIL/nanoCLR/CMakeLists.txt | 11 + .../ChibiOS/MBN_QUAIL/nanoCLR/chconf.h | 616 +++ .../ChibiOS/MBN_QUAIL/nanoCLR/halconf.h | 525 ++ .../ChibiOS/MBN_QUAIL/nanoCLR/halconf_nf.h | 14 + .../CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/main.c | 102 + .../MBN_QUAIL/nanoCLR/mbn_quail_CLR-DEBUG.ld | 76 + .../MBN_QUAIL/nanoCLR/mbn_quail_CLR.ld | 76 + .../ChibiOS/MBN_QUAIL/nanoCLR/mcuconf.h | 335 ++ .../ChibiOS/MBN_QUAIL/nanoCLR/mcuconf_nf.h | 10 + .../ChibiOS/MBN_QUAIL/nanoCLR/nanoHAL.cpp | 12 + .../MBN_QUAIL/nanoCLR/target_board.h.in | 19 + .../ChibiOS/MBN_QUAIL/target_BlockStorage.c | 15 + .../ChibiOS/MBN_QUAIL/target_BlockStorage.h | 12 + .../ChibiOS/MBN_QUAIL/target_common.c | 31 + .../ChibiOS/MBN_QUAIL/target_common.h.in | 41 + .../target_nf_devices_onewire_config.cpp | 29 + .../target_nf_devices_onewire_config.h | 17 + .../target_system_devices_dac_config.cpp | 8 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 131 + ...ndows_devices_serialcommunication_config.h | 59 + .../target_windows_devices_spi_config.cpp | 8 + .../ChibiOS/NETDUINO3_WIFI/CMakeLists.txt | 242 + .../CMSIS-OS/ChibiOS/NETDUINO3_WIFI/README.md | 28 + .../CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.c | 266 + .../CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.h | 893 ++++ .../NETDUINO3_WIFI/common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 142 + .../common/Device_BlockStorage.c | 142 + .../ChibiOS/NETDUINO3_WIFI/common/usbcfg.c | 454 ++ .../ChibiOS/NETDUINO3_WIFI/common/usbcfg.h | 17 + .../CMSIS-OS/ChibiOS/NETDUINO3_WIFI/ffconf.h | 272 + .../managed_helpers/NETDUINO3_WIFI.Adc.cs | 58 + .../NETDUINO3_WIFI/managed_helpers/README.md | 5 + .../managed_helpers/package.nuspec | 28 + .../NETDUINO3_WIFI/nanoBooter/CMakeLists.txt | 9 + .../NETDUINO3_WIFI/nanoBooter/chconf.h | 616 +++ .../NETDUINO3_WIFI/nanoBooter/halconf.h | 513 ++ .../NETDUINO3_WIFI/nanoBooter/halconf_nf.h | 15 + .../ChibiOS/NETDUINO3_WIFI/nanoBooter/main.c | 77 + .../NETDUINO3_WIFI/nanoBooter/mcuconf.h | 335 ++ .../NETDUINO3_WIFI/nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/netduino3wifi_booter-DEBUG.ld | 80 + .../nanoBooter/netduino3wifi_booter.ld | 80 + .../nanoBooter/target_board.h.in | 19 + .../NETDUINO3_WIFI/nanoCLR/CMakeLists.txt | 11 + .../ChibiOS/NETDUINO3_WIFI/nanoCLR/chconf.h | 616 +++ .../ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf.h | 525 ++ .../NETDUINO3_WIFI/nanoCLR/halconf_nf.h | 19 + .../ChibiOS/NETDUINO3_WIFI/nanoCLR/main.c | 104 + .../ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf.h | 357 ++ .../NETDUINO3_WIFI/nanoCLR/mcuconf_nf.h | 9 + .../NETDUINO3_WIFI/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/netduino3wifi_CLR-DEBUG.ld | 76 + .../nanoCLR/netduino3wifi_CLR.ld | 76 + .../NETDUINO3_WIFI/nanoCLR/target_board.h.in | 19 + .../NETDUINO3_WIFI/target_BlockStorage.c | 15 + .../NETDUINO3_WIFI/target_BlockStorage.h | 12 + .../ChibiOS/NETDUINO3_WIFI/target_common.c | 31 + .../ChibiOS/NETDUINO3_WIFI/target_common.h.in | 38 + .../target_nf_devices_can_config.cpp | 44 + .../target_nf_devices_can_config.h | 25 + .../target_nf_devices_onewire_config.cpp | 29 + .../target_nf_devices_onewire_config.h | 17 + .../target_system_devices_dac_config.cpp | 8 + .../target_windows_devices_adc_config.cpp | 29 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 67 + ...ndows_devices_serialcommunication_config.h | 31 + .../target_windows_devices_spi_config.cpp | 8 + .../target_windows_storage_config.h | 13 + .../ChibiOS/ST_NUCLEO64_F091RC/CMakeLists.txt | 209 + .../ChibiOS/ST_NUCLEO64_F091RC/README.md | 42 + .../ST_NUCLEO64_F091RC/common/CMakeLists.txt | 10 + .../common/Device_BlockStorage-DEBUG.c | 67 + .../common/Device_BlockStorage.c | 66 + .../ST_NUCLEO64_F091RC/common/serialcfg.h | 15 + .../nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F091xC_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F091xC_booter.ld | 80 + .../ST_NUCLEO64_F091RC/nanoBooter/chconf.h | 704 +++ .../ST_NUCLEO64_F091RC/nanoBooter/halconf.h | 513 ++ .../nanoBooter/halconf_nf.h | 19 + .../ST_NUCLEO64_F091RC/nanoBooter/main.c | 80 + .../ST_NUCLEO64_F091RC/nanoBooter/mcuconf.h | 246 + .../nanoBooter/mcuconf_nf.h | 10 + .../nanoBooter/target_board.h.in | 19 + .../ST_NUCLEO64_F091RC/nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F091xC_CLR-DEBUG.ld | 76 + .../nanoCLR/STM32F091xC_CLR.ld | 76 + .../ST_NUCLEO64_F091RC/nanoCLR/chconf.h | 704 +++ .../ST_NUCLEO64_F091RC/nanoCLR/halconf.h | 524 ++ .../ST_NUCLEO64_F091RC/nanoCLR/halconf_nf.h | 19 + .../ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/main.c | 98 + .../ST_NUCLEO64_F091RC/nanoCLR/mcuconf.h | 253 + .../ST_NUCLEO64_F091RC/nanoCLR/mcuconf_nf.h | 10 + .../ST_NUCLEO64_F091RC/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../ST_NUCLEO64_F091RC/target_BlockStorage.c | 15 + .../ST_NUCLEO64_F091RC/target_BlockStorage.h | 12 + .../ST_NUCLEO64_F091RC/target_common.c | 24 + .../ST_NUCLEO64_F091RC/target_common.h.in | 48 + .../target_system_devices_dac_config.cpp | 14 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 37 + ...ndows_devices_serialcommunication_config.h | 17 + .../target_windows_devices_spi_config.cpp | 8 + .../ST_STM32F429I_DISCOVERY/CMakeLists.txt | 213 + .../ChibiOS/ST_STM32F429I_DISCOVERY/README.md | 34 + .../common/CMakeLists.txt | 11 + .../common/Device_BlockStorage-DEBUG.c | 142 + .../common/Device_BlockStorage.c | 142 + .../ST_STM32F429I_DISCOVERY/common/usbcfg.c | 454 ++ .../ST_STM32F429I_DISCOVERY/common/usbcfg.h | 17 + .../ChibiOS/ST_STM32F429I_DISCOVERY/ffconf.h | 272 + .../managed_helpers/README.md | 5 + .../STM32F429I_DISCOVERY.Adc.cs | 43 + .../managed_helpers/package.nuspec | 28 + .../nanoBooter/CMakeLists.txt | 9 + .../nanoBooter/STM32F429xI_booter-DEBUG.ld | 80 + .../nanoBooter/STM32F429xI_booter.ld | 80 + .../nanoBooter/chconf.h | 616 +++ .../nanoBooter/halconf.h | 519 ++ .../nanoBooter/halconf_nf.h | 15 + .../ST_STM32F429I_DISCOVERY/nanoBooter/main.c | 84 + .../nanoBooter/mcuconf.h | 354 ++ .../nanoBooter/mcuconf_nf.h | 9 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F429xI_CLR-DEBUG.ld | 77 + .../nanoCLR/STM32F429xI_CLR.ld | 77 + .../ST_STM32F429I_DISCOVERY/nanoCLR/chconf.h | 616 +++ .../ST_STM32F429I_DISCOVERY/nanoCLR/halconf.h | 541 ++ .../nanoCLR/halconf_nf.h | 24 + .../ST_STM32F429I_DISCOVERY/nanoCLR/main.c | 104 + .../ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf.h | 355 ++ .../nanoCLR/mcuconf_nf.h | 25 + .../nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../target_BlockStorage.c | 15 + .../target_BlockStorage.h | 12 + .../ST_STM32F429I_DISCOVERY/target_common.c | 24 + .../target_common.h.in | 41 + .../target_external_memory.c | 106 + .../target_nf_devices_can_config.cpp | 44 + .../target_nf_devices_can_config.h | 25 + .../target_nf_devices_onewire_config.cpp | 30 + .../target_nf_devices_onewire_config.h | 17 + .../target_system_devices_dac_config.cpp | 17 + .../target_windows_devices_adc_config.cpp | 26 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 68 + ...ndows_devices_serialcommunication_config.h | 31 + .../target_windows_devices_spi_config.cpp | 8 + .../ST_STM32F769I_DISCOVERY/CMakeLists.txt | 268 + .../ChibiOS/ST_STM32F769I_DISCOVERY/README.md | 32 + .../ChibiOS/ST_STM32F769I_DISCOVERY/board.c | 266 + .../ChibiOS/ST_STM32F769I_DISCOVERY/board.h | 1768 +++++++ .../common/CMakeLists.txt | 13 + .../common/Device_BlockStorage-DEBUG.c | 106 + .../common/Device_BlockStorage.c | 106 + .../common/serialcfg.h | 15 + .../common/targetHAL_ConfigurationManager.cpp | 35 + .../ChibiOS/ST_STM32F769I_DISCOVERY/ffconf.h | 272 + .../ST_STM32F769I_DISCOVERY/lwipopts.h | 2167 ++++++++ .../managed_helpers/README.md | 5 + .../STM32F769I_DISCOVERY.Adc.cs | 53 + .../managed_helpers/package.nuspec | 28 + .../ST_STM32F769I_DISCOVERY/mbedtls_config.h | 53 + .../nanoBooter/CMakeLists.txt | 10 + .../nanoBooter/STM32F76xx_booter-DEBUG.ld | 122 + .../nanoBooter/STM32F76xx_booter.ld | 122 + .../nanoBooter/chconf.h | 606 +++ .../nanoBooter/halconf.h | 518 ++ .../nanoBooter/halconf_nf.h | 15 + .../ST_STM32F769I_DISCOVERY/nanoBooter/main.c | 86 + .../nanoBooter/mcuconf.h | 395 ++ .../nanoBooter/mcuconf_nf.h | 9 + .../nanoBooter/target_board.h.in | 19 + .../nanoCLR/CMakeLists.txt | 11 + .../nanoCLR/STM32F76xx_CLR-DEBUG.ld | 128 + .../nanoCLR/STM32F76xx_CLR.ld | 128 + .../ST_STM32F769I_DISCOVERY/nanoCLR/chconf.h | 705 +++ .../ST_STM32F769I_DISCOVERY/nanoCLR/halconf.h | 535 ++ .../nanoCLR/halconf_nf.h | 29 + .../ST_STM32F769I_DISCOVERY/nanoCLR/main.c | 101 + .../ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf.h | 404 ++ .../nanoCLR/mcuconf_nf.h | 22 + .../nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 19 + .../ST_STM32F769I_DISCOVERY/spiffs_config.h | 378 ++ .../stm32f7xx_hal_conf.h | 56 + .../target_BlockStorage.c | 15 + .../target_BlockStorage.h | 12 + .../ST_STM32F769I_DISCOVERY/target_common.c | 24 + .../target_common.h.in | 45 + .../target_external_memory.c | 111 + .../target_lwip_sntp_opts.h | 18 + .../target_nf_devices_can_config.cpp | 44 + .../target_nf_devices_can_config.h | 25 + .../target_nf_devices_onewire_config.cpp | 29 + .../target_nf_devices_onewire_config.h | 17 + .../ST_STM32F769I_DISCOVERY/target_spiffs.c | 853 ++++ .../ST_STM32F769I_DISCOVERY/target_spiffs.h | 148 + .../target_system_devices_dac_config.cpp | 14 + .../target_windows_devices_adc_config.cpp | 25 + .../target_windows_devices_i2c_config.cpp | 18 + ...ows_devices_serialcommunication_config.cpp | 255 + ...ndows_devices_serialcommunication_config.h | 108 + .../target_windows_devices_spi_config.cpp | 8 + .../target_windows_storage_config.h | 13 + .../CMSIS-OS/ChibiOS/common/CMakeLists.txt | 38 + .../CMSIS-OS/ChibiOS/common/LaunchCLR.c | 99 + .../Target_BlockStorage_STM32FlashDriver.c | 64 + .../ChibiOS/common/Target_Network.cpp | 62 + .../ChibiOS/common/Target_Windows_Storage.c | 266 + .../common/WireProtocol_HAL_Interface.c | 201 + .../common/WireProtocol_ReceiverThread.c | 63 + .../ChibiOS/common/hard_fault_handler.c | 161 + .../ChibiOS/common/nanoSupport_CRC32.c | 26 + .../ChibiOS/common/platform_BlockStorage.c | 22 + .../CMSIS-OS/ChibiOS/common/platform_heap.c | 20 + .../targets/CMSIS-OS/ChibiOS/common/rules.ld | 19 + .../CMSIS-OS/ChibiOS/common/rules_clr.ld | 21 + .../CMSIS-OS/ChibiOS/common/rules_code.ld | 79 + .../CMSIS-OS/ChibiOS/common/rules_data.ld | 266 + .../CMSIS-OS/ChibiOS/common/rules_stacks.ld | 31 + .../CMSIS-OS/ChibiOS/common/targetHAL.c | 50 + .../common/targetHAL_ConfigurationManager.cpp | 379 ++ .../ChibiOS/common/targetHAL_Network.cpp | 71 + .../ChibiOS/common/targetHAL_Time.cpp | 54 + .../ChibiOS/nanoBooter/CMakeLists.txt | 18 + .../nanoBooter/WireProtocol_App_Interface.c | 118 + .../nanoBooter/WireProtocol_MonitorCommands.c | 399 ++ .../CLR_RT_InteropAssembliesTable.cpp.in | 23 + .../ChibiOS/nanoCLR/CLR_Startup_Thread.c | 89 + .../CMSIS-OS/ChibiOS/nanoCLR/CMakeLists.txt | 79 + .../CMSIS-OS/ChibiOS/nanoCLR/Memory.cpp | 23 + ...c_native_System_Devices_Dac_DacChannel.cpp | 157 + ...ative_System_Devices_Dac_DacController.cpp | 188 + .../sys_dev_dac_native_target.h | 64 + ..._native_Windows_Devices_Adc_AdcChannel.cpp | 139 + ...tive_Windows_Devices_Adc_AdcController.cpp | 177 + .../win_dev_adc_native_target.h | 24 + ...Windows_Devices_Gpio_GpioChangeCounter.cpp | 86 + ...ve_Windows_Devices_Gpio_GpioController.cpp | 19 + ...io_native_Windows_Devices_Gpio_GpioPin.cpp | 423 ++ .../win_dev_gpio_native_target.h | 13 + ...c_native_Windows_Devices_I2C_I2cDevice.cpp | 537 ++ ...tive_Windows_Devices_I2c_I2cController.cpp | 52 + .../win_dev_i2c_native_target.h | 63 + ...tive_Windows_Devices_Pwm_PwmController.cpp | 161 + ..._pwm_native_Windows_Devices_Pwm_PwmPin.cpp | 975 ++++ .../win_dev_pwm_native_target.h | 12 + ...vices_SerialCommunication_SerialDevice.cpp | 1162 +++++ .../win_dev_serial_native_target.h | 182 + ..._native_Windows_Devices_Spi_SpiBusInfo.cpp | 43 + ...tive_Windows_Devices_Spi_SpiController.cpp | 44 + ...i_native_Windows_Devices_Spi_SpiDevice.cpp | 812 +++ .../win_dev_spi_native_target.h | 50 + ...indows_Networking_Sockets_SocketNative.cpp | 593 +++ .../win_net_sockets_native_target.h | 12 + ..._native_Windows_Storage_Devices_SDCard.cpp | 37 + ..._storage_native_Windows_Storage_FileIO.cpp | 1104 ++++ ...age_native_Windows_Storage_StorageFile.cpp | 325 ++ ...e_native_Windows_Storage_StorageFolder.cpp | 1625 ++++++ .../win_storage_native_target.h | 15 + .../nanoCLR/WireProtocol_App_Interface.c | 30 + .../nanoCLR/WireProtocol_MonitorCommands.c | 7 + .../nanoCLR/mbedtls_entropy_hardware_pool.c | 32 + .../CMSIS-OS/ChibiOS/nanoCLR/nanoCRT.cpp | 205 + ...anoFramework_Devices_Can_CanController.cpp | 460 ++ .../nf_devices_can_native_target.h | 77 + ...work_Devices_OneWire_OneWireController.cpp | 261 + .../nf_devices_onewire_native_target.h | 28 + .../nf_hardware_stm32_native.cpp | 62 + .../nf_hardware_stm32_native.h | 64 + ...oFramework_Hardware_Stm32_BackupMemory.cpp | 245 + ...ive_nanoFramework_Hardware_Stm32_Power.cpp | 251 + ...ative_nanoFramework_Hardware_Stm32_RTC.cpp | 202 + ...nanoFramework_Hardware_Stm32_Utilities.cpp | 49 + ...ative_nanoFramework_Runtime_Native_Rtc.cpp | 56 + .../CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp | 212 + .../ChibiOS/nanoCLR/targetHAL_Power.c | 166 + .../ChibiOS/nanoCLR/targetHAL_Time.cpp | 172 + .../ChibiOS/nanoCLR/targetHAL_Watchdog.c | 86 + .../CMSIS-OS/ChibiOS/nanoCLR/targetPAL.c | 40 + .../ChibiOS/nanoCLR/targetPAL_Events.cpp | 170 + .../ChibiOS/nanoCLR/targetPAL_Time.cpp | 71 + .../CMSIS-OS/ChibiOS/nanoCLR/targetRandom.cpp | 40 + .../ChibiOS/nanoCLR/target_platform.h.in | 58 + .../CMSIS-OS/ChibiOS/nf-overlay/README.md | 23 + .../os/common/ext/CCWare/inc/asmdefs.h | 229 + .../os/common/ext/CCWare/inc/hw_adc.h | 888 ++++ .../os/common/ext/CCWare/inc/hw_aes.h | 802 +++ .../os/common/ext/CCWare/inc/hw_apps_config.h | 747 +++ .../os/common/ext/CCWare/inc/hw_apps_rcm.h | 1506 ++++++ .../os/common/ext/CCWare/inc/hw_camera.h | 519 ++ .../os/common/ext/CCWare/inc/hw_common_reg.h | 1117 +++++ .../os/common/ext/CCWare/inc/hw_des.h | 339 ++ .../os/common/ext/CCWare/inc/hw_dthe.h | 392 ++ .../os/common/ext/CCWare/inc/hw_flash_ctrl.h | 1862 +++++++ .../os/common/ext/CCWare/inc/hw_gpio.h | 1349 +++++ .../os/common/ext/CCWare/inc/hw_gprcm.h | 3322 +++++++++++++ .../os/common/ext/CCWare/inc/hw_hib1p2.h | 1750 +++++++ .../os/common/ext/CCWare/inc/hw_hib3p3.h | 1138 +++++ .../os/common/ext/CCWare/inc/hw_i2c.h | 503 ++ .../os/common/ext/CCWare/inc/hw_ints.h | 117 + .../os/common/ext/CCWare/inc/hw_mcasp.h | 1706 +++++++ .../os/common/ext/CCWare/inc/hw_mcspi.h | 1745 +++++++ .../os/common/ext/CCWare/inc/hw_memmap.h | 84 + .../os/common/ext/CCWare/inc/hw_mmchs.h | 1919 +++++++ .../os/common/ext/CCWare/inc/hw_nvic.h | 1710 +++++++ .../os/common/ext/CCWare/inc/hw_ocp_shared.h | 3445 +++++++++++++ .../os/common/ext/CCWare/inc/hw_shamd5.h | 1242 +++++ .../common/ext/CCWare/inc/hw_stack_die_ctrl.h | 764 +++ .../os/common/ext/CCWare/inc/hw_timer.h | 778 +++ .../os/common/ext/CCWare/inc/hw_types.h | 76 + .../os/common/ext/CCWare/inc/hw_uart.h | 417 ++ .../os/common/ext/CCWare/inc/hw_udma.h | 336 ++ .../os/common/ext/CCWare/inc/hw_wdt.h | 131 + .../os/common/ext/CMSIS/TI/TICC3200/cc3200.h | 118 + .../ARMCMx/devices/TICC3200/cmparams.h | 119 + .../include/dummy_includes/hal_community.h | 19 + .../os/hal/include/hal_nf_community.h | 95 + .../os/hal/include/stm32_crc/hal_stm32_crc.h | 74 + .../hal/include/stm32_flash/hal_stm32_flash.h | 56 + .../hal/include/stm32_fsmc/hal_stm32_fsmc.h | 335 ++ .../include/stm32_onewire/hal_stm32_onewire.h | 117 + .../hal/include/stm32_qspi/hal_stm32_qspi.h | 75 + .../os/hal/include/stm32_rng/hal_stm32_rng.h | 87 + .../os/hal/ports/STM32/LLD/CRCv1/README.md | 8 + .../os/hal/ports/STM32/LLD/CRCv1/crc_lld.c | 331 ++ .../os/hal/ports/STM32/LLD/CRCv1/crc_lld.h | 182 + .../os/hal/ports/STM32/LLD/FLASHv1/README.md | 4 + .../hal/ports/STM32/LLD/FLASHv1/flash_lld.c | 227 + .../hal/ports/STM32/LLD/FLASHv1/flash_lld.h | 91 + .../os/hal/ports/STM32/LLD/FLASHv2/README.md | 4 + .../hal/ports/STM32/LLD/FLASHv2/flash_lld.c | 396 ++ .../hal/ports/STM32/LLD/FLASHv2/flash_lld.h | 451 ++ .../os/hal/ports/STM32/LLD/FLASHv3/README.md | 4 + .../hal/ports/STM32/LLD/FLASHv3/flash_lld.c | 236 + .../hal/ports/STM32/LLD/FLASHv3/flash_lld.h | 152 + .../os/hal/ports/STM32/LLD/FSMCv1/README.md | 4 + .../ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c | 475 ++ .../ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h | 219 + .../ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c | 168 + .../ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h | 133 + .../ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c | 123 + .../ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h | 131 + .../hal/ports/STM32/LLD/ONEWIREv1/README.md | 4 + .../ports/STM32/LLD/ONEWIREv1/onewire_lld.c | 320 ++ .../ports/STM32/LLD/ONEWIREv1/onewire_lld.h | 138 + .../os/hal/ports/STM32/LLD/QSPIv1/README.md | 5 + .../os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.c | 98 + .../os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.h | 72 + .../os/hal/ports/STM32/LLD/RNGv1/README.md | 8 + .../os/hal/ports/STM32/LLD/RNGv1/rng_lld.c | 128 + .../os/hal/ports/STM32/LLD/RNGv1/rng_lld.h | 126 + .../os/hal/ports/TI/LLD/GPIO/hal_pal_lld.c | 432 ++ .../os/hal/ports/TI/LLD/GPIO/hal_pal_lld.h | 806 +++ .../os/hal/ports/TI/LLD/GPTM/hal_st_lld.c | 244 + .../os/hal/ports/TI/LLD/GPTM/hal_st_lld.h | 199 + .../os/hal/ports/TI/LLD/RTC/hal_rtc_lld.h | 188 + .../os/hal/ports/TI/LLD/UART/hal_serial_lld.h | 437 ++ .../os/hal/ports/TI/TICC3200/hal_lld.c | 131 + .../os/hal/ports/TI/TICC3200/hal_lld.h | 234 + .../os/hal/ports/TI/TICC3200/ticc3200_isr.h | 40 + .../hal/ports/TI/TICC3200/ticc3200_registry.h | 31 + .../nf-overlay/os/hal/src/hal_community.c | 68 + .../os/hal/src/stm32_crc/hal_stm32_crc.c | 85 + .../os/hal/src/stm32_flash/hal_stm32_flash.c | 70 + .../os/hal/src/stm32_fsmc/hal_stm32_fsmc.c | 149 + .../hal/src/stm32_onewire/hal_stm32_onewire.c | 1033 ++++ .../os/hal/src/stm32_qspi/hal_stm32_qspi.c | 63 + .../os/hal/src/stm32_rng/hal_stm32_rng.c | 94 + .../nf-overlay/stm32-internal-flash-driver.md | 31 + .../CMSIS-OS/ChibiOS/spiffs/CMakeLists.txt | 14 + .../CMSIS-OS/ChibiOS/spiffs/hal_spiffs.c | 141 + .../CMSIS-OS/ChibiOS/spiffs/hal_spiffs.h | 28 + .../targets/CMSIS-OS/LwIP/arch/cc.h | 93 + .../targets/CMSIS-OS/LwIP/arch/perf.h | 57 + .../targets/CMSIS-OS/LwIP/arch/sys_arch.h | 85 + .../targets/CMSIS-OS/LwIP/nf_api_msg.c | 1954 ++++++++ .../targets/CMSIS-OS/LwIP/nf_sockets.c | 2868 +++++++++++ .../targets/CMSIS-OS/LwIP/nf_sys_arch.c | 368 ++ .../targets/CMSIS-OS/common/CMakeLists.txt | 16 + .../CMSIS-OS/common/Include/CMakeLists.txt | 13 + .../targets/CMSIS-OS/common/Include/swo.h.in | 35 + .../targets/CMSIS-OS/common/swo.cpp | 107 + .../targets/CMSIS-OS/common/syscalls.c | 64 + .../CMSIS-OS/nanoBooter/CMakeLists.txt | 18 + .../targets/CMSIS-OS/nanoCLR/CMakeLists.txt | 16 + .../targets/FreeRTOS_ESP32/CMakeLists.txt | 107 + .../ESP32_WROOM_32/CMakeLists.txt | 301 ++ .../ESP32_WROOM_32/CopyLibs.cmd | 89 + .../ESP32_WROOM_32/IDF/CMakeLists.txt | 380 ++ .../IDF/partitions_nanoclr_16mb.csv | 13 + .../IDF/partitions_nanoclr_2mb.csv | 13 + .../IDF/partitions_nanoclr_4mb.csv | 13 + .../IDF/partitions_nanoclr_8mb.csv | 13 + .../Include/CLR_Startup_Thread.h | 12 + .../Include/Esp32_DeviceMapping.h | 36 + .../ESP32_WROOM_32/Include/LaunchCLR.h | 13 + .../Include/TargetPAL_BlockStorage.h | 12 + .../Target_BlockStorage_Esp32FlashDriver.h | 32 + .../Include/Target_Windows_Storage.h | 9 + .../Include/WireProtocol_ReceiverThread.h | 13 + .../ESP32_WROOM_32/Include/esp32_os.h | 46 + .../Include/platform_target_capabilities.h | 25 + .../ESP32_WROOM_32/Include/targetHAL.h | 77 + .../ESP32_WROOM_32/Include/targetHAL_Power.h | 21 + .../ESP32_WROOM_32/Include/targetHAL_Time.h | 17 + .../ESP32_WROOM_32/Include/targetPAL.h | 11 + .../ESP32_WROOM_32/Include/targetPAL_Time.h | 12 + .../ESP32_WROOM_32/Lwip/CMakeLists.txt | 50 + .../ESP32_WROOM_32/Lwip/asdkconfig.h | 203 + .../ESP32_WROOM_32/Lwip/lwipopts.h | 860 ++++ .../ESP32_WROOM_32/Lwip/nf_api_msg.c | 2129 ++++++++ .../ESP32_WROOM_32/Lwip/nf_sockets.c | 3584 +++++++++++++ .../ESP32_WROOM_32/Lwip/nf_sys_arch.c | 565 +++ .../ESP32_WROOM_32/Network/CMakeLists.txt | 14 + .../Network/Esp32_Ethernet_Lan8720.cpp | 138 + .../Network/Esp32_SmartConfig.cpp | 87 + .../ESP32_WROOM_32/Network/Esp32_Wireless.cpp | 389 ++ .../ESP32_WROOM_32/Network/Target_Network.cpp | 271 + .../Network/targetHAL_Network.cpp | 261 + .../FreeRTOS_ESP32/ESP32_WROOM_32/README.md | 10 + .../ESP32_WROOM_32/Target_Windows_Storage.c | 161 + .../ESP32_WROOM_32/common/CMakeLists.txt | 28 + .../common/Device_BlockStorage.c | 137 + .../common/Esp32_DeviceMapping.cpp | 199 + .../ESP32_WROOM_32/common/FreeRTOS-openocd.c | 24 + .../ESP32_WROOM_32/common/GenericPort.cpp | 37 + .../Target_BlockStorage_ESP32FlashDriver.c | 269 + .../common/WireProtocol_HAL_Interface.c | 142 + .../common/WireProtocol_ReceiverThread.c | 33 + .../common/mbedtls_entropy_hardware_pool.c | 25 + .../common/platform_BlockStorage.c | 22 + .../ESP32_WROOM_32/common/platform_heap.c | 18 + .../ESP32_WROOM_32/common/targetHAL.c | 50 + .../ESP32_WROOM_32/common/targetHAL_Time.cpp | 25 + .../ESP32_WROOM_32/esp32.project.ld | 620 +++ .../ESP32_WROOM_32/esp32_out.ld | 74 + .../ESP32_WROOM_32/mbedtls_config.h | 53 + .../ESP32_WROOM_32/nanoBooter/readme.md | 4 + .../nanoCLR/CLR_Startup_Thread.c | 21 + .../ESP32_WROOM_32/nanoCLR/CMakeLists.txt | 71 + .../ESP32_WROOM_32/nanoCLR/Memory.cpp | 84 + ...c_native_System_Devices_Dac_DacChannel.cpp | 98 + ...ative_System_Devices_Dac_DacController.cpp | 124 + .../sys_dev_dac_native_target.h | 17 + ..._native_Windows_Devices_Adc_AdcChannel.cpp | 68 + ...tive_Windows_Devices_Adc_AdcController.cpp | 183 + .../win_dev_adc_native_target.h | 12 + ...Windows_Devices_Gpio_GpioChangeCounter.cpp | 303 ++ ...ve_Windows_Devices_Gpio_GpioController.cpp | 21 + ...io_native_Windows_Devices_Gpio_GpioPin.cpp | 369 ++ .../win_dev_gpio_native_target.h | 13 + ...c_native_Windows_Devices_I2C_I2cDevice.cpp | 228 + ...tive_Windows_Devices_I2c_I2cController.cpp | 37 + .../win_dev_i2c_native_target.h | 11 + ...tive_Windows_Devices_Pwm_PwmController.cpp | 113 + ..._pwm_native_Windows_Devices_Pwm_PwmPin.cpp | 233 + .../win_dev_pwm_native_target.h | 23 + ...vices_SerialCommunication_SerialDevice.cpp | 547 ++ .../win_dev_serial_native_target.h | 11 + ..._native_Windows_Devices_Spi_SpiBusInfo.cpp | 26 + ...tive_Windows_Devices_Spi_SpiController.cpp | 20 + ...i_native_Windows_Devices_Spi_SpiDevice.cpp | 437 ++ .../win_dev_spi_native_target.h | 27 + .../win_dev_wifi_native.h | 89 + ...ative_Windows_Devices_WIFI_WifiAdapter.cpp | 315 ++ ...indows_Networking_Sockets_SocketNative.cpp | 594 +++ .../win_net_sockets_native_target.h | 13 + ..._native_Windows_Storage_Devices_SDCard.cpp | 104 + ..._storage_native_Windows_Storage_FileIO.cpp | 677 +++ ...age_native_Windows_Storage_StorageFile.cpp | 194 + ...e_native_Windows_Storage_StorageFolder.cpp | 1158 +++++ .../win_storage_native_target.h | 11 + .../nanoCLR/WireProtocol_App_Interface.c | 68 + .../nanoCLR/WireProtocol_MonitorCommands.c | 7 + .../ESP32_WROOM_32/nanoCLR/app_main.c | 60 + .../nanoCLR/mbedtls_entropy_hardware_pool.c | 25 + .../ESP32_WROOM_32/nanoCLR/nanoCRT.cpp | 206 + ...work_Devices_OneWire_OneWireController.cpp | 579 +++ .../nf_devices_onewire_native_target.h | 38 + .../nanoFramework_hardware_esp32_native.cpp | 76 + .../nanoFramework_hardware_esp32_native.h | 89 + ...32_native_Hardware_Esp32_Configuration.cpp | 38 + ...p32_native_Hardware_Esp32_HighResTimer.cpp | 145 + ...re_esp32_native_Hardware_Esp32_Logging.cpp | 20 + ...ware_esp32_native_Hardware_Esp32_Sleep.cpp | 143 + ...ative_nanoFramework_Runtime_Native_Rtc.cpp | 38 + .../ESP32_WROOM_32/nanoCLR/nanoHAL.cpp | 12 + .../ESP32_WROOM_32/nanoCLR/targetHAL.cpp | 180 + .../nanoCLR/targetHAL_ConfigStorage.h | 93 + .../nanoCLR/targetHAL_ConfigStorageFatfs.cpp | 249 + .../nanoCLR/targetHAL_ConfigStorageNVS.cpp | 216 + .../nanoCLR/targetHAL_ConfigStorageSPIFFS.cpp | 243 + .../targetHAL_ConfigurationManager.cpp | 749 +++ .../ESP32_WROOM_32/nanoCLR/targetHAL_Power.c | 43 + .../ESP32_WROOM_32/nanoCLR/targetHAL_Time.cpp | 129 + .../ESP32_WROOM_32/nanoCLR/targetPAL.c | 10 + .../nanoCLR/targetPAL_Events.cpp | 178 + .../nanoCLR/targetPAL_Events.cpp.groups.cpp | 146 + .../ESP32_WROOM_32/nanoCLR/targetPAL_Time.cpp | 66 + .../ESP32_WROOM_32/nanoCLR/targetRandom.cpp | 35 + .../ESP32_WROOM_32/nanoCLR/target_board.h.in | 18 + .../nanoCLR/target_platform.h.in | 27 + .../FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.h | 297 ++ .../ESP32_WROOM_32/sdkconfig.txt | 737 +++ .../ESP32_WROOM_32/target_BlockStorage.c | 19 + .../ESP32_WROOM_32/target_BlockStorage.h | 12 + .../ESP32_WROOM_32/target_common.c | 32 + .../ESP32_WROOM_32/target_common.h.in | 41 + .../ESP32_WROOM_32/target_lwip_sntp_opts.h | 18 + .../target_nf_devices_onewire_config.cpp | 8 + .../target_nf_devices_onewire_config.h | 10 + .../target_system_devices_dac_config.cpp | 8 + .../target_windows_devices_adc_config.cpp | 8 + .../target_windows_devices_i2c_config.cpp | 8 + ...ows_devices_serialcommunication_config.cpp | 8 + .../target_windows_devices_spi_config.cpp | 8 + .../target_windows_storage_config.h | 5 + .../targets/TI-SimpleLink/CMakeLists.txt | 233 + .../Include/CLR_Startup_Thread.h | 12 + .../TI-SimpleLink/Include/CMakeLists.txt | 14 + .../Include/TargetPAL_BlockStorage.h | 11 + .../Target_BlockStorage_CC32xxFlashDriver.h | 28 + .../Include/Target_Windows_Storage.h | 9 + .../Include/WireProtocol_ReceiverThread.h | 12 + .../Include/platform_target_capabilities.h | 25 + .../TI-SimpleLink/Include/ssl_simplelink.h | 18 + .../targets/TI-SimpleLink/Include/targetHAL.h | 103 + .../targetHAL_ConfigurationManager_CC32xx.h | 19 + .../TI-SimpleLink/Include/targetHAL_Time.h | 14 + .../TI-SimpleLink/Include/targetPAL_Time.h | 9 + .../targetSimpleLinkCC32xx_LinkLocalTask.h | 239 + .../targetSimpleLinkCC32xx_ProvisioningTask.h | 145 + .../Include/targetSimpleLinkCC32xx_Sntp.h | 153 + .../Include/targetSimpleLinkCC32xx_Threads.h | 127 + .../TI_CC3220SF_LAUNCHXL/Board.h | 81 + .../TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.c | 831 ++++ .../TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.h | 186 + .../TI_CC3220SF_LAUNCHXL/CMakeLists.txt | 131 + .../TI_CC3220SF_LAUNCHXL/FreeRTOSConfig.h | 207 + .../TI_CC3220SF_LAUNCHXL/README.md | 74 + .../common/CMakeLists.txt | 10 + .../common/Device_BlockStorage-DEBUG.c | 67 + .../common/Device_BlockStorage.c | 67 + .../managed_helpers/README.md | 5 + .../TI_CC3220SF_LAUNCHXL.Gpio.cs | 38 + .../managed_helpers/package.nuspec | 28 + .../nanoCLR/CC3220SF_CLR-DEBUG.ld | 148 + .../nanoCLR/CC3220SF_CLR.ld | 148 + .../nanoCLR/CMakeLists.txt | 14 + .../TI_CC3220SF_LAUNCHXL/nanoCLR/main.c | 67 + .../TI_CC3220SF_LAUNCHXL/nanoCLR/nanoHAL.cpp | 12 + .../nanoCLR/target_board.h.in | 16 + .../nanoCLR/ti_drivers_net_wifi_Config.c | 31 + .../target_BlockStorage.c | 15 + .../target_BlockStorage.h | 12 + .../TI_CC3220SF_LAUNCHXL/target_common.c | 28 + .../TI_CC3220SF_LAUNCHXL/target_common.h.in | 53 + .../TI_CC3220SF_LAUNCHXL/target_sntp_opts.h | 24 + .../target_windows_devices_adc_config.cpp | 8 + .../target_windows_devices_i2c_config.cpp | 8 + .../target_windows_devices_pwm_config.h | 7 + .../target_windows_devices_spi_config.cpp | 8 + .../TI-SimpleLink/common/CMakeLists.txt | 37 + .../TI-SimpleLink/common/FreeRTOS-openocd.c | 20 + .../TI-SimpleLink/common/GenericPort.cpp | 53 + .../Target_BlockStorage_CC32xxFlashDriver.c | 91 + .../common/WireProtocol_HAL_Interface.c | 104 + .../common/WireProtocol_ReceiverThread.c | 31 + .../TI-SimpleLink/common/nanoSupport_CRC32.c | 21 + .../TI-SimpleLink/common/platformHAL.c | 51 + .../TI-SimpleLink/common/platformHAL_Time.cpp | 21 + .../common/platform_BlockStorage.c | 22 + .../TI-SimpleLink/common/platform_heap.c | 18 + .../targets/TI-SimpleLink/common/rules_clr.ld | 15 + .../common/simplelink_sockets.cpp | 129 + .../TI-SimpleLink/common/simplelink_sockets.h | 32 + .../common/simplelink_sockets_functions.cpp | 178 + .../common/sockets_simplelink.cpp | 900 ++++ .../TI-SimpleLink/common/ssl_simplelink.cpp | 416 ++ .../targets/TI-SimpleLink/common/syscalls.c | 45 + .../targetHAL_ConfigurationManager_CC32xx.cpp | 512 ++ .../nanoCLR/CLR_Startup_Thread.c | 19 + .../TI-SimpleLink/nanoCLR/CMakeLists.txt | 91 + .../targets/TI-SimpleLink/nanoCLR/Memory.cpp | 30 + ..._native_Windows_Devices_Adc_AdcChannel.cpp | 74 + ...tive_Windows_Devices_Adc_AdcController.cpp | 124 + .../win_dev_adc_native_target.h | 14 + ...Windows_Devices_Gpio_GpioChangeCounter.cpp | 86 + ...ve_Windows_Devices_Gpio_GpioController.cpp | 19 + ...io_native_Windows_Devices_Gpio_GpioPin.cpp | 418 ++ .../win_dev_gpio_native_target.h | 22 + ...c_native_Windows_Devices_I2C_I2cDevice.cpp | 244 + ...tive_Windows_Devices_I2c_I2cController.cpp | 33 + .../win_dev_i2c_native_target.h | 26 + ...tive_Windows_Devices_Pwm_PwmController.cpp | 73 + ..._pwm_native_Windows_Devices_Pwm_PwmPin.cpp | 120 + .../win_dev_pwm_native_target.h | 21 + ..._native_Windows_Devices_Spi_SpiBusInfo.cpp | 28 + ...tive_Windows_Devices_Spi_SpiController.cpp | 22 + ...i_native_Windows_Devices_Spi_SpiDevice.cpp | 262 + .../win_dev_spi_native_target.h | 28 + .../nanoCLR/WireProtocol_App_Interface.c | 30 + .../nanoCLR/WireProtocol_MonitorCommands.c | 7 + .../targets/TI-SimpleLink/nanoCLR/nanoCRT.cpp | 205 + .../TI-SimpleLink/nanoCLR/targetHAL.cpp | 155 + .../TI-SimpleLink/nanoCLR/targetHAL_Power.c | 39 + .../TI-SimpleLink/nanoCLR/targetHAL_Time.cpp | 128 + .../targets/TI-SimpleLink/nanoCLR/targetPAL.c | 68 + .../nanoCLR/targetPAL_Events.cpp | 179 + .../TI-SimpleLink/nanoCLR/targetPAL_Time.cpp | 67 + .../targetSimpleLinkCC32xx_LinkLocalTask.c | 2840 +++++++++++ .../targetSimpleLinkCC32xx_ProvisioningTask.c | 1547 ++++++ .../nanoCLR/targetSimpleLinkCC32xx_Sntp.c | 407 ++ .../nanoCLR/targetSimpleLinkCC32xx_Threads.c | 1062 ++++ .../nanoCLR/target_platform.h.in | 17 + .../os/win32/Include/TargetPAL_BlockStorage.h | 767 +++ .../os/win32/Include/Target_Windows_Storage.h | 9 + .../targets/os/win32/Include/targetHAL.h | 59 + .../os/win32/Include/targetHAL_Power.h | 12 + .../targets/os/win32/Include/targetHAL_Time.h | 74 + .../targets/os/win32/Include/targetPAL_time.h | 9 + .../os/win32/Include/target_BlockStorage.h | 12 + .../targets/os/win32/nanoCLR.sln | 319 ++ .../targets/os/win32/nanoCLR/CLRStartup.cpp | 736 +++ .../targets/os/win32/nanoCLR/Events.cpp | 64 + .../os/win32/nanoCLR/FileStore_Win32.cpp | 237 + .../CLR_RT_InteropAssembliesTable.cpp | 67 + .../targets/os/win32/nanoCLR/Memory.cpp | 52 + .../win32/nanoCLR/PAL/COMDirector_stubs.cpp | 86 + .../win32/nanoCLR/PAL/ConfigHelper_stubs.cpp | 76 + .../win32/nanoCLR/PAL/Target_BlockStorage.cpp | 12 + .../os/win32/nanoCLR/PAL/Watchdog_stubs.cpp | 12 + .../nanoCLR/PAL/blockstorageList_stubs.cpp | 151 + .../os/win32/nanoCLR/PAL/time_stubs.cpp | 101 + .../os/win32/nanoCLR/ParseOptions_Win32.cpp | 317 ++ .../os/win32/nanoCLR/Target_BlockStorage.cpp | 361 ++ .../targets/os/win32/nanoCLR/Various.cpp | 617 +++ .../targets/os/win32/nanoCLR/WatchDog.cpp | 9 + .../win_dev_gpio_native.cpp | 87 + .../win_dev_gpio_native.h | 81 + ...ve_Windows_Devices_Gpio_GpioController.cpp | 21 + ...io_native_Windows_Devices_Gpio_GpioPin.cpp | 197 + .../win_dev_spi_native.cpp | 74 + .../Windows.Devices.Spi/win_dev_spi_native.h | 70 + ..._native_Windows_Devices_Spi_SpiBusInfo.cpp | 43 + ...i_native_Windows_Devices_Spi_SpiDevice.cpp | 380 ++ .../targets/os/win32/nanoCLR/main.cpp | 100 + .../targets/os/win32/nanoCLR/nanoCLR.vcxproj | 280 ++ .../os/win32/nanoCLR/nanoCLR.vcxproj.filters | 141 + .../nf_rt_events_native.cpp | 59 + .../nf_rt_events_native.h | 99 + ...nanoFramework_Runtime_Events_EventSink.cpp | 61 + ...k_Runtime_Events_NativeEventDispatcher.cpp | 176 + ...oFramework_Runtime_Events_WeakDelegate.cpp | 29 + .../os/win32/nanoCLR/platform_heap.cpp | 18 + .../os/win32/nanoCLR/platform_selector.h | 68 + .../targets/os/win32/nanoCLR/stdafx.cpp | 13 + .../targets/os/win32/nanoCLR/stdafx.h | 28 + .../os/win32/nanoCLR/targetHAL_Time.cpp | 155 + .../targets/os/win32/nanoCLR/targetver.h | 13 + .../TestApplication/NF.TestApplication.nfproj | 56 + .../os/win32/netnf/TestApplication/Program.cs | 104 + .../Properties/AssemblyInfo.cs | 33 + .../netnf/TestApplication/TestApplication.sln | 25 + .../netnf/TestApplication/packages.config | 7 + .../targets/os/win32/packages.config | 6 + source/native/nf-interpreter/version.json | 24 + 1689 files changed, 305010 insertions(+), 75 deletions(-) delete mode 160000 nf-interpreter delete mode 100644 source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.command.1.tlog delete mode 100644 source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.write.1.tlog delete mode 100644 source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib-link.read.1.tlog delete mode 100644 source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib-link.write.1.tlog delete mode 100644 source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib.command.1.tlog delete mode 100644 source/Tools.CorHelper/Debug/Tools.Lib.CorHelper.idb delete mode 100644 source/Tools.Parser/Debug/Tools.Lib.Parser.idb delete mode 100644 source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.command.1.tlog delete mode 100644 source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.write.1.tlog delete mode 100644 source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.read.1.tlog delete mode 100644 source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.write.1.tlog delete mode 100644 source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib.command.1.tlog rename source/{ => native}/Tools.CorHelper/CorHelper-vs2019.vcproj (100%) rename source/{ => native}/Tools.CorHelper/CorHelper-vs2019.vcxproj (90%) rename source/{ => native}/Tools.CorHelper/CorHelper-vs2019.vcxproj.filters (100%) rename source/{ => native}/Tools.CorHelper/CorHelper.vcproj (100%) rename source/{ => native}/Tools.CorHelper/CorHelper.vcxproj (90%) rename source/{ => native}/Tools.CorHelper/CorHelper.vcxproj.filters (100%) create mode 100644 source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.command.1.tlog rename source/{ => native}/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.read.1.tlog (96%) create mode 100644 source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.write.1.tlog create mode 100644 source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib-link.read.1.tlog create mode 100644 source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib-link.write.1.tlog create mode 100644 source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib.command.1.tlog rename source/{ => native}/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Tools.Lib.CorHelper.lastbuildstate (70%) create mode 100644 source/native/Tools.CorHelper/Debug/Tools.Lib.CorHelper.idb rename source/{ => native}/Tools.CorHelper/corhlpr.cpp (100%) rename source/{ => native}/Tools.CorHelper/dotNetMF.proj (100%) rename source/{ => native}/Tools.CorHelper/stdafx.cpp (100%) rename source/{ => native}/Tools.CorHelper/stdafx.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/AssemblyParser.h (99%) rename source/{ => native}/Tools.MetaDataProcessor/AssemblyReparser.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/HAL_Windows.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/Info_Win32.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/ManagedElementTypes_Win32.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/ManagedElementTypes_Win32.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj (77%) rename source/{ => native}/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj.filters (80%) rename source/{ => native}/Tools.MetaDataProcessor/MetaDataProcessor.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj (79%) rename source/{ => native}/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj.filters (80%) rename source/{ => native}/Tools.MetaDataProcessor/ParseOptions_Win32.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/StubWinHal.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/Time_stubs.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/Various.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/WatchAssemblyBuilder.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/XmlUtil.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/cor.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/corerror.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/corhdr.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/corhlpr.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/corlib_native.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/corsym.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/minheap.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/mintime.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.sln (100%) rename source/{ => native}/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.targets (100%) rename source/{ => native}/Tools.MetaDataProcessor/nanoHAL_Watchdog_stubs.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/package.nuspec (100%) rename source/{ => native}/Tools.MetaDataProcessor/packages.config (100%) rename source/{ => native}/Tools.MetaDataProcessor/stdafx.cpp (100%) rename source/{ => native}/Tools.MetaDataProcessor/stdafx.h (100%) rename source/{ => native}/Tools.MetaDataProcessor/targetver.h (100%) rename source/{ => native}/Tools.Parser/AssemblyParser.cpp (99%) rename source/{ => native}/Tools.Parser/AssemblyParserDump.cpp (100%) rename source/{ => native}/Tools.Parser/AssemblyReparser.cpp (100%) rename source/{ => native}/Tools.Parser/ByteCodeParser.cpp (100%) rename source/{ => native}/Tools.Parser/ByteCodeParser_Load.cpp (100%) rename source/{ => native}/Tools.Parser/ByteCodeParser_Save.cpp (100%) create mode 100644 source/native/Tools.Parser/Debug/Tools.Lib.Parser.idb create mode 100644 source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.command.1.tlog rename source/{ => native}/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.read.1.tlog (84%) create mode 100644 source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.write.1.tlog create mode 100644 source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.read.1.tlog create mode 100644 source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.write.1.tlog create mode 100644 source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib.command.1.tlog rename source/{ => native}/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Tools.Lib.Parser.lastbuildstate (70%) rename source/{ => native}/Tools.Parser/FileStore_Win32.cpp (100%) rename source/{ => native}/Tools.Parser/Linker.cpp (100%) rename source/{ => native}/Tools.Parser/Parser-vs2019.vcxproj (91%) rename source/{ => native}/Tools.Parser/Parser-vs2019.vcxproj.filters (100%) rename source/{ => native}/Tools.Parser/Parser.vcxproj (91%) rename source/{ => native}/Tools.Parser/Parser.vcxproj.filters (100%) rename source/{ => native}/Tools.Parser/Support.cpp (100%) rename source/{ => native}/Tools.Parser/dotNetMF.proj (100%) rename source/{ => native}/Tools.Parser/stdafx.cpp (100%) rename source/{ => native}/Tools.Parser/stdafx.h (100%) create mode 100644 source/native/nanoFramework.Tools.MetadataProcessor.sln create mode 100644 source/native/nf-interpreter/.github/FUNDING.yml create mode 100644 source/native/nf-interpreter/.github/ISSUE_TEMPLATE.md create mode 100644 source/native/nf-interpreter/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 source/native/nf-interpreter/.github/stale.yml create mode 100644 source/native/nf-interpreter/.github_changelog_generator create mode 100644 source/native/nf-interpreter/.gitignore create mode 100644 source/native/nf-interpreter/.gitmodules create mode 100644 source/native/nf-interpreter/.vs/launch.vs.SAMPLE.json create mode 100644 source/native/nf-interpreter/.vs/tasks.vs.SAMPLE.json create mode 100644 source/native/nf-interpreter/.vscode/cmake-kits.TEMPLATE-ESP32.json create mode 100644 source/native/nf-interpreter/.vscode/launch.TEMPLATE-ESP32.json create mode 100644 source/native/nf-interpreter/.vscode/launch.TEMPLATE.json create mode 100644 source/native/nf-interpreter/.vscode/settings.TEMPLATE.json create mode 100644 source/native/nf-interpreter/.vscode/tasks.TEMPLATE-ESP32.json create mode 100644 source/native/nf-interpreter/CHANGELOG.md create mode 100644 source/native/nf-interpreter/CMake/ChibiOS-Contrib.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/ChibiOS.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/ChibiOS_target_os.h.in create mode 100644 source/native/nf-interpreter/CMake/ESP32_target_os.h.in create mode 100644 source/native/nf-interpreter/CMake/FreeRTOS.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_GCC_options.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_GCC_options.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_GCC_options.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_GCC_options.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_GCC_options.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindBuildUtils.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindCHIBIOS.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_FATFS.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_LWIP.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindChibiOS-Contrib.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindChibiOSnfOverlay.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindMBEDOS.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindNF_CoreCLR.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindNF_Debugger.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindNF_Diagnostics.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindNF_Networking.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindRTXRTOS.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindRTXRTOS2.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSPIFFS.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSTM32F0_CubePackage.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSTM32F4_CubePackage.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSTM32F7_CubePackage.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSTM32FREERTOS.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSTM32H7_CubePackage.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSTM32L0_CubePackage.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSystem.Devices.Dac.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSystem.Math.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindSystem.Net.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindTI_SimpleLink.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Adc.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Gpio.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.I2c.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Pwm.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.SerialCommunication.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Spi.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.WiFi.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Networking.Sockets.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWindows.Storage.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindWireProtocol.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindmbedTLS.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.Can.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.OneWire.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Esp32.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Stm32.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Networking.Sntp.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.ResourceManager.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Runtime.Events.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/FindnanoFramework.System.Collections.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/JSONParser.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_GCC_options.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/MBED_STM_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/NF_NativeAssemblies.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/STM32_CubePackage.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_GCC_options.cmake create mode 100644 source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_sources.cmake create mode 100644 source/native/nf-interpreter/CMake/RTXRTOS.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/SPIFFS.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/STM32.CubePackage.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/SimpleLinkCC32xxSdk.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/TI_SimpleLink_target_os.h.in create mode 100644 source/native/nf-interpreter/CMake/mBedOS.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/mbedTLS.CMakeLists.cmake.in create mode 100644 source/native/nf-interpreter/CMake/toolchain.ChibiOS.GCC.cmake create mode 100644 source/native/nf-interpreter/CMake/toolchain.FreeRtos.ESP32.GCC.cmake create mode 100644 source/native/nf-interpreter/CMake/toolchain.TI_SimpleLink.GCC.cmake create mode 100644 source/native/nf-interpreter/CMake/toolchain.mBed.GCC.cmake create mode 100644 source/native/nf-interpreter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/CMakeSettings.SAMPLE.json create mode 100644 source/native/nf-interpreter/CMakeSettings.json create mode 100644 source/native/nf-interpreter/InteropAssemblies/CLR_RT_InteropAssembliesTable.cpp.in create mode 100644 source/native/nf-interpreter/InteropAssemblies/README.md create mode 100644 source/native/nf-interpreter/LICENSE.md create mode 100644 source/native/nf-interpreter/README.md create mode 100644 source/native/nf-interpreter/README.zh-cn.md create mode 100644 source/native/nf-interpreter/RunCmd.bat create mode 100644 source/native/nf-interpreter/SetNFRoot.bat create mode 100644 source/native/nf-interpreter/VisualStudioDevelopment/CopyBuildOutput.cmd create mode 100644 source/native/nf-interpreter/VisualStudioDevelopment/README.md create mode 100644 source/native/nf-interpreter/VisualStudioDevelopment/VSDevDirectoryStructure.png create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/build-chibios-stm32.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/build-esp32.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/build-ti-simplelink.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/download-hexdfu.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/download-install-arm-gcc-toolchain.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/download-install-esp32-build-components.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/download-install-ninja.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/nb-gitversioning.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/pack-publish-artifacts.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/pack-publish-managed-helpers.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/pack-publish-ti-sl-managed-helpers.yml create mode 100644 source/native/nf-interpreter/azure-pipelines-templates/publish-bintray.yml create mode 100644 source/native/nf-interpreter/azure-pipelines.yml create mode 100644 source/native/nf-interpreter/cmake-variants.TEMPLATE-ESP32.json create mode 100644 source/native/nf-interpreter/cmake-variants.TEMPLATE.json create mode 100644 source/native/nf-interpreter/install-scripts/Set-PathVariable.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-arm-gcc-toolchain.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-esp32-idf.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-esp32-libs.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-esp32-openocd.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-esp32-toolchain.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-esp32-tools.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-nf-hex2dfu.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-ninja.ps1 create mode 100644 source/native/nf-interpreter/install-scripts/install-stm32-tools.ps1 create mode 100644 source/native/nf-interpreter/nf.props create mode 100644 source/native/nf-interpreter/nfcore.vssettings create mode 100644 source/native/nf-interpreter/sd1.bat create mode 100644 source/native/nf-interpreter/sdkconfig create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/CorLib.h create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native.h create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_AppDomain.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Array.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Attribute.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_BitConverter.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Collections_ArrayList.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Console.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Convert.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_DateTime.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Delegate.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Diagnostics_Debugger.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Double.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Enum.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Exception.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_GC.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_CultureInfo.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_DateTimeFormat.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Guid.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MarshalByRefObject.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MathInternal.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MulticastDelegate.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Number.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Object.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Random.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Assembly.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Binder.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_ConstructorInfo.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_FieldInfo.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MemberInfo.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MethodBase.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_PropertyInfo.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeFieldInfo.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeMethodInfo.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_RuntimeType.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_CompilerServices_RuntimeHelpers.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_Remoting_RemotingServices.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_String.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Decoder.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Encoding.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_AutoResetEvent.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Interlocked.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_ManualResetEvent.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Monitor.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Thread.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Timer.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_WaitHandle.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_TimeSpan.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Type.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_ValueType.cpp create mode 100644 source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_WeakReference.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_DblLinkedList.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_ArrayList.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_BinaryBlob.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Node.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Queue.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_String.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapCluster.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_Interop.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_Memory.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_RuntimeMemory.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_StackFrame.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/CLR_RT_UnicodeHelper.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Cache.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Checks.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Core.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Core.h create mode 100644 source/native/nf-interpreter/src/CLR/Core/Core.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Core.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Execution.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/GarbageCollector.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Compaction.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Info.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Interpreter.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Random.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Core/Streams.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/StringTable.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/StringTableData.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Thread.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/TypeSystem.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/TypeSystemLookup.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/Various.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Core/corhdr_private.h create mode 100644 source/native/nf-interpreter/src/CLR/Core/nanoSupport_CRC32.c create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/CMakeLists.txt create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger.h create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger_full.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger_minimal.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.h create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Info.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Profile.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Diagnostics/Profiler.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.c create mode 100644 source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.h create mode 100644 source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.c create mode 100644 source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/WireProtocol.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/WireProtocol_App_Interface.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/WireProtocol_HAL_Interface.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/WireProtocol_Message.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/WireProtocol_MonitorCommands.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Application.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Checks.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Debugging.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_ErrorCodes.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Hardware.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Interop.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Messaging.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_ParseOptions.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_PlatformDef.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Profiling.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__Serialization.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Types.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoCLR_Win32.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoPackStruct.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoSupport.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nanoWeak.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/nf_errors_exceptions.h create mode 100644 source/native/nf-interpreter/src/CLR/Include/opcode.def create mode 100644 source/native/nf-interpreter/src/CLR/Include/stdafx.h create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/Startup/CLRStartup.cpp create mode 100644 source/native/nf-interpreter/src/CLR/Startup/CLRStartup.h create mode 100644 source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.cpp create mode 100644 source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.h create mode 100644 source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math_System_Math.cpp create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj.filters create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_App_Interface.c create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_HAL_Interface.c create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_Message.c create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_MonitorCommands.c create mode 100644 source/native/nf-interpreter/src/CLR/WireProtocol/targetHAL_time.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_lwipopts_sntp.h create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.h create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp_nanoFramework_Networking_Sntp.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.h create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_NetworkInterface.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_CertificateManager.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_SslNative.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Sockets_NativeSocket.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate.cpp create mode 100644 source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2.cpp create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_ConfigurationManager.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_Network.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_Power.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_ReleaseInfo.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_Time.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_Types.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_Watchdog.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_Windows_Storage.h create mode 100644 source/native/nf-interpreter/src/HAL/Include/nanoHAL_v2.h create mode 100644 source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager.c create mode 100644 source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager_stubs.c create mode 100644 source/native/nf-interpreter/src/HAL/nanoHAL_SystemInformation.cpp create mode 100644 source/native/nf-interpreter/src/HAL/nanoHAL_Time.cpp create mode 100644 source/native/nf-interpreter/src/HAL/nanoHAL_Watchdog.c create mode 100644 source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncCompletions.cpp create mode 100644 source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncContinuations.cpp create mode 100644 source/native/nf-interpreter/src/PAL/AsyncProcCall/Async_stubs.cpp create mode 100644 source/native/nf-interpreter/src/PAL/BlockStorage/nanoPAL_BlockStorage.c create mode 100644 source/native/nf-interpreter/src/PAL/COM/COM_stubs.c create mode 100644 source/native/nf-interpreter/src/PAL/COM/ComDirector.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/GenericPort_stubs.c create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/Sockets_debugger.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.h create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/mbedtls.h create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_accept_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_add_cert_auth_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_close_socket_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_connect_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_decode_private_key_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_exit_context_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic_init_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_initialize_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_parse_certificate_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_pending_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_read_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_uninitialize_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_write_internal.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl.h create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_functions.h create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_stubs.cpp create mode 100644 source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_types.h create mode 100644 source/native/nf-interpreter/src/PAL/Double/nanoPAL_NativeDouble.cpp create mode 100644 source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_driver.cpp create mode 100644 source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_functions.cpp create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoCRT.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_AsyncProcCalls_decl.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_BlockStorage.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_COM.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_Events.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_GPIO.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_NativeDouble.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_Network.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_PerformanceCounters.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_Sockets.h create mode 100644 source/native/nf-interpreter/src/PAL/Include/nanoPAL_Time.h create mode 100644 source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.cpp create mode 100644 source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.h create mode 100644 source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets_functions.cpp create mode 100644 source/native/nf-interpreter/src/PAL/Profiler/nanoPAL_PerformanceCounters_stubs.cpp create mode 100644 source/native/nf-interpreter/src/PAL/nanoPAL_Network_stubs.cpp create mode 100644 source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.cpp create mode 100644 source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.h create mode 100644 source/native/nf-interpreter/src/Windows.Storage/win_storage_native.cpp create mode 100644 source/native/nf-interpreter/src/Windows.Storage/win_storage_native.h create mode 100644 source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.h create mode 100644 source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.h create mode 100644 source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.h create mode 100644 source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_System_Resources_ResourceManager.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.h create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.h create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Hardware_SystemInfo.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Debug.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Power.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc_stubs.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.h create mode 100644 source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Queue.cpp create mode 100644 source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Stack.cpp create mode 100644 source/native/nf-interpreter/startocd.bat create mode 100644 source/native/nf-interpreter/targets-community/.github/ISSUE_TEMPLATE.md create mode 100644 source/native/nf-interpreter/targets-community/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 source/native/nf-interpreter/targets-community/.gitignore create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Gpio.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/resources/cerb40-top.PNG create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/resources/cerb40.jpg create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Gpio.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/STM32F411xE_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/STM32F411xE_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/IngenuityMicro_Logo.svg create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/electron.pdf create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/electronpins.png create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Gpio.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/resources/oxygen-pcb.jpeg create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/resources/oxygen.jpeg create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Gpio.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.LEDs.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/serialcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/targetHAL_ConfigurationManager.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/ffconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/lwipopts.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/mbedtls_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nucleo144-f439zi.jpg create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_lwip_sntp_opts.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/serialcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/targetHAL_ConfigurationManager.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/lwipopts.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/ST_NUCLEO144_F746ZG.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/mbedtls_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nucleo144-f746zg.jpg create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_lwip_sntp_opts.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/serialcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/ST_NUCLEO64_F401RE.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/serialcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/ST_NUCLEO64_F411RE_NF.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/ST_STM32F4_DISCOVERY.Adc.cs create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR.ld create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/stm32f4_discovery.jpg create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.c create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.h.in create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets-community/LICENSE create mode 100644 source/native/nf-interpreter/targets-community/README.md create mode 100644 source/native/nf-interpreter/targets-community/azure-pipelines-templates/clone-nf-interpreter-repo.yml create mode 100644 source/native/nf-interpreter/targets-community/azure-pipelines-templates/set-build-version.yml create mode 100644 source/native/nf-interpreter/targets-community/azure-pipelines.yml create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CLR_Startup_Thread.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/LaunchCLR.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/TargetPAL_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_BlockStorage_STM32FlashDriver.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_Windows_Storage.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/WireProtocol_ReceiverThread.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/platform_target_capabilities.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Power.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Time.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Watchdog.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL_Time.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/vectors.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/platform_sys_arch.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/ffconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/NETDUINO3_WIFI.Adc.cs create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/package.nuspec create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_storage_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/serialcfg.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/ffconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/STM32F429I_DISCOVERY.Adc.cs create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/package.nuspec create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_external_memory.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/serialcfg.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/targetHAL_ConfigurationManager.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/ffconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/lwipopts.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/STM32F769I_DISCOVERY.Adc.cs create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/package.nuspec create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/mbedtls_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/chconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf_nf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/spiffs_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/stm32f7xx_hal_conf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_lwip_sntp_opts.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_storage_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/LaunchCLR.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_BlockStorage_STM32FlashDriver.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Network.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Windows_Storage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_HAL_Interface.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_ReceiverThread.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/hard_fault_handler.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/nanoSupport_CRC32.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_heap.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_clr.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_code.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_data.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_stacks.ld create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_ConfigurationManager.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Network.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_App_Interface.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_MonitorCommands.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_RT_InteropAssembliesTable.cpp.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_Startup_Thread.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Memory.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_App_Interface.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_MonitorCommands.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/mbedtls_entropy_hardware_pool.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoCRT.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_nanoFramework_Devices_Can_CanController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Watchdog.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Events.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetRandom.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/target_platform.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/asmdefs.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_adc.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_aes.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_config.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_rcm.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_camera.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_common_reg.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_des.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_dthe.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_flash_ctrl.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gpio.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gprcm.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib1p2.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib3p3.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_i2c.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ints.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcasp.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcspi.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_memmap.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mmchs.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_nvic.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ocp_shared.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_shamd5.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_stack_die_ctrl.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_timer.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_types.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_uart.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_udma.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_wdt.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CMSIS/TI/TICC3200/cc3200.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/startup/ARMCMx/devices/TICC3200/cmparams.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/dummy_includes/hal_community.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_nf_community.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_crc/hal_stm32_crc.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_flash/hal_stm32_flash.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc/hal_stm32_fsmc.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_onewire/hal_stm32_onewire.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_qspi/hal_stm32_qspi.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_rng/hal_stm32_rng.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/README.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/RTC/hal_rtc_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/UART/hal_serial_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_isr.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_registry.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc/hal_stm32_crc.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_flash/hal_stm32_flash.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_onewire/hal_stm32_onewire.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_qspi/hal_stm32_qspi.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng/hal_stm32_rng.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/stm32-internal-flash-driver.md create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/cc.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/perf.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/sys_arch.h create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_api_msg.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sockets.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sys_arch.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/common/Include/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/common/Include/swo.h.in create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/common/swo.cpp create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/common/syscalls.c create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/nanoBooter/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/CMSIS-OS/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CopyLibs.cmd create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_16mb.csv create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_2mb.csv create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_4mb.csv create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_8mb.csv create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/CLR_Startup_Thread.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Esp32_DeviceMapping.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/LaunchCLR.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/TargetPAL_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_BlockStorage_Esp32FlashDriver.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_Windows_Storage.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/WireProtocol_ReceiverThread.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/esp32_os.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/platform_target_capabilities.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Power.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Time.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL_Time.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/asdkconfig.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/lwipopts.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_api_msg.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sockets.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sys_arch.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Ethernet_Lan8720.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_SmartConfig.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Wireless.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Target_Network.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/targetHAL_Network.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/README.md create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Target_Windows_Storage.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Esp32_DeviceMapping.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/FreeRTOS-openocd.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/GenericPort.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Target_BlockStorage_ESP32FlashDriver.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_HAL_Interface.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_ReceiverThread.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/mbedtls_entropy_hardware_pool.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_heap.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32.project.ld create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32_out.ld create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/mbedtls_config.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoBooter/readme.md create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CLR_Startup_Thread.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Memory.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native_Windows_Devices_WIFI_WifiAdapter.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_App_Interface.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_MonitorCommands.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/app_main.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/mbedtls_entropy_hardware_pool.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoCRT.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_Configuration.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_HighResTimer.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_Logging.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_Sleep.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorage.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageFatfs.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageNVS.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageSPIFFS.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigurationManager.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Power.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp.groups.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetRandom.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_platform.h.in create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.txt create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.c create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.h.in create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_lwip_sntp_opts.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.h create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_system_devices_dac_config.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_serialcommunication_config.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_storage_config.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/CLR_Startup_Thread.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/TargetPAL_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_BlockStorage_CC32xxFlashDriver.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_Windows_Storage.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/WireProtocol_ReceiverThread.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/platform_target_capabilities.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/ssl_simplelink.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_ConfigurationManager_CC32xx.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_Time.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetPAL_Time.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_LinkLocalTask.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_ProvisioningTask.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Sntp.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Threads.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/Board.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/FreeRTOSConfig.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/README.md create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage-DEBUG.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/README.md create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/TI_CC3220SF_LAUNCHXL.Gpio.cs create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/package.nuspec create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR-DEBUG.ld create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR.ld create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/main.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/nanoHAL.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/target_board.h.in create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/ti_drivers_net_wifi_Config.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.h.in create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_sntp_opts.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_adc_config.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_i2c_config.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_pwm_config.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_spi_config.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/FreeRTOS-openocd.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/GenericPort.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/Target_BlockStorage_CC32xxFlashDriver.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_HAL_Interface.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_ReceiverThread.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/nanoSupport_CRC32.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_BlockStorage.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_heap.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/rules_clr.ld create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets_functions.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/sockets_simplelink.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/ssl_simplelink.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/syscalls.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/common/targetHAL_ConfigurationManager_CC32xx.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CLR_Startup_Thread.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CMakeLists.txt create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Memory.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_App_Interface.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_MonitorCommands.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/nanoCRT.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Power.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Events.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_LinkLocalTask.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_ProvisioningTask.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Sntp.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Threads.c create mode 100644 source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/target_platform.h.in create mode 100644 source/native/nf-interpreter/targets/os/win32/Include/TargetPAL_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/os/win32/Include/Target_Windows_Storage.h create mode 100644 source/native/nf-interpreter/targets/os/win32/Include/targetHAL.h create mode 100644 source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Power.h create mode 100644 source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Time.h create mode 100644 source/native/nf-interpreter/targets/os/win32/Include/targetPAL_time.h create mode 100644 source/native/nf-interpreter/targets/os/win32/Include/target_BlockStorage.h create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR.sln create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/CLRStartup.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Events.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/FileStore_Win32.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Generated/CLR_RT_InteropAssembliesTable.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Memory.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/COMDirector_stubs.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Target_BlockStorage.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/time_stubs.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/ParseOptions_Win32.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Target_BlockStorage.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Various.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/WatchDog.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.h create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.h create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/main.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.h create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_heap.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_selector.h create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.h create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/targetHAL_Time.cpp create mode 100644 source/native/nf-interpreter/targets/os/win32/nanoCLR/targetver.h create mode 100644 source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/NF.TestApplication.nfproj create mode 100644 source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Program.cs create mode 100644 source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Properties/AssemblyInfo.cs create mode 100644 source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/TestApplication.sln create mode 100644 source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/packages.config create mode 100644 source/native/nf-interpreter/targets/os/win32/packages.config create mode 100644 source/native/nf-interpreter/version.json diff --git a/.gitmodules b/.gitmodules index 72726db3..4078391d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "nf-interpreter"] - path = nf-interpreter + path = source/native/nf-interpreter url = https://github.com/nanoframework/nf-interpreter diff --git a/nf-interpreter b/nf-interpreter deleted file mode 160000 index 73389fad..00000000 --- a/nf-interpreter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 73389fad32cba0175ccc666f76c6d02c211d594b diff --git a/source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.command.1.tlog b/source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.command.1.tlog deleted file mode 100644 index 8d0a18a86812bed2ea015ace50609ac20817f676..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2962 zcmeH|OHbQC6ot>aQvU<;p3ujlRirLRVmna-jvSj%WVMO{lt?L!l2iqLeB1BN*a;*c zRR{?dku|S7_jzXK`0t;u3RPF3SRG|*D_4Wnp(5?FPWZaa4$#W9uNKY5UGjb5LAH`SPq4Lb>m}jfG%GIhWXkC}Pucu3n4F!+zXBehnZV~$UOc4WN5$w9!E(0ByHDz|{p21iT<@#;1T5^tF7;Cr+IO0*2O#CgWA3BPPBqq$ zebbz4!D_@3f+!_m$2OIDga|v~$po z!QEa;s87hQXdm>Jex;vtwjFE|r&Y-}rLlfEtB{v7FEdZMF-`oL)dBXtj+pynl5v%U=Hw@=>iSK80TMGZUEGqNgVziXBgW|+i!oSE@N-#8zn~M~bwS)A(XMzy z7v=4YunlhEWh}B!OW+bi#NO_JRjSWeRor6i;PJeVC2HW=r24>R8ZQVRTShaPNui& z&fk~m;45l&mRhho4W5KQ8~Ep*e}o1W6&lz&_IuA@1JY3y$E!j$^Oj!-n;6D(Ve~ob z1V+Dxy2MHILEYjJ*C|(LTac~2qSN)-*nh73n%Q;R-Zrl@c{76cKyOaXW(Qm1xf~AL*o)T1LLZJkb>VnVV&&@9R!68ADX$9WV2M-s4mL zE5Uy1R&Bw1DhJ&`{GVG#C)RhN%a_?&t3_~|pPRAE!sG^2ZD8*;ppGeY<@9hrYO769 zX=LK2Vhqk&Er%^|ej(IKI zj2k+@??Fy_!uY?ok)PPV8{JoBTWx-(?c0~Y+<+Smu9RsDx8&p*C3!pMuV;IXoPGTG IoH0}U1|xY$&j0`b diff --git a/source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib.command.1.tlog b/source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib.command.1.tlog deleted file mode 100644 index bfb51b426881324a10311f7c3e1aa864afefb91e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 592 zcmc(c%?^Sv5QOJ!;yV!T=$#t~6t#lkCwd@0iO;TnZBpc7JQ>q$w!1TJr?bz;O{G#z zGTLiUtx-8uqe=;N%d+fFum)u+2$vI`)q(Bk_pFv`@_A(Ey3>5R*M^Q`)buSUOV2LI zIqw;`0e5HzzXdty4&(pYdVb>mUFkY2TWh5)Do3zX@y~QFJ!;U<@MeWWnV-nTyLv=b in3VI{GRd4AJbil}uvii5-CdS2M8prjO=HRUcUCO` diff --git a/source/Tools.CorHelper/Debug/Tools.Lib.CorHelper.idb b/source/Tools.CorHelper/Debug/Tools.Lib.CorHelper.idb deleted file mode 100644 index 5fb91df1d15695eac55dfd50289094c3d6ee949d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 797696 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≧YLev;$c(oVFQg!J!=Oo`kxn|`~g2(Ci@ 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

v7WBzZyS34;HtD~`#&@Rm>(|nMf6kD< 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%0DgqZGF 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%0ANl=DL!(7QyfFD}-rG7+ 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 literal 0 HcmV?d00001 diff --git a/source/Tools.CorHelper/corhlpr.cpp b/source/native/Tools.CorHelper/corhlpr.cpp similarity index 100% rename from source/Tools.CorHelper/corhlpr.cpp rename to source/native/Tools.CorHelper/corhlpr.cpp diff --git a/source/Tools.CorHelper/dotNetMF.proj b/source/native/Tools.CorHelper/dotNetMF.proj similarity index 100% rename from source/Tools.CorHelper/dotNetMF.proj rename to source/native/Tools.CorHelper/dotNetMF.proj diff --git a/source/Tools.CorHelper/stdafx.cpp b/source/native/Tools.CorHelper/stdafx.cpp similarity index 100% rename from source/Tools.CorHelper/stdafx.cpp rename to source/native/Tools.CorHelper/stdafx.cpp diff --git a/source/Tools.CorHelper/stdafx.h b/source/native/Tools.CorHelper/stdafx.h similarity index 100% rename from source/Tools.CorHelper/stdafx.h rename to source/native/Tools.CorHelper/stdafx.h diff --git a/source/Tools.MetaDataProcessor/AssemblyParser.h b/source/native/Tools.MetaDataProcessor/AssemblyParser.h similarity index 99% rename from source/Tools.MetaDataProcessor/AssemblyParser.h rename to source/native/Tools.MetaDataProcessor/AssemblyParser.h index 93620f9c..01f88596 100644 --- a/source/Tools.MetaDataProcessor/AssemblyParser.h +++ b/source/native/Tools.MetaDataProcessor/AssemblyParser.h @@ -418,6 +418,7 @@ namespace MetaData FieldDef(Parser* holder); bool SetValue(const void* ptr, int len); + bool SetEmptyString(const void* ptr); }; struct MethodDef diff --git a/source/Tools.MetaDataProcessor/AssemblyReparser.h b/source/native/Tools.MetaDataProcessor/AssemblyReparser.h similarity index 100% rename from source/Tools.MetaDataProcessor/AssemblyReparser.h rename to source/native/Tools.MetaDataProcessor/AssemblyReparser.h diff --git a/source/Tools.MetaDataProcessor/HAL_Windows.h b/source/native/Tools.MetaDataProcessor/HAL_Windows.h similarity index 100% rename from source/Tools.MetaDataProcessor/HAL_Windows.h rename to source/native/Tools.MetaDataProcessor/HAL_Windows.h diff --git a/source/Tools.MetaDataProcessor/Info_Win32.cpp b/source/native/Tools.MetaDataProcessor/Info_Win32.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/Info_Win32.cpp rename to source/native/Tools.MetaDataProcessor/Info_Win32.cpp diff --git a/source/Tools.MetaDataProcessor/ManagedElementTypes_Win32.cpp b/source/native/Tools.MetaDataProcessor/ManagedElementTypes_Win32.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/ManagedElementTypes_Win32.cpp rename to source/native/Tools.MetaDataProcessor/ManagedElementTypes_Win32.cpp diff --git a/source/Tools.MetaDataProcessor/ManagedElementTypes_Win32.h b/source/native/Tools.MetaDataProcessor/ManagedElementTypes_Win32.h similarity index 100% rename from source/Tools.MetaDataProcessor/ManagedElementTypes_Win32.h rename to source/native/Tools.MetaDataProcessor/ManagedElementTypes_Win32.h diff --git a/source/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj b/source/native/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj similarity index 77% rename from source/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj rename to source/native/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj index 61f3f668..4b2144ce 100644 --- a/source/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj +++ b/source/native/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj @@ -99,7 +99,7 @@ Level3 Disabled WIN32;METADATAPROCESSOR;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;..\..\nf-interpreter\src\CLR\Helpers\Base64;%(AdditionalIncludeDirectories) + ..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;..\nf-interpreter\src\CLR\Helpers\Base64;%(AdditionalIncludeDirectories) MultiThreadedDebugDLL @@ -113,7 +113,7 @@ Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) + ..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) Console @@ -127,7 +127,7 @@ false true WIN32;METADATAPROCESSOR;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;..\..\nf-interpreter\src\CLR\Helpers\Base64;%(AdditionalIncludeDirectories) + ..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;..\nf-interpreter\src\CLR\Helpers\Base64;%(AdditionalIncludeDirectories) MultiThreadedDLL @@ -146,7 +146,7 @@ true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) + ..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) Console @@ -168,15 +168,15 @@ - - - - - - - - - + + + + + + + + + @@ -196,28 +196,28 @@ - + {89cf8bdb-9c8a-4d18-bc3e-4312c5bd34b1} - + {5d50772e-dac8-407d-972f-37deb4450b72} - + {d32ee397-7e49-452d-ac95-afcb3c962e3d} - + {ed4c887a-ec09-465b-b5d9-075450adc52d} - + {16bf6131-a3b8-4b97-b867-e45669fb48bd} - + {58e950cc-2ff6-423c-b006-a70a19272f20} - + {a5e9ae41-f4fa-40ce-ad82-a7861eba007b} - + {131001e3-0201-451f-a87b-951d1c5c3eee} diff --git a/source/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj.filters b/source/native/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj.filters similarity index 80% rename from source/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj.filters rename to source/native/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj.filters index 679f8d9e..cc8cdd93 100644 --- a/source/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj.filters +++ b/source/native/Tools.MetaDataProcessor/MetaDataProcessor-vs2019.vcxproj.filters @@ -56,7 +56,7 @@ Source Files - + Source Files @@ -65,16 +65,16 @@ Source Files - + Source Files Source Files - + Source Files - + Source Files @@ -89,16 +89,16 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files @@ -107,7 +107,7 @@ Source Files - + Source Files diff --git a/source/Tools.MetaDataProcessor/MetaDataProcessor.cpp b/source/native/Tools.MetaDataProcessor/MetaDataProcessor.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/MetaDataProcessor.cpp rename to source/native/Tools.MetaDataProcessor/MetaDataProcessor.cpp diff --git a/source/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj b/source/native/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj similarity index 79% rename from source/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj rename to source/native/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj index 7a508e8c..1f8037b6 100644 --- a/source/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj +++ b/source/native/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj @@ -95,7 +95,7 @@ Level3 Disabled WIN32;METADATAPROCESSOR;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) + ..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) MultiThreadedDebugDLL @@ -109,7 +109,7 @@ Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) + ..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) Console @@ -123,7 +123,7 @@ false true WIN32;METADATAPROCESSOR;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) + ..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) MultiThreadedDLL @@ -142,7 +142,7 @@ true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;..\..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) + ..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;..\nf-interpreter\src\CLR\Core;%(AdditionalIncludeDirectories) Console @@ -164,15 +164,15 @@ - - - - - - - - - + + + + + + + + + @@ -192,28 +192,28 @@ - + {89cf8bdb-9c8a-4d18-bc3e-4312c5bd34b1} - + {5d50772e-dac8-407d-972f-37deb4450b72} - + {d32ee397-7e49-452d-ac95-afcb3c962e3d} - + {ed4c887a-ec09-465b-b5d9-075450adc52d} - + {16bf6131-a3b8-4b97-b867-e45669fb48bd} - + {58e950cc-2ff6-423c-b006-a70a19272f20} - + {a5e9ae41-f4fa-40ce-ad82-a7861eba007b} - + {131001e3-0201-451f-a87b-951d1c5c3eee} diff --git a/source/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj.filters b/source/native/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj.filters similarity index 80% rename from source/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj.filters rename to source/native/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj.filters index 6593fece..3ab4e416 100644 --- a/source/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj.filters +++ b/source/native/Tools.MetaDataProcessor/MetaDataProcessor.vcxproj.filters @@ -56,7 +56,7 @@ Source Files - + Source Files @@ -65,16 +65,16 @@ Source Files - + Source Files Source Files - + Source Files - + Source Files @@ -89,16 +89,16 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files @@ -107,7 +107,7 @@ Source Files - + Source Files diff --git a/source/Tools.MetaDataProcessor/ParseOptions_Win32.cpp b/source/native/Tools.MetaDataProcessor/ParseOptions_Win32.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/ParseOptions_Win32.cpp rename to source/native/Tools.MetaDataProcessor/ParseOptions_Win32.cpp diff --git a/source/Tools.MetaDataProcessor/StubWinHal.cpp b/source/native/Tools.MetaDataProcessor/StubWinHal.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/StubWinHal.cpp rename to source/native/Tools.MetaDataProcessor/StubWinHal.cpp diff --git a/source/Tools.MetaDataProcessor/Time_stubs.cpp b/source/native/Tools.MetaDataProcessor/Time_stubs.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/Time_stubs.cpp rename to source/native/Tools.MetaDataProcessor/Time_stubs.cpp diff --git a/source/Tools.MetaDataProcessor/Various.cpp b/source/native/Tools.MetaDataProcessor/Various.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/Various.cpp rename to source/native/Tools.MetaDataProcessor/Various.cpp diff --git a/source/Tools.MetaDataProcessor/WatchAssemblyBuilder.h b/source/native/Tools.MetaDataProcessor/WatchAssemblyBuilder.h similarity index 100% rename from source/Tools.MetaDataProcessor/WatchAssemblyBuilder.h rename to source/native/Tools.MetaDataProcessor/WatchAssemblyBuilder.h diff --git a/source/Tools.MetaDataProcessor/XmlUtil.cpp b/source/native/Tools.MetaDataProcessor/XmlUtil.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/XmlUtil.cpp rename to source/native/Tools.MetaDataProcessor/XmlUtil.cpp diff --git a/source/Tools.MetaDataProcessor/cor.h b/source/native/Tools.MetaDataProcessor/cor.h similarity index 100% rename from source/Tools.MetaDataProcessor/cor.h rename to source/native/Tools.MetaDataProcessor/cor.h diff --git a/source/Tools.MetaDataProcessor/corerror.h b/source/native/Tools.MetaDataProcessor/corerror.h similarity index 100% rename from source/Tools.MetaDataProcessor/corerror.h rename to source/native/Tools.MetaDataProcessor/corerror.h diff --git a/source/Tools.MetaDataProcessor/corhdr.h b/source/native/Tools.MetaDataProcessor/corhdr.h similarity index 100% rename from source/Tools.MetaDataProcessor/corhdr.h rename to source/native/Tools.MetaDataProcessor/corhdr.h diff --git a/source/Tools.MetaDataProcessor/corhlpr.h b/source/native/Tools.MetaDataProcessor/corhlpr.h similarity index 100% rename from source/Tools.MetaDataProcessor/corhlpr.h rename to source/native/Tools.MetaDataProcessor/corhlpr.h diff --git a/source/Tools.MetaDataProcessor/corlib_native.cpp b/source/native/Tools.MetaDataProcessor/corlib_native.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/corlib_native.cpp rename to source/native/Tools.MetaDataProcessor/corlib_native.cpp diff --git a/source/Tools.MetaDataProcessor/corsym.h b/source/native/Tools.MetaDataProcessor/corsym.h similarity index 100% rename from source/Tools.MetaDataProcessor/corsym.h rename to source/native/Tools.MetaDataProcessor/corsym.h diff --git a/source/Tools.MetaDataProcessor/minheap.cpp b/source/native/Tools.MetaDataProcessor/minheap.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/minheap.cpp rename to source/native/Tools.MetaDataProcessor/minheap.cpp diff --git a/source/Tools.MetaDataProcessor/mintime.cpp b/source/native/Tools.MetaDataProcessor/mintime.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/mintime.cpp rename to source/native/Tools.MetaDataProcessor/mintime.cpp diff --git a/source/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.sln b/source/native/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.sln similarity index 100% rename from source/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.sln rename to source/native/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.sln diff --git a/source/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.targets b/source/native/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.targets similarity index 100% rename from source/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.targets rename to source/native/Tools.MetaDataProcessor/nanoFramework.Tools.MetaDataProcessor.targets diff --git a/source/Tools.MetaDataProcessor/nanoHAL_Watchdog_stubs.cpp b/source/native/Tools.MetaDataProcessor/nanoHAL_Watchdog_stubs.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/nanoHAL_Watchdog_stubs.cpp rename to source/native/Tools.MetaDataProcessor/nanoHAL_Watchdog_stubs.cpp diff --git a/source/Tools.MetaDataProcessor/package.nuspec b/source/native/Tools.MetaDataProcessor/package.nuspec similarity index 100% rename from source/Tools.MetaDataProcessor/package.nuspec rename to source/native/Tools.MetaDataProcessor/package.nuspec diff --git a/source/Tools.MetaDataProcessor/packages.config b/source/native/Tools.MetaDataProcessor/packages.config similarity index 100% rename from source/Tools.MetaDataProcessor/packages.config rename to source/native/Tools.MetaDataProcessor/packages.config diff --git a/source/Tools.MetaDataProcessor/stdafx.cpp b/source/native/Tools.MetaDataProcessor/stdafx.cpp similarity index 100% rename from source/Tools.MetaDataProcessor/stdafx.cpp rename to source/native/Tools.MetaDataProcessor/stdafx.cpp diff --git a/source/Tools.MetaDataProcessor/stdafx.h b/source/native/Tools.MetaDataProcessor/stdafx.h similarity index 100% rename from source/Tools.MetaDataProcessor/stdafx.h rename to source/native/Tools.MetaDataProcessor/stdafx.h diff --git a/source/Tools.MetaDataProcessor/targetver.h b/source/native/Tools.MetaDataProcessor/targetver.h similarity index 100% rename from source/Tools.MetaDataProcessor/targetver.h rename to source/native/Tools.MetaDataProcessor/targetver.h diff --git a/source/Tools.Parser/AssemblyParser.cpp b/source/native/Tools.Parser/AssemblyParser.cpp similarity index 99% rename from source/Tools.Parser/AssemblyParser.cpp rename to source/native/Tools.Parser/AssemblyParser.cpp index 548f6bb5..2e38c873 100644 --- a/source/Tools.Parser/AssemblyParser.cpp +++ b/source/native/Tools.Parser/AssemblyParser.cpp @@ -825,6 +825,13 @@ bool MetaData::FieldDef::SetValue( const void* ptr, int len ) return true; } +bool MetaData::FieldDef::SetEmptyString(const void* ptr) +{ + m_value.resize(0); + + return true; +} + MetaData::MethodDef::MethodDef( Parser* holder ) : m_method(holder), m_vars(holder) { m_td = mdTypeDefNil; // mdTypeDef m_td; @@ -1630,9 +1637,24 @@ HRESULT MetaData::Parser::GetTypeField( mdFieldDef fd ) } if(pValue) - { - _ASSERTE(len > 0); - db.SetValue( pValue, len ); + { + // only ASSERT for non strings because it's acceptable to have strings with 0 length + if (db.m_attr == ELEMENT_TYPE_STRING) + { + if (len == 0) + { + db.SetEmptyString(pValue); + } + else + { + db.SetValue(pValue, len); + } + } + else + { + _ASSERTE(len > 0); + db.SetValue(pValue, len); + } } m_mapDef_Field.insert( FieldDefMap::value_type( fd, db ) ); diff --git a/source/Tools.Parser/AssemblyParserDump.cpp b/source/native/Tools.Parser/AssemblyParserDump.cpp similarity index 100% rename from source/Tools.Parser/AssemblyParserDump.cpp rename to source/native/Tools.Parser/AssemblyParserDump.cpp diff --git a/source/Tools.Parser/AssemblyReparser.cpp b/source/native/Tools.Parser/AssemblyReparser.cpp similarity index 100% rename from source/Tools.Parser/AssemblyReparser.cpp rename to source/native/Tools.Parser/AssemblyReparser.cpp diff --git a/source/Tools.Parser/ByteCodeParser.cpp b/source/native/Tools.Parser/ByteCodeParser.cpp similarity index 100% rename from source/Tools.Parser/ByteCodeParser.cpp rename to source/native/Tools.Parser/ByteCodeParser.cpp diff --git a/source/Tools.Parser/ByteCodeParser_Load.cpp b/source/native/Tools.Parser/ByteCodeParser_Load.cpp similarity index 100% rename from source/Tools.Parser/ByteCodeParser_Load.cpp rename to source/native/Tools.Parser/ByteCodeParser_Load.cpp diff --git a/source/Tools.Parser/ByteCodeParser_Save.cpp b/source/native/Tools.Parser/ByteCodeParser_Save.cpp similarity index 100% rename from source/Tools.Parser/ByteCodeParser_Save.cpp rename to source/native/Tools.Parser/ByteCodeParser_Save.cpp diff --git a/source/native/Tools.Parser/Debug/Tools.Lib.Parser.idb b/source/native/Tools.Parser/Debug/Tools.Lib.Parser.idb new file mode 100644 index 0000000000000000000000000000000000000000..1218f0e36f7289376b4e160463f32fe569d38638 GIT binary patch literal 1879040 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 literal 0 HcmV?d00001 diff --git a/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.command.1.tlog b/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.command.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..bf0e7c2777309ee6f2604361bbe0099b6ce75d73 GIT binary patch literal 13326 zcmeI2+iu!G5J2a-QvV_1J?ZVC6;dC#*+DfJVUwFs5h6*0L{kJ*P4e+=&#diW5~!#Y z$w-WlFFQLso*C~R*=GLy{wfVAOJ96xN-W3HlPayYcydTP`n2 zS3@503u*P;vB#N8)rRUe<;1lzTag?wwt`lKJQ)=`yPllUSEIKhujQ4zk&zs*Zz4Uy zUf#k}f1Z1@X=MJ|iB2iCpTyk6@7Q^!HZ|(ZOO30~7C5hKF6IF5s!~e*+|H8buS>qw zc7(;y?N71PmJjkCiJs|odgP_?pVlL6tDhQY@ItnZU(i;TzjZNQ5V_uyTlpaqwr_0O zJ|!>7@r;?LXO}XTA^oa3mj$g6$1?i~@;N`1sAh<6a=cH+)@d)Zt$ivPxLjAsx$pE7 zS#p1uIw$1zle|T{M}~cJt!ttopOM|MeUx|Xm-;>KWRo$W)5_$}rM`T3qZ+KhdFpwW z`BB53j%qPJiNj~MsN`Cv#5_BUi=hNp|1{F;2turT5{T^TVZ zmlN#VrqXkCN?2WR-62=IW0l;bbJ1gLDVMKgt+$ENa~aXqc}lA*Ul^5Nw@E%%381YS zahIH*9-gh*?mzZiKIz%Ua{Y0A`e_DZuBRCs66=td@8yA*lX>Og$pPN)CJ~Egb%nX3 z+-{N8K+YXyGLjp+jorrXkz-5I?EVQUjon2&&2CG`-DY{6=bILEH>MlYjp@d8eaA`O zjrzP(W>4z-@;v@8rmrJq@oca1Y_4A}vNzBCR}W*lG2NJMOy6&&Z%fGCX8C}xFroVf zX;e3=8`X{KM)gh4z3W-I>wJ%(yZ(b}d^f%u-;M9a_sx7?$I9aQ?oj~{K=8=@6RtHS zgIxWAaoxCXTsN-oH`ljkWbr)L8m2atOQcWCjJHK8e*{k literal 0 HcmV?d00001 diff --git a/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.read.1.tlog b/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.read.1.tlog similarity index 84% rename from source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.read.1.tlog rename to source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.read.1.tlog index bb6c169e8d2ed64c566c25be93160a2a33cae1dd..c95bb788dc4e091b7c4163ee327ca50ca89441d8 100644 GIT binary patch delta 1459 zcmai!&nv@m7{|Z!{i^xV4w8dp<=`j^m*uc-{|M&+~acKfFmkkmhG>MP|;(b#W%n z3gWFEe7r6`)vp1srUG6HCXw0;c3xNVQ^U1`B#2-?)Is@HC!wtnOqBhF+5i@U3z!Ke z7z_1a9<<2S;YJN5z@(|vmq6c&K7?ox#4`A{|!M|Kz_V*s}cLE zoL3%IlH>kD6)`<|?N$-2m)>~u=;1tC3%uW{Cy?uHfXwwko_ak*9(@1kRZ#z!?J@EN D%($tr delta 665 zcmZ2j%WZ_&C^h-o#tNXCq{(MC#Q^ColSQ^{o7}R?Z?ehO1R(7*`OnrMFn`CkD6m;w z+mpcjupLogT54w&Sp3h<93X!USZvnr3NT%>2SUf~jR5l%_9cMT{@4d{4=7Y5CLh@k zaw{x^I3`ax0P`Ct#5g8L9ZZACZ&o_Q#RB61CF|hqyyKvNKo}BtA_ax7a}vgvnEdKw z7K+@yQ!qJ*g*~TpCbOMc1H=ZCKb%Q}(rlAwokg%+&Sk*GKb*^gu{X~<@4yV=Y?irP zzzj|RTdoyNHhXXa%vQNk0B29S*#u|Lx+6E);C2oYzYB>iGuiH53Y5PHN}EB&@&IhM BNoN26 diff --git a/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.write.1.tlog b/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.write.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..e220eaa6242e5102eaf256e0048ad0e2e574d14c GIT binary patch literal 6872 zcmeHL%Wi`(5S(+ReoAs^Z@rmUN<$zDq-mt6{7ApO?W`lp6>G^t5qNE^@p#s= z;ph7kDPC~F200qM;)sZ?5*b!(SG)>7?KrA|LBgNhSJ>mgzL@cvSH;%F-j95esLUZ_ zbG+MDH&=}{-!&XnGk$%mvGZp5U|-DMJs$DE-eqwmL=cgW4c9V6UvN#)WEHZegi-%+ z=PGfFc1o%$qe6^T-^prhOWyC1{qXFMt5RXnZ4miP{eP}R(8sRo3(<`0*)bNwDa3bnz!8gW>QxqM(vt#rPs zseW`}?!8MVcDIxHhk590KBDhkPAB?Xo~IM_*a3B7ocdvp(vSZTK0CK=hItthhB+1TUVvB&=W zcvGPVO{%ojpht~zSdB_;uv?y*+77Qlsd8Q`H`=S?TSj}&(_&4&9I08W^XaY^}Q90=NR|+%QImVrzgGR9|z)`S?!oZn8+RR9f)N{TrCGb zvl1WT8NRgeCyy}NGptYjIterGC9AlGAw7Jtm0oDpfwo5Xx(hVkwa51i)-F(l7ERkv zOT7k*aAa55`d zYsECNWKV4da^rgop7z1zO+DD}M@fsH$b) mL}@pWmXpeIJL$aL_`Ak(YcUNj(BPD_dd=4a-x@`*NPGc1ck5gL literal 0 HcmV?d00001 diff --git a/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.write.1.tlog b/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.write.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..28d0cf25f4af7dc058d84837125a468630d6a29d GIT binary patch literal 1778 zcmdUw-422<4293NiI1Wedgt9H;2(k!@FyYiB0jtNbw-0PU`7_QwRG#*Y1cjFyr z)k+)HTC0&qDwJu0TrzT2d#q|XC44qdbkLE1OY{|^L~6s_urjTkVYVBcg7i77(v-ap zs|vmCN|-%q$aY88yYNop;W@kMQll86%KW3JM#P$g*sY=W#ur z$J^^!iIzGk(^|D2)W~rvlxoJgWaR9&aMg+wGi{w|r#*Ko=oO>nbn?5x&!JfnJbBA+|6{knNz&{SeF|XS4hG8Oi__xNFEBtDI z5dO;e5VyojN&Lhk^ma?sM?O!6>GzZ@&WVtUc(F`R)anSW(7o;k>hIj++kkaHP=w}9 ztEZ`+28*zvD(w89*IyWKb)yBe2K-A+@$i3COpDcxj5+ypCkiqB*10bGKq%Lz3isvzUIY6}URIz`vS0p(64$aXyuTLv J-TR*+?;RGyM|1!H literal 0 HcmV?d00001 diff --git a/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Tools.Lib.Parser.lastbuildstate b/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Tools.Lib.Parser.lastbuildstate similarity index 70% rename from source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Tools.Lib.Parser.lastbuildstate rename to source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Tools.Lib.Parser.lastbuildstate index 34f2059c..d9067f79 100644 --- a/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Tools.Lib.Parser.lastbuildstate +++ b/source/native/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Tools.Lib.Parser.lastbuildstate @@ -1,2 +1,2 @@ #TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0 -Debug|Win32|E:\GitHub\nf-tool-metadata-processor\source\| +Debug|Win32|E:\GitHub\nf-tool-metadata-processor\source\native\| diff --git a/source/Tools.Parser/FileStore_Win32.cpp b/source/native/Tools.Parser/FileStore_Win32.cpp similarity index 100% rename from source/Tools.Parser/FileStore_Win32.cpp rename to source/native/Tools.Parser/FileStore_Win32.cpp diff --git a/source/Tools.Parser/Linker.cpp b/source/native/Tools.Parser/Linker.cpp similarity index 100% rename from source/Tools.Parser/Linker.cpp rename to source/native/Tools.Parser/Linker.cpp diff --git a/source/Tools.Parser/Parser-vs2019.vcxproj b/source/native/Tools.Parser/Parser-vs2019.vcxproj similarity index 91% rename from source/Tools.Parser/Parser-vs2019.vcxproj rename to source/native/Tools.Parser/Parser-vs2019.vcxproj index c96e0a27..389c3213 100644 --- a/source/Tools.Parser/Parser-vs2019.vcxproj +++ b/source/native/Tools.Parser/Parser-vs2019.vcxproj @@ -58,7 +58,7 @@ Disabled - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -76,7 +76,7 @@ MaxSpeed OnlyExplicitInline true - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDLL diff --git a/source/Tools.Parser/Parser-vs2019.vcxproj.filters b/source/native/Tools.Parser/Parser-vs2019.vcxproj.filters similarity index 100% rename from source/Tools.Parser/Parser-vs2019.vcxproj.filters rename to source/native/Tools.Parser/Parser-vs2019.vcxproj.filters diff --git a/source/Tools.Parser/Parser.vcxproj b/source/native/Tools.Parser/Parser.vcxproj similarity index 91% rename from source/Tools.Parser/Parser.vcxproj rename to source/native/Tools.Parser/Parser.vcxproj index 66d6f637..2a1e56f5 100644 --- a/source/Tools.Parser/Parser.vcxproj +++ b/source/native/Tools.Parser/Parser.vcxproj @@ -58,7 +58,7 @@ Disabled - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -76,7 +76,7 @@ MaxSpeed OnlyExplicitInline true - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDLL diff --git a/source/Tools.Parser/Parser.vcxproj.filters b/source/native/Tools.Parser/Parser.vcxproj.filters similarity index 100% rename from source/Tools.Parser/Parser.vcxproj.filters rename to source/native/Tools.Parser/Parser.vcxproj.filters diff --git a/source/Tools.Parser/Support.cpp b/source/native/Tools.Parser/Support.cpp similarity index 100% rename from source/Tools.Parser/Support.cpp rename to source/native/Tools.Parser/Support.cpp diff --git a/source/Tools.Parser/dotNetMF.proj b/source/native/Tools.Parser/dotNetMF.proj similarity index 100% rename from source/Tools.Parser/dotNetMF.proj rename to source/native/Tools.Parser/dotNetMF.proj diff --git a/source/Tools.Parser/stdafx.cpp b/source/native/Tools.Parser/stdafx.cpp similarity index 100% rename from source/Tools.Parser/stdafx.cpp rename to source/native/Tools.Parser/stdafx.cpp diff --git a/source/Tools.Parser/stdafx.h b/source/native/Tools.Parser/stdafx.h similarity index 100% rename from source/Tools.Parser/stdafx.h rename to source/native/Tools.Parser/stdafx.h diff --git a/source/native/nanoFramework.Tools.MetadataProcessor.sln b/source/native/nanoFramework.Tools.MetadataProcessor.sln new file mode 100644 index 00000000..c4c770e9 --- /dev/null +++ b/source/native/nanoFramework.Tools.MetadataProcessor.sln @@ -0,0 +1,206 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2027 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MetaDataProcessor", "MetaDataProcessor", "{FCCC9596-0809-4BB4-ACC2-3615EEC264C7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "nf-interpreter\src\CLR\Core\Core.vcxproj", "{89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CorLib", "nf-interpreter\src\CLR\CorLib\CorLib.vcxproj", "{58E950CC-2FF6-423C-B006-A70A19272F20}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Diagnostics", "nf-interpreter\src\CLR\Diagnostics\Diagnostics.vcxproj", "{A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tools.Lib.Parser", "Tools.Parser\Parser.vcxproj", "{AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Serialization", "nf-interpreter\src\CLR\Core\Serialization\Serialization.vcxproj", "{16BF6131-A3B8-4B97-B867-E45669FB48BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPC", "nf-interpreter\src\CLR\Core\RPC\RPC.vcxproj", "{ED4C887A-EC09-465B-B5D9-075450ADC52D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Messaging", "nf-interpreter\src\CLR\Messaging\Messaging.vcxproj", "{131001E3-0201-451F-A87B-951D1C5C3EEE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WireProtocol", "nf-interpreter\src\CLR\WireProtocol\WireProtocol.vcxproj", "{2337C4A4-3AB4-4014-9C29-9EBE32F4510E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hardware", "nf-interpreter\src\CLR\Core\Hardware\Hardware.vcxproj", "{5D50772E-DAC8-407D-972F-37DEB4450B72}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tools.Lib.CorHelper", "Tools.CorHelper\CorHelper.vcxproj", "{079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InterruptHandler", "nf-interpreter\src\CLR\Core\InterruptHandler\InterruptHandler.vcxproj", "{D32EE397-7E49-452D-AC95-AFCB3C962E3D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tools.MetaDataProcessor", "Tools.MetaDataProcessor\MetaDataProcessor.vcxproj", "{80209A7E-B9F0-4143-BCD1-B1891236A3CF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|Any CPU.Build.0 = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.ActiveCfg = Debug|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.Build.0 = Debug|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.ActiveCfg = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.Build.0 = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|Any CPU.ActiveCfg = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|Any CPU.Build.0 = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.ActiveCfg = Release|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.Build.0 = Release|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.ActiveCfg = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.Build.0 = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|Any CPU.Build.0 = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.ActiveCfg = Debug|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.Build.0 = Debug|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.ActiveCfg = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.Build.0 = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|Any CPU.ActiveCfg = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|Any CPU.Build.0 = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.ActiveCfg = Release|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.Build.0 = Release|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.ActiveCfg = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.Build.0 = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|Any CPU.Build.0 = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.ActiveCfg = Debug|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.Build.0 = Debug|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.ActiveCfg = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.Build.0 = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|Any CPU.ActiveCfg = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|Any CPU.Build.0 = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.ActiveCfg = Release|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.Build.0 = Release|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.ActiveCfg = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.Build.0 = Release|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|Any CPU.Build.0 = Debug|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x64.ActiveCfg = Debug|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x64.Build.0 = Debug|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x86.ActiveCfg = Debug|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x86.Build.0 = Debug|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|Any CPU.ActiveCfg = Release|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|Any CPU.Build.0 = Release|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x64.ActiveCfg = Release|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x64.Build.0 = Release|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x86.ActiveCfg = Release|Win32 + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x86.Build.0 = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|Any CPU.Build.0 = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.ActiveCfg = Debug|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.Build.0 = Debug|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.ActiveCfg = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.Build.0 = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|Any CPU.ActiveCfg = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|Any CPU.Build.0 = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.ActiveCfg = Release|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.Build.0 = Release|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.ActiveCfg = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.Build.0 = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|Any CPU.Build.0 = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.ActiveCfg = Debug|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.Build.0 = Debug|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.ActiveCfg = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.Build.0 = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|Any CPU.ActiveCfg = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|Any CPU.Build.0 = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.ActiveCfg = Release|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.Build.0 = Release|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.ActiveCfg = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.Build.0 = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|Any CPU.Build.0 = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.ActiveCfg = Debug|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.Build.0 = Debug|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.ActiveCfg = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.Build.0 = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|Any CPU.ActiveCfg = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|Any CPU.Build.0 = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.ActiveCfg = Release|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.Build.0 = Release|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.ActiveCfg = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.Build.0 = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|Any CPU.Build.0 = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.ActiveCfg = Debug|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.Build.0 = Debug|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.ActiveCfg = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.Build.0 = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|Any CPU.ActiveCfg = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|Any CPU.Build.0 = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.ActiveCfg = Release|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.Build.0 = Release|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.ActiveCfg = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.Build.0 = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|Any CPU.Build.0 = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.ActiveCfg = Debug|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.Build.0 = Debug|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.ActiveCfg = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.Build.0 = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|Any CPU.ActiveCfg = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|Any CPU.Build.0 = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.ActiveCfg = Release|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.Build.0 = Release|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.ActiveCfg = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.Build.0 = Release|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|Any CPU.Build.0 = Debug|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x64.ActiveCfg = Debug|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x64.Build.0 = Debug|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x86.ActiveCfg = Debug|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x86.Build.0 = Debug|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|Any CPU.ActiveCfg = Release|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|Any CPU.Build.0 = Release|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x64.ActiveCfg = Release|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x64.Build.0 = Release|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x86.ActiveCfg = Release|Win32 + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x86.Build.0 = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|Any CPU.Build.0 = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.ActiveCfg = Debug|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.Build.0 = Debug|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.ActiveCfg = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.Build.0 = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|Any CPU.ActiveCfg = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|Any CPU.Build.0 = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.ActiveCfg = Release|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.Build.0 = Release|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.ActiveCfg = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.Build.0 = Release|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|Any CPU.Build.0 = Debug|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x64.ActiveCfg = Debug|x64 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x64.Build.0 = Debug|x64 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x86.ActiveCfg = Debug|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x86.Build.0 = Debug|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|Any CPU.ActiveCfg = Release|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|Any CPU.Build.0 = Release|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x64.ActiveCfg = Release|x64 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x64.Build.0 = Release|x64 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x86.ActiveCfg = Release|Win32 + {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {58E950CC-2FF6-423C-B006-A70A19272F20} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {16BF6131-A3B8-4B97-B867-E45669FB48BD} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {ED4C887A-EC09-465B-B5D9-075450ADC52D} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {131001E3-0201-451F-A87B-951D1C5C3EEE} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {5D50772E-DAC8-407D-972F-37DEB4450B72} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {D32EE397-7E49-452D-AC95-AFCB3C962E3D} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + {80209A7E-B9F0-4143-BCD1-B1891236A3CF} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5DF99A8C-CA3C-451A-ABC1-4D862154708B} + EndGlobalSection +EndGlobal diff --git a/source/native/nf-interpreter/.github/FUNDING.yml b/source/native/nf-interpreter/.github/FUNDING.yml new file mode 100644 index 00000000..d2b838f9 --- /dev/null +++ b/source/native/nf-interpreter/.github/FUNDING.yml @@ -0,0 +1,2 @@ +#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +open_collective: nanoframework diff --git a/source/native/nf-interpreter/.github/ISSUE_TEMPLATE.md b/source/native/nf-interpreter/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..ce54f609 --- /dev/null +++ b/source/native/nf-interpreter/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,4 @@ +# Please **DO NOT** open issues in this repository. + + +We are now using the Home repository for centralized issue management. diff --git a/source/native/nf-interpreter/.github/PULL_REQUEST_TEMPLATE.md b/source/native/nf-interpreter/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..0f768fce --- /dev/null +++ b/source/native/nf-interpreter/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,36 @@ + + +## Description + + +## Motivation and Context + + +- Fixes/Closes/Resolves nanoFramework/Home#NNNN + +## How Has This Been Tested? + + + + +## Screenshots + +## Types of changes + +- [ ] Improvement (non-breaking change that improves a feature, code or algorithm) +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) + +## Checklist: + + +- [ ] My code follows the code style of this project. +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. +- [ ] I have read the **CONTRIBUTING** document. +- [ ] I have added tests to cover my changes. +- [ ] All new and existing tests passed. + + +Signed-off-by: GITHUB_USER diff --git a/source/native/nf-interpreter/.github/stale.yml b/source/native/nf-interpreter/.github/stale.yml new file mode 100644 index 00000000..8cf7da36 --- /dev/null +++ b/source/native/nf-interpreter/.github/stale.yml @@ -0,0 +1,19 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 + +# Issues with these labels will never be considered stale +exemptLabels: + - :pushpin: pinned + - security + +# Label to use when marking an issue as stale +staleLabel: stale + +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. diff --git a/source/native/nf-interpreter/.github_changelog_generator b/source/native/nf-interpreter/.github_changelog_generator new file mode 100644 index 00000000..f39e1766 --- /dev/null +++ b/source/native/nf-interpreter/.github_changelog_generator @@ -0,0 +1,14 @@ +user=nanoframework +project=nf-interpreter +issues=true +add_issues_wo_labels=false +add_pr_wo_labels=false +add_issues_wo_labels=false +filter_issues_by_milestone=false +exclude_labels=Area: Config-and-Build,Area: Infrastructure-and-Organization,reverted +enhancement_labels=Type: enhancement +bug_labels=Type: bug +merge_prefix=**Documentation and other chores:** +unreleased_label=**Changes available only in 'Preview' images:** +issue_line_labels=Area: ESP32,Area: STM32-ChibiOS,Area: WIN32,Area: Interpreter,Area: Common libs,Breaking-Change,documentation +author=false diff --git a/source/native/nf-interpreter/.gitignore b/source/native/nf-interpreter/.gitignore new file mode 100644 index 00000000..f279299b --- /dev/null +++ b/source/native/nf-interpreter/.gitignore @@ -0,0 +1,63 @@ +# ignore all ZIP files +*.zip +/zips/ + +# ignore build folder +/build/ +/build/.gitkeep + +# ignore cmake-variants file (will change frequently per user/board setup, use should derive content from cmake-variants.TEMPLATE.json) +cmake-variants.json + +# ignore any content inside the Interop assemblies folder +InteropAssemblies/* +!InteropAssemblies/CLR_RT_InteropAssembliesTable.cpp.in +!InteropAssemblies/README.md + +# Visual Studio Code +# ignore C/C++ launch file (will change frequently per user/board setup, use should derive content from launch.TEMPLATE.json) +.vscode/launch.json +.vscode/.cmaketools.json +.vscode/settings.json +.vscode/tasks.json +.vscode/extensions.json +.vscode/c_cpp_properties.json +.vscode/cmake-kits.json +.vscode/ipch + +# ignore CMake modules for Interop assemblies +CMake/Modules/FindINTEROP*.cmake + +# Visual Studio +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user + +# Build results +[Dd]ebug/ +[Rr]elease/ +[Rr]eleases/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio cache/options directory contents but not the example launch.vs.json +!.vs/ +.vs/* +!.vs/launch.vs.SAMPLE.json +!.vs/tasks.vs.SAMPLE.json +**/ipch/* + +# Visual C++ cache files +*.VC.db + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ diff --git a/source/native/nf-interpreter/.gitmodules b/source/native/nf-interpreter/.gitmodules new file mode 100644 index 00000000..c8fe6c8e --- /dev/null +++ b/source/native/nf-interpreter/.gitmodules @@ -0,0 +1,3 @@ +[submodule "targets-community"] + path = targets-community + url = https://github.com/nanoframework/nf-Community-Targets diff --git a/source/native/nf-interpreter/.vs/launch.vs.SAMPLE.json b/source/native/nf-interpreter/.vs/launch.vs.SAMPLE.json new file mode 100644 index 00000000..c945015d --- /dev/null +++ b/source/native/nf-interpreter/.vs/launch.vs.SAMPLE.json @@ -0,0 +1,90 @@ +{ + "version": "0.2.1", + "defaults": {}, + "configurations": [ + { + "type": "cppdbg", + "name": "ESP32 nanoCLR - Segger JLink", + "project": "Build/ESP32/nanoCLR.elf", + "cwd": "${workspaceRoot}", + "program": "Build/ESP32/nanoCLR.elf", + "MIMode": "gdb", + "stopAtEntry": false, + "externalConsole": true, + "miDebuggerPath": "C:/Esp32_Tools/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb.exe", + "setupCommands": [ + { + "text": "set logging on" + }, + { + "text": "!${workspaceRoot}/startocd.bat ESP32_JLINK" + }, + { + "text": "target extended-remote localhost:3333" + }, + { + "text": "-file-exec-and-symbols C:/usr/src/NanoFramework/nf-interpreter/build/ESP32/nanoCLR.elf" + }, + { + "text": "set remote hardware-watchpoint-limit 2" + }, + { + "text": "monitor reset halt" + }, + { + "text": "flushregs" + }, + { + "text": "thb app_main" + } + ], + "launchCompleteCommand": "None", + "serverStarted": "Info : .*Tensilica.*0x1.", + "filterStderr": true, + "filterStdout": true + }, + { + "type": "cppdbg", + "name": "STM769IDiscovery nanobooter.elf", + "project": "Build\\STM769IDiscovery\\nanobooter.elf", + "cwd": "${workspaceRoot}", + "program": "${workspaceRoot}\\BUILD\\STM769IDiscovery\\nanobooter.elf", + "MIMode": "gdb", + "externalConsole": true, + "miDebuggerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\Linux\\gcc_arm\\bin\\arm-none-eabi-gdb.exe", + "setupCommands": [ + { + "text": "-environment-cd ${workspaceRoot}\\Build" + }, + { + "text": "!${workspaceRoot}/startocd.bat STM32_STLINK" + }, + { + "text": "target extended-remote localhost:3333" + }, + { + "text": "-file-exec-and-symbols C:/usr/src/NanoFramework/nf-interpreter/build/STM769IDiscovery/nanobooter.elf" + }, + { + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "monitor reset_config none separate" + }, + { + "text": "monitor reset halt" + } + ], + "serverStarted": "Info\\ :\\ [\\w\\d\\.]*:\\ hardware", + "filterStderr": true, + "filterStdout": true + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "nanoCLR.elf", + "name": "nanoCLR.elf" + } + ] +} \ No newline at end of file diff --git a/source/native/nf-interpreter/.vs/tasks.vs.SAMPLE.json b/source/native/nf-interpreter/.vs/tasks.vs.SAMPLE.json new file mode 100644 index 00000000..8f5031ca --- /dev/null +++ b/source/native/nf-interpreter/.vs/tasks.vs.SAMPLE.json @@ -0,0 +1,76 @@ +{ + "version": "0.2.1", + "outDir": "Build\\${cpp.activeConfiguration}", + "port": "\"COM3\"", + "esptool": "python ${env.ESP32_IDF_PATH}/components/esptool_py/esptool/esptool.py", + "comment": "This is a comment", + "tasks": [ + { + "taskLabel": "task-CMakeLists", + "appliesTo": "CMakeLists.txt", + "type": "launch" + }, + { + "taskLabel": "task-nf-interpreter", + "appliesTo": "/", + "type": "launch" + }, + { + "taskLabel": "Print Output Directory", + "appliesTo": "*", + "type": "default", + "command": "${env.COMSPEC}", + "args": [ + "echo Output Directory: ${outDir} " + ] + }, + { + "taskLabel": "Erase Flash ESP32 on port ${port}", + "appliesTo": "*", + "type": "default", + "command": "${env.COMSPEC}", + "args": [ + "start \"Erasing Flash ESP32 on ${port}\" /wait runcmd -5", + "${esptool} --chip esp32 --port ${port} --baud 115200 --before \"default_reset\" --after \"hard_reset\" erase_flash" + ] + }, + { + "taskLabel": "Flash nanoCLR ESP32 on port ${port}", + "appliesTo": "*", + "type": "default", + "command": "${env.COMSPEC}", + "args": [ + "start \"ESP32 - Flashing nanoCLR ESP32 on port ${port}\" /wait runcmd -5", + "${esptool} --chip esp32 --port ${port} --baud 921600 --before \"default_reset\" --after \"hard_reset\" write_flash -z --flash_mode \"dio\" --flash_freq \"40m\" --flash_size detect 0x1000 ${env.ESP32_LIBS_PATH}/bootloader.bin 0x10000 ${outDir}/nanoCLR.bin 0x8000 ${outDir}/partitions_4mb.bin" + ] + }, + { + "taskLabel": "Erase Flash ESP32 port ${port} (Working auto-program)", + "appliesTo": "*", + "type": "default", + "command": "${env.COMSPEC}", + "args": [ + "${esptool} --chip esp32 --port ${port} --baud 921600 --before \"default_reset\" --after \"hard_reset\" erase_flash" + ] + }, + { + "taskLabel": "task-GetShortPath", + "appliesTo": "GetShortPath.bat", + "type": "launch" + }, + { + "taskName": "task-README", + "appliesTo": "README.md", + "type": "launch" + }, + { + "taskName": "task-SetNFRoot", + "appliesTo": "SetNFRoot.bat", + "type": "default", + "command": "${env.COMSPEC}", + "args": [ + "SetNFRoot.bat" + ] + } + ] +} \ No newline at end of file diff --git a/source/native/nf-interpreter/.vscode/cmake-kits.TEMPLATE-ESP32.json b/source/native/nf-interpreter/.vscode/cmake-kits.TEMPLATE-ESP32.json new file mode 100644 index 00000000..cbcba892 --- /dev/null +++ b/source/native/nf-interpreter/.vscode/cmake-kits.TEMPLATE-ESP32.json @@ -0,0 +1,6 @@ +[ + { + "name": "ESP32 Tools", + "toolchainFile": "CMake/toolchain.FreeRtos.ESP32.GCC.cmake" + } +] \ No newline at end of file diff --git a/source/native/nf-interpreter/.vscode/launch.TEMPLATE-ESP32.json b/source/native/nf-interpreter/.vscode/launch.TEMPLATE-ESP32.json new file mode 100644 index 00000000..c5a8ed25 --- /dev/null +++ b/source/native/nf-interpreter/.vscode/launch.TEMPLATE-ESP32.json @@ -0,0 +1,76 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "ESP32 nanoCLR - OLimex OCD-H", + "type": "cppdbg", + "request": "launch", + "MIMode": "gdb", + "miDebuggerPath": "/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb.exe", + "stopAtEntry":true, + "program": "/nanoCLR.elf", + + "setupCommands": [ + {"description":"" , "text" : "set logging on"}, + {"description":"" , "text" : "target extended-remote localhost:3333"}, + {"description":"" , "text" : "file /nanoCLR.elf"}, + {"description":"" , "text" : "monitor reset halt"}, + {"description":"" , "text" : "thb app_main"}, + {"description":"" , "text" : "x $a1=0"} + ], + + "launchCompleteCommand": "exec-run", + "debugServerPath": "/bin/openocd.exe", + "debugServerArgs": "-s \"/share/openocd/scripts/\" -f interface/ftdi/olimex-arm-usb-ocd-h.cfg -f target/esp32.cfg -c \"adapter_khz 3000\" " , + "serverStarted": "Info : .*Tensilica.*0x1.", + "filterStderr": true, + "externalConsole": true, + "cwd": "${cwd}", + + "logging": { + "trace": true, + "traceResponse": true, + "engineLogging": true, + "programOutput": true, + "exceptions": true, + "moduleLoad": true + } + }, + { + "name": "ESP32 nanoCLR - Wrover", + "type": "cppdbg", + "request": "launch", + "MIMode": "gdb", + "miDebuggerPath": "/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb.exe", + "stopAtEntry":true, + "program": "/nanoCLR.elf", + + "setupCommands": [ + {"description":"" , "text" : "set logging on"}, + {"description":"" , "text" : "target extended-remote localhost:3333"}, + {"description":"" , "text" : "file /nanoCLR.elf"}, + {"description":"" , "text" : "monitor reset halt"}, + {"description":"" , "text" : "thb app_main"}, + {"description":"" , "text" : "x $a1=0"} + ], + + "launchCompleteCommand": "exec-run", + "debugServerPath": "/bin/openocd.exe", + "debugServerArgs": "-s \"/share/openocd/scripts/\" -f interface/ftdi/esp32_devkitj_v1.cfg -f target/esp32.cfg -c \"adapter_khz 2000\" " , + "serverStarted": "Info : .*Tensilica.*0x1.", + "filterStderr": true, + "externalConsole": true, + "cwd": "${cwd}", + + "logging": { + "trace": true, + "traceResponse": true, + "engineLogging": true, + "programOutput": true, + "exceptions": true, + "moduleLoad": true + } + } + + ] +} diff --git a/source/native/nf-interpreter/.vscode/launch.TEMPLATE.json b/source/native/nf-interpreter/.vscode/launch.TEMPLATE.json new file mode 100644 index 00000000..12bd0344 --- /dev/null +++ b/source/native/nf-interpreter/.vscode/launch.TEMPLATE.json @@ -0,0 +1,103 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "name the launch configuration 1 (booter) here", + "type": "cppdbg", + "request": "launch", + "miDebuggerPath": "", + "targetArchitecture": "ARM", + "program": "/nanoBooter.elf", + + "setupCommands": [ + {"description":"" , "text" : "target extended-remote localhost:3333"}, + {"description":"" , "text" : "monitor reset_config none separate"}, + {"description":"" , "text" : "monitor reset halt"}, + {"description":"" , "text" : "monitor flash write_image erase \"/nanoBooter.hex\" "}, + {"description":"" , "text" : "file /nanoBooter.elf"}, + {"description":"" , "text" : "monitor reset halt"} + ], + + "customLaunchSetupCommands": [ + {"description":"" , "text" : "monitor reset_config none separate"}, + {"description":"" , "text" : "monitor reset halt"} + ], + + "launchCompleteCommand": "exec-continue", + "debugServerPath": "/bin/openocd.exe", + "debugServerArgs": "-s \"/share/openocd/scripts/\" -f interface/.cfg -f board/.cfg", + "serverStarted": "Info\\ :\\ [\\w\\d\\.]*:\\ hardware", + "filterStderr": true, + "externalConsole": true, + "cwd": "${cwd}", + // Enable the following to debug GDB + //"logging": { + // "engineLogging": true, + // "traceResponse": true + //}, + }, + + { + "name": "name the launch configuration 2 (CLR) here", + "type": "cppdbg", + "request": "launch", + "miDebuggerPath": "", + "targetArchitecture": "ARM", + "program": "/nanoCLR.elf", + + "setupCommands": [ + {"description":"" , "text" : "target extended-remote localhost:3333"}, + {"description":"" , "text" : "monitor reset_config none separate"}, + {"description":"" , "text" : "monitor reset halt"}, + {"description":"" , "text" : "monitor flash write_image erase \"/nanoCLR.hex\" "}, + {"description":"" , "text" : "file /nanoCLR.elf"}, + {"description":"" , "text" : "monitor reset halt"} + ], + + "customLaunchSetupCommands": [ + {"description":"" , "text" : "monitor reset_config none separate"}, + {"description":"" , "text" : "monitor reset halt"} + ], + + "launchCompleteCommand": "exec-continue", + "debugServerPath": "/bin/openocd.exe", + "debugServerArgs": "-s \"/share/openocd/scripts/\" -f interface/.cfg -f board/.cfg", + "serverStarted": "Info\\ :\\ [\\w\\d\\.]*:\\ hardware", + "filterStderr": true, + "externalConsole": true, + "cwd": "${cwd}" + // Enable the following to debug GDB + //"logging": { + // "engineLogging": true, + // "traceResponse": true + //}, + }, + + { + "MIMode": "gdb", + "name": "CC3200 Launchpad nanoCLR TEMPLATE", + "type": "cppdbg", + "request": "launch", + + "setupCommands": [ + {"description":"" , "text" : "target remote | e:/openocd-0.10.0/bin/openocd.exe -c \"gdb_port pipe; log_output openocd.log\" -f "}, + {"description":"" , "text" : "file /nanoCLR.elf>"}, + {"description":"" , "text" : "load"}, + {"description":"" , "text" : "set $sp = g_pfnVectors[0]"}, + {"description":"" , "text" : "set $pc = g_pfnVectors[1]"}, + {"description":"" , "text" : "break main"}, + {"description":"" , "text" : "continue", "ignoreFailures": true } + ], + + "miDebuggerPath": "", + "targetArchitecture": "ARM", + "program": "${workspaceRoot}/build/nanoCLR.elf", + + "launchCompleteCommand": "None", + "serverStarted": "Info\\ :\\ [\\w\\d\\.]*:\\ hardware", + "filterStderr": true, + "externalConsole": true, + "cwd": "${cwd}" + } + ] +} diff --git a/source/native/nf-interpreter/.vscode/settings.TEMPLATE.json b/source/native/nf-interpreter/.vscode/settings.TEMPLATE.json new file mode 100644 index 00000000..4a47defe --- /dev/null +++ b/source/native/nf-interpreter/.vscode/settings.TEMPLATE.json @@ -0,0 +1,13 @@ +{ + "cmake.preferredGenerators": [ + "ninja.exe" + ], + "cmake.generator": "ninja.exe", + "cmake.useCMakeServer" : true, + "cmake.autoRestartBuild" : true, + "cmake.configureSettings": { + "CMAKE_MAKE_PROGRAM":"/ninja/ninja.exe" + }, + "cmake.cmakePath": "/cmake/bin/cmake.exe", + "cmake.configureOnOpen": false +} diff --git a/source/native/nf-interpreter/.vscode/tasks.TEMPLATE-ESP32.json b/source/native/nf-interpreter/.vscode/tasks.TEMPLATE-ESP32.json new file mode 100644 index 00000000..58d72280 --- /dev/null +++ b/source/native/nf-interpreter/.vscode/tasks.TEMPLATE-ESP32.json @@ -0,0 +1,47 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "taskName": "Flash nanoCLR ", + "type": "shell", + "command": "python /components/esptool_py/esptool/esptool.py --chip esp32 --port \"\" --baud 921600 --before \"default_reset\" --after \"hard_reset\" write_flash -z --flash_mode \"dio\" --flash_freq \"40m\" --flash_size detect 0x1000 /bootloader.bin 0x10000 /nanoCLR.bin 0x8000 /partitions_4mb.bin", + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "taskName": "Erase flash ", + "type": "shell", + "command": "python /components/esptool_py/esptool/esptool.py --chip esp32 --port \"\" --baud 115200 --before \"default_reset\" --after \"hard_reset\" erase_flash", + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "taskName": "Flash nanoCLR Wrover ", + "type": "shell", + "command": "python /components/esptool_py/esptool/esptool.py --chip esp32 --port \"\" --baud 921600 --before \"default_reset\" --after \"hard_reset\" write_flash -z --flash_mode \"dio\" --flash_freq \"40m\" --flash_size detect 0x1000 /bootloader.bin 0x10000 /nanoCLR.bin 0x8000 /partitions_4mb.bin", + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "taskName": "Flash nanoCLR ESP32-EVB ", + "type": "shell", + "command": "python /components/esptool_py/esptool/esptool.py --chip esp32 --port \"\" --baud 921600 --before \"default_reset\" --after \"hard_reset\" write_flash -z --flash_mode \"dio\" --flash_freq \"40m\" --flash_size detect 0x1000 /bootloader.bin 0x10000 /nanoCLR.bin 0x8000 /partitions_4mb.bin", + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/source/native/nf-interpreter/CHANGELOG.md b/source/native/nf-interpreter/CHANGELOG.md new file mode 100644 index 00000000..5bfc6717 --- /dev/null +++ b/source/native/nf-interpreter/CHANGELOG.md @@ -0,0 +1,517 @@ +# Change Log + +## [**Changes available only in 'Preview' images:**](https://github.com/nanoframework/nf-interpreter/tree/HEAD) + +[Full Changelog](https://github.com/nanoframework/nf-interpreter/compare/v1.0.1...HEAD) + +**Implemented enhancements:** + +- Socket changes and fixes for HTTP [\#955](https://github.com/nanoframework/nf-interpreter/pull/955) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Rework inclusion of UART declarations in STM32 [\#951](https://github.com/nanoframework/nf-interpreter/pull/951) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add native support for Hardware.Stm32 class lib [\#935](https://github.com/nanoframework/nf-interpreter/pull/935) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Implemented Base64 encoding/decoding [\#934](https://github.com/nanoframework/nf-interpreter/pull/934) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] + +**Fixed bugs:** + +- Fix mscorlib native checksum for 1.0.6-preview-001 [\#969](https://github.com/nanoframework/nf-interpreter/pull/969) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Socket changes and fixes for HTTP [\#955](https://github.com/nanoframework/nf-interpreter/pull/955) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix UART4 setting for Windows.Device.SerialCommunication [\#950](https://github.com/nanoframework/nf-interpreter/pull/950) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fixes for issue \#416 [\#933](https://github.com/nanoframework/nf-interpreter/pull/933) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] + +**Documentation and other chores:** + +- Update nanoFramework.Hardware.Esp32 version to 1.0.2-preview-009 [\#980](https://github.com/nanoframework/nf-interpreter/pull/980) +- Update Windows.Devices.Gpio version to 1.0.2-preview-008 [\#979](https://github.com/nanoframework/nf-interpreter/pull/979) +- Update Windows.Devices.SerialCommunication version to 1.0.2-preview-009 [\#978](https://github.com/nanoframework/nf-interpreter/pull/978) +- Update Windows.Devices.Spi version to 1.0.2-preview-007 [\#977](https://github.com/nanoframework/nf-interpreter/pull/977) +- Update Windows.Devices.I2c version to 1.0.2-preview-007 [\#976](https://github.com/nanoframework/nf-interpreter/pull/976) +- Update declaration of Windows.Devices.Gpio [\#973](https://github.com/nanoframework/nf-interpreter/pull/973) +- Update declaration for Windows.Devices.Spi [\#972](https://github.com/nanoframework/nf-interpreter/pull/972) +- Update declaration for Windows.Devices.SerialCommunication [\#971](https://github.com/nanoframework/nf-interpreter/pull/971) +- Update Windows.Devices.I2c declaration [\#970](https://github.com/nanoframework/nf-interpreter/pull/970) +- Update nanoFramework.Hardware.Esp32 version to 1.0.2-preview-004 [\#968](https://github.com/nanoframework/nf-interpreter/pull/968) +- Update Windows.Devices.SerialCommunication version to 1.0.2-preview-004 [\#967](https://github.com/nanoframework/nf-interpreter/pull/967) +- Update Windows.Devices.WiFi version to 1.0.2-preview-004 [\#966](https://github.com/nanoframework/nf-interpreter/pull/966) +- Update nanoFramework.System.Net version to 1.0.2-preview-001 [\#965](https://github.com/nanoframework/nf-interpreter/pull/965) +- Update Windows.Devices.Spi version to 1.0.2-preview-004 [\#964](https://github.com/nanoframework/nf-interpreter/pull/964) +- Update Windows.Devices.Gpio version to 1.0.2-preview-004 [\#963](https://github.com/nanoframework/nf-interpreter/pull/963) +- Update nanoFramework.Hardware.Stm32 version to 1.0.2-preview-004 [\#962](https://github.com/nanoframework/nf-interpreter/pull/962) +- Update nanoFramework.Networking.Sntp version to 1.0.2-preview-005 [\#961](https://github.com/nanoframework/nf-interpreter/pull/961) +- Update Windows.Devices.I2c version to 1.0.2-preview-004 [\#960](https://github.com/nanoframework/nf-interpreter/pull/960) +- Update Windows.Devices.Adc version to 1.0.2-preview-004 [\#959](https://github.com/nanoframework/nf-interpreter/pull/959) +- Update nanoFramework.Runtime.Native version to 1.0.2-preview-004 [\#958](https://github.com/nanoframework/nf-interpreter/pull/958) +- Update nanoFramework.Runtime.Events version to 1.0.2-preview-004 [\#957](https://github.com/nanoframework/nf-interpreter/pull/957) +- Update nanoFramework.CorLib version to 1.0.6-preview-001 [\#956](https://github.com/nanoframework/nf-interpreter/pull/956) +- Update nanoFramework.Networking.Sntp version to 1.0.2-preview-002 [\#954](https://github.com/nanoframework/nf-interpreter/pull/954) +- Move System.Math to it's own class lib [\#948](https://github.com/nanoframework/nf-interpreter/pull/948) + +## [v1.0.1](https://github.com/nanoframework/nf-interpreter/tree/v1.0.1) (2018-10-18) +[Full Changelog](https://github.com/nanoframework/nf-interpreter/compare/v1.0.0...v1.0.1) + +## [v1.0.0](https://github.com/nanoframework/nf-interpreter/tree/v1.0.0) (2018-10-18) +[Full Changelog](https://github.com/nanoframework/nf-interpreter/compare/v0.0.0...v1.0.0) + +**Implemented enhancements:** + +- Work on config block [\#904](https://github.com/nanoframework/nf-interpreter/pull/904) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add support for GetCustomAttributes [\#865](https://github.com/nanoframework/nf-interpreter/pull/865) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix for issue \#402: Type.GetInterfaces doesn't return the inherited interfaces [\#851](https://github.com/nanoframework/nf-interpreter/pull/851) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix: Unable to start debug session on ESP32 when using SerialCommunication [\#846](https://github.com/nanoframework/nf-interpreter/pull/846) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix for string.LastIndexOf\(char, int\) and string.LastIndexOf\(string, int\) should search toward the beginning of the string \#400 [\#845](https://github.com/nanoframework/nf-interpreter/pull/845) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Add native implementation of resource utility [\#844](https://github.com/nanoframework/nf-interpreter/pull/844) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- SNTP fixes for ESP32 [\#838](https://github.com/nanoframework/nf-interpreter/pull/838) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix WiFi version [\#834](https://github.com/nanoframework/nf-interpreter/pull/834) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Move CLR\_SETTINGS to targets [\#832](https://github.com/nanoframework/nf-interpreter/pull/832) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Implemented WatchChar in ESP32 [\#831](https://github.com/nanoframework/nf-interpreter/pull/831) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Improve posting of managed events [\#830](https://github.com/nanoframework/nf-interpreter/pull/830) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add back GenericPort\_Write to ESP32 [\#829](https://github.com/nanoframework/nf-interpreter/pull/829) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Rework system math implementation [\#823](https://github.com/nanoframework/nf-interpreter/pull/823) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Merge watchdog branch [\#819](https://github.com/nanoframework/nf-interpreter/pull/819) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Independent watchdog skeleton definitions [\#808](https://github.com/nanoframework/nf-interpreter/pull/808) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on mbed TLS parse certificate [\#807](https://github.com/nanoframework/nf-interpreter/pull/807) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Add new Guid and random for Esp32 [\#804](https://github.com/nanoframework/nf-interpreter/pull/804) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Clean-up messaging class [\#799](https://github.com/nanoframework/nf-interpreter/pull/799) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Correct comment about heap for STM32 targets [\#794](https://github.com/nanoframework/nf-interpreter/pull/794) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update ChibiOS config files for STM32F091RC target [\#793](https://github.com/nanoframework/nf-interpreter/pull/793) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Move booter blinker thread code to main loop [\#790](https://github.com/nanoframework/nf-interpreter/pull/790) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Updates required by ChibiOS fixes [\#787](https://github.com/nanoframework/nf-interpreter/pull/787) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add support for target reporting if it has nanoBooter [\#785](https://github.com/nanoframework/nf-interpreter/pull/785) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Add support for configurable Wire Protocol packet size [\#784](https://github.com/nanoframework/nf-interpreter/pull/784) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix required for build with RelWithDebInfo [\#774](https://github.com/nanoframework/nf-interpreter/pull/774) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update native implementation of serial comm [\#767](https://github.com/nanoframework/nf-interpreter/pull/767) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add managed event on serial communication [\#766](https://github.com/nanoframework/nf-interpreter/pull/766) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add native support for runtime.native.power [\#762](https://github.com/nanoframework/nf-interpreter/pull/762) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Work native implementation of Runtime.Native.Rtc [\#761](https://github.com/nanoframework/nf-interpreter/pull/761) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update native code for nanoFramework.Runtime.Native [\#760](https://github.com/nanoframework/nf-interpreter/pull/760) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Housekeeping on ESP32 code base [\#758](https://github.com/nanoframework/nf-interpreter/pull/758) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Work string to value conversion implementation [\#756](https://github.com/nanoframework/nf-interpreter/pull/756) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Review ESP32 compiler options to enable warnings as errors [\#754](https://github.com/nanoframework/nf-interpreter/pull/754) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update TimeSpan native declarations [\#747](https://github.com/nanoframework/nf-interpreter/pull/747) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Add support to String.Format [\#744](https://github.com/nanoframework/nf-interpreter/pull/744) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Rework several RAM assignment for STM32 targets [\#741](https://github.com/nanoframework/nf-interpreter/pull/741) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on compiler warnings 🚧 [\#739](https://github.com/nanoframework/nf-interpreter/pull/739) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix ADC declaration on all targets 🚧 [\#736](https://github.com/nanoframework/nf-interpreter/pull/736) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix Debugging\_Execution\_BreakpointDef [\#735](https://github.com/nanoframework/nf-interpreter/pull/735) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix ChibiOS usbcfg code on all STM32 targets 🚧 [\#732](https://github.com/nanoframework/nf-interpreter/pull/732) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove unused code from nanoBooter main 🚧 [\#730](https://github.com/nanoframework/nf-interpreter/pull/730) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improvements on BlockStorage declarations 🚧 [\#728](https://github.com/nanoframework/nf-interpreter/pull/728) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Change OS Task priority for ReceiverThread [\#724](https://github.com/nanoframework/nf-interpreter/pull/724) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove unused exception [\#721](https://github.com/nanoframework/nf-interpreter/pull/721) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Removed all IRAM\_ATTR attributes [\#718](https://github.com/nanoframework/nf-interpreter/pull/718) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- GLOBAL\_LOCK / GLOBAL\_UNLOCK implemented [\#716](https://github.com/nanoframework/nf-interpreter/pull/716) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Update corlib to support Timeout.InfiniteTimeSpan [\#715](https://github.com/nanoframework/nf-interpreter/pull/715) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Move command to list native interop assemblies to QueryCLRCapabilities [\#714](https://github.com/nanoframework/nf-interpreter/pull/714) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add WP command to list interop native assemblies [\#710](https://github.com/nanoframework/nf-interpreter/pull/710) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update board.h [\#708](https://github.com/nanoframework/nf-interpreter/pull/708) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update win\_dev\_gpio\_native\_Windows\_Devices\_Gpio\_GpioPin.cpp [\#704](https://github.com/nanoframework/nf-interpreter/pull/704) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Update GPIO to add support for toggle [\#699](https://github.com/nanoframework/nf-interpreter/pull/699) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove UpdateTime from Engine [\#698](https://github.com/nanoframework/nf-interpreter/pull/698) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Improvements GC [\#697](https://github.com/nanoframework/nf-interpreter/pull/697) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Improvements on Time\_Uninitialize [\#696](https://github.com/nanoframework/nf-interpreter/pull/696) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on scheduler, CLR events and sys time related code [\#695](https://github.com/nanoframework/nf-interpreter/pull/695) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improvements with timers from ChibiOS API [\#694](https://github.com/nanoframework/nf-interpreter/pull/694) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add performance counters stubs [\#692](https://github.com/nanoframework/nf-interpreter/pull/692) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on PAL events and PAL time [\#690](https://github.com/nanoframework/nf-interpreter/pull/690) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- General improvements in STM32 USB code [\#689](https://github.com/nanoframework/nf-interpreter/pull/689) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improvements in STM32 I2C class lib code [\#685](https://github.com/nanoframework/nf-interpreter/pull/685) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Implement RTC SetSystemTime [\#684](https://github.com/nanoframework/nf-interpreter/pull/684) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Improvements in ChibiOS SPI native [\#679](https://github.com/nanoframework/nf-interpreter/pull/679) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on STM32 SPI implementation [\#677](https://github.com/nanoframework/nf-interpreter/pull/677) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improvements in STM32 I2C native implementation [\#671](https://github.com/nanoframework/nf-interpreter/pull/671) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Implement ADC feature for ST\_NUCLEO\_F746ZG board [\#667](https://github.com/nanoframework/nf-interpreter/pull/667) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- adc-feature-for-stm32f429i-discovery [\#666](https://github.com/nanoframework/nf-interpreter/pull/666) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add ADC helper class for STM32F769I [\#665](https://github.com/nanoframework/nf-interpreter/pull/665) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Enable external SRAM for STM32F769I-DISCO [\#664](https://github.com/nanoframework/nf-interpreter/pull/664) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix to ADC last change to managed code [\#663](https://github.com/nanoframework/nf-interpreter/pull/663) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Add FSMC driver for STM32 [\#661](https://github.com/nanoframework/nf-interpreter/pull/661) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove left overs from previous EXT GPIO stuff [\#660](https://github.com/nanoframework/nf-interpreter/pull/660) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on ADC [\#659](https://github.com/nanoframework/nf-interpreter/pull/659) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add support for ADC in STM32F769I DISCO [\#658](https://github.com/nanoframework/nf-interpreter/pull/658) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on GPIO events [\#657](https://github.com/nanoframework/nf-interpreter/pull/657) +- Various board updates for Netduino 3 Wifi [\#656](https://github.com/nanoframework/nf-interpreter/pull/656) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on native ADC [\#655](https://github.com/nanoframework/nf-interpreter/pull/655) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improvements in STM32 hard fault handler code [\#654](https://github.com/nanoframework/nf-interpreter/pull/654) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Implement Monitor\_FlashSectorMap for nanoBooter [\#647](https://github.com/nanoframework/nf-interpreter/pull/647) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix and update for STM32 flash driver [\#646](https://github.com/nanoframework/nf-interpreter/pull/646) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Various fixes for ESP32 [\#645](https://github.com/nanoframework/nf-interpreter/pull/645) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Work on random number generator [\#643](https://github.com/nanoframework/nf-interpreter/pull/643) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- STM32 HRNG driver [\#642](https://github.com/nanoframework/nf-interpreter/pull/642) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Support for serial on F4 Discovery board [\#638](https://github.com/nanoframework/nf-interpreter/pull/638) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Develop target specific call [\#633](https://github.com/nanoframework/nf-interpreter/pull/633) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- CRC32 in Wire Protocol is now optional [\#629](https://github.com/nanoframework/nf-interpreter/pull/629) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Networking [\#623](https://github.com/nanoframework/nf-interpreter/pull/623) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Remove "local time" stuff [\#622](https://github.com/nanoframework/nf-interpreter/pull/622) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on UNDONE FIXME [\#621](https://github.com/nanoframework/nf-interpreter/pull/621) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on GC [\#613](https://github.com/nanoframework/nf-interpreter/pull/613) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Improve reboot command execution [\#612](https://github.com/nanoframework/nf-interpreter/pull/612) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Correct implementation of Debugging\_Deployment\_Status [\#610](https://github.com/nanoframework/nf-interpreter/pull/610) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on native events [\#608](https://github.com/nanoframework/nf-interpreter/pull/608) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add noreturn attribute to thread function [\#606](https://github.com/nanoframework/nf-interpreter/pull/606) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on Gpio [\#603](https://github.com/nanoframework/nf-interpreter/pull/603) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix vars casing to follow code guidelines [\#602](https://github.com/nanoframework/nf-interpreter/pull/602) +- Allow events to be fired when no threads active [\#601](https://github.com/nanoframework/nf-interpreter/pull/601) +- Add check for series definition in ChibiOS targetPAL [\#600](https://github.com/nanoframework/nf-interpreter/pull/600) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improvements on Gpio setting of alternate function [\#597](https://github.com/nanoframework/nf-interpreter/pull/597) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on serial [\#585](https://github.com/nanoframework/nf-interpreter/pull/585) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add serial feature to Nucleo F746ZG [\#584](https://github.com/nanoframework/nf-interpreter/pull/584) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add Serial support to ND3 [\#581](https://github.com/nanoframework/nf-interpreter/pull/581) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add Serial feature to F429 Discovery [\#580](https://github.com/nanoframework/nf-interpreter/pull/580) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improve serial operations [\#579](https://github.com/nanoframework/nf-interpreter/pull/579) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on CLR events [\#578](https://github.com/nanoframework/nf-interpreter/pull/578) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Implement read timeout on serial device [\#577](https://github.com/nanoframework/nf-interpreter/pull/577) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update win\_dev\_serial\_native\_Windows\_Devices\_SerialCommunication\_Seri… [\#573](https://github.com/nanoframework/nf-interpreter/pull/573) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on native support for Serial.Communication [\#569](https://github.com/nanoframework/nf-interpreter/pull/569) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improve STM32 v2 flash driver [\#565](https://github.com/nanoframework/nf-interpreter/pull/565) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improve Wire Protocol trace output [\#564](https://github.com/nanoframework/nf-interpreter/pull/564) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improvements in device information [\#563](https://github.com/nanoframework/nf-interpreter/pull/563) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Revert "Rework System.DateTime \(\#553\)" [\#560](https://github.com/nanoframework/nf-interpreter/pull/560) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add pwm support for STM32F407 [\#559](https://github.com/nanoframework/nf-interpreter/pull/559) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Rework System.DateTime [\#553](https://github.com/nanoframework/nf-interpreter/pull/553) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Drivemode "Alternate" [\#552](https://github.com/nanoframework/nf-interpreter/pull/552) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- FatFS Integration [\#551](https://github.com/nanoframework/nf-interpreter/pull/551) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Clean-up type system [\#544](https://github.com/nanoframework/nf-interpreter/pull/544) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Remove ExtendedWeakReference [\#543](https://github.com/nanoframework/nf-interpreter/pull/543) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update nanoCLR project [\#542](https://github.com/nanoframework/nf-interpreter/pull/542) +- Rework bool functions and args [\#539](https://github.com/nanoframework/nf-interpreter/pull/539) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on Debugger conditions in CLR\_RT\_ExecutionEngine [\#538](https://github.com/nanoframework/nf-interpreter/pull/538) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Improvements in Wire Protocol responsivness [\#536](https://github.com/nanoframework/nf-interpreter/pull/536) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] + +**Fixed bugs:** + +- Fix bug with infinite timeout handling [\#906](https://github.com/nanoframework/nf-interpreter/pull/906) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Work on config block [\#904](https://github.com/nanoframework/nf-interpreter/pull/904) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fixes to SPI for half duplex/TransferSequential [\#872](https://github.com/nanoframework/nf-interpreter/pull/872) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix STM32 series defines throughout the code [\#862](https://github.com/nanoframework/nf-interpreter/pull/862) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix enumeration of config blocks when device has no config block [\#857](https://github.com/nanoframework/nf-interpreter/pull/857) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix Convert::NativeToInt64 for multiple base conversions [\#855](https://github.com/nanoframework/nf-interpreter/pull/855) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix for issue \#390: object.GetHashCode not working [\#852](https://github.com/nanoframework/nf-interpreter/pull/852) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix for issue \\#402: Type.GetInterfaces doesn't return the inherited interfaces [\#851](https://github.com/nanoframework/nf-interpreter/pull/851) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix for issue \#409: NativeToDouble doesn't support the "e"/"E" exponential char [\#850](https://github.com/nanoframework/nf-interpreter/pull/850) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix for issue 403: type.GetMethods returns also static methods of the base class [\#849](https://github.com/nanoframework/nf-interpreter/pull/849) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- The format for 64bit values is "ll" not "l" [\#848](https://github.com/nanoframework/nf-interpreter/pull/848) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Uncommented the CLR\_RT\_TypeSystem::FindTypeDef functionality [\#847](https://github.com/nanoframework/nf-interpreter/pull/847) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix for string.LastIndexOf\\(char, int\\) and string.LastIndexOf\\(string, int\\) should search toward the beginning of the string \\#400 [\#845](https://github.com/nanoframework/nf-interpreter/pull/845) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix for double.ToString\(\) and float.ToString\(\) [\#841](https://github.com/nanoframework/nf-interpreter/pull/841) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix Random.Next returns negative numbers \#405 [\#840](https://github.com/nanoframework/nf-interpreter/pull/840) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix Math.Round [\#839](https://github.com/nanoframework/nf-interpreter/pull/839) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix DateTime.DaysInMonth [\#837](https://github.com/nanoframework/nf-interpreter/pull/837) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix single precision Truncate\_\_\_STATIC\_\_R4\_\_R4 [\#836](https://github.com/nanoframework/nf-interpreter/pull/836) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Rework math calls [\#827](https://github.com/nanoframework/nf-interpreter/pull/827) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Rework system math implementation [\#823](https://github.com/nanoframework/nf-interpreter/pull/823) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Config changes [\#818](https://github.com/nanoframework/nf-interpreter/pull/818) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix number conversion [\#816](https://github.com/nanoframework/nf-interpreter/pull/816) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix ToString for doubles and floats [\#815](https://github.com/nanoframework/nf-interpreter/pull/815) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix tiny printf implementation [\#813](https://github.com/nanoframework/nf-interpreter/pull/813) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix I2c issues [\#803](https://github.com/nanoframework/nf-interpreter/pull/803) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Remove debug code on SSL Network timeouts [\#802](https://github.com/nanoframework/nf-interpreter/pull/802) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Flash erase fix [\#801](https://github.com/nanoframework/nf-interpreter/pull/801) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix ChibiOS ADCv2 config struct [\#789](https://github.com/nanoframework/nf-interpreter/pull/789) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix typo in function name [\#786](https://github.com/nanoframework/nf-interpreter/pull/786) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix LaunchCLR to detect valid image [\#780](https://github.com/nanoframework/nf-interpreter/pull/780) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix declaration for build config RelWithDebInfo [\#779](https://github.com/nanoframework/nf-interpreter/pull/779) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fixes required for STM32F0 series [\#778](https://github.com/nanoframework/nf-interpreter/pull/778) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improve code in CheckValidCLRImage [\#776](https://github.com/nanoframework/nf-interpreter/pull/776) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix time methods as per \#350 \#351 [\#770](https://github.com/nanoframework/nf-interpreter/pull/770) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fixes with declarations for SMT32L0 series [\#757](https://github.com/nanoframework/nf-interpreter/pull/757) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improved code to remove compiler warning [\#749](https://github.com/nanoframework/nf-interpreter/pull/749) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix format specifier for double printf [\#743](https://github.com/nanoframework/nf-interpreter/pull/743) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix issue with CLR\_RT\_UnicodeHelper::ConvertFromUTF8 [\#742](https://github.com/nanoframework/nf-interpreter/pull/742) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Various fixes with Devices.Gpio [\#740](https://github.com/nanoframework/nf-interpreter/pull/740) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix System.Math.Truncate [\#734](https://github.com/nanoframework/nf-interpreter/pull/734) [[Area: Common libs](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Common%20libs)] +- Fix wrong field declaration in System\_String [\#727](https://github.com/nanoframework/nf-interpreter/pull/727) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Improvement on Serial NativeRead [\#722](https://github.com/nanoframework/nf-interpreter/pull/722) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Correct ConstraintException in type system lookup table [\#720](https://github.com/nanoframework/nf-interpreter/pull/720) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Corrected the device selector string for the ESP32 serial ports [\#717](https://github.com/nanoframework/nf-interpreter/pull/717) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- SPI: Use the max clock frequency if unset \(\#327\) [\#711](https://github.com/nanoframework/nf-interpreter/pull/711) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix bug with unwanted read or write after I2C operation [\#709](https://github.com/nanoframework/nf-interpreter/pull/709) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix ESP32 Gpio toggle [\#703](https://github.com/nanoframework/nf-interpreter/pull/703) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix issues with ESP32 time and event functions [\#700](https://github.com/nanoframework/nf-interpreter/pull/700) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Work on STM32 SPI [\#686](https://github.com/nanoframework/nf-interpreter/pull/686) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Correct calls to cache helpers for STM32 targets [\#676](https://github.com/nanoframework/nf-interpreter/pull/676) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix error introduced in last ESP32 I2C change [\#674](https://github.com/nanoframework/nf-interpreter/pull/674) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Improve debug session start [\#669](https://github.com/nanoframework/nf-interpreter/pull/669) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on GPIO events [\#657](https://github.com/nanoframework/nf-interpreter/pull/657) +- Added header for ESP32 to define uint8\_t etc [\#649](https://github.com/nanoframework/nf-interpreter/pull/649) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix and update for STM32 flash driver [\#646](https://github.com/nanoframework/nf-interpreter/pull/646) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Various fixes for ESP32 [\#645](https://github.com/nanoframework/nf-interpreter/pull/645) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Correct code writing single bytes to flash [\#644](https://github.com/nanoframework/nf-interpreter/pull/644) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix var name for config block [\#641](https://github.com/nanoframework/nf-interpreter/pull/641) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix STM32F7 loader files [\#640](https://github.com/nanoframework/nf-interpreter/pull/640) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix wrong button check in booter \(STM32F4 disco\) [\#636](https://github.com/nanoframework/nf-interpreter/pull/636) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Correct code reading Gpio value [\#635](https://github.com/nanoframework/nf-interpreter/pull/635) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Rework code for Serial ouput stream Store [\#607](https://github.com/nanoframework/nf-interpreter/pull/607) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix serial com Store\(\) delay [\#605](https://github.com/nanoframework/nf-interpreter/pull/605) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix Wire Protocol comm issues [\#596](https://github.com/nanoframework/nf-interpreter/pull/596) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix inclusion of target source file for serial API [\#587](https://github.com/nanoframework/nf-interpreter/pull/587) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on serial [\#585](https://github.com/nanoframework/nf-interpreter/pull/585) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update win\_dev\_serial\_native\_Windows\_Devices\_SerialCommunication\_Seri… [\#574](https://github.com/nanoframework/nf-interpreter/pull/574) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix UART definition requried for serial support [\#572](https://github.com/nanoframework/nf-interpreter/pull/572) +- Correct UART\_INIT macro for F4 and F0 targets [\#570](https://github.com/nanoframework/nf-interpreter/pull/570) +- Correct CRT heap size for nanoBooter [\#556](https://github.com/nanoframework/nf-interpreter/pull/556) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Change Spi Full-duplex buffer size [\#546](https://github.com/nanoframework/nf-interpreter/pull/546) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Amend comparison size of assembly marker [\#541](https://github.com/nanoframework/nf-interpreter/pull/541) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Correct missing call to wait debugger commands [\#537](https://github.com/nanoframework/nf-interpreter/pull/537) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix managed heap initialization [\#534](https://github.com/nanoframework/nf-interpreter/pull/534) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] + +**Documentation and other chores:** + +- Merge back changes from Release 1.0.0 [\#928](https://github.com/nanoframework/nf-interpreter/pull/928) +- Merge 'develop' for Release 1.0.0 [\#927](https://github.com/nanoframework/nf-interpreter/pull/927) +- Update nanoFramework.CorLib version to 1.0.4 [\#918](https://github.com/nanoframework/nf-interpreter/pull/918) +- normalize line endings [\#900](https://github.com/nanoframework/nf-interpreter/pull/900) +- Update nanoFramework.CorLib version to 1.0.1-preview118 [\#898](https://github.com/nanoframework/nf-interpreter/pull/898) +- High Res Timer added to Nanoframework.Hardware.Esp32 [\#866](https://github.com/nanoframework/nf-interpreter/pull/866) +- remove obsolete parameter BOARD\_NAME [\#861](https://github.com/nanoframework/nf-interpreter/pull/861) +- Getting the MinSizeRel build working for the ESP32 [\#796](https://github.com/nanoframework/nf-interpreter/pull/796) +- Changed build back to Debug [\#783](https://github.com/nanoframework/nf-interpreter/pull/783) +- Updated the ESP32 build documentation [\#755](https://github.com/nanoframework/nf-interpreter/pull/755) +- Add FP information about STM32 targets to readme [\#753](https://github.com/nanoframework/nf-interpreter/pull/753) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix for timeout errors on I2C introduced with 3.0 release. [\#746](https://github.com/nanoframework/nf-interpreter/pull/746) +- Initial ESP32 native hardware support [\#712](https://github.com/nanoframework/nf-interpreter/pull/712) +- Improvements in ESP32 related docs [\#691](https://github.com/nanoframework/nf-interpreter/pull/691) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Updated the setup procedure for the ESP32 development [\#682](https://github.com/nanoframework/nf-interpreter/pull/682) [[Area: ESP32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20ESP32)] +- Fix issues that stopped ESP32 build after change to events [\#611](https://github.com/nanoframework/nf-interpreter/pull/611) +- ESP32 Gpio update to support SetAlternateFunction [\#598](https://github.com/nanoframework/nf-interpreter/pull/598) +- Update sub module community targets @1d0bc8b0 [\#575](https://github.com/nanoframework/nf-interpreter/pull/575) +- Update target\_windows\_devices\_serialcommunication\_config.cpp [\#571](https://github.com/nanoframework/nf-interpreter/pull/571) +- Include community board in select clause for I2C [\#567](https://github.com/nanoframework/nf-interpreter/pull/567) +- PWM - Add more MCUs [\#558](https://github.com/nanoframework/nf-interpreter/pull/558) +- PWM support initial commit [\#557](https://github.com/nanoframework/nf-interpreter/pull/557) +- Update corlib\_native\_System\_Number.cpp [\#550](https://github.com/nanoframework/nf-interpreter/pull/550) +- Update corlib\_native\_System\_Number.cpp [\#549](https://github.com/nanoframework/nf-interpreter/pull/549) +- Update targetHAL\_Time.cpp [\#548](https://github.com/nanoframework/nf-interpreter/pull/548) + +## [v0.0.0](https://github.com/nanoframework/nf-interpreter/tree/v0.0.0) (2017-09-26) +**Implemented enhancements:** + +- Add exception handlers for debug [\#488](https://github.com/nanoframework/nf-interpreter/pull/488) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update Devces.Gpio native code for 1.0.0.22 [\#470](https://github.com/nanoframework/nf-interpreter/pull/470) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add CR+LF to improve output [\#463](https://github.com/nanoframework/nf-interpreter/pull/463) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add more SetResult\_\* methods [\#460](https://github.com/nanoframework/nf-interpreter/pull/460) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on System.Convert [\#459](https://github.com/nanoframework/nf-interpreter/pull/459) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Enhanced 16bit support [\#457](https://github.com/nanoframework/nf-interpreter/pull/457) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Enable SPI5 \(this is used in the board mems sensor\) [\#453](https://github.com/nanoframework/nf-interpreter/pull/453) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update test app for nanoCLR [\#450](https://github.com/nanoframework/nf-interpreter/pull/450) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Update native code for System.Globalization [\#446](https://github.com/nanoframework/nf-interpreter/pull/446) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on events [\#441](https://github.com/nanoframework/nf-interpreter/pull/441) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on Events [\#440](https://github.com/nanoframework/nf-interpreter/pull/440) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Improve assembly loading [\#439](https://github.com/nanoframework/nf-interpreter/pull/439) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Correct types in declarations of Async Process calls [\#437](https://github.com/nanoframework/nf-interpreter/pull/437) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add native code for System.Console [\#431](https://github.com/nanoframework/nf-interpreter/pull/431) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- SPI native code [\#429](https://github.com/nanoframework/nf-interpreter/pull/429) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on Devices.Spi [\#428](https://github.com/nanoframework/nf-interpreter/pull/428) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Move CLRStartup to its own OS thread [\#425](https://github.com/nanoframework/nf-interpreter/pull/425) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on Devices.Spi native [\#424](https://github.com/nanoframework/nf-interpreter/pull/424) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on Devices.Gpio [\#418](https://github.com/nanoframework/nf-interpreter/pull/418) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Rename NativeEvents native code [\#409](https://github.com/nanoframework/nf-interpreter/pull/409) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update nanoCLR test solution [\#406](https://github.com/nanoframework/nf-interpreter/pull/406) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Minor fixes [\#401](https://github.com/nanoframework/nf-interpreter/pull/401) +- Fix flash driver for use in SMT32F7 series [\#400](https://github.com/nanoframework/nf-interpreter/pull/400) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Various fixes for MBN\_QUAIL [\#395](https://github.com/nanoframework/nf-interpreter/pull/395) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on Execution [\#375](https://github.com/nanoframework/nf-interpreter/pull/375) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Update test app in nanoCLR [\#374](https://github.com/nanoframework/nf-interpreter/pull/374) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Initial work on Events [\#373](https://github.com/nanoframework/nf-interpreter/pull/373) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improve ContiguousBlockAssemblies [\#371](https://github.com/nanoframework/nf-interpreter/pull/371) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Remove endianess checking of assemblies [\#368](https://github.com/nanoframework/nf-interpreter/pull/368) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Aligned CorLib declarations with managed stubs [\#367](https://github.com/nanoframework/nf-interpreter/pull/367) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix issues with assemblies loading at startup [\#365](https://github.com/nanoframework/nf-interpreter/pull/365) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove addresses from Debugging\_Deployment\_Status [\#362](https://github.com/nanoframework/nf-interpreter/pull/362) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add error code to reply of access memory commands [\#361](https://github.com/nanoframework/nf-interpreter/pull/361) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Enable IncrementalDeployment in capabilites [\#360](https://github.com/nanoframework/nf-interpreter/pull/360) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on Debugging\_Deployment\_Status [\#359](https://github.com/nanoframework/nf-interpreter/pull/359) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Improvements in flash driver [\#358](https://github.com/nanoframework/nf-interpreter/pull/358) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Work on DeviceBlockInfo\_FindRegionFromAddress [\#357](https://github.com/nanoframework/nf-interpreter/pull/357) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on Debugging\_Deployment\_Status [\#356](https://github.com/nanoframework/nf-interpreter/pull/356) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Sync flags with debugger library code [\#350](https://github.com/nanoframework/nf-interpreter/pull/350) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Remove unsupported c\_Monitor\_SignatureKeyUpdate [\#349](https://github.com/nanoframework/nf-interpreter/pull/349) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Work on ChibiOS v17 USB code [\#344](https://github.com/nanoframework/nf-interpreter/pull/344) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Second try on Windows.Devices.Gpio [\#329](https://github.com/nanoframework/nf-interpreter/pull/329) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update Nuget packages [\#318](https://github.com/nanoframework/nf-interpreter/pull/318) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Update documentation to include API option [\#317](https://github.com/nanoframework/nf-interpreter/pull/317) +- Add native code for base class library \(mscolib\) [\#310](https://github.com/nanoframework/nf-interpreter/pull/310) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Include support for ChibiOS syscalls to use newlib stuff [\#309](https://github.com/nanoframework/nf-interpreter/pull/309) +- Add declaration for MDP [\#301](https://github.com/nanoframework/nf-interpreter/pull/301) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add Interop feature to CLR [\#299](https://github.com/nanoframework/nf-interpreter/pull/299) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- removed unused include for nanoHAL.h [\#298](https://github.com/nanoframework/nf-interpreter/pull/298) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Remove legacy functions [\#293](https://github.com/nanoframework/nf-interpreter/pull/293) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update Nuget for MSBuild System [\#291](https://github.com/nanoframework/nf-interpreter/pull/291) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Add code to output to VS console [\#290](https://github.com/nanoframework/nf-interpreter/pull/290) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Update Nuget packages [\#289](https://github.com/nanoframework/nf-interpreter/pull/289) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Replace path for mscorlib.pe [\#288](https://github.com/nanoframework/nf-interpreter/pull/288) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Improve error reporting detail [\#286](https://github.com/nanoframework/nf-interpreter/pull/286) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix ComputeAssemblyHash [\#279](https://github.com/nanoframework/nf-interpreter/pull/279) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Moved nanoCLR\_ParseOptions file to src folder [\#277](https://github.com/nanoframework/nf-interpreter/pull/277) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Enable Target\_GetReleaseInfo [\#267](https://github.com/nanoframework/nf-interpreter/pull/267) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Enable GetClrReleaseInfo in Debugger [\#266](https://github.com/nanoframework/nf-interpreter/pull/266) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Revert types to well known defined types [\#251](https://github.com/nanoframework/nf-interpreter/pull/251) +- Replace types with standard C [\#250](https://github.com/nanoframework/nf-interpreter/pull/250) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Correct declaration to use standard types [\#249](https://github.com/nanoframework/nf-interpreter/pull/249) +- Replace attributes with define [\#248](https://github.com/nanoframework/nf-interpreter/pull/248) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Complete work on \#195 [\#240](https://github.com/nanoframework/nf-interpreter/pull/240) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Rework code base to have a single debugger and messaging port [\#238](https://github.com/nanoframework/nf-interpreter/pull/238) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Rename ReplyCommand in WireProtocol C implementation [\#236](https://github.com/nanoframework/nf-interpreter/pull/236) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Further work on BlockStorage [\#235](https://github.com/nanoframework/nf-interpreter/pull/235) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update build-instructions.md [\#229](https://github.com/nanoframework/nf-interpreter/pull/229) +- Moved linker symbols to targetHAL [\#218](https://github.com/nanoframework/nf-interpreter/pull/218) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update documentation on contributions [\#217](https://github.com/nanoframework/nf-interpreter/pull/217) +- Add GetSector in STM32 flash driver [\#214](https://github.com/nanoframework/nf-interpreter/pull/214) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- First implement of Monitor\_CheckMemory logic. [\#211](https://github.com/nanoframework/nf-interpreter/pull/211) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Implement Monitor\_MemoryMap command [\#207](https://github.com/nanoframework/nf-interpreter/pull/207) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add flash driver for STM32F7 series [\#200](https://github.com/nanoframework/nf-interpreter/pull/200) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Rework HAL time functions [\#160](https://github.com/nanoframework/nf-interpreter/pull/160) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Cleaned up unused,obsolete and unsupported platforms and toolchains [\#99](https://github.com/nanoframework/nf-interpreter/pull/99) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- WP test app over USB CDC [\#65](https://github.com/nanoframework/nf-interpreter/pull/65) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Implement Wire Protocol in plain C [\#56](https://github.com/nanoframework/nf-interpreter/pull/56) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Moved CLR folder up one level [\#50](https://github.com/nanoframework/nf-interpreter/pull/50) +- Add test app for mBed RTOS [\#16](https://github.com/nanoframework/nf-interpreter/pull/16) +- Add demo app for FreeRTOS [\#15](https://github.com/nanoframework/nf-interpreter/pull/15) +- Add support for specifing RTOS for build [\#14](https://github.com/nanoframework/nf-interpreter/pull/14) + +**Fixed bugs:** + +- Add missing defines in mcuconf header of ST\_STM32F769I\_DISCOVERY [\#487](https://github.com/nanoframework/nf-interpreter/pull/487) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix linker file for ST\_STM32F769I\_DISCOVERY [\#486](https://github.com/nanoframework/nf-interpreter/pull/486) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove references to removed source files [\#447](https://github.com/nanoframework/nf-interpreter/pull/447) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Correct wrong declation of argument in Interop code [\#417](https://github.com/nanoframework/nf-interpreter/pull/417) +- Correct issue with flash driver for STM32F4XX devices [\#415](https://github.com/nanoframework/nf-interpreter/pull/415) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix flash driver for use in SMT32F7 series [\#400](https://github.com/nanoframework/nf-interpreter/pull/400) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Various fixes for MBN\\_QUAIL [\#395](https://github.com/nanoframework/nf-interpreter/pull/395) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Various fixes in ST\_STM32F429I\_DISCOVERY [\#394](https://github.com/nanoframework/nf-interpreter/pull/394) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix debugger wait loop [\#383](https://github.com/nanoframework/nf-interpreter/pull/383) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix ContiguousBlockAssemblies [\#372](https://github.com/nanoframework/nf-interpreter/pull/372) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Correct submodule naming [\#256](https://github.com/nanoframework/nf-interpreter/pull/256) +- Fixed ram0 start address on linker file [\#206](https://github.com/nanoframework/nf-interpreter/pull/206) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add missing \#ifdef for Win32 nanoCLR solution [\#175](https://github.com/nanoframework/nf-interpreter/pull/175) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] + +**Documentation and other chores:** + +- Fix linker files for SMT32F7 series [\#516](https://github.com/nanoframework/nf-interpreter/pull/516) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix issue \#70 [\#515](https://github.com/nanoframework/nf-interpreter/pull/515) +- Fix compilation error for F091 with SPI [\#508](https://github.com/nanoframework/nf-interpreter/pull/508) +- Changed I2C transmit timeout [\#507](https://github.com/nanoframework/nf-interpreter/pull/507) +- Replace duplicate implementations of SafeSprint\* [\#506](https://github.com/nanoframework/nf-interpreter/pull/506) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Add implementation for TimeSpan.ToString\(\) [\#505](https://github.com/nanoframework/nf-interpreter/pull/505) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove unused vars and related code file [\#504](https://github.com/nanoframework/nf-interpreter/pull/504) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix I2C for F769I reference board [\#500](https://github.com/nanoframework/nf-interpreter/pull/500) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Increase memory for image of firmware [\#499](https://github.com/nanoframework/nf-interpreter/pull/499) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Activate channels for SPI, I2C [\#498](https://github.com/nanoframework/nf-interpreter/pull/498) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Correct include version for I2C [\#497](https://github.com/nanoframework/nf-interpreter/pull/497) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Definitive fix for I2C and SPI on F7 MCU [\#495](https://github.com/nanoframework/nf-interpreter/pull/495) +- Work on I2C for STM32F7xx [\#492](https://github.com/nanoframework/nf-interpreter/pull/492) +- Improve HAL EXT initialization [\#491](https://github.com/nanoframework/nf-interpreter/pull/491) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fixes exception in ToString\(\) [\#490](https://github.com/nanoframework/nf-interpreter/pull/490) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Fix ChibiOS rules [\#489](https://github.com/nanoframework/nf-interpreter/pull/489) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Dereference Unsigned shorts in SPI [\#484](https://github.com/nanoframework/nf-interpreter/pull/484) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove setting of PB3 for SWO [\#482](https://github.com/nanoframework/nf-interpreter/pull/482) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Improve SWO config [\#481](https://github.com/nanoframework/nf-interpreter/pull/481) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Spi f7 [\#480](https://github.com/nanoframework/nf-interpreter/pull/480) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Remove ST\_NUCLEO144\_F746ZG from nF overlay [\#476](https://github.com/nanoframework/nf-interpreter/pull/476) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Update program with SPI test code [\#474](https://github.com/nanoframework/nf-interpreter/pull/474) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Correct assembly name [\#473](https://github.com/nanoframework/nf-interpreter/pull/473) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update nanoCLR test app to latest Nugets [\#472](https://github.com/nanoframework/nf-interpreter/pull/472) [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Disable Gpio on F091 board [\#471](https://github.com/nanoframework/nf-interpreter/pull/471) +- SetResult - Fix bytes return values [\#469](https://github.com/nanoframework/nf-interpreter/pull/469) +- Update docs [\#467](https://github.com/nanoframework/nf-interpreter/pull/467) +- I2c [\#445](https://github.com/nanoframework/nf-interpreter/pull/445) +- Add missing file to nanoCLR [\#438](https://github.com/nanoframework/nf-interpreter/pull/438) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: WIN32](https://github.com/nanoframework/nf-interpreter/labels/Area:%20WIN32)] +- Add documentation on using Ninja build [\#436](https://github.com/nanoframework/nf-interpreter/pull/436) +- Improve documentation [\#426](https://github.com/nanoframework/nf-interpreter/pull/426) +- Improve communication responsiveness [\#423](https://github.com/nanoframework/nf-interpreter/pull/423) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- refactored template to make it slightly simpler [\#410](https://github.com/nanoframework/nf-interpreter/pull/410) +- Improvements in documentation for class libraries [\#405](https://github.com/nanoframework/nf-interpreter/pull/405) +- Corrections for F69I \(deployment still fails\) [\#396](https://github.com/nanoframework/nf-interpreter/pull/396) +- Fix regions on F746ZG \(\#391\) [\#392](https://github.com/nanoframework/nf-interpreter/pull/392) +- updates to documentation \(\#386\) [\#389](https://github.com/nanoframework/nf-interpreter/pull/389) +- fix for USB connection issues with F769I [\#388](https://github.com/nanoframework/nf-interpreter/pull/388) +- Devices.Gpio fixes [\#387](https://github.com/nanoframework/nf-interpreter/pull/387) +- F746 device id \(\#380\) [\#384](https://github.com/nanoframework/nf-interpreter/pull/384) +- update travis arm toolchain [\#381](https://github.com/nanoframework/nf-interpreter/pull/381) +- update travis arm toolchain \#196 and cmake to 3.8.2 [\#379](https://github.com/nanoframework/nf-interpreter/pull/379) +- updated documents [\#378](https://github.com/nanoframework/nf-interpreter/pull/378) +- Add documenation about thread execution and context switching [\#376](https://github.com/nanoframework/nf-interpreter/pull/376) +- F7 improvements and attempts at CLR RAM optimisations for some boards [\#370](https://github.com/nanoframework/nf-interpreter/pull/370) +- clr managed heap document improvements [\#369](https://github.com/nanoframework/nf-interpreter/pull/369) +- Add doc with explanation about deployment [\#363](https://github.com/nanoframework/nf-interpreter/pull/363) +- Fix \#353 [\#354](https://github.com/nanoframework/nf-interpreter/pull/354) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix issue \#337 [\#338](https://github.com/nanoframework/nf-interpreter/pull/338) +- Work on new DateTime native side [\#336](https://github.com/nanoframework/nf-interpreter/pull/336) +- Fixes \#314 [\#315](https://github.com/nanoframework/nf-interpreter/pull/315) +- Fix declaration of Interop\_Marshal\_GetField for bool type [\#295](https://github.com/nanoframework/nf-interpreter/pull/295) +- Add stdafx.h include [\#282](https://github.com/nanoframework/nf-interpreter/pull/282) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Update Community Targets submodule [\#280](https://github.com/nanoframework/nf-interpreter/pull/280) +- Moved nanoCLR\_ParseOptions file to src folder \(\#277\) [\#278](https://github.com/nanoframework/nf-interpreter/pull/278) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add documentation about cmake-variants.TEMPLATE.json [\#276](https://github.com/nanoframework/nf-interpreter/pull/276) +- Correct GNU ARM Eclipse OpenOCD link [\#273](https://github.com/nanoframework/nf-interpreter/pull/273) +- Correct issue when checking for user button pressed [\#271](https://github.com/nanoframework/nf-interpreter/pull/271) +- Add missing CLRStartup thread to reference boards [\#262](https://github.com/nanoframework/nf-interpreter/pull/262) +- Fix \#259 [\#261](https://github.com/nanoframework/nf-interpreter/pull/261) +- Correct linker scripts to aling deployment [\#260](https://github.com/nanoframework/nf-interpreter/pull/260) +- Correct button check [\#258](https://github.com/nanoframework/nf-interpreter/pull/258) +- Correction for support of community boards [\#253](https://github.com/nanoframework/nf-interpreter/pull/253) +- Update gitignore for VS Code [\#246](https://github.com/nanoframework/nf-interpreter/pull/246) +- Fixes issue \#118 [\#245](https://github.com/nanoframework/nf-interpreter/pull/245) +- Fix Quail nanoBooter main code [\#244](https://github.com/nanoframework/nf-interpreter/pull/244) +- Update README.md [\#243](https://github.com/nanoframework/nf-interpreter/pull/243) +- Fix \#241 [\#242](https://github.com/nanoframework/nf-interpreter/pull/242) +- update build instructions related to launch.json [\#234](https://github.com/nanoframework/nf-interpreter/pull/234) +- Initial implementation of Monitor\_FlashSectorMap \(\#215\) [\#223](https://github.com/nanoframework/nf-interpreter/pull/223) +- Moved some declarations to nanoHAL\_v2 [\#204](https://github.com/nanoframework/nf-interpreter/pull/204) +- Add dummy flash sector 11 definition [\#203](https://github.com/nanoframework/nf-interpreter/pull/203) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Implement AccessMemory function [\#198](https://github.com/nanoframework/nf-interpreter/pull/198) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Implement Monitor\_EraseMemory command [\#197](https://github.com/nanoframework/nf-interpreter/pull/197) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- HAL config was missing the USE\_SERIAL definition [\#194](https://github.com/nanoframework/nf-interpreter/pull/194) +- Add Travis CI badge to readme [\#193](https://github.com/nanoframework/nf-interpreter/pull/193) +- Correct filename case [\#190](https://github.com/nanoframework/nf-interpreter/pull/190) +- Correct file name case [\#189](https://github.com/nanoframework/nf-interpreter/pull/189) +- Change filename case [\#187](https://github.com/nanoframework/nf-interpreter/pull/187) +- update Travis file [\#183](https://github.com/nanoframework/nf-interpreter/pull/183) +- Add Travis file [\#180](https://github.com/nanoframework/nf-interpreter/pull/180) +- Aligned CMakes for reference boards [\#179](https://github.com/nanoframework/nf-interpreter/pull/179) +- Enable WireProtocol in nanoBooter [\#177](https://github.com/nanoframework/nf-interpreter/pull/177) +- Quail board support again [\#168](https://github.com/nanoframework/nf-interpreter/pull/168) +- Fix mcu configs for NUCLEO901 in nanoCLR [\#167](https://github.com/nanoframework/nf-interpreter/pull/167) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Uncomment line that was causing issues with nanoCLR image detection [\#163](https://github.com/nanoframework/nf-interpreter/pull/163) +- Lineup the sys tick configurations on all reference boards [\#156](https://github.com/nanoframework/nf-interpreter/pull/156) +- Add code to check for valid CLR image and launch it [\#155](https://github.com/nanoframework/nf-interpreter/pull/155) +- Revert ChibiOS setting for using classic periodic timer [\#153](https://github.com/nanoframework/nf-interpreter/pull/153) +- Add STM32F429I\_DISCOVERY board [\#147](https://github.com/nanoframework/nf-interpreter/pull/147) [[Area: STM32-ChibiOS](https://github.com/nanoframework/nf-interpreter/labels/Area:%20STM32-ChibiOS)] +- Implement HAL\_Time\_TicksToTimeMilliSec [\#145](https://github.com/nanoframework/nf-interpreter/pull/145) +- Moved include of target\_board header to targetHAL [\#144](https://github.com/nanoframework/nf-interpreter/pull/144) +- Deleted nanoCLR.VC.db [\#138](https://github.com/nanoframework/nf-interpreter/pull/138) +- Fixes \#81 [\#137](https://github.com/nanoframework/nf-interpreter/pull/137) +- Resolves \#133 [\#135](https://github.com/nanoframework/nf-interpreter/pull/135) +- Rename FLASH in HAL\_SYSTEM\_CONFIG struct [\#129](https://github.com/nanoframework/nf-interpreter/pull/129) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Add logo in common size \(32x32\) [\#117](https://github.com/nanoframework/nf-interpreter/pull/117) +- Correct "source" directory references in \/CMakeLists.txt \#96 [\#111](https://github.com/nanoframework/nf-interpreter/pull/111) +- Rename nanoCLR [\#105](https://github.com/nanoframework/nf-interpreter/pull/105) +- Added empty line to make GitHub diff happy [\#103](https://github.com/nanoframework/nf-interpreter/pull/103) +- Correct buffer size for ST\_NUCLEO\_F091RC [\#102](https://github.com/nanoframework/nf-interpreter/pull/102) +- Add Monitor\_Reboot command [\#100](https://github.com/nanoframework/nf-interpreter/pull/100) +- \[WIP\] nanoCLR [\#95](https://github.com/nanoframework/nf-interpreter/pull/95) +- Fixed copyright notice in CMakeLists [\#94](https://github.com/nanoframework/nf-interpreter/pull/94) +- Fixed project name [\#88](https://github.com/nanoframework/nf-interpreter/pull/88) +- Import cmake build [\#84](https://github.com/nanoframework/nf-interpreter/pull/84) +- Renamed keepers to maintainers, fixed links [\#75](https://github.com/nanoframework/nf-interpreter/pull/75) +- Updated organization name nanoFramework [\#74](https://github.com/nanoframework/nf-interpreter/pull/74) +- Updated copyright notice header format to handle partial content [\#66](https://github.com/nanoframework/nf-interpreter/pull/66) +- Fix 58 [\#63](https://github.com/nanoframework/nf-interpreter/pull/63) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Fix variable names in WireProtocol\_Receiver [\#60](https://github.com/nanoframework/nf-interpreter/pull/60) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- Added Developer Certificate of Origin documentation [\#52](https://github.com/nanoframework/nf-interpreter/pull/52) +- Updated copyright notice header format [\#49](https://github.com/nanoframework/nf-interpreter/pull/49) +- Add official logo files [\#36](https://github.com/nanoframework/nf-interpreter/pull/36) +- Updated README-s [\#34](https://github.com/nanoframework/nf-interpreter/pull/34) +- \[WIP\] nanoBooter mbed-os sample implementation [\#32](https://github.com/nanoframework/nf-interpreter/pull/32) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- \[WIP\] Wire protocol proof-of-concept [\#31](https://github.com/nanoframework/nf-interpreter/pull/31) [[Area: Interpreter](https://github.com/nanoframework/nf-interpreter/labels/Area:%20Interpreter)] +- cosmetic changes in doc [\#29](https://github.com/nanoframework/nf-interpreter/pull/29) +- add preliminary versions of documentation [\#25](https://github.com/nanoframework/nf-interpreter/pull/25) +- update information about build deliverables [\#24](https://github.com/nanoframework/nf-interpreter/pull/24) +- Small correction on typos [\#17](https://github.com/nanoframework/nf-interpreter/pull/17) +- Add support for STM32F0 series [\#13](https://github.com/nanoframework/nf-interpreter/pull/13) +- Add readme file to perform as documentation index [\#12](https://github.com/nanoframework/nf-interpreter/pull/12) +- Add preliminary version of documentation with build and VS Code debug instructions [\#11](https://github.com/nanoframework/nf-interpreter/pull/11) +- Initial works on CMake build and debug for VS Code [\#10](https://github.com/nanoframework/nf-interpreter/pull/10) +- Added README-s, LICENSE and CONTRIBUTORS [\#1](https://github.com/nanoframework/nf-interpreter/pull/1) + + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/source/native/nf-interpreter/CMake/ChibiOS-Contrib.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/ChibiOS-Contrib.CMakeLists.cmake.in new file mode 100644 index 00000000..e0e66965 --- /dev/null +++ b/source/native/nf-interpreter/CMake/ChibiOS-Contrib.CMakeLists.cmake.in @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(ChibiOS-Contrib-download NONE) + +include(ExternalProject) + +# download ChibiOS Community contributions source from GitHub repo +# need to specify nanoframework as the active branch +ExternalProject_Add( + ChibiOS-Contrib + PREFIX ChibiOS-Contrib + SOURCE_DIR ${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Source + GIT_REPOSITORY https://github.com/nanoframework/ChibiOS-Contrib + GIT_TAG nanoframework # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) diff --git a/source/native/nf-interpreter/CMake/ChibiOS.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/ChibiOS.CMakeLists.cmake.in new file mode 100644 index 00000000..eaf0b167 --- /dev/null +++ b/source/native/nf-interpreter/CMake/ChibiOS.CMakeLists.cmake.in @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(ChibiOS-download NONE) + +include(ExternalProject) + +# download ChibiOS source from official SVN repo +ExternalProject_Add( + ChibiOS + PREFIX ChibiOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/ChibiOS_Source + GIT_REPOSITORY https://github.com/nanoframework/chibios + GIT_TAG ${CHIBIOS_GIT_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) diff --git a/source/native/nf-interpreter/CMake/ChibiOS_target_os.h.in b/source/native/nf-interpreter/CMake/ChibiOS_target_os.h.in new file mode 100644 index 00000000..1621ff73 --- /dev/null +++ b/source/native/nf-interpreter/CMake/ChibiOS_target_os.h.in @@ -0,0 +1,33 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_OS_H_ +#define _TARGET_OS_H_ + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +#define VERSION_MAJOR @nanoFramework_VERSION_MAJOR@U +#define VERSION_MINOR @nanoFramework_VERSION_MINOR@U +#define VERSION_BUILD @nanoFramework_VERSION_PATCH@U +#define VERSION_REVISION @nanoFramework_VERSION_TWEAK@U + +#define NANOCLR_LIGHT_MATH @TARGET_LIGHT_MATH@ +#define DP_FLOATINGPOINT @TARGET_DP_FLOATINGPOINT@ + +#define SUPPORT_ANY_BASE_CONVERSION @TARGET_SUPPORT_ANY_BASE_CONVERSION@ + +#define HAS_CONFIG_BLOCK @TARGET_HAS_CONFIG_BLOCK@ + +#define NANOCLR_REFLECTION @TARGET_NANOCLR_REFLECTION@ + +#define NANOCLR_SYSTEM_COLLECTIONS @TARGET_SYSTEM_COLLECTIONS@ + +#endif /* _TARGET_OS_H_ */ diff --git a/source/native/nf-interpreter/CMake/ESP32_target_os.h.in b/source/native/nf-interpreter/CMake/ESP32_target_os.h.in new file mode 100644 index 00000000..1ae5bc75 --- /dev/null +++ b/source/native/nf-interpreter/CMake/ESP32_target_os.h.in @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_OS_H_ +#define _TARGET_OS_H_ + +#define VERSION_MAJOR @nanoFramework_VERSION_MAJOR@U +#define VERSION_MINOR @nanoFramework_VERSION_MINOR@U +#define VERSION_BUILD @nanoFramework_VERSION_PATCH@U +#define VERSION_REVISION @nanoFramework_VERSION_TWEAK@U + +#define NANOCLR_LIGHT_MATH @TARGET_LIGHT_MATH@ +#define DP_FLOATINGPOINT @TARGET_DP_FLOATINGPOINT@ + +#define SUPPORT_ANY_BASE_CONVERSION @TARGET_SUPPORT_ANY_BASE_CONVERSION@ + +#define HAS_CONFIG_BLOCK @TARGET_HAS_CONFIG_BLOCK@ + +#define NANOCLR_REFLECTION @TARGET_NANOCLR_REFLECTION@ + +#define NANOCLR_SYSTEM_COLLECTIONS @TARGET_SYSTEM_COLLECTIONS@ + +#endif /* _TARGET_OS_H_ */ diff --git a/source/native/nf-interpreter/CMake/FreeRTOS.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/FreeRTOS.CMakeLists.cmake.in new file mode 100644 index 00000000..ac289de6 --- /dev/null +++ b/source/native/nf-interpreter/CMake/FreeRTOS.CMakeLists.cmake.in @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(FreeRTOS-download NONE) + +include(ExternalProject) + +# download FreeRTOS source from official Amazon GitHub repo +ExternalProject_Add( + FreeRTOS + PREFIX FreeRTOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/FreeRTOS_Source + GIT_REPOSITORY https://github.com/aws/amazon-freertos.git + GIT_TAG ${FREERTOS_VERSION_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_GCC_options.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_GCC_options.cmake new file mode 100644 index 00000000..7b89de2b --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_GCC_options.cmake @@ -0,0 +1,47 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################# +# WHEN ADDING A NEW SERIES add the appropriate GCC options below +################################################################# + +# need to specify this for assembler +set(CMAKE_ASM_FLAGS " -mthumb -mcpu=cortex-m0 -mfloat-abi=soft -mabi=aapcs -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") + +# need to specify linker flags here +set(CMAKE_EXE_LINKER_FLAGS " -Wl,--gc-sections -Wl,--no-wchar-size-warning -Wl,--print-memory-usage -mthumb -mcpu=cortex-m0 -mfloat-abi=soft -mabi=aapcs -nostartfiles " CACHE INTERNAL "executable linker flags") + + +function(NF_SET_COMPILER_OPTIONS TARGET) + + # include any extra options coming from any extra args? + target_compile_options(${TARGET} PUBLIC ${ARGN} -mthumb -mcpu=cortex-m0 -mabi=aapcs -nostdlib -Wall -Wextra -Werror -ffunction-sections -fshort-wchar -falign-functions=16 -fdata-sections -fno-builtin -fno-common -fomit-frame-pointer -mlong-calls -fdollars-in-identifiers -fno-exceptions -fno-unroll-loops -frounding-math -fsignaling-nans -ffloat-store -fno-math-errno -ftree-vectorize -fcheck-new ) + + # this series doesn't have FPU + target_compile_definitions(${TARGET} PUBLIC -DCORTEX_USE_FPU=FALSE) + +endfunction() + + +function(NF_SET_LINKER_OPTIONS TARGET) + + # request specs from newlib nano + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --specs=nano.specs ") + + # set extra linker flags + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " ${ARGN}") + + # set optimization linker flags for RELEASE and MinSizeRel + if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-linker-plugin -Os") + endif() + + # set optimization flags + nf_set_optimization_options(${TARGET}) + + # set link map + nf_set_link_map(${TARGET}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_sources.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_sources.cmake new file mode 100644 index 00000000..86a435fc --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F0xx_sources.cmake @@ -0,0 +1,138 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# from startup_stm32f0xx.mk +# List of the ChibiOS generic STM32F0xx startup and CMSIS files. + +################################################################################ +# WHEN ADDING A NEW BOARD add the source code file for the STM32F0xx\platform.mk +################################################################################ + +set(CHIBIOS_PORT_SRCS + # startup code + crt1.c + vectors.S + crt0_v6m.S + + nvic.c + stm32_isr.c + hal_lld.c + + hal_adc_lld.c + hal_can_lld.c + hal_dac_lld.c + stm32_dma.c + stm32_exti.c + hal_pal_lld.c + hal_i2c_lld.c + hal_rtc_lld.c + + hal_i2s_lld.c + hal_spi_lld.c + + hal_st_lld.c + hal_gpt_lld.c + hal_icu_lld.c + hal_pwm_lld.c + + hal_serial_lld.c + hal_uart_lld.c + + hal_usb_lld.c + + hal_wdg_lld.c + + # RT + chcore.c + chcore_v6m.c + chcoreasm_v6m.S +) + +foreach(SRC_FILE ${CHIBIOS_PORT_SRCS}) + set(CHIBIOS_F0_SRC_FILE SRC_FILE-NOTFOUND) + find_file(CHIBIOS_F0_SRC_FILE ${SRC_FILE} + PATHS + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/common/ARMCMx + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/STM32F0xx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USBv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1 + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${CHIBIOS_F0_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_SOURCES ${CHIBIOS_F0_SRC_FILE}) +endforeach() + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/portability/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/devices/STM32F0xx) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ARM/CMSIS/Core/Include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ST/STM32F0xx) + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USBv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1) + + +#################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the include directory(ies) below +#################################################################################### +# component STM32_FLASH +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1) +# component STM32_CRC +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) +# component STM32_ONEWIRE +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1) + +############################################################################################################################### +# Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding +# following the template below. +# +# list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/) +############################################################################################################################### + + +#################################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the source file(s) specific to this series below +#################################################################################################### +# component STM32_FLASH +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c) +# component STM32_CRC +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) +# component STM32_ONEWIRE +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c) + +########################################################################################################################## +# Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework +# overlay component that you are adding following the template below. +# +# list(APPEND CHIBIOS_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/) +########################################################################################################################## diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_GCC_options.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_GCC_options.cmake new file mode 100644 index 00000000..a7d444ba --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_GCC_options.cmake @@ -0,0 +1,47 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################# +# WHEN ADDING A NEW SERIES add the appropriate GCC options below +################################################################# + +# need to specify this for assembler +set(CMAKE_ASM_FLAGS " -mthumb -mcpu=cortex-m4 -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") + +# need to specify linker flags here +set(CMAKE_EXE_LINKER_FLAGS " -Wl,--gc-sections -Wl,--no-wchar-size-warning -Wl,--print-memory-usage -mthumb -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mabi=aapcs -nostartfiles " CACHE INTERNAL "executable linker flags") + + +function(NF_SET_COMPILER_OPTIONS TARGET) + + # include any extra options coming from any extra args? + target_compile_options(${TARGET} PUBLIC ${ARGN} -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mabi=aapcs -nostdlib -Wall -Wextra -Werror -ffunction-sections -fshort-wchar -falign-functions=16 -fdata-sections -fno-builtin -fno-common -fomit-frame-pointer -mlong-calls -fdollars-in-identifiers -fno-exceptions -fno-unroll-loops -frounding-math -fsignaling-nans -ffloat-store -fno-math-errno -ftree-vectorize -fcheck-new ) + + # this series has FPU + target_compile_definitions(${TARGET} PUBLIC -DCORTEX_USE_FPU=TRUE) + +endfunction() + + +function(NF_SET_LINKER_OPTIONS TARGET) + + # request specs from newlib nano + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --specs=nano.specs ") + + # set extra linker flags + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " ${ARGN}") + + # set optimization linker flags for RELEASE and MinSizeRel + if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-linker-plugin -Os") + endif() + + # set optimization flags + nf_set_optimization_options(${TARGET}) + + # set link map + nf_set_link_map(${TARGET}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake new file mode 100644 index 00000000..8a25d5ea --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F4xx_sources.cmake @@ -0,0 +1,166 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# from startup_stm32f4xx.mk +# List of the ChibiOS generic STM32F4xx startup and CMSIS files. + +################################################################################################ +# WHEN ADDING A NEW BOARD add the source code file for the hal/ports/STM32/STM32F4xx/platform.mk +################################################################################################ + +set(CHIBIOS_PORT_SRCS + # startup code + crt1.c + vectors.S + crt0_v7m.S + + nvic.c + stm32_isr.c + hal_lld.c + + hal_adc_lld.c + hal_can_lld.c + hal_crypto_lld.c + hal_dac_lld.c + stm32_dma.c + stm32_exti.c + hal_pal_lld.c + hal_i2c_lld.c + hal_mac_lld.c + hal_usb_lld.c + hal_wspi_lld.c + hal_trng_lld.c + hal_rtc_lld.c + hal_sdc_lld.c + + hal_i2s_lld.c + hal_spi_lld.c + + hal_st_lld.c + hal_gpt_lld.c + hal_icu_lld.c + hal_pwm_lld.c + + hal_serial_lld.c + hal_uart_lld.c + + hal_wdg_lld.c + + # RT + chcore.c + chcore_v7m.c + chcoreasm_v7m.S +) + +foreach(SRC_FILE ${CHIBIOS_PORT_SRCS}) + set(CHIBIOS_F4_SRC_FILE SRC_FILE-NOTFOUND) + find_file(CHIBIOS_F4_SRC_FILE ${SRC_FILE} + PATHS + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/common/ARMCMx + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/STM32F4xx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CRYPv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/MACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/OTGv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/QUADSPIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RNGv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SDIOv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1 + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${CHIBIOS_F4_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_SOURCES ${CHIBIOS_F4_SRC_FILE}) +endforeach() + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/portability/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/devices/STM32F4xx) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ARM/CMSIS/Core/Include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ST/STM32F4xx) + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CRYPv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/MACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/OTGv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/QUADSPIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RNGv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SDIOv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1) + + +#################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the include directory(ies) below +#################################################################################### +# component STM32_FLASH +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2) +# component STM32_CRC +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) +# component STM32_RNG +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1) +# component STM32_ONEWIRE (One Wire driver) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1) +# component STM32_QSPI (Quad-SPI) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1) + +############################################################################################################################### +# Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding +# following the template below. +# +# list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/) +############################################################################################################################### + + +#################################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the source file(s) specific to this series below +#################################################################################################### +# component STM32_FLASH +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.c) +# component STM32_CRC +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) +# component STM32_RNG +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c) +# component STM32_ONEWIRE +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c) +# component STM32_QSPI (Quad-SPI) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.c) + +########################################################################################################################## +# Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework +# overlay component that you are adding following the template below. +# +# list(APPEND CHIBIOS_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/) +########################################################################################################################## diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_GCC_options.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_GCC_options.cmake new file mode 100644 index 00000000..5c901ec9 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_GCC_options.cmake @@ -0,0 +1,48 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################# +# WHEN ADDING A NEW SERIES add the appropriate GCC options below +################################################################# + +# need to specify this for assembler +set(CMAKE_ASM_FLAGS " -mthumb -mcpu=cortex-m7 -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") + +# need to specify linker flags here +set(CMAKE_EXE_LINKER_FLAGS " -Wl,--gc-sections -Wl,--no-wchar-size-warning -Wl,--print-memory-usage -mthumb -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mabi=aapcs -nostartfiles " CACHE INTERNAL "executable linker flags") + + +function(NF_SET_COMPILER_OPTIONS TARGET) + + # include any extra options coming from any extra args? + # STMF7 cores have SP and DP, the default is SP. DP can be set if developer realy needs that. + target_compile_options(${TARGET} PUBLIC ${ARGN} -mthumb -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mabi=aapcs -nostdlib -Wall -Wextra -Werror -ffunction-sections -fshort-wchar -falign-functions=16 -fdata-sections -fno-builtin -fno-common -fomit-frame-pointer -mlong-calls -fdollars-in-identifiers -fno-exceptions -fno-unroll-loops -frounding-math -fsignaling-nans -ffloat-store -fno-math-errno -ftree-vectorize -fcheck-new ) + + # this series has FPU + target_compile_definitions(${TARGET} PUBLIC -DCORTEX_USE_FPU=TRUE) + +endfunction() + + +function(NF_SET_LINKER_OPTIONS TARGET) + + # request specs from newlib nano + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --specs=nano.specs ") + + # set extra linker flags + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " ${ARGN}") + + # set optimization linker flags for RELEASE and MinSizeRel + if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-linker-plugin -Os") + endif() + + # set optimization flags + nf_set_optimization_options(${TARGET}) + + # set link map + nf_set_link_map(${TARGET}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake new file mode 100644 index 00000000..f3b2ff2c --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32F7xx_sources.cmake @@ -0,0 +1,168 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# from startup_stm32f7xx.mk +# List of the ChibiOS generic STM32F7xx startup and CMSIS files. + +################################################################################################ +# WHEN ADDING A NEW BOARD add the source code file for the hal/ports/STM32/STM32F7xx/platform.mk +################################################################################################ + +set(CHIBIOS_PORT_SRCS + # startup code + crt1.c + vectors.S + crt0_v7m.S + + nvic.c + stm32_isr.c + hal_lld.c + + hal_adc_lld.c + hal_can_lld.c + hal_crypto_lld.c + hal_dac_lld.c + stm32_dma.c + stm32_exti.c + hal_pal_lld.c + hal_i2c_lld.c + hal_mac_lld.c + hal_usb_lld.c + hal_wspi_lld.c + hal_trng_lld.c + hal_rtc_lld.c + hal_sdc_lld.c + + hal_i2s_lld.c + hal_spi_lld.c + + hal_st_lld.c + hal_gpt_lld.c + hal_icu_lld.c + hal_pwm_lld.c + + hal_serial_lld.c + hal_uart_lld.c + + hal_wdg_lld.c + + # RT + chcore.c + chcore_v7m.c + chcoreasm_v7m.S +) + +foreach(SRC_FILE ${CHIBIOS_PORT_SRCS}) + set(CHIBIOS_F7_SRC_FILE SRC_FILE-NOTFOUND) + find_file(CHIBIOS_F7_SRC_FILE ${SRC_FILE} + PATHS + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/common/ARMCMx + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/STM32F7xx + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CRYPv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/MACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/OTGv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/QUADSPIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RNGv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SDMMCv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1 + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${CHIBIOS_F7_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_SOURCES ${CHIBIOS_F7_SRC_FILE}) +endforeach() + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/portability/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/devices/STM32F7xx) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ARM/CMSIS/Core/Include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ST/STM32F7xx) + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CRYPv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/MACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/OTGv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/QUADSPIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RNGv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SDMMCv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1) + + +#################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the include directory(ies) below +#################################################################################### +# component STM32_FLASH +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2) +# component STM32_CRC +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) +# component STM32_RNG +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1) +# component STM32_ONEWIRE +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1) +# component STM32_QSPI (Quad-SPI) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/STM32_CubePackage_Source/Drivers/STM32F7xx_HAL_Driver/Inc") + +############################################################################################################################### +# Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding +# following the template below. +# +# list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/) +############################################################################################################################### + + +#################################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the source file(s) specific to this series below +#################################################################################################### +# component STM32_FLASH +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.c) +# component STM32_CRC +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) +# component STM32_RNG +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c) +# component STM32_ONEWIRE +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c) +# component STM32_QSPI (Quad-SPI) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.c) + +########################################################################################################################## +# Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework +# overlay component that you are adding following the template below. +# +# list(APPEND CHIBIOS_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/) +########################################################################################################################## diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_GCC_options.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_GCC_options.cmake new file mode 100644 index 00000000..5c901ec9 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_GCC_options.cmake @@ -0,0 +1,48 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################# +# WHEN ADDING A NEW SERIES add the appropriate GCC options below +################################################################# + +# need to specify this for assembler +set(CMAKE_ASM_FLAGS " -mthumb -mcpu=cortex-m7 -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") + +# need to specify linker flags here +set(CMAKE_EXE_LINKER_FLAGS " -Wl,--gc-sections -Wl,--no-wchar-size-warning -Wl,--print-memory-usage -mthumb -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mabi=aapcs -nostartfiles " CACHE INTERNAL "executable linker flags") + + +function(NF_SET_COMPILER_OPTIONS TARGET) + + # include any extra options coming from any extra args? + # STMF7 cores have SP and DP, the default is SP. DP can be set if developer realy needs that. + target_compile_options(${TARGET} PUBLIC ${ARGN} -mthumb -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mabi=aapcs -nostdlib -Wall -Wextra -Werror -ffunction-sections -fshort-wchar -falign-functions=16 -fdata-sections -fno-builtin -fno-common -fomit-frame-pointer -mlong-calls -fdollars-in-identifiers -fno-exceptions -fno-unroll-loops -frounding-math -fsignaling-nans -ffloat-store -fno-math-errno -ftree-vectorize -fcheck-new ) + + # this series has FPU + target_compile_definitions(${TARGET} PUBLIC -DCORTEX_USE_FPU=TRUE) + +endfunction() + + +function(NF_SET_LINKER_OPTIONS TARGET) + + # request specs from newlib nano + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --specs=nano.specs ") + + # set extra linker flags + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " ${ARGN}") + + # set optimization linker flags for RELEASE and MinSizeRel + if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-linker-plugin -Os") + endif() + + # set optimization flags + nf_set_optimization_options(${TARGET}) + + # set link map + nf_set_link_map(${TARGET}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake new file mode 100644 index 00000000..d31fd89e --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32H7xx_sources.cmake @@ -0,0 +1,165 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# from os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32h7xx.mk +# List of the ChibiOS generic STM32H7xx startup and CMSIS files. + +################################################################################################ +# WHEN ADDING A NEW BOARD add the source code file for the hal/ports/STM32/STM32H7xx/platform.mk +################################################################################################ + +set(CHIBIOS_PORT_SRCS + # startup code + crt1.c + vectors.S + crt0_v7m.S + + nvic.c + stm32_isr.c + hal_lld.c + + hal_adc_lld.c + hal_can_lld.c + hal_crypto_lld.c + hal_dac_lld.c + stm32_dma.c + stm32_exti.c + hal_pal_lld.c + hal_i2c_lld.c + hal_mac_lld.c + hal_usb_lld.c + hal_wspi_lld.c + hal_trng_lld.c + hal_rtc_lld.c + hal_sdc_lld.c + + hal_i2s_lld.c + hal_spi_lld.c + + hal_st_lld.c + hal_gpt_lld.c + hal_icu_lld.c + hal_pwm_lld.c + + hal_serial_lld.c + hal_uart_lld.c + + hal_wdg_lld.c + + # RT + chcore.c + chcore_v7m.c + chcoreasm_v7m.S +) + +foreach(SRC_FILE ${CHIBIOS_PORT_SRCS}) + set(CHIBIOS_H7_SRC_FILE SRC_FILE-NOTFOUND) + find_file(CHIBIOS_H7_SRC_FILE ${SRC_FILE} + PATHS + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/common/ARMCMx + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/STM32H7xx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv4 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CRYPv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv3 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv3 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv3 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/MACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/OTGv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/QUADSPIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RNGv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SDMMCv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv3 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2 + # ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USBv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1 + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${CHIBIOS_H7_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_SOURCES ${CHIBIOS_H7_SRC_FILE}) +endforeach() + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/portability/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/devices/STM32H7xx) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ARM/CMSIS/Core/Include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ST/STM32H7xx) + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv4) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CRYPv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv3) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv3) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv3) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/MACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/OTGv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/QUADSPIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RNGv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SDMMCv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv3) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2) +# list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USBv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1) + + +#################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the include directory(ies) below +#################################################################################### +# component STM32_FLASH +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2) +# component STM32_CRC +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) +# component STM32_RNG +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1) +# component STM32_ONEWIRE +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1) + +############################################################################################################################### +# Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding +# following the template below. +# +# list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/) +############################################################################################################################### + + +#################################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the source file(s) specific to this series below +#################################################################################################### +# component STM32_FLASH +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.c) +# component STM32_CRC +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) +# component STM32_RNG +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c) +# component STM32_ONEWIRE +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c) + +########################################################################################################################## +# Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework +# overlay component that you are adding following the template below. +# +# list(APPEND CHIBIOS_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/) +########################################################################################################################## diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_GCC_options.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_GCC_options.cmake new file mode 100644 index 00000000..a2bd1ea3 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_GCC_options.cmake @@ -0,0 +1,51 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################# +# WHEN ADDING A NEW SERIES add the appropriate GCC options below +################################################################# + +# need to specify this for assembler +##################################################################### +# because nanoCLR is loaded the VTOR has to be init in ChibiOS CRT0 +# this define has to be placed here because it's on an assembly file +##################################################################### +set(CMAKE_ASM_FLAGS " -mthumb -mcpu=cortex-m0plus -mfloat-abi=soft -mabi=aapcs -mtune=cortex-m0plus -x assembler-with-cpp -DCRT0_VTOR_INIT=TRUE" CACHE INTERNAL "asm compiler flags") + +# need to specify linker flags here +set(CMAKE_EXE_LINKER_FLAGS " -Wl,--gc-sections -Wl,--no-wchar-size-warning -Wl,--print-memory-usage -mthumb -mcpu=cortex-m0plus -mfloat-abi=soft -mabi=aapcs -mtune=cortex-m0plus -nostartfiles " CACHE INTERNAL "executable linker flags") + + +function(NF_SET_COMPILER_OPTIONS TARGET) + + # include any extra options coming from any extra args? + target_compile_options(${TARGET} PUBLIC ${ARGN} -mthumb -mcpu=cortex-m0plus -mfloat-abi=soft -mabi=aapcs -mtune=cortex-m0plus -nostdlib -Wall -Wextra -Werror -ffunction-sections -fshort-wchar -falign-functions=16 -fdata-sections -fno-builtin -fno-common -fomit-frame-pointer -mlong-calls -fdollars-in-identifiers -fno-exceptions -fno-unroll-loops -frounding-math -fsignaling-nans -ffloat-store -fno-math-errno -ftree-vectorize -fcheck-new ) + + # this series doesn't have FPU + target_compile_definitions(${TARGET} PUBLIC -DCORTEX_USE_FPU=FALSE) + +endfunction() + + +function(NF_SET_LINKER_OPTIONS TARGET) + + # request specs from newlib nano + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --specs=nano.specs ") + + # set extra linker flags + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " ${ARGN}") + + # set optimization linker flags for RELEASE and MinSizeRel + if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-linker-plugin -Os") + endif() + + # set optimization flags + nf_set_optimization_options(${TARGET}) + + # set link map + nf_set_link_map(${TARGET}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_sources.cmake b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_sources.cmake new file mode 100644 index 00000000..fe07cfc4 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/CHIBIOS_STM32L0xx_sources.cmake @@ -0,0 +1,142 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# from startup_stm32l0xx.mk +# List of the ChibiOS generic STM32L0xx startup and CMSIS files. + +################################################################################ +# WHEN ADDING A NEW BOARD add the source code file for the STM32L0xx\platform.mk +################################################################################ + +set(CHIBIOS_PORT_SRCS + # startup code + crt1.c + vectors.S + crt0_v6m.S + + nvic.c + stm32_isr.c + hal_lld.c + + hal_adc_lld.c + hal_can_lld.c + hal_dac_lld.c + stm32_dma.c + stm32_exti.c + hal_pal_lld.c + hal_i2c_lld.c + hal_rtc_lld.c + + hal_i2s_lld.c + hal_spi_lld.c + + hal_st_lld.c + hal_gpt_lld.c + hal_icu_lld.c + hal_pwm_lld.c + + hal_serial_lld.c + hal_uart_lld.c + + hal_usb_lld.c + + hal_wdg_lld.c + + # RT + chcore.c + chcore_v6m.c + chcoreasm_v6m.S +) + +foreach(SRC_FILE ${CHIBIOS_PORT_SRCS}) + set(CHIBIOS_L0_SRC_FILE SRC_FILE-NOTFOUND) + find_file(CHIBIOS_L0_SRC_FILE ${SRC_FILE} + PATHS + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/common/ARMCMx + + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/STM32L0xx + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USBv1 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1 + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${CHIBIOS_L0_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_SOURCES ${CHIBIOS_L0_SRC_FILE}) +endforeach() + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/portability/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/devices/STM32L0xx) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ARM/CMSIS/Core/Include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/ST/STM32L0xx) + +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/ADCv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/CANv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DACv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/DMAv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/EXTIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/GPIOv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/I2Cv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/RTCv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/SPIv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/TIMv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USARTv2) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/USBv1) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/LLD/xWDGv1) + + +#################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the include directory(ies) below +#################################################################################### +# component STM32_FLASH +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3) +# component STM32_CRC +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1) +# component STM32_RNG +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1) +# component STM32_ONEWIRE +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1) + +############################################################################################################################### +# Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding +# following the template below. +# +# list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/) +############################################################################################################################### + + +#################################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the source file(s) specific to this series below +#################################################################################################### +# component STM32_FLASH +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.c) +# component STM32_CRC +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c) +# component STM32_RNG +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c) +# component STM32_ONEWIRE +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c) + +########################################################################################################################## +# Add above ALL the source code file(s) low level driver specif for a series required for a new nanoFramework +# overlay component that you are adding following the template below. +# +# list(APPEND CHIBIOS_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/) +########################################################################################################################## diff --git a/source/native/nf-interpreter/CMake/Modules/FindBuildUtils.cmake b/source/native/nf-interpreter/CMake/Modules/FindBuildUtils.cmake new file mode 100644 index 00000000..6373e03c --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindBuildUtils.cmake @@ -0,0 +1,91 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +function(NF_GENERATE_DFU_PACKAGE FILE1 ADDRESS1 FILE2 ADDRESS2 OUTPUTFILENAME) + + add_custom_command( + + TARGET ${NANOCLR_PROJECT_NAME}.elf POST_BUILD + + COMMAND ${TOOL_HEX2DFU_PREFIX}/hex2dfu + + -b="${FILE1}" -a="${ADDRESS1}" + -b="${FILE2}" -a="${ADDRESS2}" + -o="${OUTPUTFILENAME}" + + WORKING_DIRECTORY ${TOOL_HEX2DFU_PREFIX} + + COMMENT "exporting bin files to DFU image" + ) + + # need to add a dependency of NANOCLR to NANOBOOTER because DFU util needs bin outputs of both targets + add_dependencies(${NANOCLR_PROJECT_NAME}.elf ${NANOBOOTER_PROJECT_NAME}.elf) + +endfunction() + +function(NF_GENERATE_BUILD_OUTPUT_FILES TARGET) + + # need to remove the .elf suffix from target name + string(FIND ${TARGET} "." TARGET_EXTENSION_DOT_INDEX) + string(SUBSTRING ${TARGET} 0 ${TARGET_EXTENSION_DOT_INDEX} TARGET_SHORT) + + set(TARGET_HEX_FILE ${PROJECT_BINARY_DIR}/${TARGET_SHORT}.hex) + set(TARGET_S19_FILE ${PROJECT_BINARY_DIR}/${TARGET_SHORT}.s19) + set(TARGET_BIN_FILE ${PROJECT_BINARY_DIR}/${TARGET_SHORT}.bin) + set(TARGET_DUMP_FILE ${PROJECT_BINARY_DIR}/${TARGET_SHORT}.lst) + + if(CMAKE_BUILD_TYPE EQUAL "Release" OR CMAKE_BUILD_TYPE EQUAL "MinSizeRel") + + add_custom_command(TARGET ${TARGET_SHORT}.elf POST_BUILD + # copy target image to other formats + COMMAND ${CMAKE_OBJCOPY} -Oihex $ ${TARGET_HEX_FILE} + COMMAND ${CMAKE_OBJCOPY} -Osrec $ ${TARGET_S19_FILE} + COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${TARGET_BIN_FILE} + + # copy target file to build folder (this is only usefull for debugging in VS Code because of path in launch.json) + COMMAND ${CMAKE_OBJCOPY} $ ${PROJECT_SOURCE_DIR}/build/${TARGET_SHORT}.elf + + COMMENT "Generate nanoBooter HEX and BIN files for deployment") + + else() + + add_custom_command(TARGET ${TARGET_SHORT}.elf POST_BUILD + # copy target image to other formats + COMMAND ${CMAKE_OBJCOPY} -Oihex $ ${TARGET_HEX_FILE} + COMMAND ${CMAKE_OBJCOPY} -Osrec $ ${TARGET_S19_FILE} + COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${TARGET_BIN_FILE} + + # copy target file to build folder (this is only usefull for debugging in VS Code because of path in launch.json) + COMMAND ${CMAKE_OBJCOPY} $ ${PROJECT_SOURCE_DIR}/build/${TARGET_SHORT}.elf + + # dump target image as source code listing + # ONLY when DEBUG info is available, this is on 'Debug' and 'RelWithDebInfo' + COMMAND ${CMAKE_OBJDUMP} -d -EL -S $ > ${TARGET_DUMP_FILE} + + COMMENT "Generate nanoBooter HEX and BIN files for deployment, LST file for debug") + + endif() + + nf_add_hex_bin_dump_targets(${TARGET}) + + # add this to print the size of the output targets + nf_print_size_of_targets(${TARGET}) + +endfunction() + + +####################################################################################################################################### +# this function sets the linker options AND a specific linker file (full path and name, including extension) +function(NF_SET_LINKER_OPTIONS_AND_FILE TARGET LINKER_FILE_NAME) + + get_target_property(TARGET_LD_FLAGS ${TARGET} LINK_FLAGS) + if(TARGET_LD_FLAGS) + set(TARGET_LD_FLAGS "-T${LINKER_FILE_NAME} ${TARGET_LD_FLAGS}") + else() + set(TARGET_LD_FLAGS "-T${LINKER_FILE_NAME}") + endif() + set_target_properties(${TARGET} PROPERTIES LINK_FLAGS ${TARGET_LD_FLAGS}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS.cmake b/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS.cmake new file mode 100644 index 00000000..41fca7de --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS.cmake @@ -0,0 +1,181 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################################################################################### +# WHEN ADDING A NEW SERIES, add the respective name to the list below along with the CMake files with GCC options and source files +################################################################################################################################### + +# check if the series name is supported + +set(CHIBIOS_STM_SUPPORTED_SERIES "STM32F0xx" "STM32F4xx" "STM32F7xx" "STM32H7xx" "TICC3200" CACHE INTERNAL "supported STM series names for ChibiOS") +set(CHIBIOS_TI_SUPPORTED_SERIES "TICC3200" CACHE INTERNAL "supported TI series names for ChibiOS") + +list(FIND CHIBIOS_STM_SUPPORTED_SERIES ${TARGET_SERIES} TARGET_SERIES_NAME_INDEX) +if(TARGET_SERIES_NAME_INDEX EQUAL -1) + # series is NOT supported by STM + # try TI + list(FIND CHIBIOS_TI_SUPPORTED_SERIES ${TARGET_SERIES} TARGET_SERIES_NAME_INDEX) + if(TARGET_SERIES_NAME_INDEX EQUAL -1) + message(FATAL_ERROR "\n\nSorry but the ${TARGET_SERIES} is not supported at this time...\nYou can wait for it to be added, or you might want to contribute by working on a PR for it.\n\n") + else() + # series is supported by TI + set(TARGET_VENDOR "TI" CACHE INTERNAL "target vendor is TI") + endif() +else() + # series is supported by STM + set(TARGET_VENDOR "STM" CACHE INTERNAL "target vendor is STM") +endif() + +# including here the CMake files for the source files specific to the target series +include(CHIBIOS_${TARGET_SERIES}_sources) +# and here the GCC options tuned for the target series +include(CHIBIOS_${TARGET_SERIES}_GCC_options) + +# message("ChibiOS board series is ${TARGET_SERIES}") # debug helper + +# set include directories for ChibiOS +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/license) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/common/ARMCMx) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/boards/${CHIBIOS_BOARD}) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/osal/rt) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/oslib/include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/rt/include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/ports/STM32/${TARGET_SERIES}) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ports/ARMCMx/compilers/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/abstractions/cmsis_os) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/startup/ARMCMx/compilers/GCC) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/CMSIS/include) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/ext/CMSIS/ST/${TARGET_SERIES}) + +# append dummy include directory when not using ChibiOS-Contrib +if(NOT CHIBIOS_CONTRIB_REQUIRED) + list(APPEND CHIBIOS_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/dummy_includes") +endif() + +# append include directory for boards in the nanoFramework ChibiOS 'overlay' +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/boards/${CHIBIOS_BOARD}) + +# append include directory for boards in the nanoFramework ChibiOS 'overlay' provideded by the community +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets-community/CMSIS-OS/ChibiOS/nf-overlay/os/hal/boards/${CHIBIOS_BOARD}) + +# +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CMSIS/TI/${TARGET_SERIES}) +list(APPEND CHIBIOS_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/startup/ARMCMx/devices/${TARGET_SERIES}) + + +# source files and GCC options according to target vendor and series + +# source files for ChibiOS +set(CHIBIOS_SRCS + # HAL-OSAL files + hal.c + hal_st.c + + hal_buffers.c + hal_queues.c + hal_mmcsd.c + + hal_adc.c + hal_can.c + hal_crypto.c + hal_dac.c + hal_gpt.c + hal_i2c.c + hal_i2s.c + hal_icu.c + hal_mac.c + hal_mmc_spi.c + hal_pal.c + hal_pwm.c + hal_rtc.c + hal_sdc.c + hal_serial.c + hal_serial_usb.c + hal_sio.c + hal_spi.c + hal_trng.c + hal_uart.c + hal_usb.c + hal_wdg.c + hal_wspi.c + + # OSAL RT + osal.c + + # RT + chsys.c + chdebug.c + chtrace.c + chvt.c + chschd.c + chthreads.c + chtm.c + chstats.c + chregistry.c + chsem.c + chmtx.c + chcond.c + chevents.c + chmsg.c + chdynamic.c + + chmboxes.c + chmemcore.c + chmemheaps.c + chmempools.c + chpipes.c + chfactory.c + + # required to use malloc and other newlib stuff + syscalls.c + + # CMSIS + cmsis_os.c + + # board file(s) + board.c + +) + +foreach(SRC_FILE ${CHIBIOS_SRCS}) + set(CHIBIOS_SRC_FILE SRC_FILE -NOTFOUND) + find_file(CHIBIOS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/src + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/osal/rt + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/rt/src + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/oslib/src + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/common/abstractions/cmsis_os + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/various + + # the following hint order is for the board.c file, it has to match the search order of the main CMake otherwise we'll pick one that is the pair + # this path hint is for OEM boards for which the board file(s) are probably located directly in the "target" folder along with remaining files + ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD} + + # this path hint is for the alternative boards folder in the nanoFramework ChibiOS 'overlay' + ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/boards/${CHIBIOS_BOARD} + + # this path hint is for the usual location of the board.c file + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/boards/${CHIBIOS_BOARD} + + # this path hint is for the alternative boards folder in the nanoFramework ChibiOS 'overlay' provideded by the community + ${PROJECT_SOURCE_DIR}/targets-community/CMSIS-OS/ChibiOS/nf-overlay/os/hal/boards/${CHIBIOS_BOARD} + + # this path hint is for Community provided boards that are located directly in the "targets-community" folder + ${PROJECT_SOURCE_DIR}/targets-community/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD} + + CMAKE_FIND_ROOT_PATH_BOTH + ) + #message("${SRC_FILE} >> ${CHIBIOS_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_SOURCES ${CHIBIOS_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(CHIBIOS DEFAULT_MSG CHIBIOS_INCLUDE_DIRS CHIBIOS_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_FATFS.cmake b/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_FATFS.cmake new file mode 100644 index 00000000..1b2ae5e4 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_FATFS.cmake @@ -0,0 +1,64 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xvf ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/fatfs-0.13_patched.7z + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/ +) + + +# List of the required FatFs include files. +list(APPEND CHIBIOS_FATFS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/fatfs/src) + + +set(FATFS_SRCS + # bindings + fatfs_syscall.c + + # fatfs + ff.c + ffunicode.c +) + +foreach(SRC_FILE ${FATFS_SRCS}) + set(FATFS_SRC_FILE SRC_FILE -NOTFOUND) + find_file(FATFS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/various/fatfs_bindings + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/fatfs/src + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${FATFS_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_FATFS_SOURCES ${FATFS_SRC_FILE}) +endforeach() + +# fatfs_diskio is hacked because of USB Host, so we need to use the source from the appropriate location +if(NF_FEATURE_HAS_USB_MSD) + # get it from ChibiOS contribution + list(APPEND CHIBIOS_FATFS_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/various/fatfs_bindings/fatfs_diskio.c) +else() + # get it from standard ChibiOS + list(APPEND CHIBIOS_FATFS_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/various/fatfs_bindings/fatfs_diskio.c) +endif() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(CHIBIOS_FATFS DEFAULT_MSG CHIBIOS_FATFS_INCLUDE_DIRS CHIBIOS_FATFS_SOURCES) + +# setup target to unzip ChibiOS external filesystem components +add_custom_target( CHIBIOS_FILESYSTEM_COMPONENTS ALL ) + +add_custom_command(TARGET CHIBIOS_FILESYSTEM_COMPONENTS +PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E tar xvf ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/fatfs-0.13_patched.7z + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/ + DEPENDS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/fatfs-0.13_patched.7z + + VERBATIM +) + +# this depends on ChibiOS target being already downloaded +add_dependencies(CHIBIOS_FILESYSTEM_COMPONENTS ChibiOS) diff --git a/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_LWIP.cmake b/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_LWIP.cmake new file mode 100644 index 00000000..18c34782 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindCHIBIOS_LWIP.cmake @@ -0,0 +1,233 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# extract LwIP source files +execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xvf ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip-2.0.3-patched.7z + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/ +) + +# List of the required lwIp include files. +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/Lwip) +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/various) +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/various/lwip_bindings) +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/include) +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/include/lwip) +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/include/netif) +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/include/posix) +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/DeviceInterfaces/Networking.Sntp) + +set(LWIP_SRCS + + # sys_arch.c + + # core + init.c + def.c + dns.c + inet_chksum.c + ip.c + mem.c + memp.c + netif.c + pbuf.c + raw.c + stats.c + sys.c + tcp.c + tcp_in.c + tcp_out.c + timeouts.c + udp.c + + # ipv4 + autoip.c + dhcp.c + etharp.c + icmp.c + igmp.c + ip4_frag.c + ip4.c + ip4_addr.c + + # ip6 + dhcp6.c + ethip6.c + icmp6.c + inet6.c + ip6.c + ip6_addr.c + ip6_frag.c + mld6.c + nd6.c + + # api + api_lib.c + # api_msg.c + err.c + netbuf.c + netdb.c + netifapi.c + # sockets.c + tcpip.c + + # api patched files for nanoframework + nf_api_msg.c + nf_sockets.c + nf_sys_arch.c + + # bindings + nf_lwipthread.c + + # platform implementations + platform_sys_arch.c + + #extras + evtimer.c + + # netif + ethernet.c + slipif.c + + # 6LoWPAN + # lowpan6.c + + # PPP + auth.c + ccp.c + chap-md5.c + chap_ms.c + chap-new.c + demand.c + eap.c + ecp.c + eui64.c + fsm.c + ipcp.c + ipv6cp.c + lcp.c + magic.c + mppe.c + multilink.c + ppp.c + pppapi.c + pppcrypt.c + pppoe.c + pppol2tp.c + pppos.c + upap.c + utils.c + vj.c + + # PPP SSL + arc4.c + des.c + md4.c + md5.c + sha1.c + + # APPS! + + # SNMPv2c agent + # snmp_asn1.c + # snmp_core.c + # snmp_mib2.c + # snmp_mib2_icmp.c + # snmp_mib2_interfaces.c + # snmp_mib2_ip.c + # snmp_mib2_snmp.c + # snmp_mib2_system.c + # snmp_mib2_tcp.c + # snmp_mib2_udp.c + # snmp_msg.c + # snmpv3.c + # snmp_netconn.c + # snmp_pbuf_stream.c + # snmp_raw.c + # snmp_scalar.c + # snmp_table.c + # snmp_threadsync.c + # snmp_traps.c + # snmpv3_mbedtls.c + # snmpv3_dummy.c + + # http server + # fs.c + # httpd.c + + # iperf server + # lwiperf.c + + # SNTP client + # this one is added below if NF_NETWORKING_SNTP option is ON + # sntp.c + + # MDNS responder + mdns.c + + # NetBIOS server + # netbiosns.c + + # TFTP server + # tftp_server.c + + # MQTT client + # mqtt.c +) + +if(NF_NETWORKING_SNTP) + list(APPEND LWIP_SRCS sntp.c) +endif() + +foreach(SRC_FILE ${LWIP_SRCS}) + set(LWIP_SRC_FILE SRC_FILE -NOTFOUND) + find_file(LWIP_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/various + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/core + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/core/ipv4 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/core/ipv6 + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/api + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/netif + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/netif/ppp + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/netif/ppp/polarssl + + ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/Lwip + ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/Lwip + + # APPS: + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/snmp + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/httpd + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/lwiperf + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/sntp + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/mdns + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/netbiosns + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/tftp + ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/apps/mqtt + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${LWIP_SRC_FILE}") # debug helper + list(APPEND CHIBIOS_LWIP_SOURCES ${LWIP_SRC_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(CHIBIOS_LWIP DEFAULT_MSG CHIBIOS_LWIP_INCLUDE_DIRS CHIBIOS_LWIP_SOURCES) + +# setup target to unzip ChibiOS external network components +add_custom_target( CHIBIOS_NETWORK_COMPONENTS ALL ) + +add_custom_command(TARGET CHIBIOS_NETWORK_COMPONENTS +PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E tar xvf ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip-2.0.3-patched.7z + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/ + DEPENDS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip-2.0.3-patched.7z + + VERBATIM +) + +# this depends on ChibiOS target being already downloaded +add_dependencies(CHIBIOS_NETWORK_COMPONENTS ChibiOS) diff --git a/source/native/nf-interpreter/CMake/Modules/FindChibiOS-Contrib.cmake b/source/native/nf-interpreter/CMake/Modules/FindChibiOS-Contrib.cmake new file mode 100644 index 00000000..69c5d9ac --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindChibiOS-Contrib.cmake @@ -0,0 +1,46 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories for ChibiOS-Contrib + +# the path is one folder UP from the includes directory to allow a selective inclusion of our own hal_community.h +list(APPEND CHIBIOS_CONTRIB_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/include) + +#################################################################################### +# WHEN ADDING A NEW ChibiOS-Contrib component add the include directory(ies) below +#################################################################################### +# component IMACOMPONENT +#list(APPEND CHIBIOS_CONTRIB_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/include/IMACOMPONENT) + +# USB Host v1 +list(APPEND CHIBIOS_CONTRIB_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/ports/STM32/LLD/USBHv1) + + +#################################################################################################################################### +# Because we've "hacked" ChibiOS overlay mechanism used by the community contributions we can't add the "official" hal_community.c # +# Instead we have to add the required and equivalent calls that exist in the official source file # +# in our hal_community.c @ targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c # +# the include paths are to be added to our hal_community.h @ targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_community.h # +#################################################################################################################################### + + +#################################################################################################### +# WHEN ADDING A NEW ChibiOS-Contrib component add the source file(s) specific to it below +#################################################################################################### +# component IMACOMPONENT +# list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/IMACOMPONENT/source-file-1.c) +# list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/IMACOMPONENT/source-file-2.c) +# list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/IMACOMPONENT/source-file-3.c) + +# USB Host v1 +list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/hal_usbh.c) +list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/usbh/hal_usbh_msd.c) +list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/usbh/hal_usbh_desciter.c) +list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/usbh/hal_usbh_hub.c) +list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/src/hal_usb_msd.c) +list(APPEND CHIBIOS_CONTRIB_SOURCES ${PROJECT_BINARY_DIR}/ChibiOS-Contrib_Source/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(CHIBIOS_CONTRIB DEFAULT_MSG CHIBIOS_CONTRIB_INCLUDE_DIRS CHIBIOS_CONTRIB_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindChibiOSnfOverlay.cmake b/source/native/nf-interpreter/CMake/Modules/FindChibiOSnfOverlay.cmake new file mode 100644 index 00000000..82aabec2 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindChibiOSnfOverlay.cmake @@ -0,0 +1,69 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories for ChibiOS nanoFramework Overlay +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include) + +#################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the include directory(ies) below +#################################################################################### +# component STM32_FLASH +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_flash) +# component STM32_CRC +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_crc) +# component STM32_RNG +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_rng) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc) +# component STM32_ONEWIRE (One Wire driver) +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_onewire) +# component STM32_QSPI (QSPI driver) +list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_qspi) + +################################################################################################################################## +# Add above the required include directory(ies) for a new nanoFramework overlay component that you are adding +# following the template below. +# +# If the component includes a low level driver specific to a series, make sure you add the include dirs +# in the CHIBIOS_NNNNNN_sources.cmake +# +# list(APPEND ChibiOSnfOverlay_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/) +################################################################################################################################## + + +################################################## +# source files for ChibiOS nanoFramework Overlay +################################################## +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c) + +#################################################################################################### +# WHEN ADDING A NEW CHIBIOS OVERLAY component add the source file(s) specific to this series below +#################################################################################################### +# component STM32_FLASH +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_flash/hal_stm32_flash.c) +# component STM32_CRC +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc/hal_stm32_crc.c) +# component STM32_RNG +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng/hal_stm32_rng.c) +# component STM32_FSMC (Flexible Memory Controller) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c) +# component STM32_ONEWIRE (One Wire driver) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_onewire/hal_stm32_onewire.c) +# component STM32_QSPI (QSPI driver) +list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_qspi/hal_stm32_qspi.c) + +######################################################################################################################### +# Add above ALL the source code file(s) required for a new nanoFramework overlay component that you are adding +# following the template below. +# +# If the component includes a low level driver specific to a series, make sure you add the source files +# in the CHIBIOS_NNNNNN_sources.cmake +# +# list(APPEND ChibiOSnfOverlay_SOURCES ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/) +######################################################################################################################### + + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ChibiOSnfOverlay DEFAULT_MSG ChibiOSnfOverlay_INCLUDE_DIRS ChibiOSnfOverlay_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindMBEDOS.cmake b/source/native/nf-interpreter/CMake/Modules/FindMBEDOS.cmake new file mode 100644 index 00000000..65518a6b --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindMBEDOS.cmake @@ -0,0 +1,389 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +include(JSONParser) + +# read mBed targets file +file(READ "${PROJECT_BINARY_DIR}/mBedOS_Source/targets/targets.json" TARGETS_JSON) + +# try to find target +string(FIND ${TARGETS_JSON} ${MBED_TARGET} FOUND_TARGET) + +# message(STATUS "${MBED_TARGET} @ ${FOUND_TARGET}") + +if(${FOUND_TARGET} GREATER -1) + # target found + + message(STATUS "mBed target '${MBED_TARGET}' found") + # get substring with data + math(EXPR FOUND_TARGET "${FOUND_TARGET} - 1") + + # because there is not an elegant way of finding the end of the json section of this target we are setting this to 1000 chars + # the downside is that for most target this overuns to the next target + string(SUBSTRING "${TARGETS_JSON}" ${FOUND_TARGET} 2000 TARGET_TENTATIVE_JSON) +else() + message(FATAL_ERROR "\n\nSorry but ${MBED_TARGET} seems to be missing in the list of the mBed supported targets...\n\n") +endif() + +# parse target data +sbeParseJson(MBED_TARGET_DATA TARGET_TENTATIVE_JSON) + +# try to extract relevant data +foreach(var ${MBED_TARGET_DATA}) + + # sanity check when json parse has overun to the next target + string(FIND ${var} "MBED_TARGET_DATA.${MBED_TARGET}" MBED_TARGET_NAME_FOUND) + if(MBED_TARGET_NAME_FOUND GREATER -1) + + # seems to belong to target, extract data + #message("${var} : ${${var}}") # debug helper + + # core + string(FIND ${var} "core" MBED_TARGET_CORE_INDEX) + if(${MBED_TARGET_CORE_INDEX} GREATER -1) + set(MBED_TARGET_CORE ${${var}}) + endif() + + # extra labels 0 is: target vendor + string(FIND ${var} "MBED_TARGET_DATA.${MBED_TARGET}.extra_labels_0" MBED_TARGET_VENDOR_INDEX) + if(${MBED_TARGET_VENDOR_INDEX} GREATER -1) + set(MBED_TARGET_VENDOR ${${var}}) + endif() + + # extra labels 1 is: target series/variant + string(FIND ${var} "MBED_TARGET_DATA.${MBED_TARGET}.extra_labels_1" MBED_TARGET_SERIES_INDEX) + if(${MBED_TARGET_SERIES_INDEX} GREATER -1) + set(MBED_TARGET_SERIES ${${var}}) + endif() + + # extra labels 2 is used for compiler defs + string(FIND ${var} "MBED_TARGET_DATA.${MBED_TARGET}.extra_labels_2" MBED_TARGET_EXTRA_LABEL2_INDEX) + if(${MBED_TARGET_EXTRA_LABEL2_INDEX} GREATER -1) + set(MBED_TARGET_EXTRA_LABEL2 ${${var}}) + endif() + + # 'macros' lists target aditional macros + string(FIND ${var} "MBED_TARGET_DATA.${MBED_TARGET}.macros_" MBED_TARGET_MACROS_INDEX) + if(${MBED_TARGET_MACROS_INDEX} GREATER -1) + list(APPEND MBED_TARGET_MACROS ${${var}}) + endif() + + # 'device has' lists target features + string(FIND ${var} "MBED_TARGET_DATA.${MBED_TARGET}.device_has_" MBED_TARGET_DEVICE_HAS_INDEX) + if(${MBED_TARGET_DEVICE_HAS_INDEX} GREATER -1) + list(APPEND MBED_TARGET_FEATURES ${${var}}) + endif() + + # 'supported form factors' lists supported form factors for board + string(FIND ${var} "MBED_TARGET_DATA.${MBED_TARGET}.supported_form_factors_" MBED_TARGET_DEVICE_FORM_FACTORS_INDEX) + if(${MBED_TARGET_DEVICE_FORM_FACTORS_INDEX} GREATER -1) + list(APPEND MBED_TARGET_DEVICE_FORM_FACTORS ${${var}}) + endif() + + endif() + +endforeach() + +message("mBed target has ${MBED_TARGET_CORE}") +message("mBed target vendor is ${MBED_TARGET_VENDOR}") +message("mBed target series is ${MBED_TARGET_SERIES}") +#message("mBed target features: ${MBED_TARGET_FEATURES}") + +# get target core short name +string(REPLACE "Cortex-" "" MBED_TARGET_CORE_SHORT ${MBED_TARGET_CORE} ) + +# set compiler options (general) +string(APPEND MBEDOS_COMPILE_OPTIONS "-D__CORTEX_${MBED_TARGET_CORE_SHORT} -D__MBED__=1 -DTARGET_LIKE_MBED -D__MBED_CMSIS_RTOS_CM -DTOOLCHAIN_object -D__CMSIS_RTOS -DTOOLCHAIN_GCC -DTARGET_CORTEX_M -DARM_MATH_C${MBED_TARGET_CORE_SHORT} -DTARGET_${MBED_TARGET_CORE_SHORT} -DTOOLCHAIN_GCC_ARM -DTARGET_RELEASE -DTARGET_LIKE_CORTEX_${MBED_TARGET_CORE_SHORT} -D__CORTEX_${MBED_TARGET_CORE_SHORT} -DTARGET_${MBED_TARGET_VENDOR} -DTARGET_${MBED_TARGET_SERIES} -DTARGET_UVISOR_UNSUPPORTED -DTARGET_${MBED_TARGET}") + +# extra compiler def from extra label 2 +if(MBED_TARGET_EXTRA_LABEL2) + string(APPEND MBEDOS_COMPILE_OPTIONS " -DTARGET_${MBED_TARGET_EXTRA_LABEL2}") +endif() + +# set compiler options (target specific features) +foreach(feature ${MBED_TARGET_FEATURES}) + string(APPEND MBEDOS_COMPILE_OPTIONS " -DDEVICE_${feature}=1") +endforeach() + +# set compiler options (form factors) +foreach(ff ${MBED_TARGET_DEVICE_FORM_FACTORS}) + string(APPEND MBEDOS_COMPILE_OPTIONS " -DTARGET_FF_${ff}") +endforeach() + +# set compiler options (macros) +foreach(macro ${MBED_TARGET_MACROS}) + string(APPEND MBEDOS_COMPILE_OPTIONS " -D${macro}") +endforeach() + +#message(">>MBEDOS_COMPILE_OPTIONS: ${MBEDOS_COMPILE_OPTIONS}<<") # debug helper + +# set include directories for mBed RTOS +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/cmsis) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/cmsis/TOOLCHAIN_GCC) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/docs) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/drivers) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/events) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/events/equeue) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/greentea-client) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/greentea-client/greentea-client) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/greentea-client/source) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/unity) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/unity/source) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/unity/unity) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/utest) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/utest/source) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/utest/utest) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/importer) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/inc) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/inc/mbedtls) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/platform) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/platform/inc) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/platform/src) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/src) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/nanostack) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/netsocket) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/features/storage) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/hal) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/hal/storage_abstraction) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/platform) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx/TARGET_CORTEX_M) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx/TARGET_CORTEX_M/TARGET_${MBED_TARGET_CORE_SHORT}) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx/TARGET_CORTEX_M/TARGET_${MBED_TARGET_CORE_SHORT}/TOOLCHAIN_GCC) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/targets) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/device) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET}) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET}/device) +list(APPEND MBEDOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET}/device/TOOLCHAIN_GCC_ARM) + +# source files and GCC options according to target vendor and series +if("${MBED_TARGET_VENDOR}" STREQUAL "STM") + include(MBED_${MBED_TARGET_SERIES}_sources) + include(MBED_${MBED_TARGET_SERIES}_GCC_options) +endif() + +# source files for RTOS +set(MBEDRTOS_SRCS + # drivers + AnalogIn.cpp + BusIn.cpp + BusInOut.cpp + BusOut.cpp + CAN.cpp + Ethernet.cpp + FileBase.cpp + FileLike.cpp + FilePath.cpp + FileSystemLike.cpp + I2C.cpp + I2CSlave.cpp + InterruptIn.cpp + InterruptManager.cpp + LocalFileSystem.cpp + RawSerial.cpp + SPI.cpp + SPISlave.cpp + Serial.cpp + SerialBase.cpp + Stream.cpp + Ticker.cpp + Timeout.cpp + Timer.cpp + TimerEvent.cpp + + # events + EventQueue.cpp + equeue.c + equeue_mbed.cpp + equeue_posix.c + + # features + greentea_metrics.cpp + greentea_serial.cpp + test_env.cpp + unity.c + mbed-utest-shim.cpp + unity_handler.cpp + utest_case.cpp + utest_default_handlers.cpp + utest_greentea_handlers.cpp + utest_harness.cpp + utest_shim.cpp + utest_stack_trace.cpp + utest_types.cpp + + # mbed tls + mbed_trng.c + aes.c + aesni.c + arc4.c + asn1parse.c + asn1write.c + base64.c + bignum.c + blowfish.c + camellia.c + ccm.c + certs.c + cipher.c + cipher_wrap.c + cmac.c + ctr_drbg.c + debug.c + des.c + dhm.c + ecdh.c + ecdsa.c + ecjpake.c + ecp.c + ecp_curves.c + entropy.c + entropy_poll.c + error.c + gcm.c + havege.c + hmac_drbg.c + md.c + md2.c + md4.c + md5.c + md_wrap.c + memory_buffer_alloc.c + net_sockets.c + oid.c + padlock.c + pem.c + pk.c + pk_wrap.c + pkcs11.c + pkcs12.c + pkcs5.c + pkparse.c + pkwrite.c + platform.c + ripemd160.c + rsa.c + sha1.c + sha256.c + sha512.c + ssl_cache.c + ssl_ciphersuites.c + ssl_cli.c + ssl_cookie.c + ssl_srv.c + ssl_ticket.c + ssl_tls.c + threading.c + timing.c + version.c + version_features.c + x509.c + x509_create.c + x509_crl.c + x509_crt.c + x509_csr.c + x509write_crt.c + x509write_csr.c + xtea.c + + # net socket + NetworkInterface.cpp + NetworkStack.cpp + Socket.cpp + SocketAddress.cpp + TCPServer.cpp + TCPSocket.cpp + UDPSocket.cpp + WiFiAccessPoint.cpp + nsapi_dns.cpp + + # mBed HAL + mbed_gpio.c + mbed_lp_ticker_api.c + mbed_pinmap_common.c + mbed_ticker_api.c + mbed_us_ticker_api.c + + # mBed platfom + CallChain.cpp + mbed_alloc_wrappers.cpp + mbed_assert.c + mbed_board.c + mbed_critical.c + mbed_error.c + mbed_interface.c + mbed_mem_trace.c + mbed_rtc_time.cpp + mbed_semihost_api.c + mbed_stats.c + mbed_wait_api_no_rtos.c + mbed_wait_api_rtos.cpp + retarget.cpp + + # RTOS + Mutex.cpp + RtosTimer.cpp + Semaphore.cpp + Thread.cpp + rtos_idle.c + HAL_CM.c + RTX_Conf_CM.c + rt_CMSIS.c + rt_Event.c + rt_List.c + rt_Mailbox.c + rt_MemBox.c + rt_Memory.c + rt_Mutex.c + rt_OsEventObserver.c + rt_Robin.c + rt_Semaphore.c + rt_System.c + rt_Task.c + rt_Time.c + rt_Timer.c +) + +foreach(SRC_FILE ${MBEDRTOS_SRCS}) + set(MBEDOS_SRC_FILE SRC_FILE-NOTFOUND) + find_file(MBEDOS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/mBedOS_Source/drivers + ${PROJECT_BINARY_DIR}/mBedOS_Source/events + ${PROJECT_BINARY_DIR}/mBedOS_Source/events/equeue + ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/greentea-client/source + ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/unity/source + ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/utest + ${PROJECT_BINARY_DIR}/mBedOS_Source/features/frameworks/utest/source + + ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/platform/src + ${PROJECT_BINARY_DIR}/mBedOS_Source/features/mbedtls/src + ${PROJECT_BINARY_DIR}/mBedOS_Source/features/netsocket + + ${PROJECT_BINARY_DIR}/mBedOS_Source/hal + + ${PROJECT_BINARY_DIR}/mBedOS_Source/platform + + ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos + ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx + ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx/TARGET_CORTEX_M + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${MBEDOS_SRC_FILE}") # debug helper + list(APPEND MBEDOS_SOURCES ${MBEDOS_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDOS DEFAULT_MSG MBEDOS_INCLUDE_DIRS MBEDOS_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindNF_CoreCLR.cmake b/source/native/nf-interpreter/CMake/Modules/FindNF_CoreCLR.cmake new file mode 100644 index 00000000..76cae905 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindNF_CoreCLR.cmake @@ -0,0 +1,256 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories for nanoFramework Core, CoreLib and CLR startup + +# include directories for Core +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) + +# include directories for CoreLib +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/CorLib) + +# CLR startup +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Startup) + +# others +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Diagnostics) +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Debugger) +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Helpers/TinyPrintf) +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Helpers/Base64) +list(APPEND NF_CoreCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/nanoFramework.Runtime.Native) + +# source files for nanoFramework Core, CoreLib and CLR startup +set(NF_CoreCLR_SRCS + + # Core + Cache.cpp + Checks.cpp + CLR_RT_DblLinkedList.cpp + CLR_RT_HeapBlock.cpp + CLR_RT_HeapBlock_Array.cpp + CLR_RT_HeapBlock_ArrayList.cpp + CLR_RT_HeapBlock_BinaryBlob.cpp + CLR_RT_HeapBlock_Delegate.cpp + CLR_RT_HeapBlock_Delegate_List.cpp + CLR_RT_HeapBlock_Finalizer.cpp + CLR_RT_HeapBlock_Lock.cpp + CLR_RT_HeapBlock_LockRequest.cpp + CLR_RT_HeapBlock_Node.cpp + CLR_RT_HeapBlock_String.cpp + CLR_RT_HeapBlock_Timer.cpp + CLR_RT_HeapBlock_WaitForObject.cpp + CLR_RT_HeapCluster.cpp + CLR_RT_Interop.cpp + CLR_RT_Memory.cpp + CLR_RT_ObjectToEvent_Destination.cpp + CLR_RT_ObjectToEvent_Source.cpp + CLR_RT_RuntimeMemory.cpp + CLR_RT_StackFrame.cpp + CLR_RT_SystemAssembliesTable.cpp + CLR_RT_UnicodeHelper.cpp + Core.cpp + Execution.cpp + GarbageCollector.cpp + GarbageCollector_Compaction.cpp + GarbageCollector_ComputeReachabilityGraph.cpp + GarbageCollector_Info.cpp + Interpreter.cpp + Random.cpp + Streams.cpp + StringTable.cpp + Thread.cpp + TypeSystemLookup.cpp + StringTableData.cpp + TypeSystem.cpp + nanoSupport_CRC32.c + nanoHAL_SystemInformation.cpp + # Various.cpp + + # CoreLib + corlib_native_System_AppDomain.cpp + corlib_native_System_Array.cpp + corlib_native_System_Attribute.cpp + corlib_native_System_BitConverter.cpp + corlib_native_System_Collections_ArrayList.cpp + corlib_native_System_Console.cpp + corlib_native_System_Convert.cpp + corlib_native_System_DateTime.cpp + corlib_native_System_Delegate.cpp + corlib_native_System_Diagnostics_Debugger.cpp + corlib_native_System_Double.cpp + corlib_native_System_Enum.cpp + corlib_native_System_Exception.cpp + corlib_native_System_GC.cpp + corlib_native_System_Globalization_CultureInfo.cpp + corlib_native_System_Globalization_DateTimeFormat.cpp + corlib_native_System_Guid.cpp + corlib_native_System_MarshalByRefObject.cpp + corlib_native_System_MathInternal.cpp + corlib_native_System_MulticastDelegate.cpp + corlib_native_System_Number.cpp + corlib_native_System_Object.cpp + corlib_native_System_Random.cpp + corlib_native_System_Reflection_Binder.cpp + corlib_native_System_Reflection_MemberInfo.cpp + corlib_native_System_Runtime_CompilerServices_RuntimeHelpers.cpp + corlib_native_System_Runtime_Remoting_RemotingServices.cpp + corlib_native_System_String.cpp + corlib_native_System_Text_UTF8Decoder.cpp + corlib_native_System_Text_UTF8Encoding.cpp + corlib_native_System_Threading_AutoResetEvent.cpp + corlib_native_System_Threading_Interlocked.cpp + corlib_native_System_Threading_ManualResetEvent.cpp + corlib_native_System_Threading_Monitor.cpp + corlib_native_System_Threading_Thread.cpp + corlib_native_System_Threading_Timer.cpp + corlib_native_System_Threading_WaitHandle.cpp + corlib_native_System_TimeSpan.cpp + corlib_native_System_ValueType.cpp + corlib_native_System_WeakReference.cpp + corlib_native.cpp + + # CLR startup + CLRStartup.cpp + + # Messaging + Messaging.cpp + + # Runtime.Native + nf_rt_native.cpp + nf_rt_native_nanoFramework_Runtime_Hardware_SystemInfo.cpp + nf_rt_native_nanoFramework_Runtime_Native_Debug.cpp + nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint.cpp + nf_rt_native_nanoFramework_Runtime_Native_Power.cpp + nf_rt_native_nanoFramework_Runtime_Native_Rtc_stubs.cpp + + # Core stubs + Hardware_stub.cpp + InterruptHandler_stub.cpp + NativeEventDispatcher_stub.cpp + RPC_stub.cpp + BinaryFormatter_stub.cpp + + # CLR stubs + Debugger_stub.cpp + Diagnostics_stub.cpp + Messaging_stub.cpp + + # Helpers + printf.c + + # HAL + nanoHAL_Time.cpp + nanoHAL_Watchdog.c + + # PAL + nanoPAL_BlockStorage.c + nanoPAL_NativeDouble.cpp + nanoPAL_Network_stubs.cpp + nanoPAL_PerformanceCounters_stubs.cpp + + # PAL stubs + Async_stubs.cpp + COM_stubs.c + GenericPort_stubs.c + + # target specifics + target_BlockStorage.c +) + +# include System.Reflection API files depending on build option +if(NF_FEATURE_SUPPORT_REFLECTION) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Reflection_Assembly.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Reflection_ConstructorInfo.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Reflection_FieldInfo.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Reflection_MethodBase.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Reflection_PropertyInfo.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Reflection_RuntimeFieldInfo.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Reflection_RuntimeMethodInfo.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_RuntimeType.cpp) + list(APPEND NF_CoreCLR_SRCS corlib_native_System_Type.cpp) +endif() + +# include Collection support files depending on build option +if(API_nanoFramework.System.Collections) + list(APPEND NF_CoreCLR_SRCS CLR_RT_HeapBlock_Queue.cpp) + list(APPEND NF_CoreCLR_SRCS CLR_RT_HeapBlock_Stack.cpp) +endif() + +# need a conditional include because of ESP32 building network as a library +if(NOT USE_SECURITY_MBEDTLS_OPTION) + list(APPEND NF_CoreCLR_SRCS base64.c) +endif() + +# include configuration manager file +if(NF_FEATURE_HAS_CONFIG_BLOCK) + # feature enabled, full support + list(APPEND NF_CoreCLR_SRCS nanoHAL_ConfigurationManager.c) +else() + # feature disabled, stubs only + list(APPEND NF_CoreCLR_SRCS nanoHAL_ConfigurationManager_stubs.c) +endif() + +foreach(SRC_FILE ${NF_CoreCLR_SRCS}) + set(NF_CoreCLR_SRC_FILE SRC_FILE-NOTFOUND) + find_file(NF_CoreCLR_SRC_FILE ${SRC_FILE} + PATHS + + # Core + ${PROJECT_SOURCE_DIR}/src/CLR/Core + + # CoreLib + ${PROJECT_SOURCE_DIR}/src/CLR/CorLib + + # CLR startup + ${PROJECT_SOURCE_DIR}/src/CLR/Startup + + # Runtime.Native + ${PROJECT_SOURCE_DIR}/src/nanoFramework.Runtime.Native + + # Core stubs + ${PROJECT_SOURCE_DIR}/src/CLR/Core/Hardware + ${PROJECT_SOURCE_DIR}/src/CLR/Core/InterruptHandler + ${PROJECT_SOURCE_DIR}/src/CLR/Core/NativeEventDispatcher + ${PROJECT_SOURCE_DIR}/src/CLR/Core/RPC + ${PROJECT_SOURCE_DIR}/src/CLR/Core/Serialization + + # CLR stubs + ${PROJECT_SOURCE_DIR}/src/CLR/Debugger + ${PROJECT_SOURCE_DIR}/src/CLR/Diagnostics + ${PROJECT_SOURCE_DIR}/src/CLR/Messaging + + # Helpers + ${PROJECT_SOURCE_DIR}/src/CLR/Helpers/TinyPrintf + ${PROJECT_SOURCE_DIR}/src/CLR/Helpers/Base64 + + # HAL + ${PROJECT_SOURCE_DIR}/src/HAL + + # PAL + ${PROJECT_SOURCE_DIR}/src/PAL + ${PROJECT_SOURCE_DIR}/src/PAL/BlockStorage + ${PROJECT_SOURCE_DIR}/src/PAL/Double + + # PAL stubs + ${PROJECT_SOURCE_DIR}/src/PAL/AsyncProcCall + ${PROJECT_SOURCE_DIR}/src/PAL/COM + ${PROJECT_SOURCE_DIR}/src/PAL/Profiler + + # target + "${TARGET_BASE_LOCATION}" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${NF_CoreCLR_SRC_FILE}") # debug helper + list(APPEND NF_CoreCLR_SOURCES ${NF_CoreCLR_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NF_CoreCLR DEFAULT_MSG NF_CoreCLR_INCLUDE_DIRS NF_CoreCLR_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindNF_Debugger.cmake b/source/native/nf-interpreter/CMake/Modules/FindNF_Debugger.cmake new file mode 100644 index 00000000..84655de4 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindNF_Debugger.cmake @@ -0,0 +1,53 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories for nanoFramework Debugger +list(APPEND NF_Debugger_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Debugger) +list(APPEND NF_Debugger_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Messaging) +list(APPEND NF_Debugger_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/WireProtocol) +list(APPEND NF_Debugger_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) + +# source files for nanoFramework Debugger +set(NF_Debugger_SRCS + + Debugger.cpp + + Messaging.cpp + + WireProtocol_Message.c + WireProtocol_MonitorCommands.c + WireProtocol_HAL_Interface.c + WireProtocol_App_Interface.c + + nanoSupport_CRC32.c +) + +# add the debugger source file according to the build flavor +if(NF_BUILD_RTM) + set(NF_Debugger_SRCS ${NF_Debugger_SRCS} Debugger_minimal.cpp) +else() + set(NF_Debugger_SRCS ${NF_Debugger_SRCS} Debugger_full.cpp) +endif() + + +foreach(SRC_FILE ${NF_Debugger_SRCS}) + set(NF_Debugger_SRC_FILE SRC_FILE-NOTFOUND) + find_file(NF_Debugger_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_SOURCE_DIR}/src/CLR/Debugger + ${PROJECT_SOURCE_DIR}/src/CLR/Messaging + ${PROJECT_SOURCE_DIR}/src/CLR/WireProtocol + ${PROJECT_SOURCE_DIR}/src/CLR/Core + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${NF_Debugger_SRC_FILE}") # debug helper + list(APPEND NF_Debugger_SOURCES ${NF_Debugger_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NF_Debugger DEFAULT_MSG NF_Debugger_INCLUDE_DIRS NF_Debugger_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindNF_Diagnostics.cmake b/source/native/nf-interpreter/CMake/Modules/FindNF_Diagnostics.cmake new file mode 100644 index 00000000..a5b68c76 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindNF_Diagnostics.cmake @@ -0,0 +1,33 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories +list(APPEND NF_Diagnostics_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Diagnostics) +list(APPEND NF_Diagnostics_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) + +# source files +set(NF_Diagnostics_SRCS + + Info.cpp + Profile.cpp + Profiler.cpp +) + +foreach(SRC_FILE ${NF_Diagnostics_SRCS}) + set(NF_Diagnostics_SRC_FILE SRC_FILE-NOTFOUND) + find_file(NF_Diagnostics_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_SOURCE_DIR}/src/CLR/Diagnostics + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${NF_Diagnostics_SRC_FILE}") # debug helper + list(APPEND NF_Diagnostics_SOURCES ${NF_Diagnostics_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NF_Diagnostics DEFAULT_MSG NF_Diagnostics_INCLUDE_DIRS NF_Diagnostics_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindNF_Networking.cmake b/source/native/nf-interpreter/CMake/Modules/FindNF_Networking.cmake new file mode 100644 index 00000000..281b6aa8 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindNF_Networking.cmake @@ -0,0 +1,107 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories for nanoFramework network +list(APPEND NF_Networking_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Com/sockets) +list(APPEND NF_Networking_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Com/sockets/ssl) +list(APPEND NF_Networking_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Lwip) +list(APPEND NF_Networking_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/DeviceInterfaces/Networking.Sntp) + +if(USE_SECURITY_MBEDTLS_OPTION) + list(APPEND NF_Networking_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Com/sockets/ssl/mbedTLS) +endif() + +# source files for nanoFramework Networking +set(NF_Networking_SRCS + + #pal Socket + sockets_lwip.cpp + + #Lwip + LwIP_Sockets.cpp + LwIP_Sockets_functions.cpp + +) + +# need a conditional include because of ESP32 building network as a library +if(NOT USE_SECURITY_MBEDTLS_OPTION) + list(APPEND NF_Networking_SRCS ssl_stubs.cpp) +endif() + +# source files for security layer +set(NF_Networking_Security_SRCS + + ssl.cpp + ssl_accept_internal.cpp + ssl_add_cert_auth_internal.cpp + ssl_close_socket_internal.cpp + ssl_connect_internal.cpp + ssl_decode_private_key_internal.cpp + ssl_exit_context_internal.cpp + ssl_generic.cpp + ssl_generic_init_internal.cpp + ssl_initialize_internal.cpp + ssl_parse_certificate_internal.cpp + ssl_pending_internal.cpp + ssl_read_internal.cpp + ssl_uninitialize_internal.cpp + ssl_write_internal.cpp + +) + + +if(NF_FEATURE_DEBUGGER) + list(APPEND NF_Networking_SRCS sockets_debugger.cpp) +endif() + +# add source files in two steps +# 1st pass: common source files +foreach(SRC_FILE ${NF_Networking_SRCS}) + set(NF_Networking_SRC_FILE SRC_FILE-NOTFOUND) + find_file(NF_Networking_SRC_FILE ${SRC_FILE} + PATHS + + ${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets + ${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl + + ${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS + + ${PROJECT_SOURCE_DIR}/src/PAL/Lwip + ${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES} + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${NF_Networking_SRC_FILE}") # debug helper + list(APPEND NF_Networking_SOURCES ${NF_Networking_SRC_FILE}) +endforeach() + +if(USE_SECURITY_MBEDTLS_OPTION) + set(NF_Security_Search_Path "${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS") +endif() + +if(USE_SECURITY_MBEDTLS_OPTION) + + # 2nd pass: security files if option is selected + foreach(SRC_FILE ${NF_Networking_Security_SRCS}) + set(NF_Networking_SRC_FILE SRC_FILE-NOTFOUND) + find_file(NF_Networking_SRC_FILE ${SRC_FILE} + PATHS + + ${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl + ${NF_Security_Search_Path} + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${NF_Networking_SRC_FILE}") # debug helper + list(APPEND NF_Networking_SOURCES ${NF_Networking_SRC_FILE}) + endforeach() + +endif() + + +include(FindPackageHandleStandardArgs) + + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NF_Networking DEFAULT_MSG NF_Networking_INCLUDE_DIRS NF_Networking_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindRTXRTOS.cmake b/source/native/nf-interpreter/CMake/Modules/FindRTXRTOS.cmake new file mode 100644 index 00000000..c36076bb --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindRTXRTOS.cmake @@ -0,0 +1,99 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +if(NOT STM32_CHIP_TYPE) + STM32_GET_CHIP_TYPE(${TARGET_CHIP} STM32_CHIP_TYPE) + if(NOT STM32_CHIP_TYPE) + message(FATAL_ERROR "Unknown chip: ${TARGET_CHIP}.") + endif() + message(STATUS "${TARGET_CHIP} is ${STM32_CHIP_TYPE} device") +endif() +string(TOLOWER ${STM32_CHIP_TYPE} STM32_CHIP_TYPE_LOWER) + + +# build path hints according to device series +if(STM32_SERIES STREQUAL "F0") + set(RTXRTOS_HAL_NAME HAL_CM0.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M0) +elseif(STM32_SERIES STREQUAL "F1") + set(RTXRTOS_HAL_NAME HAL_CM0.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M0) +elseif(STM32_SERIES STREQUAL "F2") + set(RTXRTOS_HAL_NAME HAL_CM0.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M0) +elseif(STM32_SERIES STREQUAL "F3") + set(RTXRTOS_HAL_NAME HAL_CM3.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M3) +elseif(STM32_SERIES STREQUAL "F4") + set(RTXRTOS_HAL_NAME HAL_CM4.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M4) +elseif(STM32_SERIES STREQUAL "F7") + set(RTXRTOS_HAL_NAME HAL_CM4.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M7) +elseif(STM32_SERIES STREQUAL "L0") + set(RTXRTOS_HAL_NAME HAL_CM0.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M0) +elseif(STM32_SERIES STREQUAL "L1") + set(RTXRTOS_HAL_NAME HAL_CM0.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M0) +elseif(STM32_SERIES STREQUAL "L4") + set(RTXRTOS_HAL_NAME HAL_CM4.S) + set(RTXRTOS_COMPILE_OPTIONS -D__CORTEX_M4) +endif() + +# set include directories for RXT RTOS +list(APPEND RTXRTOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS/RTX/INC) +list(APPEND RTXRTOS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS/RTX/SRC) + +set(RTXRTOS_SRCS + Mutex.cpp + RtosTimer.cpp + Semaphore.cpp + Thread.cpp + + HAL_CM.c + rt_CMSIS.c + rt_Event.c + rt_List.c + rt_Mailbox.c + rt_MemBox.c + rt_Memory.c + rt_Mutex.c + rt_Robin.c + rt_Semaphore.c + rt_System.c + rt_Task.c + rt_Time.c + rt_Timer.c +) + +foreach(SRC_FILE ${RTXRTOS_SRCS}) + set(RTXRTOS_SRC_FILE SRC_FILE-NOTFOUND) + find_file(RTXRTOS_SRC_FILE ${SRC_FILE} + PATHS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS/RTX/SRC ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS/Template/CPP + CMAKE_FIND_ROOT_PATH_BOTH + ) + list(APPEND RTXRTOS_SOURCES ${RTXRTOS_SRC_FILE}) +endforeach() + +# find path for HAL_CMx file +set(RTXRTOS_SRC_FILE SRC_FILE-NOTFOUND) +find_file(RTXRTOS_SRC_FILE ${RTXRTOS_HAL_NAME} + PATHS PATHS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS/RTX/SRC/GCC + CMAKE_FIND_ROOT_PATH_BOTH +) +list(APPEND RTXRTOS_SOURCES ${RTXRTOS_SRC_FILE}) + +# find path for SVC_Table file +set(RTXRTOS_SRC_FILE SRC_FILE-NOTFOUND) +find_file(RTXRTOS_SRC_FILE SVC_Table.S + PATHS PATHS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS/RTX/SRC/GCC + CMAKE_FIND_ROOT_PATH_BOTH +) +list(APPEND RTXRTOS_SOURCES ${RTXRTOS_SRC_FILE}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(RTXRTOS DEFAULT_MSG RTXRTOS_INCLUDE_DIRS RTXRTOS_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindRTXRTOS2.cmake b/source/native/nf-interpreter/CMake/Modules/FindRTXRTOS2.cmake new file mode 100644 index 00000000..cc3342ae --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindRTXRTOS2.cmake @@ -0,0 +1,112 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +if(NOT STM32_CHIP_TYPE) + STM32_GET_CHIP_TYPE(${TARGET_CHIP} STM32_CHIP_TYPE) + if(NOT STM32_CHIP_TYPE) + message(FATAL_ERROR "Unknown chip: ${TARGET_CHIP}.") + endif() + message(STATUS "${TARGET_CHIP} is ${STM32_CHIP_TYPE} device") +endif() +string(TOLOWER ${STM32_CHIP_TYPE} STM32_CHIP_TYPE_LOWER) + + +# build path hints according to device series +if(STM32_SERIES STREQUAL "F0") + set(RTXRTOS2_HAL_NAME irq_cm0.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M0 -DCMSIS_device_header=ARMCM0.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM0/Include) +elseif(STM32_SERIES STREQUAL "F1") + set(RTXRTOS2_HAL_NAME irq_cm0.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M0 -DCMSIS_device_header=ARMCM0.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM0/Include) +elseif(STM32_SERIES STREQUAL "F2") + set(RTXRTOS2_HAL_NAME irq_cm0.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M0 -DCMSIS_device_header=ARMCM0.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM0/Include) +elseif(STM32_SERIES STREQUAL "F3") + set(RTXRTOS2_HAL_NAME irq_cm3.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M3 -DCMSIS_device_header=ARMCM3.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM3/Include) +elseif(STM32_SERIES STREQUAL "F4") + set(RTXRTOS2_HAL_NAME irq_cm4f.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M4 -DCMSIS_device_header=ARMCM4.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM4/Include) +elseif(STM32_SERIES STREQUAL "F7") + set(RTXRTOS2_HAL_NAME irq_cm4f.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M7 -DCMSIS_device_header=ARMCM7.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM7/Include) +elseif(STM32_SERIES STREQUAL "L0") + set(RTXRTOS2_HAL_NAME irq_cm0.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M0 -DCMSIS_device_header=ARMCM0.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM0/Include) +elseif(STM32_SERIES STREQUAL "L1") + set(RTXRTOS2_HAL_NAME irq_cm0.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M0 -DCMSIS_device_header=ARMCM0.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM0/Include) +elseif(STM32_SERIES STREQUAL "L4") + set(RTXRTOS2_HAL_NAME irq_cm4f.S) + set(RTXRTOS2_COMPILE_OPTIONS -D__CORTEX_M4 -DCMSIS_device_header=ARMCM4.h) + list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/Device/ARM/ARMCM0/Include) +endif() + +# set include directories for RXT RTOS +list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/Core/Include) +list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS2/Include) +list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS2/RTX/Include) +list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS2/RTX/Include1) +list(APPEND RTXRTOS2_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS2/RTX/Source) + +set(RTXRTOS2_SRCS + Events.c + MemPool.c + MsgQueue.c + Mutex.c + Semaphore.c + Thread.c + Timer.c + + rtx_delay.c + rtx_evflags.c + rtx_kernel.c + rtx_memory.c + rtx_mempool.c + rtx_msgqueue.c + rtx_mutex.c + rtx_semaphore.c + rtx_system.c + rtx_thread.c + rtx_timer.c + user_svc.c +) + +foreach(SRC_FILE ${RTXRTOS2_SRCS}) + set(RTXRTOS2_SRC_FILE SRC_FILE-NOTFOUND) + find_file(RTXRTOS2_SRC_FILE ${SRC_FILE} + PATHS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS2/RTX/Source ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS2/RTX/Template + CMAKE_FIND_ROOT_PATH_BOTH + ) + list(APPEND RTXRTOS2_SOURCES ${RTXRTOS2_SRC_FILE}) +endforeach() + +# find path for HAL_CMx file +set(RTXRTOS2_SRC_FILE SRC_FILE-NOTFOUND) +find_file(RTXRTOS2_SRC_FILE ${RTXRTOS2_HAL_NAME} + PATHS PATHS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS2/RTX/Source/GCC + CMAKE_FIND_ROOT_PATH_BOTH +) +list(APPEND RTXRTOS2_SOURCES ${RTXRTOS2_SRC_FILE}) + +# # find path for SVC_Table file +# set(RTXRTOS2_SRC_FILE SRC_FILE-NOTFOUND) +# find_file(RTXRTOS2_SRC_FILE SVC_Table.S +# PATHS PATHS ${PROJECT_BINARY_DIR}/RTXRTOS_Source/CMSIS/RTOS/RTX/SRC/GCC +# CMAKE_FIND_ROOT_PATH_BOTH +# ) +# list(APPEND RTXRTOS2_SOURCES ${RTXRTOS2_SRC_FILE}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(RTXRTOS2 DEFAULT_MSG RTXRTOS2_INCLUDE_DIRS RTXRTOS2_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSPIFFS.cmake b/source/native/nf-interpreter/CMake/Modules/FindSPIFFS.cmake new file mode 100644 index 00000000..d3a13b9e --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSPIFFS.cmake @@ -0,0 +1,40 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# List of the required include paths +list(APPEND SPIFFS_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/SPIFFS_Source/src) + +set(src_spiffs + + spiffs_nucleus.c + spiffs_gc.c + spiffs_hydrogen.c + spiffs_cache.c + spiffs_check.c + + # HAL implementation specific to a platform + # has to be included at platform level + # hal_spiffs.c + + target_spiffs.c +) + +foreach(SRC_FILE ${src_spiffs}) + set(SPIFFS_SRC_FILE SRC_FILE -NOTFOUND) + find_file(SPIFFS_SRC_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/SPIFFS_Source/src" + "${TARGET_BASE_LOCATION}" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${SPIFFS_SRC_FILE}") # debug helper + list(APPEND SPIFFS_SOURCES ${SPIFFS_SRC_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SPIFFS DEFAULT_MSG SPIFFS_INCLUDE_DIRS SPIFFS_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSTM32F0_CubePackage.cmake b/source/native/nf-interpreter/CMake/Modules/FindSTM32F0_CubePackage.cmake new file mode 100644 index 00000000..75939aa2 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSTM32F0_CubePackage.cmake @@ -0,0 +1,31 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories +list(APPEND STM32F0_CubePackage_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/STM32F0_CubePackage_Source/Drivers/STM32F0xx_HAL_Driver/Inc") + +# source files +set(STM32F0_CubePackage_SRCS + + # add HAL files here as required +) + +foreach(SRC_FILE ${STM32F0_CubePackage_SRCS}) + set(STM32F0_CubePackage_SRC_FILE SRC_FILE-NOTFOUND) + find_file(STM32F0_CubePackage_SRC_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/STM32F0_CubePackage_Source/Drivers/STM32F0xx_HAL_Driver/Src" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${STM32F0_CubePackage_SRC_FILE}") # debug helper + list(APPEND STM32F0_CubePackage_SOURCES ${STM32F0_CubePackage_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(STM32F0_CubePackage DEFAULT_MSG STM32F0_CubePackage_INCLUDE_DIRS STM32F0_CubePackage_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSTM32F4_CubePackage.cmake b/source/native/nf-interpreter/CMake/Modules/FindSTM32F4_CubePackage.cmake new file mode 100644 index 00000000..557c94f4 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSTM32F4_CubePackage.cmake @@ -0,0 +1,35 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories +list(APPEND STM32F4_CubePackage_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/STM32F4_CubePackage_Source/Drivers/STM32F4xx_HAL_Driver/Inc") + +# source files +set(STM32F4_CubePackage_SRCS + + # add HAL files here as required + + # SPIFFS + stm32f4xx_hal_dma.c + stm32f4xx_hal_qspi.c +) + +foreach(SRC_FILE ${STM32F4_CubePackage_SRCS}) + set(STM32F4_CubePackage_SRC_FILE SRC_FILE-NOTFOUND) + find_file(STM32F4_CubePackage_SRC_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/STM32F4_CubePackage_Source/Drivers/STM32F4xx_HAL_Driver/Src" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${STM32F4_CubePackage_SRC_FILE}") # debug helper + list(APPEND STM32F4_CubePackage_SOURCES ${STM32F4_CubePackage_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(STM32F4_CubePackage DEFAULT_MSG STM32F4_CubePackage_INCLUDE_DIRS STM32F4_CubePackage_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSTM32F7_CubePackage.cmake b/source/native/nf-interpreter/CMake/Modules/FindSTM32F7_CubePackage.cmake new file mode 100644 index 00000000..c5fb281c --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSTM32F7_CubePackage.cmake @@ -0,0 +1,34 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories +list(APPEND STM32F7_CubePackage_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/STM32F7_CubePackage_Source/Drivers/STM32F7xx_HAL_Driver/Inc") + +# source files +set(STM32F7_CubePackage_SRCS + + # add HAL files here as required + + # SPIFFS + stm32f7xx_hal_dma.c + stm32f7xx_hal_qspi.c +) + +foreach(SRC_FILE ${STM32F7_CubePackage_SRCS}) + set(STM32F7_CubePackage_SRC_FILE SRC_FILE-NOTFOUND) + find_file(STM32F7_CubePackage_SRC_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/STM32F7_CubePackage_Source/Drivers/STM32F7xx_HAL_Driver/Src/" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${STM32F7_CubePackage_SRC_FILE}") # debug helper + list(APPEND STM32F7_CubePackage_SOURCES ${STM32F7_CubePackage_SRC_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(STM32F7_CubePackage DEFAULT_MSG STM32F7_CubePackage_INCLUDE_DIRS STM32F7_CubePackage_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSTM32FREERTOS.cmake b/source/native/nf-interpreter/CMake/Modules/FindSTM32FREERTOS.cmake new file mode 100644 index 00000000..8b557481 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSTM32FREERTOS.cmake @@ -0,0 +1,115 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +if(NOT STM32_CHIP_TYPE) + STM32_GET_CHIP_TYPE(${TARGET_CHIP} STM32_CHIP_TYPE) + if(NOT STM32_CHIP_TYPE) + message(FATAL_ERROR "Unknown chip: ${TARGET_CHIP}.") + endif() + message(STATUS "${TARGET_CHIP} is ${STM32_CHIP_TYPE} device") +endif() +string(TOLOWER ${STM32_CHIP_TYPE} STM32_CHIP_TYPE_LOWER) + +# find path of STM32 CMSIS FreeRTOS port for include files +find_path(STM32CMSISFREERTOS_INCLUDE_DIR cmsis_os.h + PATH_SUFFIXES CMSIS_RTOS + HINTS ${STM32Cube_DIR}/Middlewares/Third_Party/FreeRTOS/Source + CMAKE_FIND_ROOT_PATH_BOTH +) + +# set path search for FreeRTOS distribution +set(FREERTOS_HEADERS + croutine.h + deprecated_definitions.h + event_groups.h + FreeRTOS.h + list.h + mpu_prototypes.h + mpu_wrappers.h + portable.h + projdefs.h + queue.h + semphr.h + StackMacros.h + task.h + timers.h +) + +# build path hints according to device series +if(STM32_SERIES STREQUAL "F0") + set(FREERTOS_PATH_SUFFIXES ARM_CM0) +elseif(STM32_SERIES STREQUAL "F1") + set(FREERTOS_PATH_SUFFIXES ARM_CM0) +elseif(STM32_SERIES STREQUAL "F2") + set(FREERTOS_PATH_SUFFIXES ARM_CM0) +elseif(STM32_SERIES STREQUAL "F3") + set(FREERTOS_PATH_SUFFIXES ARM_CM3) +elseif(STM32_SERIES STREQUAL "F4") + set(FREERTOS_PATH_SUFFIXES ARM_CM4F) +elseif(STM32_SERIES STREQUAL "F7") + set(FREERTOS_PATH_SUFFIXES ARM_CM7) +elseif(STM32_SERIES STREQUAL "L0") + set(FREERTOS_PATH_SUFFIXES ARM_CM0) +elseif(STM32_SERIES STREQUAL "L1") + set(FREERTOS_PATH_SUFFIXES ARM_CM0) +elseif(STM32_SERIES STREQUAL "L4") + set(FREERTOS_PATH_SUFFIXES ARM_CM4F) +endif() + +find_path(FREERTOS_INCLUDE_DIR ${FREERTOS_HEADERS} + PATH_SUFFIXES FreeRTOS_Source Include + PATHS ${PROJECT_BINARY_DIR}/FreeRTOS_Source + CMAKE_FIND_ROOT_PATH_BOTH +) + +find_path(FREERTOS_PORTABLE_INCLUDE_DIR portmacro.h + PATHS ${PROJECT_BINARY_DIR}/FreeRTOS_Source/portable/GCC/${FREERTOS_PATH_SUFFIXES} + CMAKE_FIND_ROOT_PATH_BOTH +) + +set(STM32FREERTOS_INCLUDE_DIR + ${STM32CMSISFREERTOS_INCLUDE_DIR} + ${FREERTOS_INCLUDE_DIR} + ${FREERTOS_PORTABLE_INCLUDE_DIR} +) + +set(SRC_FILE_FOUND SRC_FILE-NOTFOUND) +find_file(SRC_FILE_FOUND cmsis_os.c + #PATH_SUFFIXES CMSIS_RTOS + PATHS ${STM32Cube_DIR}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS + CMAKE_FIND_ROOT_PATH_BOTH +) +list(APPEND STM32FREERTOS_SOURCES ${SRC_FILE_FOUND}) + +set(FREERTOS_SOURCES + croutine.c + event_groups.c + list.c + queue.c + tasks.c + timers.c + port.c + + # choose here the appropriate memory management for FreeRTOS (see http://www.freertos.org/a00111.html) + # heap_1.c + # heap_2.c + # heap_3.c + heap_4.c + #heap_5.c +) + +foreach(SRC_FILE ${FREERTOS_SOURCES}) + set(FREERTOS_SRC_FILE SRC_FILE-NOTFOUND) + find_file(FREERTOS_SRC_FILE ${SRC_FILE} + PATH_SUFFIXES FreeRTOS_Source Include ${FREERTOS_PATH_SUFFIXES} + PATHS ${PROJECT_BINARY_DIR} ${PROJECT_BINARY_DIR}/FreeRTOS_Source/portable/MemMang ${PROJECT_BINARY_DIR}/FreeRTOS_Source/portable/GCC + CMAKE_FIND_ROOT_PATH_BOTH + ) + list(APPEND STM32FREERTOS_SOURCES ${FREERTOS_SRC_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(STM32FREERTOS DEFAULT_MSG STM32FREERTOS_INCLUDE_DIR STM32FREERTOS_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSTM32H7_CubePackage.cmake b/source/native/nf-interpreter/CMake/Modules/FindSTM32H7_CubePackage.cmake new file mode 100644 index 00000000..1f0cb07d --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSTM32H7_CubePackage.cmake @@ -0,0 +1,34 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories +list(APPEND STM32H7_CubePackage_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/STM32H7_CubePackage_Source/Drivers/STM32H7xx_HAL_Driver/Inc") + +# source files +set(STM32H7_CubePackage_SRCS + + # add HAL files here as required + + # SPIFFS + stm32h7xx_hal_qspi.c +) + +foreach(SRC_FILE ${STM32H7_CubePackage_SRCS}) + set(STM32H7_CubePackage_SRC_FILE SRC_FILE-NOTFOUND) + find_file(STM32H7_CubePackage_SRC_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/STM32H7_CubePackage_Source/Drivers/STM32H7xx_HAL_Driver/Src" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${STM32H7_CubePackage_SRC_FILE}") # debug helper + list(APPEND STM32H7_CubePackage_SOURCES ${STM32H7_CubePackage_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(STM32H7_CubePackage DEFAULT_MSG STM32H7_CubePackage_INCLUDE_DIRS STM32H7_CubePackage_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSTM32L0_CubePackage.cmake b/source/native/nf-interpreter/CMake/Modules/FindSTM32L0_CubePackage.cmake new file mode 100644 index 00000000..e126f65f --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSTM32L0_CubePackage.cmake @@ -0,0 +1,31 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories +list(APPEND STM32L0_CubePackage_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/STM32L0_CubePackage_Source/Drivers/STM32L0xx_HAL_Driver/Inc") + +# source files +set(STM32_CubePackage_SRCS + + # add HAL files here as required +) + +foreach(SRC_FILE ${STM32L0_CubePackage_SRCS}) + set(STM32L0_CubePackage_SRC_FILE SRC_FILE-NOTFOUND) + find_file(STM32L0_CubePackage_SRC_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/STM32L0_CubePackage_Source/Drivers/STM32L0xx_HAL_Driver/Src" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${STM32L0_CubePackage_SRC_FILE}") # debug helper + list(APPEND STM32L0_CubePackage_SOURCES ${STM32L0_CubePackage_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(STM32L0_CubePackage DEFAULT_MSG STM32L0_CubePackage_INCLUDE_DIRS STM32L0_CubePackage_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSystem.Devices.Dac.cmake b/source/native/nf-interpreter/CMake/Modules/FindSystem.Devices.Dac.cmake new file mode 100644 index 00000000..94b36889 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSystem.Devices.Dac.cmake @@ -0,0 +1,46 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/System.Devices.Dac") + + +# set include directories +list(APPEND System.Devices.Dac_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND System.Devices.Dac_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND System.Devices.Dac_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND System.Devices.Dac_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND System.Devices.Dac_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND System.Devices.Dac_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/System.Devices.Dac) + + +# source files +set(System.Devices.Dac_SRCS + + sys_dev_dac_native.cpp + sys_dev_dac_native_System_Devices_Dac_DacController.cpp + sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp + + target_system_devices_dac_config.cpp +) + +foreach(SRC_FILE ${System.Devices.Dac_SRCS}) + set(System.Devices.Dac_SRC_FILE SRC_FILE-NOTFOUND) + find_file(System.Devices.Dac_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_SOURCE_DIR}/src/System.Devices.Dac + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${System.Devices.Dac_SRC_FILE}") # debug helper + list(APPEND System.Devices.Dac_SOURCES ${System.Devices.Dac_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(System.Devices.Dac DEFAULT_MSG System.Devices.Dac_INCLUDE_DIRS System.Devices.Dac_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSystem.Math.cmake b/source/native/nf-interpreter/CMake/Modules/FindSystem.Math.cmake new file mode 100644 index 00000000..e211bf2b --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSystem.Math.cmake @@ -0,0 +1,38 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${PROJECT_SOURCE_DIR}/src/CLR/System.Math") + + +# set include directories +list(APPEND System.Math_INCLUDE_DIRS "${BASE_PATH_FOR_THIS_MODULE}") + + +# source files +set(System.Math_SRCS + + nf_native_system_math.cpp + nf_native_system_math_System_Math.cpp + +) + +foreach(SRC_FILE ${System.Math_SRCS}) + set(System.Math_SRC_FILE SRC_FILE-NOTFOUND) + find_file(System.Math_SRC_FILE ${SRC_FILE} + PATHS + "${BASE_PATH_FOR_THIS_MODULE}" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${System.Math_SRC_FILE}") # debug helper + list(APPEND System.Math_SOURCES ${System.Math_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(System.Math DEFAULT_MSG System.Math_INCLUDE_DIRS System.Math_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindSystem.Net.cmake b/source/native/nf-interpreter/CMake/Modules/FindSystem.Net.cmake new file mode 100644 index 00000000..3f8f444f --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindSystem.Net.cmake @@ -0,0 +1,47 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set include directories +list(APPEND System.Net_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/HAL/Include") +list(APPEND System.Net_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/DeviceInterfaces/System.Net") + +# source files +set(System.Net_SRCS + + # System.Net + sys_net_native.cpp + sys_net_native_System_Net_Sockets_NativeSocket.cpp + + # System.Net.NetworkInformation + sys_net_native_System_Net_NetworkInformation_NetworkInterface.cpp + sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration.cpp + sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration.cpp + + # System.Security.Cryptography.X509Certificates + sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate.cpp + sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2.cpp + + # System.Net.Security + sys_net_native_System_Net_Security_SslNative.cpp + sys_net_native_System_Net_Security_CertificateManager.cpp + +) + +foreach(SRC_FILE ${System.Net_SRCS}) + set(System.Net_SRC_FILE SRC_FILE-NOTFOUND) + find_file(System.Net_SRC_FILE ${SRC_FILE} + PATHS + + "${PROJECT_SOURCE_DIR}/src/DeviceInterfaces/System.Net" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${System.Net_SRC_FILE}") # debug helper + list(APPEND System.Net_SOURCES ${System.Net_SRC_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(System.Net DEFAULT_MSG System.Net_INCLUDE_DIRS System.Net_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindTI_SimpleLink.cmake b/source/native/nf-interpreter/CMake/Modules/FindTI_SimpleLink.cmake new file mode 100644 index 00000000..9c76d4ee --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindTI_SimpleLink.cmake @@ -0,0 +1,95 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################################################################################### +# WHEN ADDING A NEW series add the respective name to the list below along with the CMake files with GCC options and source files +################################################################################################################################### + +# check if the series name is supported + +set(TI_SIMPLELINK_SUPPORTED_SERIES "CC32xx" CACHE INTERNAL "supported TI series names") + +list(FIND TI_SIMPLELINK_SUPPORTED_SERIES ${TARGET_SERIES} TARGET_SERIES_NAME_INDEX) +if(TI_SIMPLELINK_SUPPORTED_SERIES EQUAL -1) + if(TARGET_SERIES_NAME_INDEX EQUAL -1) + message(FATAL_ERROR "\n\nSorry but the ${TARGET_SERIES} is not supported at this time...\nYou can wait for it to be added, or you might want to contribute by working on a PR for it.\n\n") + else() + # series is supported by TI + set(TARGET_VENDOR "TI" CACHE INTERNAL "target vendor is TI") + endif() +endif() + +# including here the CMake files for the source files specific to the target series +include(TI_SimpleLink_${TARGET_SERIES}_sources) + +# and here the GCC options tuned for the target series +include(TI_SimpleLink_${TARGET_SERIES}_GCC_options) + +# includes for FreeRTOS +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/FreeRTOS_Source/lib/include") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/FreeRTOS_Source/lib/include/private") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/FreeRTOS_Source/lib/FreeRTOS/portable/GCC/ARM_CM3") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${TARGET_BASE_LOCATION}") + +# source files for FreeRTOS +set(FreeRTOS_SRCS + + # FreeRTOS + event_groups.c + list.c + queue.c + stream_buffer.c + tasks.c + timers.c + port.c + heap_4.c + clock.c + memory.c + mqueue.c + pthread_barrier.c + pthread_cond.c + pthread.c + pthread_mutex.c + pthread_rwlock.c + sched.c + semaphore.c + sleep.c + timer.c + PTLS.c + aeabi_portable.c + ClockP_freertos.c + DebugP_freertos.c + MutexP_freertos.c + SemaphoreP_freertos.c + SystemP_freertos.c + HwiPCC32XX_freertos.c + PowerCC32XX_freertos.c + startup_cc32xx_gcc.c + +) + +foreach(SRC_FILE ${FreeRTOS_SRCS}) + set(FreeRTOS_SCR_FILE SRC_FILE -NOTFOUND) + find_file(FreeRTOS_SCR_FILE ${SRC_FILE} + PATHS + + # FreeRTOS + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/posix/freertos" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/source" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/kernel/freertos/dpl" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/kernel/freertos/startup" + "${PROJECT_BINARY_DIR}/FreeRTOS_Source/lib/FreeRTOS/portable/MemMang" + "${PROJECT_BINARY_DIR}/FreeRTOS_Source/lib/FreeRTOS/portable/GCC/ARM_CM3" + "${PROJECT_BINARY_DIR}/FreeRTOS_Source/lib/FreeRTOS" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${FreeRTOS_SCR_FILE}") # debug helper + list(APPEND TI_SimpleLink_SOURCES ${FreeRTOS_SCR_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(TI_SimpleLink DEFAULT_MSG TI_SimpleLink_INCLUDE_DIRS TI_SimpleLink_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Adc.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Adc.cmake new file mode 100644 index 00000000..70d6479a --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Adc.cmake @@ -0,0 +1,46 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Devices.Adc") + + +# set include directories +list(APPEND Windows.Devices.Adc_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND Windows.Devices.Adc_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND Windows.Devices.Adc_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND Windows.Devices.Adc_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND Windows.Devices.Adc_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Devices.Adc_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Adc) + + +# source files +set(Windows.Devices.Adc_SRCS + + win_dev_adc_native.cpp + win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp + win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp + + target_windows_devices_adc_config.cpp +) + +foreach(SRC_FILE ${Windows.Devices.Adc_SRCS}) + set(Windows.Devices.Adc_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Devices.Adc_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Adc + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Devices.Adc_SRC_FILE}") # debug helper + list(APPEND Windows.Devices.Adc_SOURCES ${Windows.Devices.Adc_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Devices.Adc DEFAULT_MSG Windows.Devices.Adc_INCLUDE_DIRS Windows.Devices.Adc_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Gpio.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Gpio.cmake new file mode 100644 index 00000000..7cda082a --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Gpio.cmake @@ -0,0 +1,60 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Devices.Gpio") + + +# set include directories +list(APPEND Windows.Devices.Gpio_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND Windows.Devices.Gpio_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND Windows.Devices.Gpio_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND Windows.Devices.Gpio_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND Windows.Devices.Gpio_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Devices.Gpio_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Gpio) + + +# source files +set(Windows.Devices.Gpio_SRCS + + # class library source files + win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp + win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp + win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp + win_dev_gpio_native.cpp + + # core source files + AsyncCompletions.cpp + AsyncContinuations.cpp + NativeEventDispatcher.cpp + InterruptHandler.cpp + Hardware.cpp +) + +foreach(SRC_FILE ${Windows.Devices.Gpio_SRCS}) + set(Windows.Devices.Gpio_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Devices.Gpio_SRC_FILE ${SRC_FILE} + PATHS + + # class library source files + ${BASE_PATH_FOR_THIS_MODULE} + + # core source files + ${PROJECT_SOURCE_DIR}/src/PAL/AsyncProcCall + ${PROJECT_SOURCE_DIR}/src/CLR/Core/NativeEventDispatcher + ${PROJECT_SOURCE_DIR}/src/CLR/Core/InterruptHandler + ${PROJECT_SOURCE_DIR}/src/CLR/Core/Hardware + ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Gpio + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Devices.Gpio_SRC_FILE}") # debug helper + list(APPEND Windows.Devices.Gpio_SOURCES ${Windows.Devices.Gpio_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Devices.Gpio DEFAULT_MSG Windows.Devices.Gpio_INCLUDE_DIRS Windows.Devices.Gpio_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.I2c.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.I2c.cmake new file mode 100644 index 00000000..ea9f242c --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.I2c.cmake @@ -0,0 +1,46 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Devices.I2c") + + +# set include directories +list(APPEND Windows.Devices.I2c_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND Windows.Devices.I2c_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND Windows.Devices.I2c_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND Windows.Devices.I2c_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND Windows.Devices.I2c_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Devices.I2c_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Devices.I2c) + + +# source files +set(Windows.Devices.I2c_SRCS + + win_dev_i2c_native.cpp + win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp + win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp + + target_windows_devices_i2c_config.cpp +) + +foreach(SRC_FILE ${Windows.Devices.I2c_SRCS}) + set(Windows.Devices.I2c_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Devices.I2c_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_SOURCE_DIR}/src/Windows.Devices.I2c + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Devices.I2c_SRC_FILE}") # debug helper + list(APPEND Windows.Devices.I2c_SOURCES ${Windows.Devices.I2c_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Devices.I2c DEFAULT_MSG Windows.Devices.I2c_INCLUDE_DIRS Windows.Devices.I2c_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Pwm.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Pwm.cmake new file mode 100644 index 00000000..3dbc6351 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Pwm.cmake @@ -0,0 +1,43 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Devices.Pwm") + + +# set include directories +list(APPEND Windows.Devices.Pwm_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND Windows.Devices.Pwm_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND Windows.Devices.Pwm_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND Windows.Devices.Pwm_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND Windows.Devices.Pwm_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Devices.Pwm_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Pwm) + + +# source files +set(Windows.Devices.Pwm_SRCS + + win_dev_pwm_native.cpp + win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp + win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp +) + +foreach(SRC_FILE ${Windows.Devices.Pwm_SRCS}) + set(Windows.Devices.Pwm_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Devices.Pwm_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Pwm + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Devices.Pwm_SRC_FILE}") # debug helper + list(APPEND Windows.Devices.Pwm_SOURCES ${Windows.Devices.Pwm_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Devices.Pwm DEFAULT_MSG Windows.Devices.Pwm_INCLUDE_DIRS Windows.Devices.Pwm_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.SerialCommunication.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.SerialCommunication.cmake new file mode 100644 index 00000000..5c3baf41 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.SerialCommunication.cmake @@ -0,0 +1,42 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Devices.SerialCommunication") + + +# set include directories +list(APPEND Windows.Devices.SerialCommunication_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Devices.SerialCommunication_INCLUDE_DIRS ${TARGET_BASE_LOCATION}) +list(APPEND Windows.Devices.SerialCommunication_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Devices.SerialCommunication) + + +# source files +set(Windows.Devices.SerialCommunication_SRCS + + win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp + win_dev_serial_native.cpp + + target_windows_devices_serialcommunication_config.cpp +) + +foreach(SRC_FILE ${Windows.Devices.SerialCommunication_SRCS}) + set(Windows.Devices.SerialCommunication_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Devices.SerialCommunication_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_SOURCE_DIR}/src/Windows.Devices.SerialCommunication + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Devices.SerialCommunication_SRC_FILE}") # debug helper + list(APPEND Windows.Devices.SerialCommunication_SOURCES ${Windows.Devices.SerialCommunication_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Devices.SerialCommunication DEFAULT_MSG Windows.Devices.SerialCommunication_INCLUDE_DIRS Windows.Devices.SerialCommunication_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Spi.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Spi.cmake new file mode 100644 index 00000000..ec3f708f --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.Spi.cmake @@ -0,0 +1,47 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Devices.Spi") + + +# set include directories +list(APPEND Windows.Devices.Spi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND Windows.Devices.Spi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND Windows.Devices.Spi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND Windows.Devices.Spi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND Windows.Devices.Spi_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Devices.Spi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Spi) + + +# source files +set(Windows.Devices.Spi_SRCS + + win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp + win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp + win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp + win_dev_spi_native.cpp + + target_windows_devices_spi_config.cpp +) + +foreach(SRC_FILE ${Windows.Devices.Spi_SRCS}) + set(Windows.Devices.Spi_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Devices.Spi_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Spi + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Devices.Spi_SRC_FILE}") # debug helper + list(APPEND Windows.Devices.Spi_SOURCES ${Windows.Devices.Spi_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Devices.Spi DEFAULT_MSG Windows.Devices.Spi_INCLUDE_DIRS Windows.Devices.Spi_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.WiFi.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.WiFi.cmake new file mode 100644 index 00000000..e1221581 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Devices.WiFi.cmake @@ -0,0 +1,42 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Devices.Wifi") + + +# set include directories +list(APPEND Windows.Devices.Wifi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND Windows.Devices.Wifi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND Windows.Devices.Wifi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND Windows.Devices.Wifi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND Windows.Devices.Wifi_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Devices.Wifi_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Wifi) + + +# source files +set(Windows.Devices.Wifi_SRCS + + win_dev_wifi_native.cpp + win_dev_wifi_native_Windows_Devices_WIFI_WifiAdapter.cpp +) + +foreach(SRC_FILE ${Windows.Devices.Wifi_SRCS}) + set(Windows.Devices.Wifi_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Devices.Wifi_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${PROJECT_SOURCE_DIR}/src/Windows.Devices.Wifi + + CMAKE_FIND_ROOT_PATH_BOTH + ) + #message("${SRC_FILE} >> ${Windows.Devices.Wifi_SRC_FILE}") # debug helper + list(APPEND Windows.Devices.Wifi_SOURCES ${Windows.Devices.Wifi_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Devices.Wifi DEFAULT_MSG Windows.Devices.Wifi_INCLUDE_DIRS Windows.Devices.Wifi_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Networking.Sockets.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Networking.Sockets.cmake new file mode 100644 index 00000000..a54b830f --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Networking.Sockets.cmake @@ -0,0 +1,45 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +#set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Networking.Sockets") +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/System.Net") + + +# set include directories +list(APPEND Windows.Networking.Sockets_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) +list(APPEND Windows.Networking.Sockets_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) +list(APPEND Windows.Networking.Sockets_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include) +list(APPEND Windows.Networking.Sockets_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) +list(APPEND Windows.Networking.Sockets_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Networking.Sockets_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Networking.Sockets) + + +# source files +set(Windows.Networking.Sockets_SRCS + +# win_net_sockets_native.cpp +# win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp + sys_net_native.cpp + sys_net_native_System_Net_Sockets_NativeSocket.cpp +) + +foreach(SRC_FILE ${Windows.Networking.Sockets_SRCS}) + set(Windows.Networking.Sockets_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Networking.Sockets_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${PROJECT_SOURCE_DIR}/src/Windows.Networking.Sockets + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Networking.Sockets_SRC_FILE}") # debug helper + list(APPEND Windows.Networking.Sockets_SOURCES ${Windows.Networking.Sockets_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Networking.Sockets DEFAULT_MSG Windows.Networking.Sockets_INCLUDE_DIRS Windows.Networking.Sockets_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWindows.Storage.cmake b/source/native/nf-interpreter/CMake/Modules/FindWindows.Storage.cmake new file mode 100644 index 00000000..2577f5e7 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWindows.Storage.cmake @@ -0,0 +1,52 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/Windows.Storage") + + +# set include directories +if(RTOS_CHIBIOS_CHECK) + list(APPEND Windows.Storage_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/fatfs/src) + set( PROJECT_COMMON_PATH ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/common) +endif() + +list(APPEND Windows.Storage_INCLUDE_DIRS ${TARGET_BASE_LOCATION}/Include) +list(APPEND Windows.Storage_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND Windows.Storage_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/Windows.Storage) + + +# source files +set(Windows.Storage_SRCS + + win_storage_native_Windows_Storage_FileIO.cpp + win_storage_native_Windows_Storage_StorageFile.cpp + win_storage_native_Windows_Storage_StorageFolder.cpp + win_storage_native_Windows_Storage_Devices_SDCard.cpp + win_storage_native.cpp + + Target_Windows_Storage.c +) + +foreach(SRC_FILE ${Windows.Storage_SRCS}) + set(Windows.Storage_SRC_FILE SRC_FILE-NOTFOUND) + find_file(Windows.Storage_SRC_FILE ${SRC_FILE} + PATHS + + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_COMMON_PATH} + ${PROJECT_SOURCE_DIR}/src/Windows.Storage + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${Windows.Storage_SRC_FILE}") # debug helper + list(APPEND Windows.Storage_SOURCES ${Windows.Storage_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Windows.Storage DEFAULT_MSG Windows.Storage_INCLUDE_DIRS Windows.Storage_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindWireProtocol.cmake b/source/native/nf-interpreter/CMake/Modules/FindWireProtocol.cmake new file mode 100644 index 00000000..4ab68c8c --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindWireProtocol.cmake @@ -0,0 +1,71 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# handle Wire Protocol _TRACE_ preferences, if any +option(NF_WP_TRACE_ERRORS "option to Trace errors with Wire Protocol") +option(NF_WP_TRACE_HEADERS "option to Trace headers with Wire Protocol") +option(NF_WP_TRACE_STATE "option to Trace state with Wire Protocol") +option(NF_WP_TRACE_NODATA "option to Trace empty packets with Wire Protocol") +option(NF_WP_TRACE_ALL "option to Trace with Wire Protocol") +option(NF_WP_IMPLEMENTS_CRC32 "option to report if target implements CRC32 in Wire Protocol") + +# this one has to follow the declaration on src\CLR\Include\WireProtocol_Message.h +# #define TRACE_ERRORS 1 +# #define TRACE_HEADERS 2 +# #define TRACE_STATE 4 +# #define TRACE_NODATA 8 + +# default to 0 (no Wire Protocol trace) +set(WP_TRACE_MASK 0 CACHE INTERNAL "WP trace mask") + +if(NF_WP_TRACE_ERRORS) + math(EXPR WP_TRACE_MASK "${WP_TRACE_MASK} + 1") +endif() +if(NF_WP_TRACE_HEADERS) + math(EXPR WP_TRACE_MASK "${WP_TRACE_MASK} + 2") +endif() +if(NF_WP_TRACE_STATE) + math(EXPR WP_TRACE_MASK "${WP_TRACE_MASK} + 4") +endif() +if(NF_WP_TRACE_NODATA) + math(EXPR WP_TRACE_MASK "${WP_TRACE_MASK} + 8") +endif() +if(NF_WP_TRACE_ALL) + math(EXPR WP_TRACE_MASK "8 + 4 + 2 + 1") +endif() + +message(STATUS "Wire Protocol TRACE_MASK is '${WP_TRACE_MASK}'") # debug helper + +# set include directories for Wire Protocol +list(APPEND WireProtocol_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include) + +# source files for Wire Protocol +set(WireProtocol_SRCS + + WireProtocol_Message.c + WireProtocol_MonitorCommands.c + WireProtocol_HAL_Interface.c + WireProtocol_App_Interface.c + + nanoSupport_CRC32.c +) + +foreach(SRC_FILE ${WireProtocol_SRCS}) + set(WireProtocol_SRC_FILE SRC_FILE-NOTFOUND) + find_file(WireProtocol_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_SOURCE_DIR}/src/CLR/WireProtocol + ${PROJECT_SOURCE_DIR}/src/CLR/Core + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${WireProtocol_SRC_FILE}") # debug helper + list(APPEND WireProtocol_SOURCES ${WireProtocol_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(WireProtocol DEFAULT_MSG WireProtocol_INCLUDE_DIRS WireProtocol_SOURCES) \ No newline at end of file diff --git a/source/native/nf-interpreter/CMake/Modules/FindmbedTLS.cmake b/source/native/nf-interpreter/CMake/Modules/FindmbedTLS.cmake new file mode 100644 index 00000000..52149f83 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindmbedTLS.cmake @@ -0,0 +1,157 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# because of issues when passing the config file as a string when using ExternalProject_Add with mbedTLS +# we are replicating their CMakeList here. Actually this is more a simplified version... + +# List of the required include paths +list(APPEND mbedTLS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/mbedTLS_Source/include/) + +option(USE_PKCS11_HELPER_LIBRARY "Build mbed TLS with the pkcs11-helper library." OFF) +option(ENABLE_ZLIB_SUPPORT "Build mbed TLS with zlib library." OFF) + +if(ENABLE_ZLIB_SUPPORT) + find_package(ZLIB) + + if(ZLIB_FOUND) + include_directories(${ZLIB_INCLUDE_DIR}) + endif(ZLIB_FOUND) +endif(ENABLE_ZLIB_SUPPORT) + +# add_subdirectory(library) +# add_subdirectory(include) + +set(src_crypto + aes.c + aesni.c + arc4.c + aria.c + asn1parse.c + asn1write.c + base64.c + bignum.c + blowfish.c + camellia.c + ccm.c + cipher.c + cipher_wrap.c + cmac.c + ctr_drbg.c + des.c + dhm.c + ecdh.c + ecdsa.c + ecjpake.c + ecp.c + ecp_curves.c + entropy.c + entropy_poll.c + error.c + gcm.c + havege.c + hkdf.c + hmac_drbg.c + md.c + md2.c + md4.c + md5.c + md_wrap.c + memory_buffer_alloc.c + oid.c + padlock.c + pem.c + pk.c + pk_wrap.c + pkcs12.c + pkcs5.c + pkparse.c + pkwrite.c + platform.c + platform_util.c + ripemd160.c + rsa.c + rsa_internal.c + sha1.c + sha256.c + sha512.c + threading.c + timing.c + version.c + version_features.c + xtea.c + + # platform implementation of hardware random provider + mbedtls_entropy_hardware_pool.c +) + +set(src_x509 + certs.c + pkcs11.c + x509.c + x509_create.c + x509_crl.c + x509_crt.c + x509_csr.c + x509write_crt.c + x509write_csr.c +) + +set(src_tls + debug.c + net_sockets.c + ssl_cache.c + ssl_ciphersuites.c + ssl_cli.c + ssl_cookie.c + ssl_srv.c + ssl_ticket.c + ssl_tls.c +) + +foreach(SRC_FILE ${src_crypto}) + set(MBEDTLS_SRC_FILE SRC_FILE -NOTFOUND) + find_file(MBEDTLS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/mbedTLS_Source/library + + ${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/ + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${MBEDTLS_SRC_FILE}") # debug helper + list(APPEND mbedTLS_SOURCES ${MBEDTLS_SRC_FILE}) +endforeach() + +# unset this warning as error required for this source file +SET_SOURCE_FILES_PROPERTIES( ${PROJECT_BINARY_DIR}/mbedTLS_Source/library/hmac_drbg.c PROPERTIES COMPILE_FLAGS -Wno-maybe-uninitialized) +SET_SOURCE_FILES_PROPERTIES( ${PROJECT_BINARY_DIR}/mbedTLS_Source/library/x509_crt.c PROPERTIES COMPILE_FLAGS -Wno-maybe-uninitialized) + +foreach(SRC_FILE ${src_x509}) + set(MBEDTLS_SRC_FILE SRC_FILE -NOTFOUND) + find_file(MBEDTLS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/mbedTLS_Source/library + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${MBEDTLS_SRC_FILE}") # debug helper + list(APPEND mbedTLS_SOURCES ${MBEDTLS_SRC_FILE}) +endforeach() + +foreach(SRC_FILE ${src_tls}) + set(MBEDTLS_SRC_FILE SRC_FILE -NOTFOUND) + find_file(MBEDTLS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/mbedTLS_Source/library + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${MBEDTLS_SRC_FILE}") # debug helper + list(APPEND mbedTLS_SOURCES ${MBEDTLS_SRC_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(mbedTLS DEFAULT_MSG mbedTLS_INCLUDE_DIRS mbedTLS_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.Can.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.Can.cmake new file mode 100644 index 00000000..384152a8 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.Can.cmake @@ -0,0 +1,42 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/nanoFramework.Devices.Can") + + +# set include directories +list(APPEND nanoFramework.Devices.Can_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND nanoFramework.Devices.Can_INCLUDE_DIRS ${TARGET_BASE_LOCATION}) +list(APPEND nanoFramework.Devices.Can_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/nanoFramework.Devices.Can) + +# source files +set(nanoFramework.Devices.Can_SRCS + + nf_devices_can_native_nanoFramework_Devices_Can_CanController.cpp + nf_devices_can_native.cpp + + target_nf_devices_can_config.cpp +) + +foreach(SRC_FILE ${nanoFramework.Devices.Can_SRCS}) + set(nanoFramework.Devices.Can_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.Devices.Can_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_SOURCE_DIR}/src/nanoFramework.Devices.Can + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.Devices.Can_SRC_FILE}") # debug helper + list(APPEND nanoFramework.Devices.Can_SOURCES ${nanoFramework.Devices.Can_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.Devices.Can DEFAULT_MSG nanoFramework.Devices.Can_INCLUDE_DIRS nanoFramework.Devices.Can_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.OneWire.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.OneWire.cmake new file mode 100644 index 00000000..c3d9e3a4 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Devices.OneWire.cmake @@ -0,0 +1,42 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/nanoFramework.Devices.OneWire") + + +# set include directories +list(APPEND nanoFramework.Devices.OneWire_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE}) +list(APPEND nanoFramework.Devices.OneWire_INCLUDE_DIRS ${TARGET_BASE_LOCATION}) +list(APPEND nanoFramework.Devices.OneWire_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/nanoFramework.Devices.OneWire) + +# source files +set(nanoFramework.Devices.OneWire_SRCS + + nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp + nf_devices_onewire_native.cpp + + target_nf_devices_onewire_config.cpp +) + +foreach(SRC_FILE ${nanoFramework.Devices.OneWire_SRCS}) + set(nanoFramework.Devices.OneWire_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.Devices.OneWire_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + ${TARGET_BASE_LOCATION} + ${PROJECT_SOURCE_DIR}/src/nanoFramework.Devices.OneWire + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.Devices.OneWire_SRC_FILE}") # debug helper + list(APPEND nanoFramework.Devices.OneWire_SOURCES ${nanoFramework.Devices.OneWire_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.Devices.OneWire DEFAULT_MSG nanoFramework.Devices.OneWire_INCLUDE_DIRS nanoFramework.Devices.OneWire_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Esp32.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Esp32.cmake new file mode 100644 index 00000000..9255d68c --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Esp32.cmake @@ -0,0 +1,42 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/nanoFramework.Hardware.Esp32") + + +# set include directories +list(APPEND nanoFramework.Hardware.Esp32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/CLR/Core") +list(APPEND nanoFramework.Hardware.Esp32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/CLR/Include") +list(APPEND nanoFramework.Hardware.Esp32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/HAL/Include") +list(APPEND nanoFramework.Hardware.Esp32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/PAL/Include") +list(APPEND nanoFramework.Hardware.Esp32_INCLUDE_DIRS "${BASE_PATH_FOR_THIS_MODULE}") + +# source files +set(nanoFramework.Hardware.Esp32_SRCS + + nanoFramework_hardware_esp32_native.cpp + nanoFramework_hardware_esp32_native_Hardware_Esp32_sleep.cpp + nanoFramework_hardware_esp32_native_Hardware_Esp32_Logging.cpp + nanoFramework_hardware_esp32_native_Hardware_Esp32_HighResTimer.cpp + nanoFramework_hardware_esp32_native_Hardware_Esp32_Configuration.cpp +) + +foreach(SRC_FILE ${nanoFramework.Hardware.Esp32_SRCS}) + set(nanoFramework.Hardware.Esp32_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.Hardware.Esp32_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.Hardware.Esp32_SRC_FILE}") # debug helper + list(APPEND nanoFramework.Hardware.Esp32_SOURCES ${nanoFramework.Hardware.Esp32_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.Hardware.Esp32 DEFAULT_MSG nanoFramework.Hardware.Esp32_INCLUDE_DIRS nanoFramework.Hardware.Esp32_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Stm32.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Stm32.cmake new file mode 100644 index 00000000..87dfaeb5 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Hardware.Stm32.cmake @@ -0,0 +1,44 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/nanoFramework.Hardware.Stm32") + + +# set include directories +# list(APPEND nanoFramework.Hardware.Stm32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/CLR/Core") +# list(APPEND nanoFramework.Hardware.Stm32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/CLR/Include") +# list(APPEND nanoFramework.Hardware.Stm32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/HAL/Include") +# list(APPEND nanoFramework.Hardware.Stm32_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/PAL/Include") +list(APPEND nanoFramework.Hardware.Stm32_INCLUDE_DIRS "${BASE_PATH_FOR_THIS_MODULE}") + + +# source files +set(nanoFramework.Hardware.Stm32_SRCS + + nf_hardware_stm32_native.cpp + nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory.cpp + nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp + nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp + nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities.cpp +) + +foreach(SRC_FILE ${nanoFramework.Hardware.Stm32_SRCS}) + set(nanoFramework.Hardware.Stm32_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.Hardware.Stm32_SRC_FILE ${SRC_FILE} + PATHS + ${BASE_PATH_FOR_THIS_MODULE} + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.Hardware.Stm32_SRC_FILE}") # debug helper + list(APPEND nanoFramework.Hardware.Stm32_SOURCES ${nanoFramework.Hardware.Stm32_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.Hardware.Stm32 DEFAULT_MSG nanoFramework.Hardware.Stm32_INCLUDE_DIRS nanoFramework.Hardware.Stm32_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Networking.Sntp.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Networking.Sntp.cmake new file mode 100644 index 00000000..75604406 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Networking.Sntp.cmake @@ -0,0 +1,38 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +# set include directories +list(APPEND CHIBIOS_LWIP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ChibiOS_Source/ext/lwip/src/include/lwip) +list(APPEND nanoFramework.Networking.Sntp_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/HAL/Include") +list(APPEND nanoFramework.Networking.Sntp_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/DeviceInterfaces/Networking.Sntp") + + +# source files +set(nanoFramework.Networking.Sntp_SRCS + + # source files of the assembly + nf_networking_sntp_nanoFramework_Networking_Sntp.cpp + nf_networking_sntp.cpp +) + +foreach(SRC_FILE ${nanoFramework.Networking.Sntp_SRCS}) + set(nanoFramework.Networking.Sntp_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.Networking.Sntp_SRC_FILE ${SRC_FILE} + PATHS + + # path for source files of this module + ${PROJECT_SOURCE_DIR}/src/DeviceInterfaces/Networking.Sntp + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.Networking.Sntp_SRC_FILE}") # debug helper + list(APPEND nanoFramework.Networking.Sntp_SOURCES ${nanoFramework.Networking.Sntp_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.Networking.Sntp DEFAULT_MSG nanoFramework.Networking.Sntp_INCLUDE_DIRS nanoFramework.Networking.Sntp_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.ResourceManager.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.ResourceManager.cmake new file mode 100644 index 00000000..bb2dbb00 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.ResourceManager.cmake @@ -0,0 +1,38 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +# set include directories +list(APPEND nanoFramework.ResourceManager_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/HAL/Include") +list(APPEND nanoFramework.ResourceManager_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/nanoFramework.ResourceManager") + + +# source files +set(nanoFramework.ResourceManager_SRCS + + # source files of the assembly + nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility.cpp + nf_system_resourcemanager_System_Resources_ResourceManager.cpp + nf_system_resourcemanager.cpp +) + +foreach(SRC_FILE ${nanoFramework.ResourceManager_SRCS}) + set(nanoFramework.ResourceManager_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.ResourceManager_SRC_FILE ${SRC_FILE} + PATHS + + # path for source files of this module + ${PROJECT_SOURCE_DIR}/src/nanoFramework.ResourceManager + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.ResourceManager_SRC_FILE}") # debug helper + list(APPEND nanoFramework.ResourceManager_SOURCES ${nanoFramework.ResourceManager_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.ResourceManager DEFAULT_MSG nanoFramework.ResourceManager_INCLUDE_DIRS nanoFramework.ResourceManager_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Runtime.Events.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Runtime.Events.cmake new file mode 100644 index 00000000..d7e9be4f --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.Runtime.Events.cmake @@ -0,0 +1,55 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# native code directory +set(BASE_PATH_FOR_THIS_MODULE "${PROJECT_SOURCE_DIR}/src/nanoFramework.Runtime.Events") + + +# set include directories +list(APPEND nanoFramework.Runtime.Events_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/CLR/Core") +list(APPEND nanoFramework.Runtime.Events_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/CLR/Include") +list(APPEND nanoFramework.Runtime.Events_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/HAL/Include") +list(APPEND nanoFramework.Runtime.Events_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/PAL/Include") +list(APPEND nanoFramework.Runtime.Events_INCLUDE_DIRS "${BASE_PATH_FOR_THIS_MODULE}") + + +# source files +set(nanoFramework.Runtime.Events_SRCS + + # source files of the assembly + nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp + nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp + nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp + nf_rt_events_native.cpp + + # source files + AsyncCompletions.cpp + AsyncContinuations.cpp + nanoPAL_Events_functions.cpp + +) + +foreach(SRC_FILE ${nanoFramework.Runtime.Events_SRCS}) + set(nanoFramework.Runtime.Events_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.Runtime.Events_SRC_FILE ${SRC_FILE} + PATHS + + # path for source files of this module + ${BASE_PATH_FOR_THIS_MODULE} + + # path for AsyncProcCall and related code + ${PROJECT_SOURCE_DIR}/src/PAL/AsyncProcCall + ${PROJECT_SOURCE_DIR}/src/PAL/Events + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.Runtime.Events_SRC_FILE}") # debug helper + list(APPEND nanoFramework.Runtime.Events_SOURCES ${nanoFramework.Runtime.Events_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.Runtime.Events DEFAULT_MSG nanoFramework.Runtime.Events_INCLUDE_DIRS nanoFramework.Runtime.Events_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.System.Collections.cmake b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.System.Collections.cmake new file mode 100644 index 00000000..afa84191 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/FindnanoFramework.System.Collections.cmake @@ -0,0 +1,42 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +# set include directories +list(APPEND nanoFramework.System.Collections_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/HAL/Include") +list(APPEND nanoFramework.System.Collections_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/nanoFramework.System.Collections") + + +# the following CLR support files are required and added to the build by FindNF_CoreCLR.cmake +# CLR_RT_HeapBlock_Queue.cpp +# CLR_RT_HeapBlock_Stack.cpp + +# source files +set(nanoFramework.System.Collections_SRCS + + # source files of the assembly + nf_system_collections_System_Collections_Queue.cpp + nf_system_collections_System_Collections_Stack.cpp + nf_system_collections.cpp +) + +foreach(SRC_FILE ${nanoFramework.System.Collections_SRCS}) + set(nanoFramework.System.Collections_SRC_FILE SRC_FILE-NOTFOUND) + find_file(nanoFramework.System.Collections_SRC_FILE ${SRC_FILE} + PATHS + + # path for source files of this module + ${PROJECT_SOURCE_DIR}/src/nanoFramework.System.Collections + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoFramework.System.Collections_SRC_FILE}") # debug helper + list(APPEND nanoFramework.System.Collections_SOURCES ${nanoFramework.System.Collections_SRC_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(nanoFramework.System.Collections DEFAULT_MSG nanoFramework.System.Collections_INCLUDE_DIRS nanoFramework.System.Collections_SOURCES) diff --git a/source/native/nf-interpreter/CMake/Modules/JSONParser.cmake b/source/native/nf-interpreter/CMake/Modules/JSONParser.cmake new file mode 100644 index 00000000..b9230e4e --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/JSONParser.cmake @@ -0,0 +1,289 @@ +# source from https://github.com/sbellus/json-cmake + +cmake_minimum_required(VERSION 3.1) + +if (DEFINED JSonParserGuard) + return() +endif() + +set(JSonParserGuard yes) + +macro(sbeParseJson prefix jsonString) + cmake_policy(PUSH) + + set(json_string "${${jsonString}}") + string(LENGTH "${json_string}" json_jsonLen) + set(json_index 0) + set(json_AllVariables ${prefix}) + set(json_ArrayNestingLevel 0) + set(json_MaxArrayNestingLevel 0) + + _sbeParse(${prefix}) + + unset(json_index) + unset(json_AllVariables) + unset(json_jsonLen) + unset(json_string) + unset(json_value) + unset(json_inValue) + unset(json_name) + unset(json_inName) + unset(json_newPrefix) + unset(json_reservedWord) + unset(json_arrayIndex) + unset(json_char) + unset(json_end) + unset(json_ArrayNestingLevel) + foreach(json_nestingLevel RANGE ${json_MaxArrayNestingLevel}) + unset(json_${json_nestingLevel}_arrayIndex) + endforeach() + unset(json_nestingLevel) + unset(json_MaxArrayNestingLevel) + + cmake_policy(POP) +endmacro() + +macro(sbeClearJson prefix) + foreach(json_var ${${prefix}}) + unset(${json_var}) + endforeach() + + unset(${prefix}) + unset(json_var) +endmacro() + +macro(sbePrintJson prefix) + foreach(json_var ${${prefix}}) + message("${json_var} = ${${json_var}}") + endforeach() +endmacro() + +macro(_sbeParse prefix) + + while(${json_index} LESS ${json_jsonLen}) + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + + if("\"" STREQUAL "${json_char}") + _sbeParseNameValue(${prefix}) + elseif("{" STREQUAL "${json_char}") + _sbeMoveToNextNonEmptyCharacter() + _sbeParseObject(${prefix}) + elseif("[" STREQUAL "${json_char}") + _sbeMoveToNextNonEmptyCharacter() + _sbeParseArray(${prefix}) + endif() + + if(${json_index} LESS ${json_jsonLen}) + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + else() + break() + endif() + + if ("}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}") + break() + endif() + + _sbeMoveToNextNonEmptyCharacter() + endwhile() +endmacro() + +macro(_sbeParseNameValue prefix) + set(json_name "") + set(json_inName no) + + while(${json_index} LESS ${json_jsonLen}) + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + + # check if name ends + if("\"" STREQUAL "${json_char}" AND json_inName) + set(json_inName no) + _sbeMoveToNextNonEmptyCharacter() + if(NOT ${json_index} LESS ${json_jsonLen}) + break() + endif() + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + set(json_newPrefix ${prefix}.${json_name}) + set(json_name "") + + if(":" STREQUAL "${json_char}") + _sbeMoveToNextNonEmptyCharacter() + if(NOT ${json_index} LESS ${json_jsonLen}) + break() + endif() + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + + if("\"" STREQUAL "${json_char}") + _sbeParseValue(${json_newPrefix}) + break() + elseif("{" STREQUAL "${json_char}") + _sbeMoveToNextNonEmptyCharacter() + _sbeParseObject(${json_newPrefix}) + break() + elseif("[" STREQUAL "${json_char}") + _sbeMoveToNextNonEmptyCharacter() + _sbeParseArray(${json_newPrefix}) + break() + else() + # reserved word starts + _sbeParseReservedWord(${json_newPrefix}) + break() + endif() + else() + # name without value + list(APPEND ${json_AllVariables} ${json_newPrefix}) + set(${json_newPrefix} "") + break() + endif() + endif() + + if(json_inName) + # remove escapes + if("\\" STREQUAL "${json_char}") + math(EXPR json_index "${json_index} + 1") + if(NOT ${json_index} LESS ${json_jsonLen}) + break() + endif() + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + endif() + + set(json_name "${json_name}${json_char}") + endif() + + # check if name starts + if("\"" STREQUAL "${json_char}" AND NOT json_inName) + set(json_inName yes) + endif() + + _sbeMoveToNextNonEmptyCharacter() + endwhile() +endmacro() + +macro(_sbeParseReservedWord prefix) + set(json_reservedWord "") + set(json_end no) + while(${json_index} LESS ${json_jsonLen} AND NOT json_end) + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + + if("," STREQUAL "${json_char}" OR "}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}") + set(json_end yes) + else() + set(json_reservedWord "${json_reservedWord}${json_char}") + math(EXPR json_index "${json_index} + 1") + endif() + endwhile() + + list(APPEND ${json_AllVariables} ${prefix}) + string(STRIP "${json_reservedWord}" json_reservedWord) + set(${prefix} ${json_reservedWord}) +endmacro() + +macro(_sbeParseValue prefix) + cmake_policy(SET CMP0054 NEW) # turn off implicit expansions in if statement + + set(json_value "") + set(json_inValue no) + + while(${json_index} LESS ${json_jsonLen}) + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + + # check if json_value ends, it is ended by " + if("\"" STREQUAL "${json_char}" AND json_inValue) + set(json_inValue no) + + set(${prefix} ${json_value}) + list(APPEND ${json_AllVariables} ${prefix}) + _sbeMoveToNextNonEmptyCharacter() + break() + endif() + + if(json_inValue) + # if " is escaped consume + if("\\" STREQUAL "${json_char}") + math(EXPR json_index "${json_index} + 1") + if(NOT ${json_index} LESS ${json_jsonLen}) + break() + endif() + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + if(NOT "\"" STREQUAL "${json_char}") + # if it is not " then copy also escape character + set(json_char "\\${json_char}") + endif() + endif() + + _sbeAddEscapedCharacter("${json_char}") + endif() + + # check if value starts + if("\"" STREQUAL "${json_char}" AND NOT json_inValue) + set(json_inValue yes) + endif() + + math(EXPR json_index "${json_index} + 1") + endwhile() +endmacro() + +macro(_sbeAddEscapedCharacter char) + string(CONCAT json_value "${json_value}" "${char}") +endmacro() + +macro(_sbeParseObject prefix) + _sbeParse(${prefix}) + _sbeMoveToNextNonEmptyCharacter() +endmacro() + +macro(_sbeParseArray prefix) + math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} + 1") + set(json_${json_ArrayNestingLevel}_arrayIndex 0) + + set(${prefix} "") + list(APPEND ${json_AllVariables} ${prefix}) + + while(${json_index} LESS ${json_jsonLen}) + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + + if("\"" STREQUAL "${json_char}") + # simple value + list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) + _sbeParseValue(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) + elseif("{" STREQUAL "${json_char}") + # object + _sbeMoveToNextNonEmptyCharacter() + list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) + _sbeParseObject(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) + else() + list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) + _sbeParseReservedWord(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) + endif() + + if(NOT ${json_index} LESS ${json_jsonLen}) + break() + endif() + + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + + if("]" STREQUAL "${json_char}") + _sbeMoveToNextNonEmptyCharacter() + break() + elseif("," STREQUAL "${json_char}") + math(EXPR json_${json_ArrayNestingLevel}_arrayIndex "${json_${json_ArrayNestingLevel}_arrayIndex} + 1") + endif() + + _sbeMoveToNextNonEmptyCharacter() + endwhile() + + if(${json_MaxArrayNestingLevel} LESS ${json_ArrayNestingLevel}) + set(json_MaxArrayNestingLevel ${json_ArrayNestingLevel}) + endif() + math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} - 1") +endmacro() + +macro(_sbeMoveToNextNonEmptyCharacter) + math(EXPR json_index "${json_index} + 1") + if(${json_index} LESS ${json_jsonLen}) + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + while(${json_char} MATCHES "[ \t\n\r]" AND ${json_index} LESS ${json_jsonLen}) + math(EXPR json_index "${json_index} + 1") + string(SUBSTRING "${json_string}" ${json_index} 1 json_char) + endwhile() + endif() +endmacro() diff --git a/source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_GCC_options.cmake b/source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_GCC_options.cmake new file mode 100644 index 00000000..b7c46de5 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_GCC_options.cmake @@ -0,0 +1,16 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################# +# WHEN ADDING A NEW TARGET add the appropriate GCC options below +################################################################# + +set(CMAKE_C_FLAGS "-mthumb -mcpu=cortex-m0 -fno-builtin -std=c11 -g -Wall -ffunction-sections -fdata-sections -fomit-frame-pointer -mlong-calls -mabi=aapcs -fno-exceptions -fno-unroll-loops -ftree-vectorize -specs=nano.specs" CACHE INTERNAL "c compiler flags") +set(CMAKE_CXX_FLAGS "-mthumb -mcpu=cortex-m0 -std=c++11 -ffunction-sections -fdata-sections -fomit-frame-pointer -mlong-calls -mabi=aapcs -fno-exceptions -fno-unroll-loops -ftree-vectorize -specs=nano.specs" CACHE INTERNAL "cxx compiler flags") +set(CMAKE_ASM_FLAGS "-c -mthumb -mcpu=cortex-m0 -g -Wa,--no-warn -x assembler-with-cpp " CACHE INTERNAL "asm compiler flags") + +set(CMAKE_EXE_LINKER_FLAGS "-mthumb -mcpu=cortex-m0 -static -mabi=aapcs -Wl,-gc-sections" CACHE INTERNAL "executable linker flags") +set(CMAKE_MODULE_LINKER_FLAGS "-mthumb -mcpu=cortex-m0 -specs=nano.specs " CACHE INTERNAL "module linker flags") +set(CMAKE_SHARED_LINKER_FLAGS "-mthumb -mcpu=cortex-m0 -specs=nano.specs " CACHE INTERNAL "shared linker flags") diff --git a/source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_sources.cmake b/source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_sources.cmake new file mode 100644 index 00000000..4eb322d8 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/MBED_STM32F0_sources.cmake @@ -0,0 +1,134 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +########################################################################### +# WHEN ADDING A NEW SERIES add the include to the vendor source code below +########################################################################### +include(MBED_STM_sources) + +####################################################################################### +# WHEN ADDING A NEW TARGET add the source code file for the series\device folder below +####################################################################################### + +# sources in series\device folder +set(MBED_VENDOR_SERIES_DEVICE_SRCS + stm32f0xx_hal.c + stm32f0xx_hal_adc.c + stm32f0xx_hal_adc_ex.c + stm32f0xx_hal_can.c + stm32f0xx_hal_cec.c + stm32f0xx_hal_comp.c + stm32f0xx_hal_cortex.c + stm32f0xx_hal_crc.c + stm32f0xx_hal_crc_ex.c + stm32f0xx_hal_dac.c + stm32f0xx_hal_dac_ex.c + stm32f0xx_hal_dma.c + stm32f0xx_hal_flash.c + stm32f0xx_hal_flash_ex.c + stm32f0xx_hal_gpio.c + stm32f0xx_hal_i2c.c + stm32f0xx_hal_i2c_ex.c + stm32f0xx_hal_i2s.c + stm32f0xx_hal_irda.c + stm32f0xx_hal_iwdg.c + stm32f0xx_hal_pcd.c + stm32f0xx_hal_pcd_ex.c + stm32f0xx_hal_pwr.c + stm32f0xx_hal_pwr_ex.c + stm32f0xx_hal_rcc.c + stm32f0xx_hal_rcc_ex.c + stm32f0xx_hal_rtc.c + stm32f0xx_hal_rtc_ex.c + stm32f0xx_hal_smartcard.c + stm32f0xx_hal_smartcard_ex.c + stm32f0xx_hal_smbus.c + stm32f0xx_hal_spi.c + stm32f0xx_hal_spi_ex.c + stm32f0xx_hal_tim.c + stm32f0xx_hal_tim_ex.c + stm32f0xx_hal_tsc.c + stm32f0xx_hal_uart.c + stm32f0xx_hal_uart_ex.c + stm32f0xx_hal_usart.c + stm32f0xx_hal_wwdg.c +) +foreach(SRC_FILE ${MBED_VENDOR_SERIES_DEVICE_SRCS}) + set(MBEDOS_SRC_FILE SRC_FILE-NOTFOUND) + find_file(MBEDOS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/device + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${MBEDOS_SRC_FILE}") # debug helper + list(APPEND MBEDOS_SOURCES ${MBEDOS_SRC_FILE}) +endforeach() + +########################################################################## +# WHEN ADDING A NEW TARGET add the source code file for the series below +########################################################################## + +set(MBED_VENDOR_SERIES_AND_TARGET_SRCS + analogin_api.c + analogout_api.c + can_api.c + gpio_api.c + gpio_irq_api.c + lp_ticker.c + mbed_overrides.c + pinmap.c + port_api.c + pwmout_api.c + rtc_api.c + serial_api.c + sleep.c + spi_api.c + + PeripheralPins.c + cmsis_nvic.c + system_stm32f0xx.c +) +foreach(SRC_FILE ${MBED_VENDOR_SERIES_AND_TARGET_SRCS}) + set(MBEDOS_SRC_FILE SRC_FILE-NOTFOUND) + find_file(MBEDOS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES} + ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET} + ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET}/device + ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET}/device/TOOLCHAIN_GCC_ARM + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${MBEDOS_SRC_FILE}") # debug helper + list(APPEND MBEDOS_SOURCES ${MBEDOS_SRC_FILE}) +endforeach() + +####################################################################################################################################### +# WHEN ADDING A NEW TARGET add the respective if clause below along with the startup file and the linker file name (without extension) +####################################################################################################################################### + +# startup file +if(${MBED_TARGET} STREQUAL "NUCLEO_F091RC") + list(APPEND MBEDOS_SOURCES ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_NUCLEO_F091RC/device/TOOLCHAIN_GCC_ARM/startup_stm32f091xc.S) + set(LINKER_FILE "STM32F091XC") +endif() + +####################################################################################################################################### + + +################################################################ +# WHEN ADDING A NEW TARGET check if the linker file below works +################################################################ + +function(MBED_SET_LINKER_OPTIONS TARGET) + + get_target_property(TARGET_LD_FLAGS ${TARGET} LINK_FLAGS) + if(TARGET_LD_FLAGS) + set(TARGET_LD_FLAGS "-T${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET}/device/TOOLCHAIN_GCC_ARM/${LINKER_FILE}.LD ${TARGET_LD_FLAGS}") + else() + set(TARGET_LD_FLAGS "-T${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR}/TARGET_${MBED_TARGET_SERIES}/TARGET_${MBED_TARGET}/device/TOOLCHAIN_GCC_ARM/${LINKER_FILE}.LD") + endif() + set_target_properties(${TARGET} PROPERTIES LINK_FLAGS ${TARGET_LD_FLAGS}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/MBED_STM_sources.cmake b/source/native/nf-interpreter/CMake/Modules/MBED_STM_sources.cmake new file mode 100644 index 00000000..5116e037 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/MBED_STM_sources.cmake @@ -0,0 +1,35 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +############################################################################ +# WHEN ADDING A NEW VENDOR add the source code from the vendor folder below +############################################################################ + +# source files common for all STM targets +set(MBED_VENDOR_SRCS + hal_tick_16b.c + hal_tick_32b.c + i2c_api.c + stm_spi_api.c + trng_api.c + us_ticker_16b.c + us_ticker_32b.c +) +foreach(SRC_FILE ${MBED_VENDOR_SRCS}) + set(MBEDOS_SRC_FILE SRC_FILE-NOTFOUND) + find_file(MBEDOS_SRC_FILE ${SRC_FILE} + PATHS + ${PROJECT_BINARY_DIR}/mBedOS_Source/targets/TARGET_${MBED_TARGET_VENDOR} + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${MBEDOS_SRC_FILE}") # debug helper + list(APPEND MBEDOS_SOURCES ${MBEDOS_SRC_FILE}) +endforeach() + +# HAL_CMx file +list(APPEND MBEDOS_SOURCES ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx/TARGET_CORTEX_M/TARGET_${MBED_TARGET_CORE_SHORT}/TOOLCHAIN_GCC/HAL_C${MBED_TARGET_CORE_SHORT}.S) + +# SVC_Table file +list(APPEND MBEDOS_SOURCES ${PROJECT_BINARY_DIR}/mBedOS_Source/rtos/rtx/TARGET_CORTEX_M/TARGET_${MBED_TARGET_CORE_SHORT}/TOOLCHAIN_GCC/SVC_Table.S) diff --git a/source/native/nf-interpreter/CMake/Modules/NF_NativeAssemblies.cmake b/source/native/nf-interpreter/CMake/Modules/NF_NativeAssemblies.cmake new file mode 100644 index 00000000..35387d73 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/NF_NativeAssemblies.cmake @@ -0,0 +1,326 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +############################################################################################ +# WHEN ADDING A NEW API add the name that corresponds to the CMake option here +# e.g.: for namespace Windows.Devices.Gpio, the CMake option is 'API_Windows.Devices.Gpio' +# and the namespace designation is 'Windows.Devices.Gpio' +########################################################################################### + +option(API_nanoFramework.Devices.Can "option for nanoFramework.Devices.Can") +option(API_nanoFramework.Devices.OneWire "option for nanoFramework.Devices.OneWire") +option(API_nanoFramework.Networking.Sntp "option for nanoFramework.Networking.Sntp") +option(API_nanoFramework.Runtime.Events "option for nanoFramework.Runtime.Events API") +option(API_nanoFramework.ResourceManager "option for nanoFramework.ResourceManager") +option(API_nanoFramework.System.Collections "option for nanoFramework.System.Collections") +option(API_System.Math "option for System.Math") +option(API_System.Net "option for System.Net") +option(API_Windows.Devices.Adc "option for Windows.Devices.Adc API") +option(API_System.Devices.Dac "option for System.Devices.Dac API") +option(API_Windows.Devices.Gpio "option for Windows.Devices.Gpio API") +option(API_Windows.Devices.I2c "option for Windows.Devices.I2c API") +option(API_Windows.Devices.Pwm "option for Windows.Devices.Pwm API") +option(API_Windows.Devices.SerialCommunication "option for Windows.Devices.SerialCommunication API") +option(API_Windows.Devices.Spi "option for Windows.Devices.Spi API") +option(API_Windows.Networking.Sockets "option for Windows.Networking.Sockets") +option(API_Windows.Storage "option for Windows.Storage") + + +# Esp32 only +option(API_Hardware.Esp32 "option for Hardware.Esp32") + + +# Stm32 only +option(API_Hardware.Stm32 "option for Hardware.Stm32") + + +################################################################# +# macro to perform individual settings to add an API to the build +macro(PerformSettingsForApiEntry apiNamespace) + + # namespace with '_' replacing '.' + string(REPLACE "." "_" apiNamespaceWithoutDots "${apiNamespace}") + + # list this option + list(APPEND apiListing "${apiNamespace}") + + # append to list of declaration for Interop Assemblies table + list(APPEND CLR_RT_NativeAssemblyDataList "extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_${apiNamespaceWithoutDots};") + + # append to list of entries for Interop Assemblies table + list(APPEND CLR_RT_NativeAssemblyDataTableEntriesList "&g_CLR_AssemblyNative_${apiNamespaceWithoutDots},") + + # find the module + find_package(${apiNamespace} REQUIRED) + + # append include directories to list with includes for all the APIs + list(APPEND TARGET_NANO_APIS_INCLUDES "${${apiNamespace}_INCLUDE_DIRS}") + list(REMOVE_DUPLICATES TARGET_NANO_APIS_INCLUDES) + + # append source files to list wiht source files for all the APIs + list(APPEND TARGET_NANO_APIS_SOURCES "${${apiNamespace}_SOURCES}") + list(REMOVE_DUPLICATES TARGET_NANO_APIS_SOURCES) + +endmacro() +################################################################# + + +############################################################################################ +# WHEN ADDING A NEW API add the corresponding block below +# required changes: +# 1. change the 'IF' to match the CMake option +# 2. change the call to PerformSettingsForApiEntry() macro with the API name (doted naming) +############################################################################################ + +macro(ParseNativeAssemblies) + + # Hardware.Esp32 + if(API_Hardware.Esp32) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.Hardware.Esp32") + endif() + + # Hardware.Stm32 + if(API_Hardware.Stm32) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.Hardware.Stm32") + endif() + + # nanoFramework.Devices.Can + if(API_nanoFramework.Devices.Can) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.Devices.Can") + endif() + + # nanoFramework.Devices.OneWire + if(API_nanoFramework.Devices.OneWire) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.Devices.OneWire") + endif() + + # nanoFramework.Networking.Sntp + if(API_nanoFramework.Networking.Sntp) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.Networking.Sntp") + endif() + + # nanoFramework.ResourceManager + if(API_nanoFramework.ResourceManager) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.ResourceManager") + endif() + + # nanoFramework.System.Collections + if(API_nanoFramework.System.Collections) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.System.Collections") + endif() + + # nanoFramework.Runtime.Events + if(API_nanoFramework.Runtime.Events) + ##### API name here (doted name) + PerformSettingsForApiEntry("nanoFramework.Runtime.Events") + + # this one is special because it requires also another assembly for events that is internal (doens't have a managed end) + + # append to list of declaration for Interop Assemblies table + list(APPEND CLR_RT_NativeAssemblyDataList "extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs;") + # append to list of entries for Interop Assemblies table + list(APPEND CLR_RT_NativeAssemblyDataTableEntriesList "&g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs,") + + endif() + + # System.Math + if(API_System.Math) + ##### API name here (doted name) + PerformSettingsForApiEntry("System.Math") + endif() + + # System.Net + if(API_System.Net) + ##### API name here (doted name) + PerformSettingsForApiEntry("System.Net") + endif() + + # Windows.Devices.Adc + if(API_Windows.Devices.Adc) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Devices.Adc") + endif() + + # System.Devices.Dac + if(API_System.Devices.Dac) + ##### API name here (doted name) + PerformSettingsForApiEntry("System.Devices.Dac") + endif() + + # Windows.Devices.Gpio + if(API_Windows.Devices.Gpio) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Devices.Gpio") + endif() + + # Windows.Devices.I2c + if(API_Windows.Devices.I2c) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Devices.I2c") + endif() + + # Windows.Devices.Pwm + if(API_Windows.Devices.Pwm) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Devices.Pwm") + endif() + + # Windows.Devices.SerialCommunication + if(API_Windows.Devices.SerialCommunication) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Devices.SerialCommunication") + endif() + + # Windows.Devices.Spi + if(API_Windows.Devices.Spi) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Devices.Spi") + endif() + + # Windows.Networking.Sockets + if(API_Windows.Networking.Sockets) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Networking.Sockets") + endif() + + # Windows.Devices.Wifi + if(API_Windows.Devices.Wifi) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Devices.Wifi") + endif() + + # Windows.Storage + if(API_Windows.Storage) + ##### API name here (doted name) + PerformSettingsForApiEntry("Windows.Storage") + endif() + + # Interop assemblies + ParseInteropAssemblies() + + + # parse the declarations to have new lines and ';' + string(REPLACE ";;" ";\n" CLR_RT_NativeAssemblyDataDeclarations "${CLR_RT_NativeAssemblyDataList}") + # parse the list to have new lines, ',' and identation + string(REPLACE ";" "\n " CLR_RT_NativeAssemblyDataTableEntries "${CLR_RT_NativeAssemblyDataTableEntriesList}") + + + # configure code file with Interop Assemblies table and... + configure_file("${PROJECT_SOURCE_DIR}/InteropAssemblies/CLR_RT_InteropAssembliesTable.cpp.in" + "${CMAKE_CURRENT_BINARY_DIR}/CLR_RT_InteropAssembliesTable.cpp" @ONLY) + # ... now add Interop Assemblies table to ChibiOS nanoCLR sources list + list(APPEND TARGET_NANO_APIS_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/CLR_RT_InteropAssembliesTable.cpp") + + # make the vars global + set(TARGET_NANO_APIS_INCLUDES ${TARGET_NANO_APIS_INCLUDES} CACHE INTERNAL "make global") + set(TARGET_NANO_APIS_SOURCES ${TARGET_NANO_APIS_SOURCES} CACHE INTERNAL "make global") + + + # output the list of APIs included + list(LENGTH apiListing apiListingLenght) + + if(apiListingLenght GREATER 0) + + # APIs included + message(STATUS "") + message(STATUS " *** APIs included ***") + message(STATUS "") + + foreach(entry ${apiListing}) + message(STATUS " ${entry}") + endforeach(entry ${}) + + message(STATUS "") + message(STATUS " *** end of APIs ***") + message(STATUS "") + + else() + # no APIs were included + message(STATUS " *** NO APIs included ***") + endif() + +endmacro() + +############################################################################## +# macro to perform individual settings to add an Interop assembly to the build +macro(PerformSettingsForInteropEntry interopAssemblyName) + + # namespace with '_' replacing '.' + string(REPLACE "." "_" interopAssemblyNameWithoutDots "${interopAssemblyName}") + + # list this option + list(APPEND interopAssemblyList "${interopAssemblyName}") + + # append to list of declaration for Interop Assemblies table + list(APPEND CLR_RT_NativeAssemblyDataList "extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_${interopAssemblyNameWithoutDots};") + + # append to list of entries for Interop Assemblies table + list(APPEND CLR_RT_NativeAssemblyDataTableEntriesList "&g_CLR_AssemblyNative_${interopAssemblyNameWithoutDots},") + + # find the module + find_package("INTEROP-${interopAssemblyName}" REQUIRED) + + ######### + # because Interop assemblies are considered and treated as like any CLR assembly we add them to the same lists + ######### + + # append include directories to list with includes for all the APIs + list(APPEND TARGET_NANO_APIS_INCLUDES "${${interopAssemblyName}_INCLUDE_DIRS}") + list(REMOVE_DUPLICATES TARGET_NANO_APIS_INCLUDES) + + # append source files to list wiht source files for all the APIs + list(APPEND TARGET_NANO_APIS_SOURCES "${${interopAssemblyName}_SOURCES}") + list(REMOVE_DUPLICATES TARGET_NANO_APIS_SOURCES) + +endmacro() + +################################################################# +# macro that adds the requested Interop assemblies to the build +# requiremens to add an Interop assemble: +# 1) add it's namespace to the NF_INTEROP_ASSEMBLIES CMake options +# 2) have the corresponding CMake module in the Modules folder (mind the correct naming) +macro(ParseInteropAssemblies) + + # check if there are any Interop assemblies to be added + if(NF_INTEROP_ASSEMBLIES) + + # loop through each Interop assembly and add it to the build + foreach(assembly ${NF_INTEROP_ASSEMBLIES}) + PerformSettingsForInteropEntry(${assembly}) + endforeach() + + endif() + + # output the list of Interop assemblies included + list(LENGTH interopAssemblyList interopAssemblyListLenght) + + if(interopAssemblyListLenght GREATER 0) + + # APIs included + message(STATUS "") + message(STATUS " *** Interop assemblies included ***") + message(STATUS "") + + foreach(entry ${interopAssemblyList}) + message(STATUS " ${entry}") + endforeach(entry ${}) + + message(STATUS "") + message(STATUS " *** end of Interop assemblies ***") + message(STATUS "") + + else() + # no Interop assemblies were included + message(STATUS " *** NO Interop assemblies included ***") + endif() + +endmacro() diff --git a/source/native/nf-interpreter/CMake/Modules/STM32_CubePackage.cmake b/source/native/nf-interpreter/CMake/Modules/STM32_CubePackage.cmake new file mode 100644 index 00000000..8285b9e7 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/STM32_CubePackage.cmake @@ -0,0 +1,103 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# include the STM32 Cube package for the appropriate series, if requested + +# check if cube package source was specified or if it's empty (default is empty) +macro(ProcessSTM32CubePackage) + + # process target series, which is in the format "STM32F4xx" + string(REPLACE "STM32" "" TARGET_SERIES_SHORT_1 "${TARGET_SERIES}") + string(REPLACE "xx" "" TARGET_SERIES_SHORT "${TARGET_SERIES_SHORT_1}") + + set(NO_STM32_CUBE_PACKAGE_SOURCE TRUE) + if(NO_STM32_CUBE_PACKAGE_SOURCE) + if(NOT "${STM32_CUBE_PACKAGE_SOURCE}" STREQUAL "") + set(NO_STM32_CUBE_PACKAGE_SOURCE FALSE) + endif() + endif() + + if(NO_STM32_CUBE_PACKAGE_SOURCE) + # no STM Cube package source specified, download it from nanoFramework fork + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + message(STATUS "STM32 ${TARGET_SERIES_SHORT} Cube package from GitHub repo") + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/STM32.CubePackage.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}-CubePackage_Download/CMakeLists.txt") + + # setup CMake project for STM32_CubePackage download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}-CubePackage_Download") + + # run build on STM32_CubePackage download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}-CubePackage_Download") + + # add STM32_CubePackage as external project + # need to specify nanoframework as the active branch + ExternalProject_Add( + STM32${TARGET_SERIES_SHORT}_CubePackage + PREFIX STM32${TARGET_SERIES_SHORT}_CubePackage + SOURCE_DIR ${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}_CubePackage_Source + GIT_REPOSITORY https://github.com/nanoframework/STM32Cube${TARGET_SERIES_SHORT} + GIT_TAG "nf-build" # target specific branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for STM32_CubePackage CMake project + ExternalProject_Get_Property(STM32${TARGET_SERIES_SHORT}_CubePackage SOURCE_DIR) + + else() + # STM32 Cube package source was specified + + # sanity check is source path exists + if(EXISTS "${STM32_CUBE_PACKAGE_SOURCE}/") + message(STATUS "STM32 Cube package source from: ${STM32_CUBE_PACKAGE_SOURCE}") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}_CubePackage_Source") + file(COPY "${STM32_CUBE_PACKAGE_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}_CubePackage_Source") + else() + message(STATUS "Using local cache of STM32 Cube package source from ${STM32_CUBE_PACKAGE_SOURCE}") + endif() + else() + message(FATAL_ERROR "Couldn't find STM32 Cube package source at ${STM32_CUBE_PACKAGE_SOURCE}/") + endif() + + # add STM32_CubePackage as external project + ExternalProject_Add( + STM32${TARGET_SERIES_SHORT}_CubePackage + PREFIX STM32${TARGET_SERIES_SHORT}_CubePackage + SOURCE_DIR ${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}_CubePackage_Source + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for STM32_CubePackage CMake project + ExternalProject_Get_Property(STM32${TARGET_SERIES_SHORT}_CubePackage SOURCE_DIR) + + endif() + +endmacro() diff --git a/source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_GCC_options.cmake b/source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_GCC_options.cmake new file mode 100644 index 00000000..72b2250a --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_GCC_options.cmake @@ -0,0 +1,48 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +################################################################# +# WHEN ADDING A NEW SERIES add the appropriate GCC options below +################################################################# + +# need to specify this for assembler +set(CMAKE_ASM_FLAGS " -mthumb -mcpu=cortex-m4 -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") + +# need to specify linker flags here +# -mfpu=fpv5-sp-d16 +set(CMAKE_EXE_LINKER_FLAGS " -Wl,--gc-sections -Wl,--no-wchar-size-warning -Wl,--print-memory-usage -mcpu=cortex-m4 -march=armv7e-m -mthumb -nostartfiles -std=c99 -mfloat-abi=soft -ffunction-sections -fdata-sections -g -gstrict-dwarf -Wall " CACHE INTERNAL "executable linker flags") + + +function(NF_SET_COMPILER_OPTIONS TARGET) + + # include any extra options coming from any extra args? + target_compile_options(${TARGET} PUBLIC ${ARGN} -march=armv7e-m -mthumb -mcpu=cortex-m4 -mfloat-abi=soft -mabi=aapcs -gstrict-dwarf -nostdlib -Wall -w -static -ffunction-sections -falign-functions=16 -fdata-sections -fno-builtin -fno-common -fsingle-precision-constant -fomit-frame-pointer -mlong-calls -fdollars-in-identifiers -fno-exceptions -fno-unroll-loops -ffast-math -ftree-vectorize -fcheck-new -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics) + + # this series has FPU + target_compile_definitions(${TARGET} PUBLIC -DCORTEX_USE_FPU=TRUE) + +endfunction() + + +function(NF_SET_LINKER_OPTIONS TARGET) + + # request specs from newlib nano + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --specs=nano.specs ") + + # set extra linker flags + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " ${ARGN}") + + # set optimization linker flags for RELEASE and MinSizeRel + if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-linker-plugin -Os") + endif() + + # set optimization flags + nf_set_optimization_options(${TARGET}) + + # set link map + nf_set_link_map(${TARGET}) + +endfunction() diff --git a/source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_sources.cmake b/source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_sources.cmake new file mode 100644 index 00000000..12c3df28 --- /dev/null +++ b/source/native/nf-interpreter/CMake/Modules/TI_SimpleLink_CC32xx_sources.cmake @@ -0,0 +1,245 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# includes for SimpleLink CC32xx SDK +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/posix/gcc") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/boards/CC3220SF_LAUNCHXL") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/devices/cc32xx") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/devices/cc32xx/driverlib") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/net") +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/bsd") + +# includes for nanoFramework SSL driver +list(APPEND TI_SimpleLink_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/PAL/Com/sockets/ssl") + + +# source files for board drivers +set(BoardDrivers_SRCS + + # board drivers + # NVS.c + # NVSRAM.c + # NVSSPI25X.c + # SD.c + # SDSPI.c + # SDFatFS.c + List.c + RingBuf.c + ADC.c + ADCCC32XX.c + # Camera.c + # CameraCC32XXDMA.c + Capture.c + CaptureCC32XX.c + CryptoCC32XX.c + UDMACC32XX.c + GPIOCC32XX.c + I2C.c + I2CCC32XX.c + I2S.c + PowerCC32XX.c + PowerCC32XX_asm.sm4g + PWM.c + PWMTimerCC32XX.c + SDHostCC32XX.c + SPI.c + SPICC32XXDMA.c + SPICC32XXDMA.c + Timer.c + TimerCC32XX.c + UART.c + UARTCC32XX.c + UARTCC32XXDMA.c + Watchdog.c + WatchdogCC32XX.c +) + +foreach(SRC_FILE ${BoardDrivers_SRCS}) + set(BoardDrivers_SCR_FILE SRC_FILE -NOTFOUND) + find_file(BoardDrivers_SCR_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/nvs" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/sd" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/adc" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/camera" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/capture" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/crypto" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/dma" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/gpio" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/i2c" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/i2s" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/power" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/pwm" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/sd" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/spi" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/timer" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/uart" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/watchdog" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/utils" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${BoardDrivers_SCR_FILE}") # debug helper + list(APPEND TI_SimpleLink_SOURCES ${BoardDrivers_SCR_FILE}) +endforeach() + +# need to specify a language for this assembler source file because its not using a standard extension +set_source_files_properties("${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/power/PowerCC32XX_asm.sm4g" PROPERTIES LANGUAGE ASM) + +# source files for drivers library +set(DriversLibrary_SRCS + + #drivers library + adc.c + aes.c + camera.c + cpu.c + crc.c + des.c + flash.c + gpio.c + hwspinlock.c + i2c.c + interrupt.c + i2s.c + pin.c + prcm.c + sdhost.c + shamd5.c + spi.c + systick.c + timer.c + uart.c + udma.c + utils.c + wdt.c + + # display specific + DisplayUart.c +) + +foreach(SRC_FILE ${DriversLibrary_SRCS}) + set(DriversLibrary_SCR_FILE SRC_FILE -NOTFOUND) + find_file(DriversLibrary_SCR_FILE ${SRC_FILE} + PATHS + + #drivers library + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/devices/cc32xx/driverlib" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/display" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${DriversLibrary_SCR_FILE}") # debug helper + list(APPEND TI_SimpleLink_SOURCES ${DriversLibrary_SCR_FILE}) +endforeach() + +# source files for SimpleLink +set(SimpleLink_SRCS + + device.c + driver.c + flowcont.c + fs.c + netapp.c + netcfg.c + netutil.c + nonos.c + sl_socket.c + spawn.c + wlan.c + cc_pal.c + eventreg.c + wlanconfig.c + + # eventreg.c + +) + +foreach(SRC_FILE ${SimpleLink_SRCS}) + set(SimpleLink_SCR_FILE SRC_FILE -NOTFOUND) + find_file(SimpleLink_SCR_FILE ${SRC_FILE} + PATHS + + #drivers library + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/net/wifi" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/net/wifi/porting" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/net/wifi/source" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${SimpleLink_SCR_FILE}") # debug helper + list(APPEND TI_SimpleLink_SOURCES ${SimpleLink_SCR_FILE}) +endforeach() + + +# source files for SimpleLink net Wi-Fi +set(SLNetWiFi_SRCS + + slnetsock.c + slnetutils.c + slnetif.c + + # bsd + netdb.c + socket.c + errnoutil.c + + # drivers + eventreg.c + slnetifwifi.c + + # utils + clock_sync.c +) + +foreach(SRC_FILE ${SLNetWiFi_SRCS}) + set(SLNetWiFi_SCR_FILE SRC_FILE -NOTFOUND) + find_file(SLNetWiFi_SCR_FILE ${SRC_FILE} + PATHS + + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/net" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/net/bsd" + + # drivers + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/net/wifi" + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/drivers/net/wifi/slnetif" + + # utils + "${PROJECT_BINARY_DIR}/SimpleLinkCC32xxSDK_Source/ti/net/utils" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${SLNetWiFi_SCR_FILE}") # debug helper + list(APPEND TI_SimpleLink_SOURCES ${SLNetWiFi_SCR_FILE}) +endforeach() + + +# source files for nanoFramework SSL driver +set(nanoSsl_SRCS + + ssl.cpp +) + +foreach(SRC_FILE ${nanoSsl_SRCS}) + set(nanoSsl_SCR_FILE SRC_FILE -NOTFOUND) + find_file(nanoSsl_SCR_FILE ${SRC_FILE} + PATHS + + "${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl" + + CMAKE_FIND_ROOT_PATH_BOTH + ) + # message("${SRC_FILE} >> ${nanoSsl_SCR_FILE}") # debug helper + list(APPEND TI_SimpleLink_SOURCES ${nanoSsl_SCR_FILE}) +endforeach() + + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SimpleLinkCC32xxSDK DEFAULT_MSG TI_SimpleLink_INCLUDE_DIRS TI_SimpleLink_SOURCES) diff --git a/source/native/nf-interpreter/CMake/RTXRTOS.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/RTXRTOS.CMakeLists.cmake.in new file mode 100644 index 00000000..c203606d --- /dev/null +++ b/source/native/nf-interpreter/CMake/RTXRTOS.CMakeLists.cmake.in @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(RTXRTOS-download NONE) + +include(ExternalProject) + +# download RTX RTOS source from official ARM GitHub repo + ExternalProject_Add( + RTXRTOS + PREFIX RTXRTOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/RTXRTOS_Source + GIT_REPOSITORY https://github.com/ARM-software/CMSIS_5 + GIT_TAG master # target master branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) diff --git a/source/native/nf-interpreter/CMake/SPIFFS.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/SPIFFS.CMakeLists.cmake.in new file mode 100644 index 00000000..d7f3e5ad --- /dev/null +++ b/source/native/nf-interpreter/CMake/SPIFFS.CMakeLists.cmake.in @@ -0,0 +1,24 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +project(SPIFFS-download NONE) + +include(ExternalProject) + +# download SPIFFS source from nanoFramework GitHub fork +ExternalProject_Add( + SPIFFS + PREFIX SPIFFS + SOURCE_DIR ${CMAKE_BINARY_DIR}/SPIFFS_Source + GIT_REPOSITORY https://github.com/nanoframework/spiffs + GIT_TAG "nf-build" # target nanoFramework modified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) diff --git a/source/native/nf-interpreter/CMake/STM32.CubePackage.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/STM32.CubePackage.CMakeLists.cmake.in new file mode 100644 index 00000000..3c99cca9 --- /dev/null +++ b/source/native/nf-interpreter/CMake/STM32.CubePackage.CMakeLists.cmake.in @@ -0,0 +1,24 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +project(STM32-CubePackage-download NONE) + +include(ExternalProject) + +# download STM32 Cube Package source from nanoFramework GitHub fork +ExternalProject_Add( + STM32${TARGET_SERIES_SHORT}_CubePackage + PREFIX STM32${TARGET_SERIES_SHORT}_CubePackage + SOURCE_DIR ${CMAKE_BINARY_DIR}/STM32${TARGET_SERIES_SHORT}_CubePackage_Source + GIT_REPOSITORY https://github.com/nanoframework/STM32Cube${TARGET_SERIES_SHORT} + GIT_TAG "nf-build" # target specific branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) diff --git a/source/native/nf-interpreter/CMake/SimpleLinkCC32xxSdk.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/SimpleLinkCC32xxSdk.CMakeLists.cmake.in new file mode 100644 index 00000000..8892b9db --- /dev/null +++ b/source/native/nf-interpreter/CMake/SimpleLinkCC32xxSdk.CMakeLists.cmake.in @@ -0,0 +1,25 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +project(SimpleLinkCC32xxSDK-download NONE) + +include(ExternalProject) + +# download SimpleLinkCC32xx SDK from nanoFramework repo +ExternalProject_Add( + SimpleLinkCC32xxSDK + PREFIX SimpleLinkCC32xxSdk + SOURCE_DIR ${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdk_Source + GIT_REPOSITORY https://github.com/nanoframework/SimpleLink_CC32xx_SDK + GIT_TAG ${TI_SL_CC32xx_SDK_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) diff --git a/source/native/nf-interpreter/CMake/TI_SimpleLink_target_os.h.in b/source/native/nf-interpreter/CMake/TI_SimpleLink_target_os.h.in new file mode 100644 index 00000000..73ec8d87 --- /dev/null +++ b/source/native/nf-interpreter/CMake/TI_SimpleLink_target_os.h.in @@ -0,0 +1,30 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_OS_H_ +#define _TARGET_OS_H_ + +#define VERSION_MAJOR @nanoFramework_VERSION_MAJOR@U +#define VERSION_MINOR @nanoFramework_VERSION_MINOR@U +#define VERSION_BUILD @nanoFramework_VERSION_PATCH@U +#define VERSION_REVISION @nanoFramework_VERSION_TWEAK@U + +#define NANOCLR_LIGHT_MATH @TARGET_LIGHT_MATH@ +#define DP_FLOATINGPOINT @TARGET_DP_FLOATINGPOINT@ + +#define SUPPORT_ANY_BASE_CONVERSION @TARGET_SUPPORT_ANY_BASE_CONVERSION@ + +#define HAS_CONFIG_BLOCK @TARGET_HAS_CONFIG_BLOCK@ + +#define NANOCLR_REFLECTION @TARGET_NANOCLR_REFLECTION@ + +#define NANOCLR_SYSTEM_COLLECTIONS @TARGET_SYSTEM_COLLECTIONS@ + +#endif /* _TARGET_OS_H_ */ diff --git a/source/native/nf-interpreter/CMake/mBedOS.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/mBedOS.CMakeLists.cmake.in new file mode 100644 index 00000000..2ce4be90 --- /dev/null +++ b/source/native/nf-interpreter/CMake/mBedOS.CMakeLists.cmake.in @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(mBedOS-download NONE) + +include(ExternalProject) + +# download mBed RTOS source from official mBed GitHub repo + ExternalProject_Add( + mBedOS + PREFIX mBedOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/mBedOS_Source + GIT_REPOSITORY https://github.com/ARMmbed/mbed-os/ + GIT_TAG master # target master branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) diff --git a/source/native/nf-interpreter/CMake/mbedTLS.CMakeLists.cmake.in b/source/native/nf-interpreter/CMake/mbedTLS.CMakeLists.cmake.in new file mode 100644 index 00000000..1be3e498 --- /dev/null +++ b/source/native/nf-interpreter/CMake/mbedTLS.CMakeLists.cmake.in @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +project(mbedTLS-download NONE) + +include(ExternalProject) + +# download mbedTLS source from official GitHub repo +ExternalProject_Add( + mbedTLS + PREFIX mbedTLS + SOURCE_DIR ${CMAKE_BINARY_DIR}/mbedTLS_Source + GIT_REPOSITORY https://github.com/nanoframework/mbedtls + GIT_TAG ${MBEDTLS_GIT_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) diff --git a/source/native/nf-interpreter/CMake/toolchain.ChibiOS.GCC.cmake b/source/native/nf-interpreter/CMake/toolchain.ChibiOS.GCC.cmake new file mode 100644 index 00000000..bee8b68e --- /dev/null +++ b/source/native/nf-interpreter/CMake/toolchain.ChibiOS.GCC.cmake @@ -0,0 +1,180 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +INCLUDE(CMakeForceCompiler) +# if( DEFINED CMAKE_CROSSCOMPILING ) +# # subsequent toolchain loading is not really needed +# return() +# endif() + + +################################################### +# set C and C++ flags for compiler detection tests +################################################### +# IMPORTANT: these flags need to be removed after +# the compiler detection otherwise they'll get +# added to all compiler build calls and +# will colide with the use of nano.specs +################################################### +set(CMAKE_C_FLAGS_INIT "-specs=nosys.specs") +set(CMAKE_CXX_FLAGS_INIT "-specs=nosys.specs") +################################################### + + +# set toolchain directories +set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/bin) +set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/arm-none-eabi/include) +set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/arm-none-eabi/lib) + +# the name of the operating system for which CMake is to build +set(CMAKE_SYSTEM_NAME Generic) + +# name of the CPU CMake is building for +set(CMAKE_SYSTEM_PROCESSOR arm) + +# macro to setup compilers +macro(SET_COMPILER_VAR var name) + find_program(CMAKE_${var} arm-none-eabi-${name} HINTS ${TOOLCHAIN_BIN_DIR} DOC "${name} tool") +endmacro() + +# setup C compiler +if(NOT CMAKE_C_COMPILER) + SET_COMPILER_VAR(C_COMPILER gcc) +endif() + +# setup C++ compiler +if(NOT CMAKE_CXX_COMPILER) + SET_COMPILER_VAR(CXX_COMPILER g++) +endif() + +# setup Assembler compiler +SET_COMPILER_VAR(ASM-ATT_COMPILER as) + +# other toolchain configurations +set(CMAKE_OBJCOPY ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-objcopy CACHE INTERNAL "objcopy tool") +set(CMAKE_OBJDUMP ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-objdump CACHE INTERNAL "objdump tool") +set(CMAKE_SIZE ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-size CACHE INTERNAL "size tool") +set(CMAKE_DEBUGER ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-gdb CACHE INTERNAL "debuger") + +# root paths to search on the filesystem for cross-compiling +set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_PREFIX}/arm-none-eabi ${EXTRA_FIND_PATH}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# set required C and C++ standard for ALL targets +set(CMAKE_C_STANDARD 11 CACHE INTERNAL "C standard for all targets") +set(CMAKE_CXX_STANDARD 11 CACHE INTERNAL "C++ standard for all targets") + +# set all C and C++ extensions to be OFF on ALL targets +# this forces the use of -std=c11 and -std=c++11 instead of -std=gnu11 and -std=gnu++11 +set(CMAKE_C_EXTENSIONS OFF CACHE INTERNAL "C compiler extensions OFF") +set(CMAKE_CXX_EXTENSIONS OFF CACHE INTERNAL "C++ compiler extensions OFF") + + +function(NF_ADD_HEX_BIN_DUMP_TARGETS TARGET) + if(EXECUTABLE_OUTPUT_PATH) + set(FILENAME "${EXECUTABLE_OUTPUT_PATH}/${TARGET}") + else() + set(FILENAME "${TARGET}") + endif() + + #get_filename_component(FNSHORT ${FILENAME} NAME_WE) + string(REGEX REPLACE "\\.[^.]*$" "" FNSHORT ${FILENAME}) + + # add targets for HEX, BIN and S19 formats with no output so they will always be built + add_custom_target(${TARGET}.hex DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Oihex ${FILENAME} ${FNSHORT}.hex) + add_custom_target(${TARGET}.s19 DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Osrec ${FILENAME} ${FNSHORT}.s19) + add_custom_target(${TARGET}.bin DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Obinary ${FILENAME} ${FNSHORT}.bin) + add_custom_target(${TARGET}.dump DEPENDS ${TARGET} COMMAND ${CMAKE_OBJDUMP} -d -EL -S ${FILENAME} ${FNSHORT}.dump) +endfunction() + + +function(NF_PRINT_SIZE_OF_TARGETS TARGET) + if(EXECUTABLE_OUTPUT_PATH) + set(FILENAME "${EXECUTABLE_OUTPUT_PATH}/${TARGET}") + else() + set(FILENAME "${TARGET}") + endif() + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_SIZE} -A -x ${FILENAME}) +endfunction() + + +function(NF_SET_OPTIMIZATION_OPTIONS TARGET) + + target_compile_options(${TARGET} PRIVATE + $<$:-Og -femit-class-debug-always -g3 -ggdb> + $<$:-O3 -flto -fuse-linker-plugin -fno-fat-lto-objects> + $<$:-Os -flto -fuse-linker-plugin -fno-fat-lto-objects> + $<$:-Os -femit-class-debug-always -g3 -ggdb> + ) + +endfunction() + + +function(NF_SET_LINK_MAP TARGET) + + # need to remove the .elf suffix from target name + string(FIND ${TARGET} "." TARGET_EXTENSION_DOT_INDEX) + string(SUBSTRING ${TARGET} 0 ${TARGET_EXTENSION_DOT_INDEX} TARGET_SHORT) + + # add linker flags to generate map file + set_property(TARGET ${TARGET_SHORT}.elf APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-Map=${PROJECT_BINARY_DIR}/${TARGET_SHORT}.map,--library-path=${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/common") + +endfunction() + + +function(NF_SET_COMPILER_DEFINITIONS TARGET) + + # definition for platform + # (always ARM here) + # ChibiOS HAL community always include (nanoFramework overlay and official community contributions optionally) + target_compile_definitions(${TARGET} PUBLIC "-DPLATFORM_ARM -DHAL_USE_COMMUNITY") + + # build types that have debugging capabilities AND are NOT RTM have to have the define 'NANOCLR_ENABLE_SOURCELEVELDEBUGGING' + if((NOT NF_BUILD_RTM) OR NF_FEATURE_DEBUGGER) + target_compile_definitions(${TARGET} PUBLIC "-DNANOCLR_ENABLE_SOURCELEVELDEBUGGING ") + endif() + + # set compiler definition for RTM build option + if(NF_BUILD_RTM) + target_compile_definitions(${TARGET} PUBLIC -DBUILD_RTM) + endif() + + # set compiler definition for using Application Domains feature + if(NF_FEATURE_USE_APPDOMAINS) + target_compile_definitions(${TARGET} PUBLIC -DNANOCLR_USE_APPDOMAINS) + endif() + + # set compiler definition for implementing (or not) CRC32 in Wire Protocol + if(NF_WP_IMPLEMENTS_CRC32) + target_compile_definitions(${TARGET} PUBLIC -DWP_IMPLEMENTS_CRC32) + endif() + + # set definition for Wire Protocol trace mask + target_compile_definitions(${TARGET} PUBLIC -DTRACE_MASK=${WP_TRACE_MASK}) + + # set compiler definition regarding inclusion of trace messages and checks on CLR + if(NF_PLATFORM_NO_CLR_TRACE) + target_compile_definitions(${TARGET} PUBLIC -DPLATFORM_NO_CLR_TRACE=1) + endif() + + # set compiler definition regarding CLR IL inlining + if(NF_CLR_NO_IL_INLINE) + target_compile_definitions(${TARGET} PUBLIC -DNANOCLR_NO_IL_INLINE=1) + endif() + + # include any extra compiler definitions coming from extra args + target_compile_definitions(${TARGET} PUBLIC ${ARGN}) + +endfunction() + + +function(NF_SET_LINKER_FILE TARGET LINKER_FILE_NAME) + + # set linker file name + set_target_properties(${TARGET} PROPERTIES LINK_FLAGS "-T${LINKER_FILE_NAME}") + +endfunction() diff --git a/source/native/nf-interpreter/CMake/toolchain.FreeRtos.ESP32.GCC.cmake b/source/native/nf-interpreter/CMake/toolchain.FreeRtos.ESP32.GCC.cmake new file mode 100644 index 00000000..67970bca --- /dev/null +++ b/source/native/nf-interpreter/CMake/toolchain.FreeRtos.ESP32.GCC.cmake @@ -0,0 +1,95 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +INCLUDE(CMakeForceCompiler) +# if( DEFINED CMAKE_CROSSCOMPILING ) +# # subsequent toolchain loading is not really needed +# return() +# endif() + +# check for toolchain path +# if(NOT TOOLCHAIN_PREFIX) +# message( "tcp ${TOOLCHAIN_PREFIX}" ) +# message(STATUS "\n-- ########################################\nNo TOOLCHAIN_PREFIX specified, need one!\nCall CMake with -DTOOLCHAIN_PREFIX=\"\"\n specifing the path to your GCC toolchain") +# message(STATUS "\nNOTE: mind the forward slash in the path, without trailing slash.)") +# message(STATUS "########################################\n\n") +# message(FATAL_ERROR "No TOOLCHAIN_PREFIX specified") +# endif() + +# Stop cmake trying to check if compiler works +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY ) + +# set toolchain directories +set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/xtensa-esp32-elf/bin) +set(TOOLCHAIN_INC_DIR ${ESP32_IDF_PATH}/components/newlib/include) +set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/xtensa-esp32-elf/xtensa-esp32-elf/lib) + +# the name of the operating system for which CMake is to build +set(CMAKE_SYSTEM_NAME Generic) + +# name of the CPU CMake is building for +set(CMAKE_SYSTEM_PROCESSOR xtensa-esp32) + +# macro to setup compilers +macro(SET_COMPILER_VAR var name) + find_program(CMAKE_${var} xtensa-esp32-elf-${name} HINTS ${TOOLCHAIN_BIN_DIR} DOC "${name} tool") +endmacro() + +# setup C compiler +if(NOT CMAKE_C_COMPILER) + SET_COMPILER_VAR(C_COMPILER gcc) +endif() +SET_COMPILER_VAR(C_COMPILER gcc) + +# setup C++ compiler +if(NOT CMAKE_CXX_COMPILER) + SET_COMPILER_VAR(CXX_COMPILER g++) +endif() + +# setup Assembler compiler +SET_COMPILER_VAR(ASM-ATT_COMPILER as) + +# other toolchain configurations +set(CMAKE_OBJCOPY ${TOOLCHAIN_BIN_DIR}/xtensa-esp32-elf-objcopy CACHE INTERNAL "objcopy tool") +set(CMAKE_OBJDUMP ${TOOLCHAIN_BIN_DIR}/xtensa-esp32-elf-objdump CACHE INTERNAL "objdump tool") +set(CMAKE_SIZE ${TOOLCHAIN_BIN_DIR}/xtensa-esp32-elf-size CACHE INTERNAL "size tool") +set(CMAKE_DEBUGER ${TOOLCHAIN_BIN_DIR}/xtensa-esp32-elf-gdb CACHE INTERNAL "debuger") + +set(GCC_ESP32_LINKER_FLAGS, " -nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--start-group -Wl,--print-memory-usage " CACHE INTERNAL "Gcc esp32 liker flags" ) +set(GCC_ESP32_LINKER_LIBS, " ${ESP32_IDF_PATH}/components/newlib/lib/libc.a ${ESP32_IDF_PATH}/components/newlib/lib/libm.a ${ESP32_IDF_PATH}/components/esp32/libhal.a -L${ESP32_IDF_PATH}/components/esp32/lib -lcore -lrtc -lnet80211 -lmesh -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 -lphy -lgcc -lstdc++ " CACHE INTERNAL "Gcc esp32 liker libs") +set(GCC_ESP32_LINKER_LD, " -L ${ESP32_IDF_PATH}/components/esp32/ld -T esp32_out.ld -u ld_include_panic_highint_hdl -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld " CACHE INTERNAL "Gcc esp32 liker LD") + +# set debug flags +#set(CMAKE_C_FLAGS "-DTEST_WITH_C_FLAGS " CACHE INTERNAL "c compiler flags ") + + +set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "") + +set(CMAKE_C_FLAGS_DEBUG "-std=gnu99 -Og -ggdb -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Wextra -Werror -mfix-esp32-psram-cache-issue -DWITH_POSIX -DHAVE_CONFIG_H -DESP_PLATFORM -D IDF_VER=\"v3.3\" -MMD -MP " CACHE INTERNAL "c compiler flags debug") +set(CMAKE_CXX_FLAGS_DEBUG " -Og -ggdb -std=gnu++11 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Wextra -Werror -mfix-esp32-psram-cache-issue -DESP_PLATFORM " CACHE INTERNAL "cxx compiler flags debug") + +set(CMAKE_ASM_FLAGS_DEBUG " -g3 -ggdb" CACHE INTERNAL "asm compiler flags debug") + +#set(CMAKE_EXE_LINKER_FLAGS_DEBUG " ${GCC_ESP32_LINKER_FLAGS} ${GCC_ESP32_LINKER_LIBS} ${GCC_ESP32_LINKER_LD} " CACHE INTERNAL "linker flags debug") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG " -nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static " CACHE INTERNAL "linker flags debug") + +# set release flags +set(CMAKE_C_FLAGS_RELEASE " -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -MMD -MP -Wall -Wextra -Werror -mfix-esp32-psram-cache-issue -D IDF_VER=\"v3.3\" " CACHE INTERNAL "c compiler flags release") +set(CMAKE_C_FLAGS_MINSIZEREL " -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -MMD -MP -Wall -Wextra -Werror -mfix-esp32-psram-cache-issue -D IDF_VER=\"v3.3\" " CACHE INTERNAL "c compiler flags minsizerel") +set(CMAKE_CXX_FLAGS_RELEASE " -Os -std=gnu++11 -g3 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Wextra -Werror -mfix-esp32-psram-cache-issue -DESP_PLATFORM " CACHE INTERNAL "cxx compiler flags release") +set(CMAKE_CXX_FLAGS_MINSIZEREL " -Os -std=gnu++11 -g3 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Wextra -Werror -mfix-esp32-psram-cache-issue -DESP_PLATFORM " CACHE INTERNAL "cxx compiler flags minsizerel") + +set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm compiler flags release") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE " -nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static " CACHE INTERNAL "linker flags release") +set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL " -nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static " CACHE INTERNAL "linker flags minsizerel") + +set( CMAKE_C_LINK_EXECUTABLE " -o ") +set( CMAKE_CXX_LINK_EXECUTABLE " -o ") + +# root paths to search on the filesystem for cross-compiling +set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_PREFIX}/xtensa-esp32-elf ${EXTRA_FIND_PATH}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/source/native/nf-interpreter/CMake/toolchain.TI_SimpleLink.GCC.cmake b/source/native/nf-interpreter/CMake/toolchain.TI_SimpleLink.GCC.cmake new file mode 100644 index 00000000..37b908a6 --- /dev/null +++ b/source/native/nf-interpreter/CMake/toolchain.TI_SimpleLink.GCC.cmake @@ -0,0 +1,174 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +INCLUDE(CMakeForceCompiler) + +################################################### +# set C and C++ flags for compiler detection tests +################################################### +# IMPORTANT: these flags need to be removed after +# the compiler detection otherwise they'll get +# added to all compiler build calls and +# will colide with the use of nano.specs +################################################### +set(CMAKE_C_FLAGS_INIT "-specs=nosys.specs") +set(CMAKE_CXX_FLAGS_INIT "-specs=nosys.specs") +################################################### + + +# set toolchain directories +set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/bin) +set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/arm-none-eabi/include) +set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/arm-none-eabi/lib) + +# the name of the operating system for which CMake is to build +set(CMAKE_SYSTEM_NAME Generic) + +# name of the CPU CMake is building for +set(CMAKE_SYSTEM_PROCESSOR arm) + +# macro to setup compilers +macro(SET_COMPILER_VAR var name) + find_program(CMAKE_${var} arm-none-eabi-${name} HINTS ${TOOLCHAIN_BIN_DIR} DOC "${name} tool") +endmacro() + +# setup C compiler +if(NOT CMAKE_C_COMPILER) + SET_COMPILER_VAR(C_COMPILER gcc) +endif() + +# setup C++ compiler +if(NOT CMAKE_CXX_COMPILER) + SET_COMPILER_VAR(CXX_COMPILER g++) +endif() + +# setup Assembler compiler +SET_COMPILER_VAR(ASM-ATT_COMPILER as) + +# other toolchain configurations +set(CMAKE_OBJCOPY ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-objcopy CACHE INTERNAL "objcopy tool") +set(CMAKE_OBJDUMP ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-objdump CACHE INTERNAL "objdump tool") +set(CMAKE_SIZE ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-size CACHE INTERNAL "size tool") +set(CMAKE_DEBUGER ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-gdb CACHE INTERNAL "debuger") + +# root paths to search on the filesystem for cross-compiling +set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_PREFIX}/arm-none-eabi ${EXTRA_FIND_PATH}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# set required C and C++ standard for ALL targets +set(CMAKE_C_STANDARD 11 CACHE INTERNAL "C standard for all targets") +set(CMAKE_CXX_STANDARD 11 CACHE INTERNAL "C++ standard for all targets") + +# set all C and C++ extensions to be OFF on ALL targets +# this forces the use of -std=c11 and -std=c++11 instead of -std=gnu11 and -std=gnu++11 +set(CMAKE_C_EXTENSIONS OFF CACHE INTERNAL "C compiler extensions OFF") +set(CMAKE_CXX_EXTENSIONS OFF CACHE INTERNAL "C++ compiler extensions OFF") + + +function(NF_ADD_HEX_BIN_DUMP_TARGETS TARGET) + if(EXECUTABLE_OUTPUT_PATH) + set(FILENAME "${EXECUTABLE_OUTPUT_PATH}/${TARGET}") + else() + set(FILENAME "${TARGET}") + endif() + + # add targets for HEX, BIN and S19 formats with no output so they will always be built + add_custom_target(${TARGET}.hex DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Oihex ${FILENAME} ${FILENAME}.hex) + add_custom_target(${TARGET}.s19 DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Osrec ${FILENAME} ${FILENAME}.s19) + add_custom_target(${TARGET}.bin DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Obinary ${FILENAME} ${FILENAME}.bin) + add_custom_target(${TARGET}.dump DEPENDS ${TARGET} COMMAND ${CMAKE_OBJDUMP} -d -EL -S ${FILENAME} ${FILENAME}.dump) +endfunction() + + +function(NF_PRINT_SIZE_OF_TARGETS TARGET) + if(EXECUTABLE_OUTPUT_PATH) + set(FILENAME "${EXECUTABLE_OUTPUT_PATH}/${TARGET}") + else() + set(FILENAME "${TARGET}") + endif() + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_SIZE} -A -x ${FILENAME}) +endfunction() + + +function(NF_SET_OPTIMIZATION_OPTIONS TARGET) + + target_compile_options(${TARGET} PRIVATE + $<$:-Og -femit-class-debug-always -g3 -ggdb> + $<$:-O3 -flto -fuse-linker-plugin -fno-fat-lto-objects> + $<$:-Os -flto -fuse-linker-plugin -fno-fat-lto-objects> + $<$:-Os -femit-class-debug-always -g3 -ggdb> + ) + +endfunction() + + +function(NF_SET_LINK_MAP TARGET) + + # need to remove the .elf suffix from target name + string(FIND ${TARGET} "." TARGET_EXTENSION_DOT_INDEX) + string(SUBSTRING ${TARGET} 0 ${TARGET_EXTENSION_DOT_INDEX} TARGET_SHORT) + + # add linker flags to generate map file + set_property(TARGET ${TARGET_SHORT}.elf APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-Map=${PROJECT_SOURCE_DIR}/build/${TARGET_SHORT}.map,--library-path=${PROJECT_SOURCE_DIR}/targets/TI-SimpleLink/common") + +endfunction() + + +function(NF_SET_COMPILER_DEFINITIONS TARGET) + + # definition for platform + # (always ARM here) + target_compile_definitions(${TARGET} PUBLIC "-DPLATFORM_ARM ") + + # definitions required for SimpleLink CC32xx SDK + target_compile_definitions(${TARGET} PUBLIC -Dgcc -DPTLS_TLS_INDEX=0 -DCC32XX -DBOARD_DISPLAY_USE_UART_ANSI=0 -DBOARD_DISPLAY_USE_LCD=0 -DconfigNUM_THREAD_LOCAL_STORAGE_POINTERS=1 -DSL_PLATFORM_MULTI_THREADED) + + # build types that have debugging capabilities AND are NOT RTM have to have the define 'NANOCLR_ENABLE_SOURCELEVELDEBUGGING' + if((NOT NF_BUILD_RTM) OR NF_FEATURE_DEBUGGER) + target_compile_definitions(${TARGET} PUBLIC "-DNANOCLR_ENABLE_SOURCELEVELDEBUGGING ") + endif() + + # set compiler definition for RTM build option + if(NF_BUILD_RTM) + target_compile_definitions(${TARGET} PUBLIC -DBUILD_RTM) + endif() + + # set compiler definition for using Application Domains feature + if(NF_FEATURE_USE_APPDOMAINS) + target_compile_definitions(${TARGET} PUBLIC -DNANOCLR_USE_APPDOMAINS) + endif() + + # set compiler definition for implementing (or not) CRC32 in Wire Protocol + if(NF_WP_IMPLEMENTS_CRC32) + target_compile_definitions(${TARGET} PUBLIC -DWP_IMPLEMENTS_CRC32) + endif() + + # set definition for Wire Protocol trace mask + target_compile_definitions(${TARGET} PUBLIC -DTRACE_MASK=${WP_TRACE_MASK}) + + # set compiler definition regarding inclusion of trace messages and checks on CLR + if(NF_PLATFORM_NO_CLR_TRACE) + target_compile_definitions(${TARGET} PUBLIC -DPLATFORM_NO_CLR_TRACE=1) + endif() + + # set compiler definition regarding CLR IL inlining + if(NF_CLR_NO_IL_INLINE) + target_compile_definitions(${TARGET} PUBLIC -DNANOCLR_NO_IL_INLINE=1) + endif() + + # include any extra compiler definitions coming from extra args + target_compile_definitions(${TARGET} PUBLIC ${ARGN}) + +endfunction() + + +function(NF_SET_LINKER_FILE TARGET LINKER_FILE_NAME) + + # set linker file name + set_target_properties(${TARGET} PROPERTIES LINK_FLAGS "-T${LINKER_FILE_NAME}") + +endfunction() diff --git a/source/native/nf-interpreter/CMake/toolchain.mBed.GCC.cmake b/source/native/nf-interpreter/CMake/toolchain.mBed.GCC.cmake new file mode 100644 index 00000000..b2917483 --- /dev/null +++ b/source/native/nf-interpreter/CMake/toolchain.mBed.GCC.cmake @@ -0,0 +1,101 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +INCLUDE(CMakeForceCompiler) +# if( DEFINED CMAKE_CROSSCOMPILING ) +# # subsequent toolchain loading is not really needed +# return() +# endif() + +# check for toolchain path +if(NOT TOOLCHAIN_PREFIX) + message(STATUS "\n-- ########################################\nNo TOOLCHAIN_PREFIX specified, need one!\nCall CMake with -DTOOLCHAIN_PREFIX=\"\"\n specifing the path to your GCC toolchain (ex: E:/GNU_Tools_ARM_Embedded/5_4_2016q3)") + message(STATUS "\nNOTE: mind the forward slash in the path, without trailing slash.)") + message(STATUS "########################################\n\n") + message(FATAL_ERROR "No TOOLCHAIN_PREFIX specified") +endif() + +# set toolchain directories +set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/bin) +set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/arm-none-eabi/include) +set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/arm-none-eabi/lib) + +# the name of the operating system for which CMake is to build +set(CMAKE_SYSTEM_NAME Generic) + +# name of the CPU CMake is building for +set(CMAKE_SYSTEM_PROCESSOR arm) + +# macro to setup compilers +macro(SET_COMPILER_VAR var name) + find_program(CMAKE_${var} arm-none-eabi-${name} HINTS ${TOOLCHAIN_BIN_DIR} DOC "${name} tool") +endmacro() + +# setup C compiler +if(NOT CMAKE_C_COMPILER) + SET_COMPILER_VAR(C_COMPILER gcc) + if(CMAKE_C_COMPILER) + CMAKE_FORCE_C_COMPILER(${CMAKE_C_COMPILER} GNU) + endif() +endif() +SET_COMPILER_VAR(C_COMPILER gcc) + +# setup C++ compiler +if(NOT CMAKE_CXX_COMPILER) + SET_COMPILER_VAR(CXX_COMPILER g++) + if(CMAKE_CXX_COMPILER) + CMAKE_FORCE_CXX_COMPILER(${CMAKE_CXX_COMPILER} GNU) + endif() +endif() + +# setup Assembler compiler +SET_COMPILER_VAR(ASM-ATT_COMPILER as) + +# other toolchain configurations +set(CMAKE_OBJCOPY ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-objcopy CACHE INTERNAL "objcopy tool") +set(CMAKE_OBJDUMP ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-objdump CACHE INTERNAL "objdump tool") +set(CMAKE_SIZE ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-size CACHE INTERNAL "size tool") +set(CMAKE_DEBUGER ${TOOLCHAIN_BIN_DIR}/arm-none-eabi-gdb CACHE INTERNAL "debuger") + +# set debug flags +set(CMAKE_C_FLAGS_DEBUG "-Og -femit-class-debug-always -g3 -ggdb" CACHE INTERNAL "c compiler flags debug") +set(CMAKE_CXX_FLAGS_DEBUG "-Og -femit-class-debug-always -g3 -ggdb" CACHE INTERNAL "cxx compiler flags debug") +set(CMAKE_ASM_FLAGS_DEBUG "-g3 -ggdb" CACHE INTERNAL "asm compiler flags debug") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE INTERNAL "linker flags debug") + +# set release flags +set(CMAKE_C_FLAGS_RELEASE "-Os -flto" CACHE INTERNAL "c compiler flags release") +set(CMAKE_CXX_FLAGS_RELEASE "-Os -flto" CACHE INTERNAL "cxx compiler flags release") +set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm compiler flags release") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-flto" CACHE INTERNAL "linker flags release") + +# root paths to search on the filesystem for cross-compiling +set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_PREFIX}/arm-none-eabi ${EXTRA_FIND_PATH}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +function(MBED_ADD_HEX_BIN_DUMP_TARGETS TARGET) + if(EXECUTABLE_OUTPUT_PATH) + set(FILENAME "${EXECUTABLE_OUTPUT_PATH}/${TARGET}") + else() + set(FILENAME "${TARGET}") + endif() + + # add targets for HEX, BIN and S19 formats with no output so they will always be built + add_custom_target(${TARGET}.hex DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Oihex ${FILENAME} ${FILENAME}.hex) + add_custom_target(${TARGET}.s19 DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Osrec ${FILENAME} ${FILENAME}.s19) + add_custom_target(${TARGET}.bin DEPENDS ${TARGET} COMMAND ${CMAKE_OBJCOPY} -Obinary ${FILENAME} ${FILENAME}.bin) + add_custom_target(${TARGET}.dump DEPENDS ${TARGET} COMMAND ${CMAKE_OBJDUMP} -d -EL -S ${FILENAME} ${FILENAME}.dump) +endfunction() + +function(MBED_PRINT_SIZE_OF_TARGETS TARGET) + if(EXECUTABLE_OUTPUT_PATH) + set(FILENAME "${EXECUTABLE_OUTPUT_PATH}/${TARGET}") + else() + set(FILENAME "${TARGET}") + endif() + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_SIZE} ${FILENAME}) +endfunction() diff --git a/source/native/nf-interpreter/CMakeLists.txt b/source/native/nf-interpreter/CMakeLists.txt new file mode 100644 index 00000000..8f9039d9 --- /dev/null +++ b/source/native/nf-interpreter/CMakeLists.txt @@ -0,0 +1,730 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.11) +include(CMakeToolsHelpers OPTIONAL) +include(ExternalProject) + +# set(CMAKE_VERBOSE_MAKEFILE 1) # debug helper + +# the following prevents launchin a build in the source tree +set(CMAKE_DISABLE_SOURCE_CHANGES ON) +set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) + +# fatal error and message explaining this +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(STATUS "\n-- ###############################################\n") + message(STATUS "Please run the build outside of the source tree.\n\n") + message(STATUS "Hint: create a 'build' folder and run CMake from there..") + message(STATUS "###############################################\n\n") + message(FATAL_ERROR "Build launched in the source tree.") +endif() +######################################### + + +######################################################## +# path to local CMake modules +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules) +######################################################## + + +###################################################### +# set build type to release if not specified otherwise +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() +###################################################### + +# add compiler define for DEBUG +add_compile_options("$<$:-DDEBUG>") + +###################################################### +# set time stamp of build +string(TIMESTAMP BUILD_TIMESTAMP UTC) +###################################################### + +####################### +# handle RTOSes choice + +if("${RTOS}" STREQUAL "") + # no RTOS selected, defaulting to ChibiOS + set(RTOS "CHIBIOS") +endif() + +# list of supported RTOSes +# when adding a new RTOS add the corresponding string below AND... +# ... also on the compare block below +set(RTOS_SUPPORTED "CHIBIOS" "FREERTOS_ESP32" "TI_SIMPLELINK" CACHE INTERNAL "supported RTOS options") + +list(FIND RTOS_SUPPORTED ${RTOS} RTOS_INDEX) +if(RTOS_INDEX EQUAL -1) + message(FATAL_ERROR "\n\n'${RTOS}' is an invalid option for RTOS. Please choose a valid RTOS.\n\n") +else() + message(STATUS "\nSetting RTOS to ${RTOS}\n") +endif() + +string(COMPARE EQUAL "CHIBIOS" "${RTOS}" RTOS_CHIBIOS_CHECK) +string(COMPARE EQUAL "FREERTOS_ESP32" "${RTOS}" RTOS_FREERTOS_ESP32_CHECK) +string(COMPARE EQUAL "TI_SIMPLELINK" "${RTOS}" RTOS_TI_SIMPLELINK_CHECK) + +########################################################################## + +if(RTOS_FREERTOS_ESP32_CHECK) + set(RTOS_FREERTOS_ESP32_CHECK TRUE) + set(RTOS_TI_SIMPLELINK_CHECK FALSE) + set(RTOS_CHIBIOS_CHECK FALSE) +endif() + +if(RTOS_CHIBIOS_CHECK) + set(RTOS_CHIBIOS_CHECK TRUE) + set(RTOS_FREERTOS_ESP32_CHECK FALSE) + set(RTOS_TI_SIMPLELINK_CHECK FALSE) +endif() + +if(RTOS_TI_SIMPLELINK_CHECK) + set(RTOS_TI_SIMPLELINK_CHECK TRUE) + set(RTOS_FREERTOS_ESP32_CHECK FALSE) + set(RTOS_CHIBIOS_CHECK FALSE) +endif() + +####################### + + +########################################## +# set default toolchain to GCC +set(TOOLCHAIN GCC) +# have it lower case too for file names +string(TOLOWER TOOLCHAIN_LOWER ${TOOLCHAIN}) +########################################## + +if(RTOS_CHIBIOS_CHECK) + + # check for toolchain path + if(NOT TOOLCHAIN_PREFIX) + message(STATUS "\n-- ########################################\nNo TOOLCHAIN_PREFIX specified, need one!\nCall CMake with -DTOOLCHAIN_PREFIX=\"\"\n specifing the path to your GCC toolchain (ex: E:/GNU_Tools_ARM_Embedded/5_4_2016q3)") + message(STATUS "\nNOTE: mind the forward slash in the path, without trailing slash.)") + message(STATUS "########################################\n\n") + message(FATAL_ERROR "No TOOLCHAIN_PREFIX specified") + endif() + + message(STATUS "\nSetting Toolchain file for ChibiOS \n") + # set toolchain file + set(CMAKE_TOOLCHAIN_FILE CMake/toolchain.ChibiOS.${TOOLCHAIN}.cmake) + + # Set up short path substitution on Windows + if(WIN32) + if(EXISTS ${CMAKE_SOURCE_DIR}/SetNFRoot.bat) + execute_process(COMMAND ${CMAKE_SOURCE_DIR}/SetNFRoot.bat OUTPUT_VARIABLE NFROOT OUTPUT_STRIP_TRAILING_WHITESPACE) + set(ENV{nfRoot} ${NFROOT}) + endif() + endif() + +elseif(RTOS_FREERTOS_ESP32_CHECK) + message(STATUS "\nSetting Toolchain file for FreeRTOS ESP32 \n") + set(CMAKE_TOOLCHAIN_FILE CMake/toolchain.FreeRtos.ESP32.${TOOLCHAIN}.cmake) + +elseif(RTOS_TI_SIMPLELINK_CHECK) + message(STATUS "\nSetting Toolchain file for FreeRTOS CC32XX \n") + set(CMAKE_TOOLCHAIN_FILE CMake/toolchain.TI_SimpleLink.${TOOLCHAIN}.cmake) + +endif() + +######################################### + +# set default version +if(NOT BUILD_VERSION) + set(BUILD_VERSION 0.0.0.0) +endif() +project(nanoFramework VERSION ${BUILD_VERSION}) + +####################### +message(STATUS "") +message(STATUS "Building nanoFramework version ${PROJECT_VERSION} using build type '${CMAKE_BUILD_TYPE}'.") +message(STATUS "Source directory is '${PROJECT_SOURCE_DIR}'.") +message(STATUS "Build directory is '${PROJECT_BINARY_DIR}'.") +message(STATUS "Toolchain is '${TOOLCHAIN}'.") +message(STATUS "") +####################### + + +################################################################# +# ouput RTM build option +# Build RTM version of firmware (default is OFF so the build is not RTM and the CLR outputs some debug informations) +option(NF_BUILD_RTM "option to build with RTM definition") + +if(NF_BUILD_RTM) + message(STATUS "***************************") + message(STATUS "** Building RTM firmware **") + message(STATUS "***************************") + message(STATUS "") +endif() +################################################################# + +if(RTOS_CHIBIOS_CHECK) + + ################################################################# + # clear CMAKE_C_FLAGS_INIT and CMAKE_CXX_FLAGS_INIT + # (this needs to be here and not before because by now + # the compiler detection has already occurred) + set(CMAKE_C_FLAGS "" CACHE INTERNAL "clear c compiler flags") + set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "clear cxx compiler flags") + ################################################################# + + + ################################################################# + # clear some CMake flavor flags that are being set as default + # in the GNU compiler init + # we want to control and fine tune these + set(CMAKE_C_FLAGS_DEBUG "" CACHE INTERNAL "clear c compiler flags") + set(CMAKE_C_FLAGS_MINSIZEREL "" CACHE INTERNAL "clear c compiler flags") + set(CMAKE_C_FLAGS_RELEASE "" CACHE INTERNAL "clear c compiler flags") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "clear c compiler flags") + set(CMAKE_CXX_FLAGS_DEBUG "" CACHE INTERNAL "clear c++ compiler flags") + set(CMAKE_CXX_FLAGS_MINSIZEREL "" CACHE INTERNAL "clear c++ compiler flags") + set(CMAKE_CXX_FLAGS_RELEASE "" CACHE INTERNAL "clear c++ compiler flags") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "clear c++ compiler flags") + ################################################################# + + + ################################################################# + # clear default libraries that are set by CMake + # we want to control + set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "" CACHE INTERNAL "clear c linker default libs") + set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "" CACHE INTERNAL "clear c++ linker default libs") + ################################################################# + +endif() + +################################################################################# +# chooses if double-point float point support is provided by the platform +# (default is OFF which means that single-precision floating point is effective) +option(DP_FLOATINGPOINT "option to enable support for double-precision floating point") + +if(DP_FLOATINGPOINT) + set(TARGET_DP_FLOATINGPOINT TRUE CACHE INTERNAL "DP FP support") + message(STATUS "Double-precision floating point is effective") +else() + set(TARGET_DP_FLOATINGPOINT FALSE CACHE INTERNAL "DP FP support") + message(STATUS "Single-precision floating point is effective") +endif() + +################################################################################# +# chooses if build without complex math functions +# (default is OFF which means that all floating point math functions are available) +option(NF_FEATURE_LIGHT_MATH "option to build without complex math functions") + +if(NF_FEATURE_LIGHT_MATH) + set(TARGET_LIGHT_MATH TRUE CACHE INTERNAL "Complex Math functions disabled") + message(STATUS "Complex math functions not available") +else() + set(TARGET_LIGHT_MATH FALSE CACHE INTERNAL "Complex Math functions enabled") + message(STATUS "Complex math functions available") +endif() + +################################################################################### +# chooses if platform provides support for converting string to values on any base +# (default is OFF which means that conversion to value from base 10 and 16 (partial) is effective) +option(SUPPORT_ANY_BASE_CONVERSION "option to enable support for converting strings to value on any base") + +if(SUPPORT_ANY_BASE_CONVERSION) + set(TARGET_SUPPORT_ANY_BASE_CONVERSION TRUE CACHE INTERNAL "Option for string conversion to value from any base") + message(STATUS "String conversion to value on any base is effective") +else() + set(TARGET_SUPPORT_ANY_BASE_CONVERSION FALSE CACHE INTERNAL "Option for string conversion to value from base 10 and partial for 16") + message(STATUS "String conversion to value from base 10 and 16 (partial) is effective") +endif() + +################################################################# +# true random number generation option supported by hardware +option(USE_RNG "option to enable use of true random generator hardware block" ON) + +if(USE_RNG) + message(STATUS "Random Number Generation by target MCU is activated") +else() + message(STATUS "Random Number Generation by target MCU is NOT activated") +endif() + +################################################################# +# nanoFramework features +################################################################# + +################################################################### +# debugger (default is OFF so no support for debugging is included +option(NF_FEATURE_DEBUGGER "option to enable support for debugging") + +if(NF_FEATURE_DEBUGGER) + message(STATUS "Support for debugging managed applications is included.") +else() + message(STATUS "Support for debugging managed applications IS NOT included.") +endif() + +################################################################# +# enables Application Domains support in nanoCLR +# (default is OFF so Application Domains is NOT supported) +option(NF_FEATURE_USE_APPDOMAINS "option to enable Application Domains") + +if(NF_FEATURE_USE_APPDOMAINS) + message(STATUS "Application Domains support is included") +else() + message(STATUS "Application Domains support IS NOT included") +endif() + +################################################################# +# disable all trace messages and checks on CLR +# (default is OFF so all traces and checks are enabled) +option(NF_PLATFORM_NO_CLR_TRACE "option to disable all trace stuff in CLR") + +if(NF_PLATFORM_NO_CLR_TRACE) + message(STATUS "CLR has all trace messages and checks DISABLED") +else() + message(STATUS "CLR has all trace messages and checks enabled") +endif() + +################################################################# +# disable CLR IL inlining +# (default is OFF so CLR IL inline is enabled) +option(NF_CLR_NO_IL_INLINE "option to disable CLR IL inlining") + +if(NF_CLR_NO_IL_INLINE) + message(STATUS "CLR IL inlining is DISABLED") +else() + message(STATUS "CLR IL inlining is enabled") +endif() + +################################################################# +# enables configuration block storage support +# (default is OFF so Configuration block storage is NOT supported) +option(NF_FEATURE_HAS_CONFIG_BLOCK "option to enable configuration block storage") + +if(NF_FEATURE_HAS_CONFIG_BLOCK) + set(TARGET_HAS_CONFIG_BLOCK TRUE CACHE INTERNAL "Option for config block") + message(STATUS "Configuration block storage is included") +else() + set(TARGET_HAS_CONFIG_BLOCK FALSE CACHE INTERNAL "Option for config block") + message(STATUS "Configuration block storage IS NOT included") +endif() + +################################################################# +# enables support for SD Card +# (default is OFF so SD Card is NOT supported) +option(NF_FEATURE_HAS_SDCARD "option to enable support for SD Card") + +if(NF_FEATURE_HAS_SDCARD) + + # this feature currently is supported only on ChibiOS and ESP32 FreeRTOS + if(NOT RTOS_CHIBIOS_CHECK AND NOT RTOS_FREERTOS_ESP32_CHECK) + message(FATAL_ERROR "Support for SD Card is only available for ChibiOS Cortex-M and ESP32 targets.") + endif() + + # force inclusion of Windows.Storage API + set(API_Windows.Storage ON CACHE INTERNAL "Forcing Windows.Storage API option to ON") + + message(STATUS "Support for SD Card is included") +else() + message(STATUS "Support for SD Card IS NOT included") +endif() + +################################################################# + +################################################################# +# enables USB Mass Storage support +# (default is OFF so USB Mass Storage is NOT supported) +option(NF_FEATURE_HAS_USB_MSD "option to enable USB Mass Storage") + +if(NF_FEATURE_HAS_USB_MSD) + + # this feature currently is supported only on ChibiOS + if(NOT RTOS_CHIBIOS_CHECK) + message(FATAL_ERROR "Support for USB Mass Storage is only available for ChibiOS Cortex-M targets.") + endif() + + # this feature requires inclusion of ChibiOS contribution repository + set(CHIBIOS_CONTRIB_REQUIRED ON CACHE INTERNAL "Forcing ChibiOS contribution repo option to ON") + + # force inclusion of Windows.Storage API + set(API_Windows.Storage ON CACHE INTERNAL "Forcing Windows.Storage API option to ON") + + message(STATUS "Support for USB Mass Storage is included") +else() + message(STATUS "Support for USB Mass Storage IS NOT included") +endif() + +################################################################# + +################################################################# +# enables support for SPI file system +# (default is OFF so SPIFFS is NOT supported) +option(NF_FEATURE_USE_SPIFFS "option to enable support for SPI file system") + +if(NF_FEATURE_USE_SPIFFS) + + # this feature currently is supported only on ChibiOS and ESP32 + if(NOT RTOS_CHIBIOS_CHECK) + message(FATAL_ERROR "Support for SPIFFS is only available for ChibiOS Cortex-M and ESP32 targets.") + endif() + + # force inclusion of Windows.Storage API + set(API_Windows.Storage ON CACHE INTERNAL "Forcing Windows.Storage API option to ON") + + set(NF_FEATURE_USE_SPIFFS_OPTION TRUE CACHE INTERNAL "Set nF SPIFFS feature TRUE") + + message(STATUS "Support for SPIFFS is included") +else() + set(NF_FEATURE_USE_SPIFFS_OPTION FALSE CACHE INTERNAL "Set nF SPIFFS feature FALSE") + message(STATUS "Support for SPIFFS IS NOT included") +endif() + +################################################################# + +if(RTOS_CHIBIOS_CHECK) + + ################################################################# + # ARM Cortex-M Single Wire Output (SWO) + # (default is OFF so no SWO output) + + option(SWO_OUTPUT "option to enable SWO") + + if(SWO_OUTPUT) + set(SWO_OUTPUT_OPTION TRUE CACHE INTERNAL "Single Wire Output Option") + message(STATUS "Single Wire Output (SWO) enabled") + else() + set(SWO_OUTPUT_OPTION FALSE CACHE INTERNAL "Single Wire Output Option") + endif() + + ################################################################# + + ################################################################# + # enables use of ChibiOS Community contribution + # (default is OFF so ChibiOS Community is NOT included) + option(CHIBIOS_CONTRIB_REQUIRED "option to include ChibiOS Community contributions repository") + ################################################################# + +endif() + +################################################################# +# reports Wire Protocol CRC32 implementation +if(NF_WP_IMPLEMENTS_CRC32) + message(STATUS "Wire Protocol implements CRC32") +else() + message(STATUS "Wire Protocol does NOT implement CRC32") +endif() + +################################################################# +# enables Networking support in nanoCLR +# declares Networking option +# needs to show before the API namespaces processing because it's used there +# (default is OFF so Networking is NOT supported) +option(USE_NETWORKING_OPTION "option to use networking") + +# (default is OFF so mbed TLS is NOT used) +option(NF_SECURITY_MBEDTLS "option to use mbed TLS as the network security provider") + +# set default option for SNTP to ON +option(NF_NETWORKING_SNTP "option to use add SNTP support, requires networking otherwise has no effect" ON) + +################################################################# + +############################################# +# handles inclusion of System.Reflection API +############################################# + +# set default option for SNTP to ON +option(NF_FEATURE_SUPPORT_REFLECTION "option to add support for System.Reflection API" ON) + +if(NF_FEATURE_SUPPORT_REFLECTION) + set(TARGET_NANOCLR_REFLECTION TRUE CACHE INTERNAL "enable support for System.Reflection API") + message(STATUS "Support for System.Reflection API enabled") +else() + set(TARGET_NANOCLR_REFLECTION FALSE CACHE INTERNAL "DISABLE support for System.Reflection API") + message(STATUS "Support for System.Reflection API **IS NOT** enabled") +endif() + +################################################################# + +################################################################# + +############################################# +# handles inclusion of System.Collections API +############################################# + +if(API_nanoFramework.System.Collections) + set(TARGET_SYSTEM_COLLECTIONS TRUE CACHE INTERNAL "enable support for System.Collections API") + message(STATUS "Support for System.Collections API enabled") +else() + set(TARGET_SYSTEM_COLLECTIONS FALSE CACHE INTERNAL "DISABLE support for System.Collections API") + message(STATUS "Support for System.Collections API **IS NOT** enabled") +endif() + +################################################################# + +################################################################# +# manage HAL/PAL required for API namespaces +################################################################# +# for some APIs we need to enable the device in the HAL config +# and/or manage other APIs that are required + +if( API_nanoFramework.Devices.OneWire OR + API_Windows.Devices.SerialCommunication) + + set(HAL_USE_UART_OPTION TRUE CACHE INTERNAL "HAL OneWire for nanoFramework.Devices.OneWire") + +else() + set(HAL_USE_UART_OPTION FALSE CACHE INTERNAL "HAL OneWire for nanoFramework.Devices.OneWire") +endif() + +if( API_System.Net OR + API_Windows.Networking.Sockets) + + # set NETWORKING option to true + set(USE_NETWORKING_OPTION TRUE CACHE INTERNAL "NF feature NETWORKING") + + # set Security module to use + if(NF_SECURITY_MBEDTLS ) + set(USE_SECURITY_MBEDTLS_OPTION TRUE CACHE INTERNAL "NF security MBEDTLS") + endif() + + if(API_Windows.Devices.Wifi) + set(USE_WIFI_OPTION TRUE CACHE INTERNAL "Wifi for Windows.Devices.WiFi") + else() + set(USE_WIFI_OPTION FALSE CACHE INTERNAL "Wifi for Windows.Devices.WiFi") + endif() + +endif() + + +if(API_Windows.Devices.Adc) + set(HAL_USE_ADC_OPTION TRUE CACHE INTERNAL "HAL ADC for Windows.Devices.Adc") +else() + set(HAL_USE_ADC_OPTION FALSE CACHE INTERNAL "HAL ADC for Windows.Devices.Adc") +endif() + + +if(API_System.Devices.Dac) + set(HAL_USE_DAC_OPTION TRUE CACHE INTERNAL "HAL DAC for System.Devices.Dac") +else() + set(HAL_USE_DAC_OPTION FALSE CACHE INTERNAL "HAL DAC for System.Devices.Dac") +endif() + + +if(API_Windows.Devices.Gpio) + set(HAL_USE_GPIO_OPTION TRUE CACHE INTERNAL "HAL GPIO for Windows.Devices.Gpio") +else() + set(HAL_USE_GPIO_OPTION FALSE CACHE INTERNAL "HAL GPIO for Windows.Devices.Gpio") +endif() + + +if(API_Windows.Devices.I2c) + set(HAL_USE_I2C_OPTION TRUE CACHE INTERNAL "HAL I2C for Windows.Devices.I2c") +else() + set(HAL_USE_I2C_OPTION FALSE CACHE INTERNAL "HAL I2C for Windows.Devices.I2c") +endif() + + +if(API_Windows.Devices.Pwm) + set(HAL_USE_PWM_OPTION TRUE CACHE INTERNAL "HAL PWM for Windows.Devices.Pwm") +else() + set(HAL_USE_PWM_OPTION FALSE CACHE INTERNAL "HAL PWM for Windows.Devices.Pwm") +endif() + + +if(API_Windows.Devices.Spi) + set(HAL_USE_SPI_OPTION TRUE CACHE INTERNAL "HAL SPI for Windows.Devices.Spi") +else() + set(HAL_USE_SPI_OPTION FALSE CACHE INTERNAL "HAL SPI for Windows.Devices.Spi") +endif() + + +if(API_nanoFramework.Devices.Can) + set(HAL_USE_CAN_OPTION TRUE CACHE INTERNAL "HAL CAN for nanoFramework.Devices.Can") +else() + set(HAL_USE_CAN_OPTION FALSE CACHE INTERNAL "HAL CAN for nanoFramework.Devices.Can") +endif() + + +if(API_nanoFramework.Devices.OneWire) + set(HAL_USE_STM32_ONEWIRE_OPTION TRUE CACHE INTERNAL "HAL STM32_ONEWIRE for nanoFramework.Devices.OneWire") +else() + set(HAL_USE_STM32_ONEWIRE_OPTION FALSE CACHE INTERNAL "HAL STM32_ONEWIRE for nanoFramework.Devices.OneWire") +endif() + +if(NF_FEATURE_HAS_SDCARD) + set(HAL_USE_SDC_OPTION TRUE CACHE INTERNAL "HAL SDC for NF_FEATURE_HAS_SDCARD") +else() + set(HAL_USE_SDC_OPTION FALSE CACHE INTERNAL "HAL SDC for NF_FEATURE_HAS_SDCARD") +endif() + +if(NF_FEATURE_HAS_USB_MSD) + set(HAL_USBH_USE_MSDC_OPTION TRUE CACHE INTERNAL "HAL USBH_USE_MSD for NF_FEATURE_HAS_USB_MSD") +else() + set(HAL_USBH_USE_MSDC_OPTION FALSE CACHE INTERNAL "HAL USBH_USE_MSD for NF_FEATURE_HAS_USB_MSD") +endif() + +################################################################# +# manage dependent APIs required for some API namespaces +################################################################# + +# include nanoFramework.Runtime.Events API +if( API_nanoFramework.Devices.OneWire OR + API_System.Net OR + API_Windows.Devices.Gpio OR + API_Windows.Devices.SerialCommunication OR + API_Windows.Networking.Sockets OR + API_nanoFramework.Devices.Can OR + API_Windows.Storage) + + # these APIs requires nanoFramework.Runtime.Events + set(API_nanoFramework.Runtime.Events ON CACHE INTERNAL "enable of API_nanoFramework.Runtime.Events") + +endif() + +if(API_System.Net) + # manage inclusion of SNTP + if(NF_NETWORKING_SNTP) + set(API_nanoFramework.Networking.Sntp ON CACHE INTERNAL "enable API_nanoFramework.Networking.Sntp") + else() + set(API_nanoFramework.Networking.Sntp OFF CACHE INTERNAL "disable API_nanoFramework.Networking.Sntp") + endif() +endif() + + +################################################################# +# handles Networking support at HAL level + +if(USE_NETWORKING_OPTION) + set(HAL_USE_MAC_OPTION TRUE CACHE INTERNAL "HAL MAC for USE_NETWORKING_OPTION") + + if(NF_SECURITY_MBEDTLS) + message(STATUS "Support for networking enabled with security from mbedTLS") + elseif(RTOS_TI_SIMPLELINK_CHECK) + message(STATUS "Support for networking enabled with security") + else() + message(STATUS "Support for networking enabled WITHOUT security") + endif() + + # sanity check for missing configuration block option + # which is required for network + + if(NOT NF_FEATURE_HAS_CONFIG_BLOCK) + message(FATAL_ERROR "\n\nERROR: network build requires NF_FEATURE_HAS_CONFIG_BLOCK build option to be 'ON'. Make sure you have that on your cmake-variants or in the build command line.") + endif() + +else() + set(HAL_USE_MAC_OPTION FALSE CACHE INTERNAL "HAL MAC for USE_NETWORKING_OPTION") + message(STATUS "Support for networking IS NOT enabled") +endif() + +################################################################# + + +################################################################# +# enables filesysytem support in nanoCLR + +if(NF_FEATURE_HAS_SDCARD OR NF_FEATURE_HAS_USB_MSD) + set(USE_FILESYSTEM_OPTION TRUE CACHE INTERNAL "NF feature FILESYSTEM") +else() + set(USE_FILESYSTEM_OPTION FALSE CACHE INTERNAL "NF feature FILESYSTEM") +endif() + +################################################################# + + +################################################################# +# RTC (real time clock) (default is OFF so RTC is NOT included) +option(NF_FEATURE_RTC "option to use hardware RTC") + +if(NF_FEATURE_RTC) + set(HAL_USE_RTC_OPTION TRUE CACHE INTERNAL "NF feature RTC") +else() + set(HAL_USE_RTC_OPTION FALSE CACHE INTERNAL "NF feature RTC") +endif() + +################################################################# + +################################################################# +# CPU watchdog (default is ON so watchdog is included) +option(NF_FEATURE_WATCHDOG "option to use hardware watchdog" ON) + +if(NF_FEATURE_WATCHDOG) + set(HAL_USE_WDG_OPTION TRUE CACHE INTERNAL "NF feature watchdog") +else() + set(HAL_USE_WDG_OPTION FALSE CACHE INTERNAL "NF feature watchdog") +endif() + +################################################################# + +####################### +# ChibiOS +if(RTOS_CHIBIOS_CHECK) + + # Define base path for the class libraries + set(BASE_PATH_FOR_CLASS_LIBRARIES_MODULES "${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nanoCLR") + + add_subdirectory(targets/CMSIS-OS/ChibiOS) + add_subdirectory(targets/CMSIS-OS/common) + add_subdirectory(targets/CMSIS-OS/common/Include) + add_subdirectory(targets/CMSIS-OS/nanoBooter) + add_subdirectory(targets/CMSIS-OS/nanoCLR) + + # now add the subdirectory for the board + # try to find board in the targets folder + if(EXISTS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}) + + # board found + message(STATUS "Support for target board '${CHIBIOS_BOARD}' found") + message(STATUS "${CHIBIOS_BOARD_DEFINITIONS_LOCATION}") + + # add TARGET board directory + add_subdirectory("${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}") + + else() + + # try to find board in the Community targets folder + if(EXISTS ${PROJECT_SOURCE_DIR}/targets-community/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}) + # board found + message(STATUS "Support for target board '${CHIBIOS_BOARD}' found in Community targets") + message(STATUS "${CHIBIOS_BOARD_DEFINITIONS_LOCATION}") + + # add TARGET board directory from Community + add_subdirectory("targets-community/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}") + else() + # board NOT found in targets folder + # board NOT found in targets folder + message(FATAL_ERROR "\n\nSorry but support for ${CHIBIOS_BOARD} target is not available...\n\You can wait for that to be added or you might want to contribute and start working on a PR for that.\n\n") + endif() + + endif() + +####################### +# FreeRTOS_ESP32 +elseif(RTOS_FREERTOS_ESP32_CHECK) + + if("${TARGET_SERIES}" STREQUAL "ESP32") + message(STATUS "Platform ESP32 target board: ${ESP32_BOARD}") + + # check watchdog feature + # EPS32 build has watchdog enabled by default, so setting it to OFF doens't make sense + # becuase the build system can't honour that preference + if(NOT NF_FEATURE_WATCHDOG) + message(FATAL_ERROR "\n\nESP32 watchdog is enabled by default in so you can't have the NF_FEATURE_WATCHDOG option set to OFF.\n\n") + endif() + + # Define base path for the class libraries + set(BASE_PATH_FOR_CLASS_LIBRARIES_MODULES "${PROJECT_SOURCE_DIR}/targets/FreeRTOS_ESP32/${ESP32_BOARD}/nanoCLR") + + add_subdirectory(targets/FreeRTOS_ESP32) + + # set target base location + set(TARGET_BASE_LOCATION "${PROJECT_SOURCE_DIR}/targets/FreeRTOS_ESP32/${ESP32_BOARD}") + add_subdirectory(targets/FreeRTOS_ESP32/${ESP32_BOARD}) + + endif() + +####################### +# TI_SIMPLELINK +elseif(RTOS_TI_SIMPLELINK_CHECK) + + add_subdirectory(targets/TI-SimpleLink) + +endif() diff --git a/source/native/nf-interpreter/CMakeSettings.SAMPLE.json b/source/native/nf-interpreter/CMakeSettings.SAMPLE.json new file mode 100644 index 00000000..a18ff205 --- /dev/null +++ b/source/native/nf-interpreter/CMakeSettings.SAMPLE.json @@ -0,0 +1,519 @@ +{ + "configurations": [ + { + "name": "ESP32", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "gcc-arm" ], + "environments": [ { "PATH": "C:\\Windows\\system32;${env.PATH}" } ], + "buildRoot": "${workspaceRoot}/Build\\${name}", + "installRoot": "${workspaceRoot}/Build/install/${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "intelliSenseMode": "linux-gcc-arm", + "variables": [ + { + "name": "EXECUTABLE_OUTPUT_PATH", + "value": "${workspaceRoot}/Build/${name}", + "type": "PATH" + }, + { + "name": "ESP32_TOOLCHAIN_PATH", + "value": "C:/ESP32_TOOLS", + "type": "PATH" + }, + { + "name": "TOOLCHAIN_PREFIX", + "value": "C:/ESP32_TOOLS", + "type": "PATH" + }, + { + "name": "ESP32_IDF_PATH", + "value": "C:/ESP32_TOOLS/esp-idf-v3.3", + "type": "PATH" + }, + { + "name": "ESP32_LIBS_PATH", + "value": "C:/ESP32_TOOLS/libs-v3.3", + "type": "PATH" + }, + { + "name": "CMAKE_SYSTEM_NAME", + "value": "Generic", + "type": "STRING" + }, + { + "name": "GIT_EXECUTABLE", + "value": "${env.VSINSTALLDIR}/Common7/IDE/CommonExtensions/Microsoft/TeamFoundation/Team Explorer/Git/cmd/git.exe", + "type": "FILEPATH" + }, + { + "name": "GIT_VERSION_STRING", + "value": "2.19.0", + "type": "STRING" + }, + { + "name": "TARGET_SERIES", + "value": "ESP32", + "type": "STRING" + }, + { + "name": "ESP32_BOARD", + "value": "ESP32_WROOM_32", + "type": "STRING" + }, + { + "name": "USE_RNG", + "value": "True", + "type": "BOOL" + }, + { + "name": "TARGET_LIGHT_MATH", + "value": "FALSE", + "type": "BOOL" + }, + { + "name": "TARGET_DP_FLOATINGPOINT", + "value": "FALSE", + "type": "BOOL" + }, + { + "name": "TARGET_SUPPORT_ANY_BASE_CONVERSION", + "value": "FALSE", + "type": "BOOL" + }, + { + "name": "RTOS", + "value": "FREERTOS_ESP32", + "type": "STRING" + }, + { + "name": "NF_BUILD_RTM", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_ERRORS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_HEADERS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_STATE", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_NODATA", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_ALL", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_IMPLEMENTS_CRC32", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_DEBUGGER", + "value": "True", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_RTC", + "value": "True", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_USE_APPDOMAINS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_WATCHDOG", + "value": "True", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_HAS_CONFIG_BLOCK", + "value": "True", + "type": "BOOL" + }, + { + "name": "NF_PLATFORM_NO_CLR_TRACE", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_CLR_NO_IL_INLINE", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_INTEROP_ASSEMBLIES", + "value": "False", + "type": "BOOL" + }, + { + "name": "NF_NETWORKING_SNTP", + "value": "True", + "type": "BOOL" + }, + { + "name": "NF_SECURITY_MBEDTLS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "API_nanoFramework.Devices.OneWire", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_System.Math", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_nanoFramework.ResourceManager", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_System.Net", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Adc", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_System.Devices.Dac", + "value": "False", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Gpio", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.I2c", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Pwm", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.SerialCommunication", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Spi", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Wifi", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Networking.Sockets", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "API_Windows.Storage", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Hardware.Esp32", + "value": "True", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_USE_SPIFFS", + "value": "False", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_HAS_SDCARD", + "value": "True", + "type": "BOOL" + } + ] + }, + { + "name": "STM769IDiscovery", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "gcc-arm" ], + "environments": [ { "PATH": "C:\\Windows\\system32;${env.PATH}" } ], + "buildRoot": "${env.nfRoot}Build/${name}", + "installRoot": "${workspaceRoot}/Build/install/${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "intelliSenseMode": "linux-gcc-arm", + "variables": [ + { + "name": "EXECUTABLE_OUTPUT_PATH", + "value": "${workspaceRoot}/Build/${name}", + "type": "STRING" + }, + { + "name": "TOOLCHAIN_PREFIX", + "value": "${env.GNU_GCC_TOOLCHAIN_PATH}", + "type": "PATH" + }, + { + "name": "CMAKE_SYSTEM_NAME", + "value": "Generic", + "type": "STRING" + }, + { + "name": "TARGET_SERIES", + "value": "STM32F7xx", + "type": "STRING" + }, + { + "name": "CHIBIOS_BOARD", + "value": "ST_STM32F769I_DISCOVERY", + "type": "STRING" + }, + { + "name": "CHIBIOS_SOURCE", + "value": "C:/usr/src/NanoFramework/ChibiOS", + "type": "PATH" + }, + { + "name": "CHIBIOS_VERSION", + "value": "", + "type": "STRING" + }, + { + "name": "USE_RNG", + "value": "ON", + "type": "BOOL" + }, + { + "name": "TARGET_LIGHT_MATH", + "value": "FALSE", + "type": "BOOL" + }, + { + "name": "TARGET_DP_FLOATINGPOINT", + "value": "FALSE", + "type": "BOOL" + }, + { + "name": "TARGET_SUPPORT_ANY_BASE_CONVERSION", + "value": "ON", + "type": "BOOL" + }, + { + "name": "TOOL_HEX2DFU_PREFIX", + "value": "${env.HEX2DFU_PATH}", + "type": "PATH" + }, + { + "name": "RTOS", + "value": "CHIBIOS", + "type": "STRING" + }, + { + "name": "SWO_OUTPUT_OPTION", + "value": "TRUE", + "type": "BOOL" + }, + { + "name": "NF_BUILD_RTM", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_ERRORS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_HEADERS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_STATE", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_NODATA", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_TRACE_ALL", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_WP_IMPLEMENTS_CRC32", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_DEBUGGER", + "value": "ON", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_RTC", + "value": "ON", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_USE_APPDOMAINS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_WATCHDOG", + "value": "ON", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_HAS_CONFIG_BLOCK", + "value": "ON", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_HAS_SDCARD", + "value": "ON", + "type": "BOOL" + }, + { + "name": "NF_PLATFORM_NO_CLR_TRACE", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_CLR_NO_IL_INLINE", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_INTEROP_ASSEMBLIES", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_NETWORKING_SNTP", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "NF_SECURITY_MBEDTLS", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "MBEDTLS_SOURCE", + "value": "", + "type": "PATH" + }, + { + "name": "API_nanoFramework.Devices.OneWire", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_System.Math", + "value": "ON", + "type": "BOOL" + }, + { + "name": "API_System.Net", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Adc", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_System.Devices.Dac", + "value": "False", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Gpio", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.I2c", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Pwm", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.SerialCommunication", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Devices.Spi", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Windows.Networking.Sockets", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "API_Windows.Storage", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_nanoFramework.Devices.Can", + "value": "True", + "type": "BOOL" + }, + { + "name": "API_Hardware.Esp32", + "value": "OFF", + "type": "BOOL" + }, + { + "name": "API_Hardware.Stm32", + "value": "True", + "type": "BOOL" + } + ] + } + ] +} \ No newline at end of file diff --git a/source/native/nf-interpreter/CMakeSettings.json b/source/native/nf-interpreter/CMakeSettings.json new file mode 100644 index 00000000..4f1b76b0 --- /dev/null +++ b/source/native/nf-interpreter/CMakeSettings.json @@ -0,0 +1,460 @@ +{ + "configurations": [ + { + "name": "STM769IDiscovery", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "gcc-arm" + ], + "environments": [ + { + "PATH": "C:\\Windows\\system32;${env.PATH}" // Work around for Ninja not finding Cmd.exe with add_custom_command + } + ], + "buildRoot": "${env.nfRoot}Build/${name}", + "installRoot": "${workspaceRoot}/Build/install/${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "intelliSenseMode": "linux-gcc-arm", + "variables": [ + { + "name": "EXECUTABLE_OUTPUT_PATH", + "value": "${workspaceRoot}/Build/${name}" + }, + { + "name": "TOOLCHAIN_PREFIX:PATH", + "value": "${env.GNU_GCC_TOOLCHAIN_PATH}" + }, + { + "name": "CMAKE_SYSTEM_NAME", + "value": "Generic" + }, + { + "name": "GIT_EXECUTABLE", + "value": "${env.VSINSTALLDIR}/Common7/IDE/CommonExtensions/Microsoft/TeamFoundation/Team Explorer/Git/cmd/git.exe" + }, + { + "name": "GIT_VERSION_STRING", + "value": "2.19.0" + }, + { + "name": "TARGET_SERIES:STRING", + "value": "STM32F7xx" + }, + { + "name": "CHIBIOS_BOARD:STRING", + "value": "ST_STM32F769I_DISCOVERY" + }, + { + "name": "CHIBIOS_SOURCE:PATH", // manually download, problems at the moment with value="" which forces a auto copy; causes failure with access denied at build? ( on .git directory) + "value": "C:/usr/src/NanoFramework/ChibiOS" + }, + { + "name": "CHIBIOS_VERSION", // default blank, set to specific version ( Not working with Visual Studio, clone and checkout specific manually) + "value": "" + }, + { + "name": "USE_RNG:BOOL", //option to enable use of true random generator hardware block + "value": "ON" + }, + { + "name": "TARGET_LIGHT_MATH:BOOL", //option to build without complex math function + "value": "FALSE" + }, + { + "name": "TARGET_DP_FLOATINGPOINT:BOOL", + "value": "FALSE" + }, + { + "name": "TARGET_SUPPORT_ANY_BASE_CONVERSION:BOOL", //"Option for string conversion to value from base 10 and partial for 16" + "value": "ON" + }, + { + "name": "TOOL_HEX2DFU_PREFIX:PATH", //"PATH for HEX TOOL" + "value": "${env.HEX2DFU_PATH}" + }, + { + "name": "RTOS:STRING", //"Selected Operating system + "value": "CHIBIOS" + }, + { + "name": "SWO_OUTPUT_OPTION:BOOL", // Single Wire Output Option + "value": "TRUE" + }, + { + "name": "NF_BUILD_RTM:BOOL", // OFF-default-ON-to-enable-RTM-build + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_ERRORS:BOOL", //OFF-default-ON-to-enable-trace-error-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_HEADERS:BOOL", //OFF-default-ON-to-enable-trace-header-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_STATE:BOOL", //OFF-default-ON-to-enable-trace-state-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_NODATA:BOOL", //OFF-default-ON-to-enable-trace-no-data-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_ALL:BOOL", //OFF-default-ON-to-enable-trace-all-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_IMPLEMENTS_CRC32:BOOL", //OFF-default-ON-to-enable-CRC32-wire-protocol + "value": "OFF" + }, + { + "name": "NF_FEATURE_DEBUGGER:BOOL", //OFF-default-ON-to-include-managed-app-debugging-capability + "value": "OFF" + }, + { + "name": "NF_FEATURE_RTC:BOOL", //OFF-default-ON-to-enable-hardware-RTC + "value": "ON" + }, + { + "name": "NF_FEATURE_USE_APPDOMAINS:BOOL", //OFF-default-ON-to-enable-support-for-Application-Domains + "value": "OFF" + }, + { + "name": "NF_FEATURE_WATCHDOG:BOOL", //ON-to-enable-hardware-watchdog-ON-is-default + "value": "ON" + }, + { + "name": "NF_FEATURE_HAS_CONFIG_BLOCK:BOOL", //OFF-default-ON-to-enable-configuration-block-storage + "value": "ON" + }, + { + "name": "NF_FEATURE_HAS_SDCARD:BOOL", //OFF-default-ON-to-enable-sd-card + "value": "ON" + }, + { + "name": "NF_PLATFORM_NO_CLR_TRACE:BOOL", //OFF-default-ON-to-disable-all-trace-on-CLR + "value": "OFF" + }, + { + "name": "NF_CLR_NO_IL_INLINE:BOOL", //OFF-default-ON-to-disable-CLR-IL-inlining + "value": "OFF" + }, + { + "name": "NF_INTEROP_ASSEMBLIES:BOOL", //OFF-default-ON-to-disable-CLR-IL-inlining + "value": "OFF" + }, + { + "name": "NF_NETWORKING_SNTP:BOOL", //ON-default-to-add-SNTP-client-requires-networking + "value": "ON" + }, + { + "name": "NF_SECURITY_MBEDTLS:BOOL", //OFF-default-ON-to-add-network-security-from-mbedTLS + "value": "ON" + }, + { + "name": "MBEDTLS_SOURCE:PATH", //path-to-mbedtls-source-mind-the-forward-slashes + "value": "" + }, + // LIBRARIES + { + "name": "API_nanoFramework.Devices.OneWire:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_System.Math:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_System.Net:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Adc:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_System.Devices.Dac:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Gpio:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.I2c:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Pwm:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.SerialCommunication:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Spi:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Networking.Sockets:BOOL", //OFF-default-ON-to-add-this-API + "value": "OFF" + }, + { + "name": "API_Windows.Storage:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_nanoFramework.Devices.Can:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Hardware.Esp32:BOOL", //OFF-default-ON-to-add-this-API + "value": "OFF" + }, + { + "name": "API_Hardware.Stm32:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + } + ] + }, + { + "name": "ESP32", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "gcc-arm" + ], + "environments": [ + { + // Work around for Ninja not finding Cmd.exe with add_custom_command + "PATH": "C:\\Windows\\system32;C:\\Program Files\\Espressif\\ESP-IDF Tools\\mconf-idf;c:\\python27;${env.PATH}", + + // ESP32 paths set up in environment so we can use in variables + "ESP32_IDF_VERSION": "v3.3", + "ESP32_TOOLS": "C:\\ESP32_TOOLS", + "ESP32_IDF": "${env.ESP32_TOOLS}\\esp-idf-${env.ESP32_IDF_VERSION}", + "ESP32_LIB": "${env.ESP32_TOOLS}\\libs-${env.ESP32_IDF_VERSION}", + "ESP32_MBEDTLS_SOURCE": "${env.ESP32_IDF}/Components/mbedtls/mbedtls", + + "IDF_PATH": "${env.ESP32_IDF}" + } + ], + "buildRoot": "${workspaceRoot}/Build\\${name}", + "installRoot": "${workspaceRoot}/Build/install/${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "intelliSenseMode": "linux-gcc-arm", + "variables": [ + { + "name": "EXECUTABLE_OUTPUT_PATH", + "value": "${workspaceRoot}/Build/${name}" + }, + { + "name": "ESP32_TOOLCHAIN_PATH:PATH", + "value": "${env.ESP32_TOOLS}" + }, + { + "name": "TOOLCHAIN_PREFIX:PATH", + "value": "${env.ESP32_TOOLS}" + }, + { + "name": "ESP32_IDF_PATH:PATH", + "value": "${env.ESP32_IDF}" + }, + { + "name": "ESP32_LIBS_PATH:PATH", + "value": "${env.ESP32_LIB}" + }, + { + "name": "CMAKE_SYSTEM_NAME:STRING", + "value": "Generic" + }, + { + "name": "GIT_EXECUTABLE:FILEPATH", + "value": "${env.VSINSTALLDIR}/Common7/IDE/CommonExtensions/Microsoft/TeamFoundation/Team Explorer/Git/cmd/git.exe" + }, + { + "name": "GIT_VERSION_STRING:STRING", + "value": "2.19.0" + }, + { + "name": "TARGET_SERIES:STRING", + "value": "ESP32" + }, + { + "name": "ESP32_BOARD:STRING", + "value": "ESP32_WROOM_32" + }, + { + "name": "USE_RNG:BOOL", //option to enable use of true random generator hardware block + "value": "ON" + }, + { + "name": "TARGET_LIGHT_MATH:BOOL", //option to build without complex math function + "value": "FALSE" + }, + { + "name": "TARGET_DP_FLOATINGPOINT:BOOL", + "value": "TRUE" + }, + { + "name": "TARGET_SUPPORT_ANY_BASE_CONVERSION:BOOL", //"Option for string conversion to value from base 10 and partial for 16" + "value": "FALSE" + }, + { + "name": "RTOS:STRING", //"Selected Operating system + "value": "FREERTOS_ESP32" + }, + { + "name": "NF_BUILD_RTM:BOOL", // OFF-default-ON-to-enable-RTM-build + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_ERRORS:BOOL", //OFF-default-ON-to-enable-trace-error-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_HEADERS:BOOL", //OFF-default-ON-to-enable-trace-header-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_STATE:BOOL", //OFF-default-ON-to-enable-trace-state-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_NODATA:BOOL", //OFF-default-ON-to-enable-trace-no-data-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_TRACE_ALL:BOOL", //OFF-default-ON-to-enable-trace-all-messages-wire-protocol + "value": "OFF" + }, + { + "name": "NF_WP_IMPLEMENTS_CRC32:BOOL", //OFF-default-ON-to-enable-CRC32-wire-protocol + "value": "OFF" + }, + { + "name": "NF_FEATURE_DEBUGGER:BOOL", //OFF-default-ON-to-include-managed-app-debugging-capability + "value": "ON" + }, + { + "name": "NF_FEATURE_RTC:BOOL", //OFF-default-ON-to-enable-hardware-RTC + "value": "ON" + }, + { + "name": "NF_FEATURE_USE_APPDOMAINS:BOOL", //OFF-default-ON-to-enable-support-for-Application-Domains + "value": "OFF" + }, + { + "name": "NF_FEATURE_WATCHDOG:BOOL", //ON-to-enable-hardware-watchdog-ON-is-default + "value": "ON" + }, + { + "name": "NF_FEATURE_HAS_CONFIG_BLOCK:BOOL", //OFF-default-ON-to-enable-configuration-block-storage + "value": "ON" + }, + { + "name": "NF_PLATFORM_NO_CLR_TRACE:BOOL", //OFF-default-ON-to-disable-all-trace-on-CLR + "value": "OFF" + }, + { + "name": "NF_CLR_NO_IL_INLINE:BOOL", //OFF-default-ON-to-disable-CLR-IL-inlining + "value": "OFF" + }, + { + "name": "NF_INTEROP_ASSEMBLIES:BOOL", //OFF-default-ON-to-disable-CLR-IL-inlining + "value": "OFF" + }, + { + "name": "NF_NETWORKING_SNTP:BOOL", //ON-default-to-add-SNTP-client-requires-networking + "value": "ON" + }, + { + "name": "NF_SECURITY_MBEDTLS:BOOL", + "value": "ON" + }, + { + "name": "MBEDTLS_SOURCE:PATH", //path-to-mbedtls-source-mind-the-forward-slashes + "value": "${env.ESP32_MBEDTLS_SOURCE}" + }, + // LIBRARIES + { + "name": "API_nanoFramework.Devices.OneWire:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_System.Math:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_System.Net:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_nanoFramework.ResourceManager:BOOL", + "value": "ON" + }, + { + "name": "API_Windows.Devices.Adc:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_System.Devices.Dac:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Gpio:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.I2c:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Pwm:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.SerialCommunication:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Spi:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Windows.Devices.Wifi:BOOL", + "value": "True" + }, + { + "name": "API_Windows.Networking.Sockets:BOOL", //OFF-default-ON-to-add-this-API + "value": "OFF" + }, + { + "name": "API_Windows.Storage:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "API_Hardware.Esp32:BOOL", //OFF-default-ON-to-add-this-API + "value": "ON" + }, + { + "name": "NF_FEATURE_USE_SPIFFS", + "value": "False", + "type": "BOOL" + }, + { + "name": "NF_FEATURE_HAS_SDCARD", + "value": "True", + "type": "BOOL" + } + ] + } + ] +} diff --git a/source/native/nf-interpreter/InteropAssemblies/CLR_RT_InteropAssembliesTable.cpp.in b/source/native/nf-interpreter/InteropAssemblies/CLR_RT_InteropAssembliesTable.cpp.in new file mode 100644 index 00000000..78ae4af5 --- /dev/null +++ b/source/native/nf-interpreter/InteropAssemblies/CLR_RT_InteropAssembliesTable.cpp.in @@ -0,0 +1,23 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#include + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Native; +@CLR_RT_NativeAssemblyDataDeclarations@ + +const CLR_RT_NativeAssemblyData *g_CLR_InteropAssembliesNativeData[] = +{ + &g_CLR_AssemblyNative_mscorlib, + &g_CLR_AssemblyNative_nanoFramework_Runtime_Native, + @CLR_RT_NativeAssemblyDataTableEntries@ + NULL +}; diff --git a/source/native/nf-interpreter/InteropAssemblies/README.md b/source/native/nf-interpreter/InteropAssemblies/README.md new file mode 100644 index 00000000..ff8e08be --- /dev/null +++ b/source/native/nf-interpreter/InteropAssemblies/README.md @@ -0,0 +1,6 @@ + +This folder contains the configuration file for the Assemblies Table collection. + +It's a placeholder for the Interop assemblies source files. +The source files for each Interop assembly should be placed in it's own folder. +Anything inside this folder is ignored by an exception pattern in .gitignore file. diff --git a/source/native/nf-interpreter/LICENSE.md b/source/native/nf-interpreter/LICENSE.md new file mode 100644 index 00000000..44a0d2d8 --- /dev/null +++ b/source/native/nf-interpreter/LICENSE.md @@ -0,0 +1,192 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + Copyright 2017 The nanoFramework project contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/source/native/nf-interpreter/README.md b/source/native/nf-interpreter/README.md new file mode 100644 index 00000000..a7ee1155 --- /dev/null +++ b/source/native/nf-interpreter/README.md @@ -0,0 +1,103 @@ +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![#yourfirstpr](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](https://github.com/nanoframework/Home/blob/master/CONTRIBUTING.md) + [![Discord](https://img.shields.io/discord/478725473862549535.svg)](https://discord.gg/gCyBu8T) + + +![nanoFramework logo](https://github.com/nanoframework/Home/blob/master/resources/logo/nanoFramework-repo-logo.png) + +----- +Document Language: [English](README.md) | [中文简体](README.zh-cn.md) + +### Welcome to the **nanoFramework** Interpreter repository! + +This repo contains: + +* **nanoFramework** agnostic blocks + * [CLR](src/CLR) + * [HAL](src/HAL) + * [PAL](src/PAL) +* Target reference for CMSIS OS + * [ChibiOS](targets/CMSIS-OS/ChibiOS) + * Reference target boards + * [Mikrobus QUAIL](targets/CMSIS-OS/ChibiOS/MBN_QUAIL) + * [ST NUCLEO64 F091RC](targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC) + * [ST STM32F429I DISCOVERY](targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY) + * [ST STM32F769I DISCOVERY](targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY) + * [Wilderness Labs Netduino3 WiFi](targets/CMSIS-OS/ChibiOS/NETDIUNO3_WIFI) + * ChibiOS overlay for **nanoFramework** + * [STM32 1.Wire driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_onewire) + * [STM32 CRC32 driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc) + * [STM32 Flash driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_flash) + * [STM32 Flexible Memory Controller driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc) + * [STM32 Random number generator driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng) +* Target reference for FreeRTOS + * [ESP32_WROOM_32](targets/FreeRTOS_ESP32/ESP32_WROOM_32) +* Target references for TI SimpleLink + * [TI CC3220SF_LAUNCHXL](targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL) +* Target reference for other OSes + * [Win32 OS (test project only at this time)](targets/os/win32) +* [CMake files for the build system](CMake) + + +## Build status + +| Component | Build Status | Build Status (develop) | +|:-|---|---| +| nanoBooter + nanoCLR | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=master)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=master) | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=develop)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=develop) | +| Win32 test project | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=master)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=master) | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=develop)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=develop) | + + +## Firmware for reference boards + + +Each of the following ZIP files contains the image files for nanoBooter and nanoCLR in various formats (HEX, BIN and DFU). They should be flashed in the target boards using an appropriate software utility. + +The **stable** versions are RTM builds with the smallest possible size. They include the latest stable version. The debugging feature is disabled and only minimal (or none) error messages. + +The **preview** versions are continuous builds of the reference targets. They include the latest version of all features and bug corrections. They also have the debugging feature enabled along with detailed error messages. + + +| Target | Stable | Preview | +|:-|---|---| +| ST_STM32F429I_DISCOVERY | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ST_STM32F429I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ST_STM32F429I_DISCOVERY/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ST_STM32F429I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ST_STM32F429I_DISCOVERY/_latestVersion) | +| ST_NUCLEO64_F091RC | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ST_NUCLEO64_F091RC/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ST_NUCLEO64_F091RC/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ST_NUCLEO64_F091RC/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ST_NUCLEO64_F091RC/_latestVersion) | +| ST_STM32F769I_DISCOVERY | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ST_STM32F769I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ST_STM32F769I_DISCOVERY/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ST_STM32F769I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ST_STM32F769I_DISCOVERY/_latestVersion) | +| MBN_QUAIL | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/MBN_QUAIL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/MBN_QUAIL/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/MBN_QUAIL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/MBN_QUAIL/_latestVersion) | +| NETDUINO3_WIFI | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/NETDUINO3_WIFI/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/NETDUINO3_WIFI/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/NETDUINO3_WIFI/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/NETDUINO3_WIFI/_latestVersion) | +| ESP32_WROOM_32 | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ESP32_WROOM_32/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ESP32_WROOM_32/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ESP32_WROOM_32/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ESP32_WROOM_32/_latestVersion) | +| TI_CC3220SF_LAUNCHXL | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/TI_CC3220SF_LAUNCHXL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/TI_CC3220SF_LAUNCHXL/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/TI_CC3220SF_LAUNCHXL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/TI_CC3220SF_LAUNCHXL/_latestVersion) | + + +The above firmware builds include support for the class libraries and features marked below. + + +| Target | Gpio | Spi | I2c | Pwm | Adc | Dac | Serial | OneWire | Events | SWO | Networking | Large Heap | +|:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: | +| ST_STM32F429I_DISCOVERY | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | +| ST_NUCLEO64_F091RC | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | +| ST_STM32F769I_DISCOVERY | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| MBN_QUAIL | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | | +| NETDUINO3_WIFI | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | | +| ESP32_WROOM_32 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | | +| TI_CC3220SF_LAUNCHXL | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | | :heavy_check_mark: | | :heavy_check_mark: | | + + +## Feedback and documentation + +For documentation, providing feedback, issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home). + +Join our Discord community [here](https://discord.gg/gCyBu8T). + + +## Credits + +The list of contributors to this project can be found at [CONTRIBUTORS](https://github.com/nanoframework/Home/blob/master/CONTRIBUTORS.md). + + +## License + +The nanoFramework Interpreter is licensed under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). + + +## Code of Conduct +This project has adopted the code of conduct defined by the [Contributor Covenant](CODE_OF_CONDUCT.md) +to clarify expected behavior in our community. diff --git a/source/native/nf-interpreter/README.zh-cn.md b/source/native/nf-interpreter/README.zh-cn.md new file mode 100644 index 00000000..7cdd04f7 --- /dev/null +++ b/source/native/nf-interpreter/README.zh-cn.md @@ -0,0 +1,101 @@ +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![#yourfirstpr](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](https://github.com/nanoframework/Home/blob/master/CONTRIBUTING.md) + [![Discord](https://img.shields.io/discord/478725473862549535.svg)](https://discord.gg/gCyBu8T) + + +![nanoFramework logo](https://github.com/nanoframework/Home/blob/master/resources/logo/nanoFramework-repo-logo.png) + +----- +文档语言: [English](README.md) | [中文简体](README.zh-cn.md) + +### 欢迎使用 **nanoFramework** 解析器! + +本库包括: + +* **nanoFramework** 核心板块 + * [CLR](src/CLR) + * [HAL](src/HAL) + * [PAL](src/PAL) +* CMSIS OS 移植 + * [ChibiOS](targets/CMSIS-OS/ChibiOS) + * 板卡移植 + * [Mikrobus QUAIL](targets/CMSIS-OS/ChibiOS/MBN_QUAIL) + * [ST NUCLEO64 F091RC](targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC) + * [ST STM32F429I DISCOVERY](targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY) + * [ST STM32F769I DISCOVERY](targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY) + * [Wilderness Labs Netduino3 WiFi](targets/CMSIS-OS/ChibiOS/NETDIUNO3_WIFI) + * ChibiOS 增强 **nanoFramework** + * [STM32 1.Wire driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_onewire) + * [STM32 CRC32 driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc) + * [STM32 Flash driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_flash) + * [STM32 Flexible Memory Controller driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc) + * [STM32 Random number generator driver](targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng) +* FreeRTOS 移植 + * [ESP32_WROOM_32](targets/FreeRTOS_ESP32/ESP32_WROOM_32) +* TI SimpleLink 移植 + * [TI CC3220SF_LAUNCHXL](targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL) +* 其它系统移植 + * [Win32 OS (test project only at this time)](targets/os/win32) +* [CMake 编译文件](CMake) + + +## 编译状态 + +| 组件 | 编译状态 | 编译状态(开发) | +|:-|---|---| +| nanoBooter + nanoCLR | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=master)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=master) | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=develop)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=develop) | +| Win32 test project | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=master)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=master) | [![Build Status](https://dev.azure.com/nanoframework/nf-interpreter/_apis/build/status/nanoframework.nf-interpreter?branchName=develop)](https://dev.azure.com/nanoframework/nf-interpreter/_build/latest?definitionId=34?branchName=develop) | + + +## 评估板固件 + + +以下每个ZIP文件包括了nanoBooter和nanoCLR镜像(HEX,BIN,DFU)。可以使用相应烧写工具把它们写入目标板卡中。 + +**稳定** 版是RTM最小大小编译。它包含了最后稳定版本,关闭调试功能,仅有最少或没有错误信息。 +**预览** 版是目标板持续编译。它包含所有功能和错误修正的最后版本,也包括调试信息和详细错误信息。 + + +| 目标 | 稳定 | 预览 | +|:-|---|---| +| ST_STM32F429I_DISCOVERY | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ST_STM32F429I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ST_STM32F429I_DISCOVERY/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ST_STM32F429I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ST_STM32F429I_DISCOVERY/_latestVersion) | +| ST_NUCLEO64_F091RC | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ST_NUCLEO64_F091RC/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ST_NUCLEO64_F091RC/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ST_NUCLEO64_F091RC/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ST_NUCLEO64_F091RC/_latestVersion) | +| ST_STM32F769I_DISCOVERY | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ST_STM32F769I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ST_STM32F769I_DISCOVERY/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ST_STM32F769I_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ST_STM32F769I_DISCOVERY/_latestVersion) | +| MBN_QUAIL | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/MBN_QUAIL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/MBN_QUAIL/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/MBN_QUAIL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/MBN_QUAIL/_latestVersion) | +| NETDUINO3_WIFI | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/NETDUINO3_WIFI/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/NETDUINO3_WIFI/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/NETDUINO3_WIFI/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/NETDUINO3_WIFI/_latestVersion) | +| ESP32_WROOM_32 | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/ESP32_WROOM_32/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/ESP32_WROOM_32/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/ESP32_WROOM_32/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/ESP32_WROOM_32/_latestVersion) | +| TI_CC3220SF_LAUNCHXL | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images/TI_CC3220SF_LAUNCHXL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images/TI_CC3220SF_LAUNCHXL/_latestVersion) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-dev/TI_CC3220SF_LAUNCHXL/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-dev/TI_CC3220SF_LAUNCHXL/_latestVersion) | + + +以上固件支持以下类库和功能。 + + +| Target | Gpio | Spi | I2c | Pwm | Adc | Dac | Serial | OneWire | Events | SWO | Networking | Large Heap | +|:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: |:-: | +| ST_STM32F429I_DISCOVERY | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | +| ST_NUCLEO64_F091RC | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | +| ST_STM32F769I_DISCOVERY | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| MBN_QUAIL | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | | +| NETDUINO3_WIFI | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | | +| ESP32_WROOM_32 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | | +| TI_CC3220SF_LAUNCHXL | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | | :heavy_check_mark: | | :heavy_check_mark: | | + + +## 文档反馈 + +有关文档、提供反馈、问题以及如何做出贡献的信息,请参阅 [Home repo](https://github.com/nanoframework/Home). + +加入我们的讨论社区 [here](https://discord.gg/gCyBu8T). + + +## Credits + +本项目贡献者可在 [CONTRIBUTORS](https://github.com/nanoframework/Home/blob/master/CONTRIBUTORS.md) 中找到。 + + +## 授权 + +nanoFramework 解析器基于 [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0) 授权。 + + +## 行为准则 +本项目采用了 [Contributor Covenant](CODE_OF_CONDUCT.md) 规范来阐明社区预期行为。 diff --git a/source/native/nf-interpreter/RunCmd.bat b/source/native/nf-interpreter/RunCmd.bat new file mode 100644 index 00000000..d998f942 --- /dev/null +++ b/source/native/nf-interpreter/RunCmd.bat @@ -0,0 +1,26 @@ + @echo off + REM Call with first parameter as timeout, number of seconds to delay after command finishes + REM Rest of parameters are the command to run and arguments to be passed to it + REM If timeout = 0, always wait for user input. timeout < 0, wait for user only if error + setlocal + set errwait=0 + set dly=%1 + if %1 lss 0 set errwait=1 & set /A dly=0-%1 + set _tail=%* + call set _tail=%%_tail:*%1=%% + %_tail% + if %ERRORLEVEL% neq 0 goto :cmderror + if %dly% equ 0 goto :waitforuser + +:tick + timeout %dly% + exit 0 + +:cmderror + Echo "Error %ERRORLEVEL% processing command" + if %errwait% equ 0 goto :tick +:waitforuser + pause + exit 0 + + diff --git a/source/native/nf-interpreter/SetNFRoot.bat b/source/native/nf-interpreter/SetNFRoot.bat new file mode 100644 index 00000000..91118ad5 --- /dev/null +++ b/source/native/nf-interpreter/SetNFRoot.bat @@ -0,0 +1,132 @@ +@echo off +REM SetNFRoot - Find/Create and return short path for current directory +REM DAV 01APR19 +setlocal + +if %1.==. goto :set_path + +:check_opts +if /I %1==-h goto :help +if /I %1==-d set rmsubst=-d + +:set_path +set _mypath=%~dp0 +call :setshortpath %_mypath% +rem pushd %shortpath% +if [%rmsubst%]==[-d] goto :remsubst +goto :end + +:remsubst +set v=%shortpath:~0,2% +echo Remove subst of %mypath% on %v% +if [%rmsubst%]==[-d] subst /D %v% +endlocal & set "nfRoot=%_mypath%" +setx nfRoot %nfRoot% >nul +echo %nfRoot% +goto :eof + +:end +:: Clear %errorlevel% +call set _a=a > nul +endlocal & set "nfRoot=%shortpath%" +setx nfRoot %nfRoot% >nul +echo %nfRoot% +rem popd +::exit +goto :eof + +:: ============ Utility commands ===== + +:: === Help +:help +echo: +echo Usage: %0 [opt] +echo: +echo opt = -d Delete subst if exists +echo opt = -h Display this help message +echo: +echo Command line tool to find or create a short directory path +echo for the current directory using the subst command +echo: +goto :eof + +REM ========================================================== +REM Utility Functions +REM +REM Call to set a short path to try avoid overflowing 250 char file path limit +:setshortpath +set "mypath=%~1" +set shortpath=%mypath% +rem echo mypath = %_mypath% + +REM Are we already on short path? +set t=%mypath:~0,3% +if /I %t%==%mypath% goto :haveshortpath + +REM Not on short path - is there already a subst for it? +FOR /F "tokens=1,3" %%G IN ('subst') DO ( + if /I "%%H\"=="%mypath%" ( + set sdg=%%G + goto :foundsubst + ) +) +REM No subst short path found - create one +call :freedrive driveletter && goto :cont +echo ERROR: No free drive letter found, staying on original path +goto :haveshortpath + +:cont +echo Found free drive letter: %driveletter% 1>&2 +pushd %mypath% +subst %driveletter% . +popd +set shortpath=%driveletter%\ +echo Created new subst for %mypath% on %driveletter% 1>&2 +echo You can remove it with subst %driveletter% /D 1>&2 +goto :haveshortpath + +:foundsubst +set shortpath=%sdg:~0,3% +echo Using existing subst for %mypath% on %shortpath% 1>&2 +goto :haveshortpath + +:haveshortpath +echo Using short path %shortpath% for %mypath% 1>&2 +REM So now we have a short path if it was possible +goto :eof + +rem Finds a free drive letter. +rem +rem Parameters: +rem %1 = Output variable name. +rem +rem Example: +rem call :freedrive mydriveletter && goto :cont +rem echo ERROR: No free drive letter found. +rem goto :EOF +rem :cont +rem echo Found drive letter: %mydriveletter% +:freedrive +setlocal EnableDelayedExpansion +set exitcode=0 +set "output_var=%~1" +for %%i in (B,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) do ( + set "drive=%%i:" + rem If 'subst' fails, the drive letter is already in use. + rem This way we can even detect optical drives that have a drive + rem letter but no media in them, a case that goes undetected when + rem using 'if exist'. + subst !drive! %SystemDrive%\ >nul + if !errorlevel! == 0 ( + subst !drive! /d >nul + goto :freedrive0 + ) +) +set exitcode=1 +set drive= +:freedrive0 +endlocal & set "%output_var%=%drive%" & exit /b %exitcode% + +:exit + +:eof diff --git a/source/native/nf-interpreter/VisualStudioDevelopment/CopyBuildOutput.cmd b/source/native/nf-interpreter/VisualStudioDevelopment/CopyBuildOutput.cmd new file mode 100644 index 00000000..4579ec18 --- /dev/null +++ b/source/native/nf-interpreter/VisualStudioDevelopment/CopyBuildOutput.cmd @@ -0,0 +1,19 @@ +Rem -------------------------------------------------------------------------------- +Rem -- Open a command prompt at your build target root to run the following commands +Rem -- For example +Rem -- Open a command prompt at "Build\" +Rem -------------------------------------------------------------------------------- + +copy nanobooter.elf ..\nanobooter.elf +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objcopy.exe" -Oihex nanobooter.elf ..\nanobooter.hex +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objcopy.exe" -Osrec nanobooter.elf ..\nanobooter.s19 +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objcopy.exe" -Obinary nanobooter.elf ..\nanobooter.bin +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objdump.exe" -d -EL -S nanobooter.elf > ..\nanobooter.lst +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-size.exe" nanobooter.elf > ..\nanobooter.size.txt + +copy nanoCLR.elf ..\nanoCLR.elf +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objcopy.exe" -Oihex nanoCLR.elf ..\nanoCLR.hex +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objcopy.exe" -Osrec nanoCLR.elf ..\nanoCLR.s19 +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objcopy.exe" -Obinary nanoCLR.elf ..\nanoCLR.bin +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-objdump.exe" -d -EL -S nanoCLR.elf > ..\nanoCLR.lst +"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Linux/gcc_arm/bin/arm-none-eabi-size.exe" nanoCLR.elf > ..\nanoCLR.size.txt diff --git a/source/native/nf-interpreter/VisualStudioDevelopment/README.md b/source/native/nf-interpreter/VisualStudioDevelopment/README.md new file mode 100644 index 00000000..b391c601 --- /dev/null +++ b/source/native/nf-interpreter/VisualStudioDevelopment/README.md @@ -0,0 +1,138 @@ +### Developing firmware for the nanoframework using Visual Studio 2017 community edition + +##### 🚧 IMPORTANT : The firmware build for Visual Studio is under construction. 🚧 +Some compromises were required to get this to a working stage. +I made a decision to put the code at the top level to reduce path length of files which caused warnings of the potential to overflow the command line. +>Hard coded paths are used to ensure it works with the current CMake coding and the Microsoft usage of CMake +>There are some issues with the CMakeSettings.json file with path separators. + +
+ + +### Directory structure for the project +Two top level directories have been created to support the development with Visual Studio. +* `c:\nanoFramework\nf-interpreter` +* `c:\nanoFramework_Tools` + +#### c:\nanoFramework\nf-interpreter +- The nf-interpreter repository is cloned to this directory. +###### c:\nanoFramework\nf-interpreter\Build +- This directory contains the build output, the files in here are transient. When the CMake cache is deleted, files in this directory are deleted. +The files in this directory are only visible when selecting "Show All Files". These files are not part of the GIT repository. +At the end of a successful build the build outputs are copied to the *\Build* directory. + +> - Note: It is sometimes necessary to delete the contents of these folders if Visual Studio misbehaves. +Using Visual Studio with CMake results in what appears to be inconsistencies at times. +Sometime the CMake server goes away, shutting down Visual Studio and restarting usually fixes the problem. +
+> - Note: After clearing the Cmake cache, on occassions the build/chibios_source directory is left empty or only containing the .git file +>due to some conflict. The current CMakeLists.txt file finds the directory and does not re-copy the code. +>It is necessary to manually delete the directory from file explorer and generate the cache for the copy to run. +>_ + +#### c:\nanoFramework_Tools\ + Manually create this directory to contain the following folders. +###### c:\nanoFramework_Tools\ChibiOS ++ Copy of the ChibiOS repository cloned from https://github.com/nanoframework/chibios.git + +###### C:\nanoFramework_Tools\Tools\openocd ++ Copy of the openocd installation http://www.freddiechopin.info/en/download/category/4-openocd ++ > Currently version 0.10.0 + +###### C:\nanoFramework_Tools\Tools\ ++ Place a copy of the hex2dfu.exe tool here + + + +### Example of the directory structure + +![](VSDevDirectoryStructure.png) + + +### Major configuration files + +##### CMakeSettings.json +> Configuration file used by Visual Studio. This is the standard configuration file for CMake development. +> This file can contain more than one configuration. In addition to setting the compiler +> toolchain, additional variables are defined to select the target hardware and operating system to build. +>###### Note: Work in progress +
+ +##### CMakeLists.txt +> This is the standard CMakeLists.txt file for the nf-intepreter + +
+ + +##### launch.vs.json +> Sets up the debugging environment using the gdbserver debugging via configurations. +> The example references the openocd application. + +
+ +#### Setup and Installation + +| Software Component | Notes | Link | +|:-|---|---| +| Visual Studio 2017 community edition |Linux development with C++| +|option|Visual C++ tools for Cmake and Linux +|option|Embedded and IoT Development|GCC version 6.3.1. December/2018 +|GCC Tool Chain - Version 8-2019-q3-update|GNU Arm Embedded Toolchain|https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads# + + +#### GCC Toolchain NOTES +> Version 6.3.1 installed by Visual Studio has a problem with fallthrough, Version 8, has a problem with structures ( an issue has been raised to fix this) + +The following GCC version has been download, installed and tested. +> GNU Arm Embedded Toolchain - Version 7-2018-q2-update + https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads# + +In CMakeSettings.json the following variables determine the build tool. + + { + "name": "TOOLCHAIN_PREFIX", + "value": "C:/Program Files (x86)/GNU Tools Arm Embedded/8 2019-q3-update" + // "value": "${env.GCCPATH}" // Standard Visual Studio Install of GCC 6.3.1 + }, + +
+#### Debugging + +The launch.vs.json file contains an example configuration for setup to debug the STM32769IDiscovery board. +Additonal configurations can be added, although the implementation of the options does not seem consistent with +the VSCODE version and some options do not appear to work properly. +Also, the whole system is a bit flakey. The openocd program is run as sub process of Visual Studio,and if it runs into problems the +system fails, and you must run up task manager to end the openocd.exe task listed as a process of Visual Studio. + + +#### Diagnosing problems with the debug and launch.vs.json + +You can get a better understanding of problems that may be occuring with the gdb/openocd debug setup. +In Visual Studio select the Command Window Ctrl+Alt+A, and turn on debug logging with the following command. + +`debug.midebuglog /On:c:\Temp\debug.log` + +Run a debugging session to collect data and turn it off with the following command. + +`debug.midebuglog /Off` + +This will give you a log of the operation and communications occuring. ( Good luck!) + + +__*An example snippet displays error for "Monitor reset halt ( not quite sure why?)*__ + + 8: (1976730) ->^done + 8: (1976730) <-1005-interpreter-exec console "monitor reset halt" + 8: (1976730) ->(gdb)` + 8: (1976741) ->&"\"monitor\" command not supported by this target.\n" + 8: (1976742) ->1005^error,msg="\"monitor\" command not supported by this target." + 8: (1976742) ->(gdb) + 8: (1976742) 1005: elapsed time 11 + 8: (1976742) <-1006-interpreter-exec console "monitor reset init" + 8: (1976742) ->&"\n" + 8: (1976742) ->^done + 8: (1976742) ->(gdb) + +#### Feedback + +If you are using this your feedback is greatly appreciated. Please join our [Discord community](https://discord.gg/gCyBu8T) and start chatting about this. diff --git a/source/native/nf-interpreter/VisualStudioDevelopment/VSDevDirectoryStructure.png b/source/native/nf-interpreter/VisualStudioDevelopment/VSDevDirectoryStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..10583bddc4d4b201d40b7668815fe2b23701d5fd GIT binary patch literal 29126 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 $null + + git init "$env:Agent_TempDirectory\repo" + cd repo > $null + git remote add origin "$env:Build_Repository_Uri" + git config --global gc.auto 0 + git config --global user.name nfbot + git config --global user.email nanoframework@outlook.com + git config --global core.autocrlf true + git -c http.extraheader="AUTHORIZATION: $auth" fetch --progress origin + + git checkout develop + + cd source + + # prepare release and capture output + $release = nbgv prepare-release + + # get commit message for the merge + $commitMessage = git log -1 --pretty=%B + + # amend commit message to skip build + git commit --amend -m "$commitMessage" -m "***NO_CI***" > $null + + # push all changes to github + git -c http.extraheader="AUTHORIZATION: $auth" push --all origin + + # get release branch name + $branch = $release.Split(' ')[0] + + # start PR for release + $prRequestBody = @{title="Release $branch";body="";head="$branch";base="master"} | ConvertTo-Json + $githubApiEndpoint = "https://api.github.com/repos/$env:Build_Repository_Name/pulls" + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + + $headers = @{} + $headers.Add("Authorization","$auth") + $headers.Add("Accept","application/vnd.github.symmetra-preview+json") + + try + { + $result = Invoke-RestMethod -Method Post -UserAgent [Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer -Uri $githubApiEndpoint -Header $headers -ContentType "application/json" -Body $prRequestBody + 'Started PR for new release...' | Write-Host -NoNewline + 'OK' | Write-Host -ForegroundColor Green + } + catch + { + $result = $_.Exception.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($result) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + + "Error starting PR: $responseBody" | Write-Host -ForegroundColor Red + } + + condition: eq( variables['StartReleaseCandidate'], true ) + displayName: NBGV prepare release + +################# +# STM32 +- job: Build_STM32_targets + condition: not( eq( dependencies.Check_Build_Options.outputs['BuildOptions.SKIP_BUILD'], true ) ) + + dependsOn: + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + strategy: + matrix: + MBN_QUAIL: + BoardName: MBN_QUAIL + BuildOptions: -DTARGET_SERIES=STM32F4xx -DRTOS=CHIBIOS -DSUPPORT_ANY_BASE_CONVERSION=ON -DNF_FEATURE_DEBUGGER=ON -DNF_FEATURE_RTC=ON -DAPI_System.Math=ON -DAPI_Hardware.Stm32=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_nanoFramework.Devices.OneWire=ON -DAPI_nanoFramework.ResourceManager=ON -DAPI_nanoFramework.System.Collections=ON + GccArm_Version: + NeedsDFU: true + NETDUINO3_WIFI: + BoardName: NETDUINO3_WIFI + BuildOptions: -DTARGET_SERIES=STM32F4xx -DRTOS=CHIBIOS -DSUPPORT_ANY_BASE_CONVERSION=ON -DNF_FEATURE_DEBUGGER=ON -DNF_FEATURE_RTC=ON -DNF_FEATURE_HAS_SDCARD=ON -DAPI_System.Math=ON -DAPI_Hardware.Stm32=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_System.Devices.Dac=OFF -DAPI_nanoFramework.Devices.OneWire=ON -DAPI_Windows.Storage=ON -DAPI_nanoFramework.ResourceManager=ON -DAPI_nanoFramework.System.Collections=ON + GccArm_Version: + NeedsDFU: true + ST_STM32F429I_DISCOVERY: + BoardName: ST_STM32F429I_DISCOVERY + BuildOptions: -DTARGET_SERIES=STM32F4xx -DRTOS=CHIBIOS -DSUPPORT_ANY_BASE_CONVERSION=ON -DNF_FEATURE_DEBUGGER=ON -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DAPI_System.Math=ON -DAPI_Hardware.Stm32=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_nanoFramework.Devices.OneWire=ON -DAPI_nanoFramework.Devices.Can=ON -DAPI_nanoFramework.ResourceManager=ON -DAPI_nanoFramework.System.Collections=ON + GccArm_Version: + NeedsDFU: false + ST_NUCLEO64_F091RC: + BoardName: ST_NUCLEO64_F091RC + BuildOptions: -DTARGET_SERIES=STM32F0xx -DRTOS=CHIBIOS -DNF_FEATURE_DEBUGGER=ON -DNF_FEATURE_RTC=ON -DUSE_RNG=OFF -DNF_PLATFORM_NO_CLR_TRACE=ON -DNF_CLR_NO_IL_INLINE=ON -DAPI_Hardware.Stm32=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON + GccArm_Version: 5-2016-q3-update + NeedsDFU: false + ST_STM32F769I_DISCOVERY: + BoardName: ST_STM32F769I_DISCOVERY + BuildOptions: -DTARGET_SERIES=STM32F7xx -DRTOS=CHIBIOS -DSUPPORT_ANY_BASE_CONVERSION=ON -DNF_FEATURE_DEBUGGER=ON -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DNF_FEATURE_HAS_SDCARD=ON -DAPI_System.Math=ON -DAPI_Hardware.Stm32=ON -DNF_FEATURE_HAS_CONFIG_BLOCK=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_System.Devices.Dac=ON -DAPI_System.Net=ON -DNF_SECURITY_MBEDTLS=ON -DAPI_nanoFramework.Devices.OneWire=ON -DAPI_nanoFramework.Devices.Can=ON -DAPI_Windows.Storage=ON -DAPI_nanoFramework.ResourceManager=ON -DAPI_nanoFramework.System.Collections=ON + GccArm_Version: + NeedsDFU: false + + variables: + GNU_GCC_TOOLCHAIN_PATH: $(Agent.TempDirectory)\GNU_Tools_ARM_Embedded + HelperPackageVersion: $[counter('HelperPackageVersioncounter', 0)] + + steps: + - template: azure-pipelines-templates/nb-gitversioning.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml + + - template: azure-pipelines-templates/download-install-ninja.yml + + - template: azure-pipelines-templates/download-hexdfu.yml + + - template: azure-pipelines-templates/build-chibios-stm32.yml + + - template: azure-pipelines-templates/pack-publish-artifacts.yml + + - template: azure-pipelines-templates/publish-bintray.yml + + - template: azure-pipelines-templates/pack-publish-managed-helpers.yml + +################# +# ESP32 targets +- job: Build_ESP32_targets + condition: not( eq( dependencies.Check_Build_Options.outputs['BuildOptions.SKIP_BUILD'], true ) ) + + dependsOn: + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + # there is only a single ESP32 target, but this is already config as a matrix to make it easy to add new ones + strategy: + matrix: + ESP32_WROOM_32: + BoardName: ESP32_WROOM_32 + BuildOptions: -DTARGET_SERIES=ESP32 -DRTOS=FREERTOS_ESP32 -DNF_WP_IMPLEMENTS_CRC32=OFF -DNF_FEATURE_DEBUGGER=ON -DNF_FEATURE_RTC=ON -DNF_FEATURE_HAS_CONFIG_BLOCK=ON -DNF_FEATURE_HAS_SDCARD=ON -DAPI_System.Math=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_System.Net=ON -DAPI_Windows.Devices.Wifi=ON -DAPI_Windows.Storage=ON -DNF_SECURITY_MBEDTLS=ON -DAPI_Hardware.Esp32=ON -DSUPPORT_ANY_BASE_CONVERSION=ON -DAPI_nanoFramework.Devices.OneWire=ON -DAPI_nanoFramework.ResourceManager=ON -DAPI_nanoFramework.System.Collections=ON + + variables: + ESP32_TOOLCHAIN_PATH: $(Agent.TempDirectory)\ESP32_Tools + + steps: + - template: azure-pipelines-templates/nb-gitversioning.yml + + - template: azure-pipelines-templates/download-install-esp32-build-components.yml + + - template: azure-pipelines-templates/download-install-ninja.yml + + - template: azure-pipelines-templates/build-esp32.yml + + - task: CopyFiles@1 + inputs: + sourceFolder: $(ESP32_LIBS_PATH) + Contents: | + bootloader.bin + TargetFolder: '$(Build.ArtifactStagingDirectory)\$(BoardName)' + flattenFolders: true + condition: and( succeeded(), ne(variables['Build.Reason'], 'PullRequest') ) + displayName: Copying bootloader from ESP32 libs + + - template: azure-pipelines-templates/pack-publish-artifacts.yml + + - template: azure-pipelines-templates/publish-bintray.yml + +################# +# TI SimpleLink +- job: Build_TI_SimpleLink_targets + condition: not( eq( dependencies.Check_Build_Options.outputs['BuildOptions.SKIP_BUILD'], true ) ) + + dependsOn: + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + strategy: + matrix: + TI_CC3220SF_LAUNCHXL: + BoardName: TI_CC3220SF_LAUNCHXL + BuildOptions: -DTARGET_SERIES=CC32xx -DRTOS=TI_SIMPLELINK -DSUPPORT_ANY_BASE_CONVERSION=OFF -DNF_FEATURE_DEBUGGER=ON -DNF_FEATURE_RTC=ON -DNF_FEATURE_WATCHDOG=OFF -DNF_FEATURE_HAS_CONFIG_BLOCK=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=OFF -DAPI_Windows.Devices.Adc=ON -DAPI_System.Net=ON -DAPI_nanoFramework.System.Collections=ON + GccArm_Version: + + variables: + GNU_GCC_TOOLCHAIN_PATH: $(Agent.TempDirectory)\GNU_Tools_ARM_Embedded + HelperPackageVersion: $[counter('HelperPackageVersioncounter', 0)] + + steps: + - template: azure-pipelines-templates/nb-gitversioning.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml + + - template: azure-pipelines-templates/download-install-ninja.yml + + - template: azure-pipelines-templates/build-ti-simplelink.yml + + - template: azure-pipelines-templates/pack-publish-artifacts.yml + + - template: azure-pipelines-templates/publish-bintray.yml + + - template: azure-pipelines-templates/pack-publish-ti-sl-managed-helpers.yml + +################# +# WIN32 +- job: Build_WIN32_nanoCLR + condition: not( eq( dependencies.Check_Build_Options.outputs['BuildOptions.SKIP_BUILD'], true ) ) + + dependsOn: + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + steps: + - task: NuGetToolInstaller@0 + + - task: VSBuild@1 + inputs: + solution: 'targets\os\win32\nanoCLR.sln' + platform: 'x86' + configuration: 'Release' + +####################### +# generate change log +- job: Generate_change_log + dependsOn: + - Build_STM32_targets + - Build_ESP32_targets + - Build_TI_SimpleLink_targets + # skip build if this is a PR, submitted by nfbot and the commit message contains [version update] + condition: and( succeeded('Build_STM32_targets'), succeeded('Build_ESP32_targets'), succeeded('Build_TI_SimpleLink_targets'), not( eq(variables['Build.Reason'], 'PullRequest') ), not( and( eq(variables['Build.RequestedForId'], 'nfbot'), contains(variables['Build.SourceVersionMessage'], '[version update]') ) ) ) + + pool: + vmImage: 'VS2017-Win2016' + + steps: + - task: DotNetCoreCLI@2 + inputs: + command: custom + custom: tool + arguments: install --tool-path . nbgv + displayName: Install NBGV tool + + - task: PowerShell@2 + inputs: + targetType: 'inline' + script: nbgv cloud -a -c + errorActionPreference: 'silentlyContinue' + failOnStderr: 'false' + displayName: Set build number + # condition: ne(variables['system.pullrequest.isfork'], true) + + - task: UseRubyVersion@0 + inputs: + versionSpec: '>= 2.4' + addToPath: true + + # generate change log including future version + - script: | + gem install bundler + bundle install --retry=3 --jobs=4 + gem install github_changelog_generator + bundle exec github_changelog_generator --token $(GitHubToken) --future-release "v$(NBGV_Version)" + condition: or( eq(variables['Build.SourceBranchName'], 'master'), contains(variables['Build.SourceBranchName'], 'release') ) + displayName: Generate change log + + # generate change log including future version + - script: | + gem install github_changelog_generator + bundle exec github_changelog_generator --token $(GitHubToken) + condition: not( or( eq(variables['Build.SourceBranchName'], 'master'), contains(variables['Build.SourceBranchName'], 'release') ) ) + displayName: Generate change log + +####################### +# create or update GitHub release ON tags from release or master branches +- job: Publish_Release + dependsOn: + - Build_STM32_targets + - Build_ESP32_targets + - Build_TI_SimpleLink_targets + - Build_WIN32_nanoCLR + - Generate_change_log + + pool: + vmImage: 'VS2017-Win2016' + + steps: + - task: GitHubReleasePublish@1 + inputs: + githubEndpoint: 'nanoframework' + githubOwner: 'nanoframework' + githubRepositoryName: nf-interpreter + githubTag: v$(NBGV_Version) + githubReleaseTitle: 'nf Interpreter v$(NBGV_Version)' + githubTargetCommitsh: $(Build.SourceVersion) + githubReleaseDraft: false + githubReleasePrerelease: false + githubReuseDraftOnly: false + githubReuseRelease: true + githubEditRelease: false + githubDeleteEmptyTag: true + githubReleaseAsset: + condition: and( succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), not(contains(variables['Build.SourceBranch'], 'preview') ), ne( variables['StartReleaseCandidate'], true ) ) + displayName: Create/Update GitHub stable release + +################################## +# report build failure to Discord +- job: Report_Build_Failure + dependsOn: + - Build_STM32_targets + - Build_ESP32_targets + - Build_TI_SimpleLink_targets + - Build_WIN32_nanoCLR + condition: or( failed('Build_STM32_targets'), failed('Build_ESP32_targets'), failed('Build_TI_SimpleLink_targets'), failed('Build_WIN32_nanoCLR')) + + pool: + vmImage: 'VS2017-Win2016' + + steps: + + - checkout: self + + # step from template @ nf-tools repo + - template: azure-pipelines-templates/discord-webhook.yml@templates + parameters: + status: 'failure' + webhookUrl: '$(DiscordWebhook)' + message: '' diff --git a/source/native/nf-interpreter/cmake-variants.TEMPLATE-ESP32.json b/source/native/nf-interpreter/cmake-variants.TEMPLATE-ESP32.json new file mode 100644 index 00000000..6ffef054 --- /dev/null +++ b/source/native/nf-interpreter/cmake-variants.TEMPLATE-ESP32.json @@ -0,0 +1,77 @@ +{ + "buildType": { + "default": "debug", + "choices": { + "debug": { + "short": "Debug", + "long": "Emit debug information without performing optimizations", + "buildType": "Debug" + }, + "release": { + "short": "Release", + "long": "Enable optimizations, omit debug info", + "buildType": "Release" + }, + "minsize": { + "short": "MinSizeRel", + "long": "Optimize for smallest binary size", + "buildType": "MinSizeRel" + }, + "reldeb": { + "short": "RelWithDebInfo", + "long": "Perform optimizations AND include debugging information", + "buildType": "RelWithDebInfo" + } + } + }, + + "linkage": { + "default": "", + "choices": { + + "Esp32_nanoCLR": { + "short": "NanoCLR", + "settings": { + "BUILD_VERSION": "0.9.99.999", + "TOOLCHAIN_PREFIX": "", + "ESP32_IDF_PATH": "", + "ESP32_LIBS_PATH": "", + "EXECUTABLE_OUTPUT_PATH": "${workspaceRoot}/build", + "TARGET_SERIES": "ESP32", + "ESP32_BOARD": "ESP32_WROOM_32", + "USE_FPU": "TRUE", + "RTOS": "FREERTOS_ESP32", + "SWO_OUTPUT": "OFF", + "NF_BUILD_RTM": "OFF", + "NF_WP_TRACE_ERRORS": "OFF", + "NF_WP_TRACE_HEADERS": "OFF", + "NF_WP_TRACE_STATE": "OFF", + "NF_WP_TRACE_NODATA": "OFF", + "NF_WP_TRACE_ALL": "OFF", + "NF_WP_IMPLEMENTS_CRC32": "OFF", + "NF_FEATURE_DEBUGGER": "ON", + "NF_FEATURE_RTC": "ON", + "NF_FEATURE_USE_APPDOMAINS": "OFF", + "NF_FEATURE_SUPPORT_REFLECTION" : "ON", + "NF_FEATURE_HAS_CONFIG_BLOCK": "ON", + "NF_FEATURE_HAS_SDCARD": "ON", + "API_System.Net": "ON", + "NF_SECURITY_MBEDTLS": "ON", + "API_nanoFramework.ResourceManager" : "ON", + "API_nanoFramework.System.Collections" : "ON", + "API_Windows.Devices.Wifi": "ON", + "API_Windows.Devices.Adc": "ON", + "API_System.Devices.Dac" : "OFF", + "API_Windows.Devices.Gpio": "ON", + "API_Windows.Devices.I2c": "ON", + "API_Windows.Devices.Pwm": "ON", + "API_Windows.Devices.SerialCommunication": "ON", + "API_Windows.Devices.Spi": "ON", + "API_Windows.Networking.Sockets": "OFF", + "API_Windows.Storage": "ON", + "API_Hardware.Esp32": "ON" + } + } + } + } +} diff --git a/source/native/nf-interpreter/cmake-variants.TEMPLATE.json b/source/native/nf-interpreter/cmake-variants.TEMPLATE.json new file mode 100644 index 00000000..a9883682 --- /dev/null +++ b/source/native/nf-interpreter/cmake-variants.TEMPLATE.json @@ -0,0 +1,91 @@ +{ + "buildType": { + "default": "debug", + "choices": { + "debug": { + "short": "Debug", + "long": "Emit debug information without performing optimizations", + "buildType": "Debug" + }, + "minsize": { + "short": "MinSizeRel", + "long": "Optimize for smallest binary size", + "buildType": "MinSizeRel" + }, + "reldeb": { + "short": "RelWithDebInfo", + "long": "Perform optimizations AND include debugging information", + "buildType": "RelWithDebInfo" + } + } + }, + + "linkage": { + "default": "", + "choices": { + "OPTION_NAME_HERE": { + "short": "", + "settings": { + "BUILD_VERSION" : "0.9.99.999", + "TOOLCHAIN_PREFIX" : "", + "TOOL_HEX2DFU_PREFIX" : "", + "ESP32_IDF_PATH" : "/esp-idf", + "ESP32_LIBS_PATH" : "/libs", + "TARGET_SERIES" : "", + "USE_RNG" : "", + "DP_FLOATINGPOINT" : "", + "SUPPORT_ANY_BASE_CONVERSION" : "", + "RTOS" : "", + "CHIBIOS_SOURCE" : "", + "CHIBIOS_CONTRIB_REQUIRED" : "OFF-default-ON-to-include_ChibiOS-Contrib-repository-in-the-build", + "CHIBIOS_CONTRIB_SOURCE" : "", + "CHIBIOS_BOARD" : "", + "STM32_CUBE_PACKAGE_REQUIRED" : "", + "STM32_CUBE_PACKAGE_SOURCE" : "", + "TI_BOARD" : "", + "TI_SL_CC32xx_SDK_SOURCE" : "", + "SPIFFS_SOURCE" : "", + "SWO_OUTPUT" : "OFF-default-ON-to-enable-ARM-CortexM-Single-Wire-Output", + "NF_BUILD_RTM" : "OFF-default-ON-to-enable-RTM-build", + "NF_WP_TRACE_ERRORS" : "OFF-default-ON-to-enable-trace-error-messages-wire-protocol", + "NF_WP_TRACE_HEADERS" : "OFF-default-ON-to-enable-trace-header-messages-wire-protocol", + "NF_WP_TRACE_STATE" : "OFF-default-ON-to-enable-trace-state-messages-wire-protocol", + "NF_WP_TRACE_NODATA" : "OFF-default-ON-to-enable-trace-no-data-messages-wire-protocol", + "NF_WP_TRACE_ALL" : "OFF-default-ON-to-enable-trace-all-messages-wire-protocol", + "NF_WP_IMPLEMENTS_CRC32" : "OFF-default-ON-to-enable-CRC32-wire-protocol", + "NF_FEATURE_DEBUGGER" : "OFF-default-ON-to-include-managed-app-debugging-capability", + "NF_FEATURE_RTC" : "OFF-default-ON-to-enable-hardware-RTC", + "NF_FEATURE_USE_APPDOMAINS" : "OFF-default-ON-to-enable-support-for-Application-Domains", + "NF_FEATURE_SUPPORT_REFLECTION" : "ON-default-OFF-to-disable-support-for-System.Reflection-API", + "NF_FEATURE_WATCHDOG" : "ON-to-enable-hardware-watchdog-ON-is-default", + "NF_FEATURE_HAS_CONFIG_BLOCK" : "OFF-default-ON-to-enable-configuration-block-storage", + "NF_FEATURE_HAS_SDCARD" : "OFF-default-ON-to-enable-support-for-SDCard-storage-device", + "NF_FEATURE_HAS_USB_MSD" : "OFF-default-ON-to-enable-support-for-USB-Mass-storage-device", + "NF_FEATURE_USE_SPIFFS" : "OFF-default-ON-to-enable-support-for-SPI-flash-file-system", + "NF_PLATFORM_NO_CLR_TRACE" : "OFF-default-ON-to-disable-all-trace-on-CLR", + "NF_CLR_NO_IL_INLINE" : "OFF-default-ON-to-disable-CLR-IL-inlining", + "NF_INTEROP_ASSEMBLIES" : [ "Assembly1-Namespace", "Assembly2-Namespace" ], + "NF_NETWORKING_SNTP" : "ON-default-to-add-SNTP-client-requires-networking", + "NF_SECURITY_MBEDTLS" : "OFF-default-ON-to-add-network-security-from-mbedTLS", + "MBEDTLS_SOURCE" : "", + "API_nanoFramework.Devices.Can" : "OFF-default-ON-to-add-this-API", + "API_nanoFramework.Devices.OneWire" : "OFF-default-ON-to-add-this-API", + "API_nanoFramework.ResourceManager" : "OFF-default-ON-to-add-this-API", + "API_nanoFramework.System.Collections" : "OFF-default-ON-to-add-this-API", + "API_System.Math" : "OFF-default-ON-to-add-this-API", + "API_System.Net" : "OFF-default-ON-to-add-this-API", + "API_Windows.Devices.Adc" : "OFF-default-ON-to-add-this-API", + "API_System.Devices.Dac" : "OFF-default-ON-to-add-this-API", + "API_Windows.Devices.Gpio" : "OFF-default-ON-to-add-this-API", + "API_Windows.Devices.I2c" : "OFF-default-ON-to-add-this-API", + "API_Windows.Devices.Pwm" : "OFF-default-ON-to-add-this-API", + "API_Windows.Devices.SerialCommunication" : "OFF-default-ON-to-add-this-API", + "API_Windows.Devices.Spi" : "OFF-default-ON-to-add-this-API", + "API_Windows.Networking.Sockets" : "OFF-default-ON-to-add-this-API", + "API_Hardware.Esp32" : "OFF-default-ON-to-add-this-API", + "API_Hardware.Stm32" : "OFF-default-ON-to-add-this-API" + } + } + } + } +} diff --git a/source/native/nf-interpreter/install-scripts/Set-PathVariable.ps1 b/source/native/nf-interpreter/install-scripts/Set-PathVariable.ps1 new file mode 100644 index 00000000..cc7b6505 --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/Set-PathVariable.ps1 @@ -0,0 +1,82 @@ + ## Based on Hahndorf's awesome collection of PowerShell scripts. + ## https://github.com/hahndorf/hacops + [CmdletBinding(SupportsShouldProcess = $true)] +Param( + [parameter(Mandatory=$true)] + [string]$NewLocation) + +Begin +{ + +# requires –runasadministrator + + $regPath = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" + $hklm = [Microsoft.Win32.Registry]::LocalMachine + + Function GetOldPath() + { + $regKey = $hklm.OpenSubKey($regPath, $FALSE) + $envpath = $regKey.GetValue("Path", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) + return $envPath + } +} + +Process +{ + # Win32API error codes + $ERROR_SUCCESS = 0 + $ERROR_DUP_NAME = 34 + $ERROR_INVALID_DATA = 13 + + $NewLocation = $NewLocation.Trim(); + + If ($NewLocation -eq "" -or $NewLocation -eq $null) + { + Exit $ERROR_INVALID_DATA + } + + [string]$oldPath = GetOldPath + Write-Verbose "Old Path: $oldPath" + + # check whether the new location is already in the path + $parts = $oldPath.split(";") + If ($parts -contains $NewLocation) + { + Write-Warning ("The new location is already in the path ('"+$NewLocation+"')") + Exit $ERROR_DUP_NAME + } + + # build the new path, make sure we don't have double semicolons + $newPath = $oldPath + ";" + $NewLocation + $newPath = $newPath -replace ";;",";" + + if ($pscmdlet.ShouldProcess("%Path%", "Set $newPath")){ + # add to the current session + $env:path += ";$NewLocation" + # save into registry + $regKey = $hklm.OpenSubKey($regPath, $True) + $regKey.SetValue("Path", $newPath, [Microsoft.Win32.RegistryValueKind]::ExpandString) + Write-Output "The operation completed successfully." + } + + Exit $ERROR_SUCCESS +} + +<# +.SYNOPSIS + Adds a new item to the machine path environment variable +.DESCRIPTION + Most more popular methods to change the %path% actually break it. +.PARAMETER NewLocation + The new directory location to add at the end of the path. Can be an variable itself. +.EXAMPLE + Set-PathVariable.ps1 -NewLocation "%bin%" + Adds the string "%bin%" to the path, when using it it is expanded. +.NOTES + Tested on Windows 10 and Server 2016 + Author: Peter Hahndorf + Created: October 7th, 2016 +.LINK + https://github.com/hahndorf/hacops + https://peter.hahndorf.eu/blog/AddingToPathVariable +#> diff --git a/source/native/nf-interpreter/install-scripts/install-arm-gcc-toolchain.ps1 b/source/native/nf-interpreter/install-scripts/install-arm-gcc-toolchain.ps1 new file mode 100644 index 00000000..c365fec1 --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-arm-gcc-toolchain.ps1 @@ -0,0 +1,35 @@ +# This PS installs the ARM GNU GCC toolchain from our Bintray repository if it's not already available + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS +#Set location of nf-interpreter top-level +$nfRoot = "$PSScriptRoot\.." +$zipRoot = "$nfRoot\zips\" + +# check if path already exists +$GnuGccPathExists = Test-Path $env:GNU_GCC_TOOLCHAIN_PATH -ErrorAction SilentlyContinue + +If($GnuGccPathExists -eq $False) +{ + Write-Host "Downloading ARM GNU GCC toolchain..." + + $url = "https://bintray.com/nfbot/internal-build-tools/download_file?file_path=gcc-arm-none-eabi-8-2019-q3-update-win32.7z" + $output = "$zipRoot\gcc-arm.7z" + + # Stop security tripping us up + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + + # Create directory for zip files if necessary + md -Force $zipRoot | Out-Null + + # download 7zip with toolchain + (New-Object Net.WebClient).DownloadFile($url, $output) + + # Install 7Zip4PowerShell module from PSGallery if not already installed + Install-Module -Name 7Zip4Powershell -RequiredVersion 1.8.0 -Scope CurrentUser + + Write-Host "Installing ARM GNU GCC toolchain..." + + # unzip toolchain + Expand-7Zip -ArchiveFileName $output -TargetPath $env:GNU_GCC_TOOLCHAIN_PATH +} diff --git a/source/native/nf-interpreter/install-scripts/install-esp32-idf.ps1 b/source/native/nf-interpreter/install-scripts/install-esp32-idf.ps1 new file mode 100644 index 00000000..5dda86c7 --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-esp32-idf.ps1 @@ -0,0 +1,41 @@ +# This PS installs IDF esp32 sdk + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS +#Set location of nf-interpreter top-level +$nfRoot = "$PSScriptRoot\.." +$zipRoot = "$nfRoot\zips\" + +# check if path already exists +$Esp32IdfPathExists = Test-Path $env:ESP32_IDF_PATH -ErrorAction SilentlyContinue + +If($Esp32IdfPathExists -eq $False) +{ + $url = "https://github.com/espressif/esp-idf/releases/download/v3.3/esp-idf-v3.3.zip" + $output = "$zipRoot\esp-idf-v3.3.zip" + + # Don't download again if already exists. User can remove from zips to force... + if(![System.IO.File]::Exists($output)){ + + Write-Host "Downloading ESP32 IDF..." + + # Stop security tripping us up + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + + # Create directory for zip files if necessary + md -Force $zipRoot | Out-Null + + # download zip with Espressif IDF + (New-Object Net.WebClient).DownloadFile($url, $output) + } + + Write-Host "Installing Espressif IDF..." + + # unzip + Expand-Archive $output -DestinationPath $env:ESP32_TOOLS_PATH +} + +Write-Host "Installing python pyserial..." +# Make sure serial package is installed in python otherwise +# the esptool.py tool won't run +python -m pip install pyserial diff --git a/source/native/nf-interpreter/install-scripts/install-esp32-libs.ps1 b/source/native/nf-interpreter/install-scripts/install-esp32-libs.ps1 new file mode 100644 index 00000000..96ab1cec --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-esp32-libs.ps1 @@ -0,0 +1,38 @@ +# This PS installs the pre-compiled EPS32 libraries from our Bintray repository + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS +#Set location of nf-interpreter top-level +$nfRoot = "$PSScriptRoot\.." +$zipRoot = "$nfRoot\zips\" + +# check if path already exists +$ESP32LibPathExists = Test-Path $env:ESP32_LIBS_PATH -ErrorAction SilentlyContinue + +If($ESP32LibPathExists -eq $False) +{ + $url = "https://bintray.com/nfbot/internal-build-tools/download_file?file_path=IDF_libs-v3.3.zip" + $output = "$zipRoot\IDF_libs-v3.3.zip" + + # Don't download again if already exists. User can remove from zips to force... + if(![System.IO.File]::Exists($output)){ + + Write-Host "Downloading ESP32 pre-compiled libs..." + + # Stop security tripping us up + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + + # Create directory for zip files if necessary + md -Force $zipRoot | Out-Null + + # download zip IDF + (New-Object Net.WebClient).DownloadFile($url, $output) + } + + Write-Host "Installing ESP32 pre-compiled libs..." + + # unzip libs + #Expand-7Zip -ArchiveFileName $output -TargetPath $env:ESP32_LIBS_PATH + #unzip using PowerShell 5+ inbuilt command + Expand-Archive -Path $output -DestinationPath $env:ESP32_LIBS_PATH +} diff --git a/source/native/nf-interpreter/install-scripts/install-esp32-openocd.ps1 b/source/native/nf-interpreter/install-scripts/install-esp32-openocd.ps1 new file mode 100644 index 00000000..98c50e82 --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-esp32-openocd.ps1 @@ -0,0 +1,38 @@ +# This PS installs the OpenOCD ESP32 toolchain from Espressif downloads repository +# if it's not already available at ESP32_TOOLS_PATH\openocd-esp32 + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS +#Set location of nf-interpreter top-level +$nfRoot = "$PSScriptRoot\.." +$zipRoot = "$nfRoot\zips\" + +$env:ESP32_OPENOCD_PATH=($env:ESP32_TOOLS_PATH+'\openocd-esp32') +# check if path already exists +$OpenOCDPathExists = Test-Path $env:ESP32_OPENOCD_PATH -ErrorAction SilentlyContinue + +If($OpenOCDPathExists -eq $False) +{ + Write-Host "Downloading OpenOCD for ESP32 ..." + + $url = "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20190212/openocd-esp32-win32-0.10.0-esp32-20190212.zip" + $output = "$zipRoot\openocd-esp32.zip" + + # Stop security tripping us up + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + + # Create directory for zip files if necessary + md -Force $zipRoot | Out-Null + + # download zip with OpenOcd tool + (New-Object Net.WebClient).DownloadFile($url, $output) + + Write-Host "Installing OpenOCD..." + + # unzip + #Expand-Archive $output -DestinationPath $env:ESP32_OPENOCD_PATH + + Expand-Archive $output -DestinationPath "$PSScriptRoot\openocd-esp32" + Move-Item -Path ("$PSScriptRoot\openocd-esp32\openocd-esp32\") -Destination $env:ESP32_OPENOCD_PATH + Remove-Item "$PSScriptRoot\openocd-esp32" -Force +} diff --git a/source/native/nf-interpreter/install-scripts/install-esp32-toolchain.ps1 b/source/native/nf-interpreter/install-scripts/install-esp32-toolchain.ps1 new file mode 100644 index 00000000..ed1c7ac7 --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-esp32-toolchain.ps1 @@ -0,0 +1,41 @@ +# This PS installs the xtensa ESP32 toolchain from Espressif downloads repository +# if it's not already available at ESP32_TOOLCHAIN_PATH + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS +#Set location of nf-interpreter top-level +$nfRoot = "$PSScriptRoot\.." +$zipRoot = "$nfRoot\zips\" + +# check if path already exists +$XtensaPathExists = Test-Path $env:ESP32_TOOLCHAIN_PATH -ErrorAction SilentlyContinue + +If($XtensaPathExists -eq $False) +{ + # Download xtensa ESP32 toolchain and install + + $url = "https://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-80-g6c4433a-5.2.0.zip" + $output = "$zipRoot\xtensa-esp32-elf-win32.zip" + + # Don't download again if already exists. User can remove from zips to force... + if(![System.IO.File]::Exists($output)){ + Write-Host "Downloading Xtensa ESP32 toolchain..." + + # Stop security tripping us up + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + + # Create directory for zip files if necessary + md -Force $zipRoot | Out-Null + + # download zip with toolchain + (New-Object Net.WebClient).DownloadFile($url, $output) + } + + Write-Host "Installing Xtensa ESP32 toolchain..." + + # unzip toolchain (This used the older of the two Expand-7Zip addons) + #Expand-7Zip -ArchiveFileName $output -TargetPath $env:ESP32_TOOLCHAIN_PATH + + #unzip using PowerShell 5+ inbuilt command + Expand-Archive -Path $output -DestinationPath $env:ESP32_TOOLCHAIN_PATH +} diff --git a/source/native/nf-interpreter/install-scripts/install-esp32-tools.ps1 b/source/native/nf-interpreter/install-scripts/install-esp32-tools.ps1 new file mode 100644 index 00000000..2743b6d4 --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-esp32-tools.ps1 @@ -0,0 +1,149 @@ +[CmdletBinding(SupportsShouldProcess = $true)] +param ( +[Parameter(HelpMessage="Please enter the COM port for ESP32 flash utility [e.g. COM1 or /dev/ttyUSB0].",Position=2)][string]$COMPORT, +[switch]$force = $false +) + + +[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" +Write-Host "Install Tools to build nanoCLR into default folders and configure json files ..." +$env:BOARD_NAME = "ESP32_WROOM_32" + +If([string]::IsNullOrEmpty($COMPORT)) +{ + Write-Warning ("Please use parameter -C to set COM port for ESP32 flash utility [e.g. -C COM1], or edit tasks.json") +} + +$env:NANOCLR_COMPORT = $COMPORT + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS + +#Set location of nf-interpreter top-level +$nfRoot = "$PSScriptRoot\.." + +# create build folder if necessary +md -Force "$nfRoot\build" | Out-Null + +#Write-Host $PSScriptRoot +#Write-Host $nfRoot +Write-Host "BOARD_NAME=" $env:BOARD_NAME + +Write-Host "Set User Environment Variables ... (can be slow if many Applications running.)" +If([string]::IsNullOrEmpty($env:ESP32_TOOLS_PATH) -or $force) +{ + $env:ESP32_TOOLS_PATH= 'C:\ESP32_TOOLS' + Write-Host ("Set User Environment ESP32_TOOLS_PATH='"+$env:ESP32_TOOLS_PATH+"'") + [System.Environment]::SetEnvironmentVariable("ESP32_TOOLS_PATH", $env:ESP32_TOOLS_PATH, "User") +} +If([string]::IsNullOrEmpty($env:ESP32_TOOLCHAIN_PREFIX) -or $force) +{ + $env:ESP32_TOOLCHAIN_PREFIX= ($env:ESP32_TOOLS_PATH) + Write-Host ("Set User Environment ESP32_TOOLCHAIN_PREFIX='"+$env:ESP32_TOOLCHAIN_PREFIX+"'") + [System.Environment]::SetEnvironmentVariable("ESP32_TOOLCHAIN_PREFIX", $env:ESP32_TOOLCHAIN_PREFIX, "User") +} +If([string]::IsNullOrEmpty($env:ESP32_TOOLCHAIN_PATH) -or $force) +{ + $env:ESP32_TOOLCHAIN_PATH= ($env:ESP32_TOOLS_PATH) + Write-Host ("Set User Environment ESP32_TOOLCHAIN_PATH='"+$env:ESP32_TOOLCHAIN_PATH+"'") + [System.Environment]::SetEnvironmentVariable("ESP32_TOOLCHAIN_PATH", $env:ESP32_TOOLCHAIN_PATH, "User") +} +If([string]::IsNullOrEmpty($env:ESP32_LIBS_PATH) -or $force) +{ + $env:ESP32_LIBS_PATH=($env:ESP32_TOOLS_PATH+'\libs-v3.3') + Write-Host ("Set User Environment ESP32_LIBS_PATH='"+$env:ESP32_LIBS_PATH+"'") + [System.Environment]::SetEnvironmentVariable("ESP32_LIBS_PATH", $env:ESP32_LIBS_PATH, "User") +} +If([string]::IsNullOrEmpty($env:ESP32_IDF_PATH) -or [string]::IsNullOrEmpty($env:IDF_PATH) -or $force) +{ + $env:IDF_PATH=$env:ESP32_IDF_PATH=($env:ESP32_TOOLS_PATH+'\esp-idf-v3.3') + Write-Host ("Set User Environment ESP32_IDF_PATH='"+$env:ESP32_IDF_PATH+"'") + Write-Host ("Set User Environment IDF_PATH='"+$env:IDF_PATH+"'") + [System.Environment]::SetEnvironmentVariable("ESP32_IDF_PATH", $env:ESP32_IDF_PATH, "User") + [System.Environment]::SetEnvironmentVariable("IDF_PATH", $env:IDF_PATH, "User") +} +If([string]::IsNullOrEmpty($env:NINJA_PATH) -or $force) +{ + $env:NINJA_PATH= ($env:ESP32_TOOLS_PATH+'\ninja') + Write-Host ("Set User Environment NINJA_PATH='"+$env:NINJA_PATH+"'") + [System.Environment]::SetEnvironmentVariable("NINJA_PATH", $env:NINJA_PATH, "User") +} + +Invoke-Expression -Command $PSScriptRoot\install-esp32-toolchain.ps1 +Invoke-Expression -Command $PSScriptRoot\install-esp32-libs.ps1 +Invoke-Expression -Command $PSScriptRoot\install-esp32-idf.ps1 +Invoke-Expression -Command $PSScriptRoot\install-ninja.ps1 +Invoke-Expression -Command $PSScriptRoot\install-esp32-openocd.ps1 + +Write-Host ("Adding Ninja to the path "+$env:NINJA_PATH) +Invoke-Expression -Command "$PSScriptRoot\Set-PathVariable.ps1 -NewLocation $env:NINJA_PATH" + +$filePathExists = Test-Path "$nfRoot\cmake-variants.json" -ErrorAction SilentlyContinue +If($filePathExists -eq $False -or $force) +{ + Write-Host ("Create .\cmake-variants.json with install paths from .\cmake-variants.TEMPLATE-ESP32.json") + Copy-Item "$nfRoot\cmake-variants.TEMPLATE-ESP32.json" -Destination "$nfRoot\cmake-variants.json" -Force + $variants = (Get-Content "$nfRoot\cmake-variants.json") + $variants = $variants.Replace('', $env:ESP32_IDF_PATH.ToString().Replace("\", "/")) + $variants = $variants.Replace('', $env:ESP32_LIBS_PATH.ToString().Replace("\", "/")) + $variants = $variants.Replace('', $env:ESP32_TOOLCHAIN_PREFIX.ToString().Replace("\", "/")) + Set-Content -Path "$nfRoot\cmake-variants.json" -Value $variants +} + +$filePathExists = Test-Path "$nfRoot\.vscode\cmake-kits.json" -ErrorAction SilentlyContinue +If($filePathExists -eq $False -or $force) +{ + Copy-Item "$nfRoot\.vscode\cmake-kits.TEMPLATE-ESP32.json" -Destination "$nfRoot\.vscode\cmake-kits.json" -Force +} + +$buildFolderPath = Resolve-Path $nfRoot\build + +$filePathExists = Test-Path "$nfRoot\.vscode\tasks.json" -ErrorAction SilentlyContinue +$filePathExists=$False +If($filePathExists -eq $False -or $force) +{ + Write-Host ("Create .\.vscode\tasks.json with install paths from .\vscode\tasks.TEMPLATE-ESP32.json") + Copy-Item "$nfRoot\.vscode\tasks.TEMPLATE-ESP32.json" -Destination "$nfRoot\.vscode\tasks.json" -Force + $tasks = (Get-Content "$nfRoot\.vscode\tasks.json") + $tasks = $tasks.Replace('', $env:ESP32_IDF_PATH.ToString().Replace("\", "/")) + $tasks = $tasks.Replace('', $env:ESP32_LIBS_PATH.ToString().Replace("\", "/")) + $tasks = $tasks.Replace('', $buildFolderPath.ToString().Replace("\", "/")) + $tasks = $tasks.Replace('', $env:ESP32_TOOLCHAIN_PREFIX.ToString().Replace("\", "/")) + + # Update the COMPORT placeholder if the paramter is supplied. + If(![string]::IsNullOrEmpty($COMPORT)) + { + $tasks = $tasks.Replace('', $env:NANOCLR_COMPORT.ToString()) + } + Set-Content -Path "$nfRoot\.vscode\tasks.json" -Value $tasks +} +$filePathExists = Test-Path "$nfRoot\.vscode\launch.json" -ErrorAction SilentlyContinue +$filePathExists=$False +If($filePathExists -eq $False -or $force) +{ + Write-Host "Create .\.vscode\launch.json with install paths from .\vscode\launch.TEMPLATE-ESP32.json" + Copy-Item "$nfRoot\.vscode\launch.TEMPLATE-ESP32.json" -Destination "$nfRoot\.vscode\launch.json" -Force + + $launch = (Get-Content "$nfRoot\.vscode\launch.json") + $launch = $launch.Replace('', $buildFolderPath.ToString().Replace("\", "/")) + $launch = $launch.Replace('', $env:ESP32_OPENOCD_PATH.Replace("\", "/")) + $launch = $launch.Replace('', $env:ESP32_TOOLCHAIN_PATH.Replace("\", "/")) + Set-Content -Path "$nfRoot\.vscode\launch.json" -Value $launch +} +<# +.SYNOPSIS + Install the default ESP32 tools and libraries neede to build nanoFramework, and setup the build environemnt. +.DESCRIPTION + Power Shell Script to install the default tools to build nanoFramework, including setting the machine path and other environment variables needed for ESP32 DevKitC. Use the -Force paramter to over-write existing Environment variables. +.PARAMETER COMPORT + The COM port for NANOCLR [e.g. COM1]. +.EXAMPLE + .\install-esp32-tools.ps1 -COMPORT COM19 + Installs the tools for Espressive ESP32 to default path, define required envisonment variables and update VSCode files with paths and set COM19 in tasks.json +.NOTES + Tested on Windows 10 + Author: nanoFramework Contributors + Created: September 9th, 2018 +.LINK + https://https://github.com/nanoframework/Home +#> diff --git a/source/native/nf-interpreter/install-scripts/install-nf-hex2dfu.ps1 b/source/native/nf-interpreter/install-scripts/install-nf-hex2dfu.ps1 new file mode 100644 index 00000000..72cfdf8f --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-nf-hex2dfu.ps1 @@ -0,0 +1,21 @@ +# This PS installs nanoFramework hex2dfu command line utility + +# check if path already exists +$hex2dfuPathExists = Test-Path $env:HEX2DFU_PATH -ErrorAction SilentlyContinue + +If($hex2dfuPathExists -eq $False) +{ + & md $($env:HEX2DFU_PATH) > $null + + Write-Host "Downloading hex2dfu..." + + $url = "https://github.com/nanoframework/hex2dfu/releases/latest/download/hex2dfu.exe" + + $output = "$env:HEX2DFU_PATH\hex2dfu.exe" + + # Stop security tripping us up + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + + # download executable with utility + (New-Object Net.WebClient).DownloadFile($url, $output) +} diff --git a/source/native/nf-interpreter/install-scripts/install-ninja.ps1 b/source/native/nf-interpreter/install-scripts/install-ninja.ps1 new file mode 100644 index 00000000..e4ea2213 --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-ninja.ps1 @@ -0,0 +1,31 @@ +# This PS installs Ninja build tool + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS +#Set location of nf-interpreter top-level +$nfRoot = "$PSScriptRoot\.." +$zipRoot = "$nfRoot\zips\" + +# check if path already exists +$NinjaPathExists = Test-Path $env:NINJA_PATH -ErrorAction SilentlyContinue + +If($NinjaPathExists -eq $False) +{ + Write-Host "Downloading Ninja..." + + $url = "https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip" + $output = "$zipRoot\ninja.zip" + # Stop security tripping us up + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + + # Create directory for zip files if necessary + md -Force $zipRoot | Out-Null + + # download zip with Ninja tool + (New-Object Net.WebClient).DownloadFile($url, $output) + + Write-Host "Installing Ninja..." + + # unzip + Expand-Archive $output -DestinationPath $env:NINJA_PATH +} diff --git a/source/native/nf-interpreter/install-scripts/install-stm32-tools.ps1 b/source/native/nf-interpreter/install-scripts/install-stm32-tools.ps1 new file mode 100644 index 00000000..85878f9b --- /dev/null +++ b/source/native/nf-interpreter/install-scripts/install-stm32-tools.ps1 @@ -0,0 +1,66 @@ +$BOARD_NAME = "STM32" + +[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + +Write-Host "Install Tools to build nanoCLR into default folders and configure json files ..." +$env:BOARD_NAME = $BOARD_NAME +$env:NANOCLR_COMPORT = $COMPORT + +if($psISE) { $PSScriptRoot = Split-Path -Path $psISE.CurrentFile.FullPath} #In case running in psISE +if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # or older PS + +#Set location of nf-interpreter +$nfRoot = "$PSScriptRoot\.." + +# create build folder if necessary +md -Force "$nfRoot\build" | Out-Null + +Write-Host "BOARD_NAME=" $env:BOARD_NAME +If([string]::IsNullOrEmpty($env:GNU_GCC_TOOLCHAIN_PATH) -or $force) +{ + $env:GNU_GCC_TOOLCHAIN_PATH='C:\GNU_Tools_ARM_Embedded\8-2019-q3-update' + Write-Host ("Set User Environment GNU_GCC_TOOLCHAIN_PATH='"+$env:GNU_GCC_TOOLCHAIN_PATH+"'") + [System.Environment]::SetEnvironmentVariable("GNU_GCC_TOOLCHAIN_PATH", $env:GNU_GCC_TOOLCHAIN_PATH, "User") +} +If([string]::IsNullOrEmpty($env:HEX2DFU_PATH) -or $force) +{ + $env:HEX2DFU_PATH= 'C:\mytools\hex2dfu' + Write-Host ("Set User Environment HEX2DFU_PATH='"+$env:HEX2DFU_PATH+"'") + [System.Environment]::SetEnvironmentVariable("HEX2DFU_PATH", $env:HEX2DFU_PATH, "User") +} +If([string]::IsNullOrEmpty($env:NINJA_PATH) -or $force) +{ + $env:NINJA_PATH= 'C:\mytools\ninja' + Write-Host ("Set User Environment NINJA_PATH='"+$env:NINJA_PATH+"'") + [System.Environment]::SetEnvironmentVariable("NINJA_PATH", $env:NINJA_PATH, "User") +} + +# get build matrix (Not used anymore) +#Invoke-Expression -Command $PSScriptRoot\get-stm32-targets-to-build.ps1 + +# install tools and utilities +Invoke-Expression -Command $PSScriptRoot\install-arm-gcc-toolchain.ps1 +Invoke-Expression -Command $PSScriptRoot\install-ninja.ps1 +Invoke-Expression -Command $PSScriptRoot\install-nf-hex2dfu.ps1 + +$test = [System.Environment]::GetEnvironmentVariable("NINJA_PATH", "User") +If($test -eq "") +{ + [System.Environment]::SetEnvironmentVariable("NINJA_PATH", $env:NINJA_PATH, "User") +} + +<# +.SYNOPSIS + Install the default tools to build nanoFramework for STM32 and setup build environemnt. +.DESCRIPTION + Power Shell Script to install the default tools to build nano Framework, including setting the machine path and other environment variables needed for STM32 +.EXAMPLE + .\install-stm32-tools.ps1 + Install the tools for STM32 to default path, define required environment variables and update VSCode files with paths and set COM19 in tasks.json +.NOTES + Tested on Windows 10 + Author: nanoFramework Contributors + Created: September 9th, 2018 +.LINK + https://https://github.com/nanoframework/Home +#> diff --git a/source/native/nf-interpreter/nf.props b/source/native/nf-interpreter/nf.props new file mode 100644 index 00000000..585f1a7c --- /dev/null +++ b/source/native/nf-interpreter/nf.props @@ -0,0 +1,19 @@ + + + + + + + $(__BuildDir)\ + $(MSBuildThisFileDirectory)build\ + + $(__BinDir) + $(BuildDir)bin\$(Configuration)\ + + $(__IntDir) + $(BuildDir)obj\$(Configuration)\$(ProjectName)\ + + + + + diff --git a/source/native/nf-interpreter/nfcore.vssettings b/source/native/nf-interpreter/nfcore.vssettings new file mode 100644 index 00000000..04850706 --- /dev/null +++ b/source/native/nf-interpreter/nfcore.vssettings @@ -0,0 +1,74 @@ + + + + + + + 4 + false + 4 + true + + + 1 + 0 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 1 + 1 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + + + + diff --git a/source/native/nf-interpreter/sd1.bat b/source/native/nf-interpreter/sd1.bat new file mode 100644 index 00000000..ccadfa1d --- /dev/null +++ b/source/native/nf-interpreter/sd1.bat @@ -0,0 +1,6 @@ + @echo off + REM Run command in short-path version of this directory + setlocal + pushd B:\ + %1 + popd diff --git a/source/native/nf-interpreter/sdkconfig b/source/native/nf-interpreter/sdkconfig new file mode 100644 index 00000000..cfaea8f1 --- /dev/null +++ b/source/native/nf-interpreter/sdkconfig @@ -0,0 +1,490 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_TARGET="esp32" + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT_ENABLED is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_STACK_CHECK is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +# CONFIG_ESP32_APPTRACE_ENABLE is not set +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_AWS_IOT_SDK is not set +# CONFIG_BT_ENABLED is not set +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BT_RESERVE_DRAM=0 +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set +CONFIG_EFUSE_MAX_BLK_LEN=192 +CONFIG_IDF_TARGET_ESP32=y +CONFIG_ESP32_REV_MIN_0=y +# CONFIG_ESP32_REV_MIN_1 is not set +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=0 +CONFIG_ESP32_DPORT_WORKAROUND=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +# CONFIG_SPIRAM_SUPPORT is not set +# CONFIG_MEMMAP_TRACEMEM is not set +# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +# CONFIG_ESP32_PANIC_PRINT_HALT is not set +CONFIG_ESP32_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32_PANIC_GDBSTUB is not set +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +# CONFIG_ESP32_XTAL_FREQ_26 is not set +# CONFIG_ESP32_XTAL_FREQ_AUTO is not set +CONFIG_ESP32_XTAL_FREQ=40 +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_ESP_TIMER_PROFILING is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_PM_ENABLE is not set +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_OTA_ALLOW_HTTP is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# CONFIG_ESP32_ENABLE_COREDUMP is not set +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE=y +CONFIG_EMAC_CHECK_LINK_PERIOD_MS=2000 +CONFIG_EMAC_TASK_PRIORITY=20 +CONFIG_EMAC_TASK_STACK_SIZE=3072 +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +# CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_DEBUG_INTERNALS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +# CONFIG_HEAP_TRACING is not set +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +# CONFIG_LWIP_IP_FRAG is not set +# CONFIG_LWIP_IP_REASSEMBLY is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +# CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN is not set +# CONFIG_MBEDTLS_DEBUG is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +# CONFIG_MBEDTLS_HARDWARE_MPI is not set +# CONFIG_MBEDTLS_HARDWARE_SHA is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_RIPEMD160_C is not set +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +# CONFIG_OPENSSL_ASSERT_EXIT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPIFFS_MAX_PARTITIONS=3 +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +CONFIG_IP_LOST_TIMER_INTERVAL=120 +CONFIG_TCPIP_LWIP=y +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 diff --git a/source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj new file mode 100644 index 00000000..1f9a8abd --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj @@ -0,0 +1,212 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {58E950CC-2FF6-423C-B006-A70A19272F20} + Win32Proj + CorLib + 10.0.17763.0 + CorLib + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + NANOCLR_REFLECTION=TRUE;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include;..\..\CLR\Helpers\Base64 + + + Windows + + + + + + + Level3 + Disabled + NANOCLR_REFLECTION=TRUE;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + NANOCLR_REFLECTION=TRUE;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include;..\..\CLR\Helpers\Base64 + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NANOCLR_REFLECTION=TRUE;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj.filters new file mode 100644 index 00000000..adc9315e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/CorLib-vs2019.vcxproj.filters @@ -0,0 +1,189 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/CorLib/CorLib.h b/source/native/nf-interpreter/src/CLR/CorLib/CorLib.h new file mode 100644 index 00000000..10739403 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/CorLib.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_CORLIB_NATIVE_H_ +#define _NANOCLR_CORLIB_NATIVE_H_ + +#include +#include +//#include +//#include +//#include + +#include "corlib_native.h" +#include "nanoCRT.h" + +#if !defined(_WIN32) +#include +#endif // !defined(_WIN32) + +#endif + diff --git a/source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj b/source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj new file mode 100644 index 00000000..206d6e66 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj @@ -0,0 +1,210 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {58E950CC-2FF6-423C-B006-A70A19272F20} + Win32Proj + CorLib + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + NANOCLR_REFLECTION=TRUE;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include;..\..\CLR\Helpers\Base64 + + + Windows + + + + + + + Level3 + Disabled + NANOCLR_REFLECTION=TRUE;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + NANOCLR_REFLECTION=TRUE;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include;..\..\CLR\Helpers\Base64 + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NANOCLR_REFLECTION=TRUE;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj.filters b/source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj.filters new file mode 100644 index 00000000..3619d5c5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/CorLib.vcxproj.filters @@ -0,0 +1,186 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native.cpp new file mode 100644 index 00000000..7d9549dc --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native.cpp @@ -0,0 +1,1517 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +#if (NANOCLR_REFLECTION == TRUE) + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + Library_corlib_native_System_Object::Equals___BOOLEAN__OBJECT, + Library_corlib_native_System_Object::GetHashCode___I4, + NULL, + Library_corlib_native_System_Object::GetType___SystemType, + Library_corlib_native_System_Object::MemberwiseClone___OBJECT, + NULL, + Library_corlib_native_System_Object::ReferenceEquals___STATIC__BOOLEAN__OBJECT__OBJECT, + NULL, + Library_corlib_native_System_ValueType::Equals___BOOLEAN__OBJECT, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Exception::get_StackTrace___STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Array::System_Collections_IList_get_Item___OBJECT__I4, + Library_corlib_native_System_Array::System_Collections_IList_set_Item___VOID__I4__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Array::get_Length___I4, + NULL, + NULL, + Library_corlib_native_System_Array::CreateInstance___STATIC__SystemArray__SystemType__I4, + NULL, + Library_corlib_native_System_Array::Copy___STATIC__VOID__SystemArray__I4__SystemArray__I4__I4, + Library_corlib_native_System_Array::Clear___STATIC__VOID__SystemArray__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Array::TrySzIndexOf___STATIC__BOOLEAN__SystemArray__I4__I4__OBJECT__BYREF_I4, + Library_corlib_native_System_Delegate::Equals___BOOLEAN__OBJECT, + Library_corlib_native_System_Delegate::GetInvocationList___SZARRAY_SystemDelegate, + Library_corlib_native_System_Delegate::get_Method___SystemReflectionMethodInfo, + Library_corlib_native_System_Delegate::get_Target___OBJECT, + NULL, + Library_corlib_native_System_Delegate::Combine___STATIC__SystemDelegate__SystemDelegate__SystemDelegate, + Library_corlib_native_System_Delegate::Remove___STATIC__SystemDelegate__SystemDelegate__SystemDelegate, + Library_corlib_native_System_Delegate::op_Equality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate, + Library_corlib_native_System_Delegate::op_Inequality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate, + NULL, + NULL, + Library_corlib_native_System_MulticastDelegate::op_Equality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate, + Library_corlib_native_System_MulticastDelegate::op_Inequality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_BitConverter::get_IsLittleEndian___STATIC__BOOLEAN, + Library_corlib_native_System_BitConverter::DoubleToInt64Bits___STATIC__I8__R8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__BOOLEAN, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__CHAR, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__R8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__R4, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I2, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U4, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U2, + Library_corlib_native_System_BitConverter::Int64BitsToDouble___STATIC__R8__I8, + Library_corlib_native_System_BitConverter::ToBoolean___STATIC__BOOLEAN__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToChar___STATIC__CHAR__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToDouble___STATIC__R8__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToInt16___STATIC__I2__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToInt32___STATIC__I4__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToInt64___STATIC__I8__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToSingle___STATIC__R4__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1, + Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1__I4__I4, + Library_corlib_native_System_BitConverter::ToUInt16___STATIC__U2__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToUInt32___STATIC__U4__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToUInt64___STATIC__U8__SZARRAY_U1__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Collections_ArrayList::get_Item___OBJECT__I4, + Library_corlib_native_System_Collections_ArrayList::set_Item___VOID__I4__OBJECT, + Library_corlib_native_System_Collections_ArrayList::Add___I4__OBJECT, + NULL, + Library_corlib_native_System_Collections_ArrayList::Clear___VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Collections_ArrayList::Insert___VOID__I4__OBJECT, + NULL, + Library_corlib_native_System_Collections_ArrayList::RemoveAt___VOID__I4, + NULL, + NULL, + NULL, + Library_corlib_native_System_Collections_ArrayList::SetCapacity___VOID__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Console::OutNative___STATIC__VOID__STRING__BOOLEAN, + NULL, + NULL, + Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4, + Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Convert::ToBase64String___STATIC__STRING__SZARRAY_U1__I4__I4__BOOLEAN, + NULL, + NULL, + Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZARRAY_U1__SZARRAY_CHAR__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_DateTime::_ctor___VOID__I4__I4__I4__I4__I4__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_DateTime::get_Day___I4, + Library_corlib_native_System_DateTime::get_DayOfWeek___SystemDayOfWeek, + Library_corlib_native_System_DateTime::get_DayOfYear___I4, + Library_corlib_native_System_DateTime::get_Hour___I4, + NULL, + Library_corlib_native_System_DateTime::get_Millisecond___I4, + Library_corlib_native_System_DateTime::get_Minute___I4, + Library_corlib_native_System_DateTime::get_Month___I4, + Library_corlib_native_System_DateTime::get_Second___I4, + NULL, + NULL, + Library_corlib_native_System_DateTime::get_Year___I4, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_DateTime::DaysInMonth___STATIC__I4__I4__I4, + NULL, + Library_corlib_native_System_DateTime::get_UtcNow___STATIC__SystemDateTime, + Library_corlib_native_System_DateTime::get_Today___STATIC__SystemDateTime, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Diagnostics_Debugger::get_IsAttached___STATIC__BOOLEAN, + Library_corlib_native_System_Diagnostics_Debugger::Break___STATIC__VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Double::CompareTo___STATIC__I4__R8__R8, + Library_corlib_native_System_Double::IsInfinity___STATIC__BOOLEAN__R8, + Library_corlib_native_System_Double::IsNaN___STATIC__BOOLEAN__R8, + Library_corlib_native_System_Double::IsNegativeInfinity___STATIC__BOOLEAN__R8, + Library_corlib_native_System_Double::IsPositiveInfinity___STATIC__BOOLEAN__R8, + NULL, + NULL, + Library_corlib_native_System_GC::AnyPendingFinalizers___STATIC__BOOLEAN, + NULL, + Library_corlib_native_System_GC::SuppressFinalize___STATIC__VOID__OBJECT, + Library_corlib_native_System_GC::ReRegisterForFinalize___STATIC__VOID__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Globalization_CultureInfo::get_CurrentUICultureInternal___STATIC__SystemGlobalizationCultureInfo, + Library_corlib_native_System_Globalization_CultureInfo::set_CurrentUICultureInternal___STATIC__VOID__SystemGlobalizationCultureInfo, + Library_corlib_native_System_Globalization_DateTimeFormat::FormatDigits___STATIC__STRING__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Guid::GenerateNewGuid___STATIC__SZARRAY_U1, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_MathInternal::Abs___STATIC__I4__I4, + Library_corlib_native_System_MathInternal::Min___STATIC__I4__I4__I4, + Library_corlib_native_System_MathInternal::Max___STATIC__I4__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJECT__CHAR__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Random::Next___I4, + Library_corlib_native_System_Random::Next___I4__I4, + Library_corlib_native_System_Random::NextDouble___R8, + Library_corlib_native_System_Random::NextBytes___VOID__SZARRAY_U1, + Library_corlib_native_System_Random::_ctor___VOID, + Library_corlib_native_System_Random::_ctor___VOID__I4, + Library_corlib_native_System_Reflection_Assembly::get_FullName___STRING, + Library_corlib_native_System_Reflection_Assembly::GetType___SystemType__STRING, + NULL, + Library_corlib_native_System_Reflection_Assembly::GetTypes___SZARRAY_SystemType, + Library_corlib_native_System_Reflection_Assembly::GetVersion___VOID__BYREF_I4__BYREF_I4__BYREF_I4__BYREF_I4, + NULL, + NULL, + Library_corlib_native_System_Reflection_Assembly::GetManifestResourceNames___SZARRAY_STRING, + NULL, + Library_corlib_native_System_Reflection_Assembly::GetExecutingAssembly___STATIC__SystemReflectionAssembly, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Reflection_Assembly::LoadInternal___STATIC__SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4, + Library_corlib_native_System_Reflection_Assembly::Load___STATIC__SystemReflectionAssembly__SZARRAY_U1, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Reflection_MethodBase::get_Name___STRING, + Library_corlib_native_System_Reflection_MethodBase::get_DeclaringType___SystemType, + Library_corlib_native_System_Reflection_MethodBase::get_IsPublic___BOOLEAN, + Library_corlib_native_System_Reflection_MethodBase::get_IsStatic___BOOLEAN, + Library_corlib_native_System_Reflection_MethodBase::get_IsFinal___BOOLEAN, + Library_corlib_native_System_Reflection_MethodBase::get_IsVirtual___BOOLEAN, + Library_corlib_native_System_Reflection_MethodBase::get_IsAbstract___BOOLEAN, + Library_corlib_native_System_Reflection_MethodBase::Invoke___OBJECT__OBJECT__SZARRAY_OBJECT, + NULL, + NULL, + Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN, + Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Reflection_FieldInfo::SetValue___VOID__OBJECT__OBJECT, + Library_corlib_native_System_Reflection_FieldInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Reflection_PropertyInfo::GetValue___OBJECT__OBJECT__SZARRAY_OBJECT, + Library_corlib_native_System_Reflection_PropertyInfo::SetValue___VOID__OBJECT__OBJECT__SZARRAY_OBJECT, + NULL, + NULL, + Library_corlib_native_System_Reflection_RuntimeFieldInfo::get_Name___STRING, + Library_corlib_native_System_Reflection_RuntimeFieldInfo::get_DeclaringType___SystemType, + Library_corlib_native_System_Reflection_RuntimeFieldInfo::get_FieldType___SystemType, + Library_corlib_native_System_Reflection_RuntimeFieldInfo::GetValue___OBJECT__OBJECT, + NULL, + Library_corlib_native_System_Reflection_RuntimeMethodInfo::get_ReturnType___SystemType, + Library_corlib_native_System_Reflection_RuntimeMethodInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::InitializeArray___STATIC__VOID__SystemArray__SystemRuntimeFieldHandle, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::GetObjectValue___STATIC__OBJECT__OBJECT, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::RunClassConstructor___STATIC__VOID__SystemRuntimeTypeHandle, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::get_OffsetToStringData___STATIC__I4, + Library_corlib_native_System_Runtime_Remoting_RemotingServices::IsTransparentProxy___STATIC__BOOLEAN__OBJECT, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Type::get_DeclaringType___SystemType, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Type::GetMethod___SystemReflectionMethodInfo__STRING__SystemReflectionBindingFlags, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Type::IsInstanceOfType___BOOLEAN__OBJECT, + NULL, + Library_corlib_native_System_Type::InvokeMember___OBJECT__STRING__SystemReflectionBindingFlags__SystemReflectionBinder__OBJECT__SZARRAY_OBJECT, + Library_corlib_native_System_Type::GetConstructor___SystemReflectionConstructorInfo__SZARRAY_SystemType, + Library_corlib_native_System_Type::GetMethod___SystemReflectionMethodInfo__STRING__SZARRAY_SystemType, + Library_corlib_native_System_Type::GetMethod___SystemReflectionMethodInfo__STRING, + NULL, + NULL, + NULL, + Library_corlib_native_System_Type::get_IsNotPublic___BOOLEAN, + Library_corlib_native_System_Type::get_IsPublic___BOOLEAN, + Library_corlib_native_System_Type::get_IsClass___BOOLEAN, + Library_corlib_native_System_Type::get_IsInterface___BOOLEAN, + Library_corlib_native_System_Type::get_IsValueType___BOOLEAN, + Library_corlib_native_System_Type::get_IsAbstract___BOOLEAN, + Library_corlib_native_System_Type::get_IsEnum___BOOLEAN, + Library_corlib_native_System_Type::get_IsSerializable___BOOLEAN, + Library_corlib_native_System_Type::get_IsArray___BOOLEAN, + NULL, + NULL, + Library_corlib_native_System_Type::GetTypeInternal___STATIC__SystemType__STRING__STRING__BOOLEAN__SZARRAY_I4, + Library_corlib_native_System_Type::GetTypeFromHandle___STATIC__SystemType__SystemRuntimeTypeHandle, + NULL, + NULL, + Library_corlib_native_System_RuntimeType::get_Assembly___SystemReflectionAssembly, + Library_corlib_native_System_RuntimeType::get_Name___STRING, + Library_corlib_native_System_RuntimeType::get_FullName___STRING, + NULL, + Library_corlib_native_System_RuntimeType::get_BaseType___SystemType, + Library_corlib_native_System_RuntimeType::GetMethods___SZARRAY_SystemReflectionMethodInfo__SystemReflectionBindingFlags, + Library_corlib_native_System_RuntimeType::GetField___SystemReflectionFieldInfo__STRING__SystemReflectionBindingFlags, + Library_corlib_native_System_RuntimeType::GetFields___SZARRAY_SystemReflectionFieldInfo__SystemReflectionBindingFlags, + Library_corlib_native_System_RuntimeType::GetInterfaces___SZARRAY_SystemType, + Library_corlib_native_System_RuntimeType::GetElementType___SystemType, + Library_corlib_native_System_RuntimeType::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_String::CompareTo___I4__OBJECT, + NULL, + Library_corlib_native_System_String::get_Chars___CHAR__I4, + Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR, + Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::get_Length___I4, + Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR__I4, + Library_corlib_native_System_String::Substring___STRING__I4, + Library_corlib_native_System_String::Substring___STRING__I4__I4, + Library_corlib_native_System_String::Trim___STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::TrimStart___STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::TrimEnd___STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR, + Library_corlib_native_System_String::_ctor___VOID__CHAR__I4, + Library_corlib_native_System_String::CompareTo___I4__STRING, + Library_corlib_native_System_String::IndexOf___I4__CHAR, + Library_corlib_native_System_String::IndexOf___I4__CHAR__I4, + Library_corlib_native_System_String::IndexOf___I4__CHAR__I4__I4, + Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR, + Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4, + Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::IndexOf___I4__STRING, + Library_corlib_native_System_String::IndexOf___I4__STRING__I4, + Library_corlib_native_System_String::IndexOf___I4__STRING__I4__I4, + Library_corlib_native_System_String::LastIndexOf___I4__CHAR, + Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4, + Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4__I4, + Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR, + Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4, + Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::LastIndexOf___I4__STRING, + Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4, + Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4__I4, + Library_corlib_native_System_String::ToLower___STRING, + Library_corlib_native_System_String::ToUpper___STRING, + Library_corlib_native_System_String::Trim___STRING, + NULL, + NULL, + Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING, + Library_corlib_native_System_String::op_Equality___STATIC__BOOLEAN__STRING__STRING, + Library_corlib_native_System_String::op_Inequality___STATIC__BOOLEAN__STRING__STRING, + Library_corlib_native_System_String::Compare___STATIC__I4__STRING__STRING, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING, + Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING, + Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING__STRING, + Library_corlib_native_System_String::Concat___STATIC__STRING__SZARRAY_STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Text_UTF8Decoder::Convert___VOID__SZARRAY_U1__I4__I4__SZARRAY_CHAR__I4__I4__BOOLEAN__BYREF_I4__BYREF_I4__BYREF_BOOLEAN, + NULL, + Library_corlib_native_System_Text_UTF8Encoding::GetBytes___SZARRAY_U1__STRING, + Library_corlib_native_System_Text_UTF8Encoding::GetBytes___I4__STRING__I4__I4__SZARRAY_U1__I4, + Library_corlib_native_System_Text_UTF8Encoding::GetChars___SZARRAY_CHAR__SZARRAY_U1, + Library_corlib_native_System_Text_UTF8Encoding::GetChars___SZARRAY_CHAR__SZARRAY_U1__I4__I4, + NULL, + NULL, + Library_corlib_native_System_Threading_WaitHandle::WaitOne___BOOLEAN__I4__BOOLEAN, + NULL, + NULL, + Library_corlib_native_System_Threading_WaitHandle::WaitMultiple___STATIC__I4__SZARRAY_SystemThreadingWaitHandle__I4__BOOLEAN__BOOLEAN, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Threading_AutoResetEvent::_ctor___VOID__BOOLEAN, + Library_corlib_native_System_Threading_AutoResetEvent::Reset___BOOLEAN, + Library_corlib_native_System_Threading_AutoResetEvent::Set___BOOLEAN, + Library_corlib_native_System_Threading_Interlocked::Increment___STATIC__I4__BYREF_I4, + Library_corlib_native_System_Threading_Interlocked::Decrement___STATIC__I4__BYREF_I4, + Library_corlib_native_System_Threading_Interlocked::Exchange___STATIC__I4__BYREF_I4__I4, + Library_corlib_native_System_Threading_Interlocked::CompareExchange___STATIC__I4__BYREF_I4__I4__I4, + Library_corlib_native_System_Threading_ManualResetEvent::_ctor___VOID__BOOLEAN, + Library_corlib_native_System_Threading_ManualResetEvent::Reset___BOOLEAN, + Library_corlib_native_System_Threading_ManualResetEvent::Set___BOOLEAN, + Library_corlib_native_System_Threading_Monitor::Enter___STATIC__VOID__OBJECT, + Library_corlib_native_System_Threading_Monitor::Exit___STATIC__VOID__OBJECT, + Library_corlib_native_System_Threading_Thread::_ctor___VOID__SystemThreadingThreadStart, + Library_corlib_native_System_Threading_Thread::Start___VOID, + Library_corlib_native_System_Threading_Thread::Abort___VOID, + Library_corlib_native_System_Threading_Thread::Suspend___VOID, + Library_corlib_native_System_Threading_Thread::Resume___VOID, + Library_corlib_native_System_Threading_Thread::get_Priority___SystemThreadingThreadPriority, + Library_corlib_native_System_Threading_Thread::set_Priority___VOID__SystemThreadingThreadPriority, + Library_corlib_native_System_Threading_Thread::get_ManagedThreadId___I4, + Library_corlib_native_System_Threading_Thread::get_IsAlive___BOOLEAN, + Library_corlib_native_System_Threading_Thread::Join___VOID, + Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__I4, + Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__SystemTimeSpan, + Library_corlib_native_System_Threading_Thread::get_ThreadState___SystemThreadingThreadState, + Library_corlib_native_System_Threading_Thread::Sleep___STATIC__VOID__I4, + NULL, + Library_corlib_native_System_Threading_Thread::get_CurrentThread___STATIC__SystemThreadingThread, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Threading_Timer::Dispose___VOID, + Library_corlib_native_System_Threading_Timer::_ctor___VOID__SystemThreadingTimerCallback__OBJECT__I4__I4, + Library_corlib_native_System_Threading_Timer::_ctor___VOID__SystemThreadingTimerCallback__OBJECT__SystemTimeSpan__SystemTimeSpan, + Library_corlib_native_System_Threading_Timer::Change___BOOLEAN__I4__I4, + Library_corlib_native_System_Threading_Timer::Change___BOOLEAN__SystemTimeSpan__SystemTimeSpan, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::Equals___BOOLEAN__OBJECT, + Library_corlib_native_System_TimeSpan::ToString___STRING, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4, + Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4, + Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::CompareTo___I4__OBJECT, + NULL, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan, + Library_corlib_native_System_TimeSpan::Equals___STATIC__BOOLEAN__SystemTimeSpan__SystemTimeSpan, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_WeakReference::get_IsAlive___BOOLEAN, + Library_corlib_native_System_WeakReference::get_Target___OBJECT, + Library_corlib_native_System_WeakReference::set_Target___VOID__OBJECT, + Library_corlib_native_System_WeakReference::_ctor___VOID__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +#elif (NANOCLR_REFLECTION == FALSE) + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + Library_corlib_native_System_Object::Equals___BOOLEAN__OBJECT, + Library_corlib_native_System_Object::GetHashCode___I4, + NULL, + Library_corlib_native_System_Object::MemberwiseClone___OBJECT, + NULL, + Library_corlib_native_System_Object::ReferenceEquals___STATIC__BOOLEAN__OBJECT__OBJECT, + NULL, + Library_corlib_native_System_ValueType::Equals___BOOLEAN__OBJECT, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Exception::get_StackTrace___STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Array::System_Collections_IList_get_Item___OBJECT__I4, + Library_corlib_native_System_Array::System_Collections_IList_set_Item___VOID__I4__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Array::get_Length___I4, + NULL, + NULL, + NULL, + Library_corlib_native_System_Array::Copy___STATIC__VOID__SystemArray__I4__SystemArray__I4__I4, + Library_corlib_native_System_Array::Clear___STATIC__VOID__SystemArray__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Array::TrySzIndexOf___STATIC__BOOLEAN__SystemArray__I4__I4__OBJECT__BYREF_I4, + Library_corlib_native_System_Delegate::Equals___BOOLEAN__OBJECT, + NULL, + Library_corlib_native_System_Delegate::Combine___STATIC__SystemDelegate__SystemDelegate__SystemDelegate, + Library_corlib_native_System_Delegate::Remove___STATIC__SystemDelegate__SystemDelegate__SystemDelegate, + Library_corlib_native_System_Delegate::op_Equality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate, + Library_corlib_native_System_Delegate::op_Inequality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate, + NULL, + NULL, + Library_corlib_native_System_MulticastDelegate::op_Equality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate, + Library_corlib_native_System_MulticastDelegate::op_Inequality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_BitConverter::get_IsLittleEndian___STATIC__BOOLEAN, + Library_corlib_native_System_BitConverter::DoubleToInt64Bits___STATIC__I8__R8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__BOOLEAN, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__CHAR, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__R8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__R4, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I2, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U4, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U8, + Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U2, + Library_corlib_native_System_BitConverter::Int64BitsToDouble___STATIC__R8__I8, + Library_corlib_native_System_BitConverter::ToBoolean___STATIC__BOOLEAN__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToChar___STATIC__CHAR__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToDouble___STATIC__R8__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToInt16___STATIC__I2__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToInt32___STATIC__I4__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToInt64___STATIC__I8__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToSingle___STATIC__R4__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1, + Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1__I4__I4, + Library_corlib_native_System_BitConverter::ToUInt16___STATIC__U2__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToUInt32___STATIC__U4__SZARRAY_U1__I4, + Library_corlib_native_System_BitConverter::ToUInt64___STATIC__U8__SZARRAY_U1__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Collections_ArrayList::get_Item___OBJECT__I4, + Library_corlib_native_System_Collections_ArrayList::set_Item___VOID__I4__OBJECT, + Library_corlib_native_System_Collections_ArrayList::Add___I4__OBJECT, + NULL, + Library_corlib_native_System_Collections_ArrayList::Clear___VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Collections_ArrayList::Insert___VOID__I4__OBJECT, + NULL, + Library_corlib_native_System_Collections_ArrayList::RemoveAt___VOID__I4, + NULL, + Library_corlib_native_System_Collections_ArrayList::SetCapacity___VOID__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Console::OutNative___STATIC__VOID__STRING__BOOLEAN, + NULL, + NULL, + Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4, + Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Convert::ToBase64String___STATIC__STRING__SZARRAY_U1__I4__I4__BOOLEAN, + NULL, + NULL, + Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZARRAY_U1__SZARRAY_CHAR__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_DateTime::_ctor___VOID__I4__I4__I4__I4__I4__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_DateTime::get_Day___I4, + Library_corlib_native_System_DateTime::get_DayOfWeek___SystemDayOfWeek, + Library_corlib_native_System_DateTime::get_DayOfYear___I4, + Library_corlib_native_System_DateTime::get_Hour___I4, + NULL, + Library_corlib_native_System_DateTime::get_Millisecond___I4, + Library_corlib_native_System_DateTime::get_Minute___I4, + Library_corlib_native_System_DateTime::get_Month___I4, + Library_corlib_native_System_DateTime::get_Second___I4, + NULL, + NULL, + Library_corlib_native_System_DateTime::get_Year___I4, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_DateTime::DaysInMonth___STATIC__I4__I4__I4, + NULL, + Library_corlib_native_System_DateTime::get_UtcNow___STATIC__SystemDateTime, + Library_corlib_native_System_DateTime::get_Today___STATIC__SystemDateTime, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Diagnostics_Debugger::get_IsAttached___STATIC__BOOLEAN, + Library_corlib_native_System_Diagnostics_Debugger::Break___STATIC__VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Double::CompareTo___STATIC__I4__R8__R8, + Library_corlib_native_System_Double::IsInfinity___STATIC__BOOLEAN__R8, + Library_corlib_native_System_Double::IsNaN___STATIC__BOOLEAN__R8, + Library_corlib_native_System_Double::IsNegativeInfinity___STATIC__BOOLEAN__R8, + Library_corlib_native_System_Double::IsPositiveInfinity___STATIC__BOOLEAN__R8, + NULL, + NULL, + Library_corlib_native_System_GC::AnyPendingFinalizers___STATIC__BOOLEAN, + NULL, + Library_corlib_native_System_GC::SuppressFinalize___STATIC__VOID__OBJECT, + Library_corlib_native_System_GC::ReRegisterForFinalize___STATIC__VOID__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Globalization_CultureInfo::get_CurrentUICultureInternal___STATIC__SystemGlobalizationCultureInfo, + Library_corlib_native_System_Globalization_CultureInfo::set_CurrentUICultureInternal___STATIC__VOID__SystemGlobalizationCultureInfo, + Library_corlib_native_System_Globalization_DateTimeFormat::FormatDigits___STATIC__STRING__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Guid::GenerateNewGuid___STATIC__SZARRAY_U1, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_MathInternal::Abs___STATIC__I4__I4, + Library_corlib_native_System_MathInternal::Min___STATIC__I4__I4__I4, + Library_corlib_native_System_MathInternal::Max___STATIC__I4__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJECT__CHAR__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Random::Next___I4, + Library_corlib_native_System_Random::Next___I4__I4, + Library_corlib_native_System_Random::NextDouble___R8, + Library_corlib_native_System_Random::NextBytes___VOID__SZARRAY_U1, + Library_corlib_native_System_Random::_ctor___VOID, + Library_corlib_native_System_Random::_ctor___VOID__I4, + NULL, + NULL, + NULL, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::InitializeArray___STATIC__VOID__SystemArray__SystemRuntimeFieldHandle, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::GetObjectValue___STATIC__OBJECT__OBJECT, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::RunClassConstructor___STATIC__VOID__SystemRuntimeTypeHandle, + Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::get_OffsetToStringData___STATIC__I4, + Library_corlib_native_System_Runtime_Remoting_RemotingServices::IsTransparentProxy___STATIC__BOOLEAN__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_String::CompareTo___I4__OBJECT, + NULL, + Library_corlib_native_System_String::get_Chars___CHAR__I4, + Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR, + Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::get_Length___I4, + Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR__I4, + Library_corlib_native_System_String::Substring___STRING__I4, + Library_corlib_native_System_String::Substring___STRING__I4__I4, + Library_corlib_native_System_String::Trim___STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::TrimStart___STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::TrimEnd___STRING__SZARRAY_CHAR, + Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR, + Library_corlib_native_System_String::_ctor___VOID__CHAR__I4, + Library_corlib_native_System_String::CompareTo___I4__STRING, + Library_corlib_native_System_String::IndexOf___I4__CHAR, + Library_corlib_native_System_String::IndexOf___I4__CHAR__I4, + Library_corlib_native_System_String::IndexOf___I4__CHAR__I4__I4, + Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR, + Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4, + Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::IndexOf___I4__STRING, + Library_corlib_native_System_String::IndexOf___I4__STRING__I4, + Library_corlib_native_System_String::IndexOf___I4__STRING__I4__I4, + Library_corlib_native_System_String::LastIndexOf___I4__CHAR, + Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4, + Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4__I4, + Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR, + Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4, + Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4__I4, + Library_corlib_native_System_String::LastIndexOf___I4__STRING, + Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4, + Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4__I4, + Library_corlib_native_System_String::ToLower___STRING, + Library_corlib_native_System_String::ToUpper___STRING, + Library_corlib_native_System_String::Trim___STRING, + NULL, + NULL, + Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING, + Library_corlib_native_System_String::op_Equality___STATIC__BOOLEAN__STRING__STRING, + Library_corlib_native_System_String::op_Inequality___STATIC__BOOLEAN__STRING__STRING, + Library_corlib_native_System_String::Compare___STATIC__I4__STRING__STRING, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING, + Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING, + Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING__STRING, + Library_corlib_native_System_String::Concat___STATIC__STRING__SZARRAY_STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Text_UTF8Decoder::Convert___VOID__SZARRAY_U1__I4__I4__SZARRAY_CHAR__I4__I4__BOOLEAN__BYREF_I4__BYREF_I4__BYREF_BOOLEAN, + NULL, + Library_corlib_native_System_Text_UTF8Encoding::GetBytes___SZARRAY_U1__STRING, + Library_corlib_native_System_Text_UTF8Encoding::GetBytes___I4__STRING__I4__I4__SZARRAY_U1__I4, + Library_corlib_native_System_Text_UTF8Encoding::GetChars___SZARRAY_CHAR__SZARRAY_U1, + Library_corlib_native_System_Text_UTF8Encoding::GetChars___SZARRAY_CHAR__SZARRAY_U1__I4__I4, + NULL, + NULL, + Library_corlib_native_System_Threading_WaitHandle::WaitOne___BOOLEAN__I4__BOOLEAN, + NULL, + NULL, + Library_corlib_native_System_Threading_WaitHandle::WaitMultiple___STATIC__I4__SZARRAY_SystemThreadingWaitHandle__I4__BOOLEAN__BOOLEAN, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Threading_AutoResetEvent::_ctor___VOID__BOOLEAN, + Library_corlib_native_System_Threading_AutoResetEvent::Reset___BOOLEAN, + Library_corlib_native_System_Threading_AutoResetEvent::Set___BOOLEAN, + Library_corlib_native_System_Threading_Interlocked::Increment___STATIC__I4__BYREF_I4, + Library_corlib_native_System_Threading_Interlocked::Decrement___STATIC__I4__BYREF_I4, + Library_corlib_native_System_Threading_Interlocked::Exchange___STATIC__I4__BYREF_I4__I4, + Library_corlib_native_System_Threading_Interlocked::CompareExchange___STATIC__I4__BYREF_I4__I4__I4, + Library_corlib_native_System_Threading_ManualResetEvent::_ctor___VOID__BOOLEAN, + Library_corlib_native_System_Threading_ManualResetEvent::Reset___BOOLEAN, + Library_corlib_native_System_Threading_ManualResetEvent::Set___BOOLEAN, + Library_corlib_native_System_Threading_Monitor::Enter___STATIC__VOID__OBJECT, + Library_corlib_native_System_Threading_Monitor::Exit___STATIC__VOID__OBJECT, + Library_corlib_native_System_Threading_Thread::_ctor___VOID__SystemThreadingThreadStart, + Library_corlib_native_System_Threading_Thread::Start___VOID, + Library_corlib_native_System_Threading_Thread::Abort___VOID, + Library_corlib_native_System_Threading_Thread::Suspend___VOID, + Library_corlib_native_System_Threading_Thread::Resume___VOID, + Library_corlib_native_System_Threading_Thread::get_Priority___SystemThreadingThreadPriority, + Library_corlib_native_System_Threading_Thread::set_Priority___VOID__SystemThreadingThreadPriority, + Library_corlib_native_System_Threading_Thread::get_ManagedThreadId___I4, + Library_corlib_native_System_Threading_Thread::get_IsAlive___BOOLEAN, + Library_corlib_native_System_Threading_Thread::Join___VOID, + Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__I4, + Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__SystemTimeSpan, + Library_corlib_native_System_Threading_Thread::get_ThreadState___SystemThreadingThreadState, + Library_corlib_native_System_Threading_Thread::Sleep___STATIC__VOID__I4, + NULL, + Library_corlib_native_System_Threading_Thread::get_CurrentThread___STATIC__SystemThreadingThread, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_Threading_Timer::Dispose___VOID, + Library_corlib_native_System_Threading_Timer::_ctor___VOID__SystemThreadingTimerCallback__OBJECT__I4__I4, + Library_corlib_native_System_Threading_Timer::_ctor___VOID__SystemThreadingTimerCallback__OBJECT__SystemTimeSpan__SystemTimeSpan, + Library_corlib_native_System_Threading_Timer::Change___BOOLEAN__I4__I4, + Library_corlib_native_System_Threading_Timer::Change___BOOLEAN__SystemTimeSpan__SystemTimeSpan, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::Equals___BOOLEAN__OBJECT, + Library_corlib_native_System_TimeSpan::ToString___STRING, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4, + Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4, + Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::CompareTo___I4__OBJECT, + NULL, + NULL, + NULL, + Library_corlib_native_System_TimeSpan::Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan, + Library_corlib_native_System_TimeSpan::Equals___STATIC__BOOLEAN__SystemTimeSpan__SystemTimeSpan, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_corlib_native_System_WeakReference::get_IsAlive___BOOLEAN, + Library_corlib_native_System_WeakReference::get_Target___OBJECT, + Library_corlib_native_System_WeakReference::set_Target___VOID__OBJECT, + Library_corlib_native_System_WeakReference::_ctor___VOID__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +#else +#error "NANOCLR_REFLECTION has to be define either TRUE or FALSE. Check the build options." +#endif + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib = +{ + "mscorlib", + +#if (NANOCLR_REFLECTION == TRUE) + + 0xDCB6AEBA, + +#elif (NANOCLR_REFLECTION == FALSE) + + 0x7E26EC5E, + +#else +#error "NANOCLR_REFLECTION has to be define either TRUE or FALSE. Check the build options." +#endif + + method_lookup, + { 100, 4, 5, 0 } +}; diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native.h b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native.h new file mode 100644 index 00000000..45c1ce83 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native.h @@ -0,0 +1,1064 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _CORLIB_NATIVE_H_ +#define _CORLIB_NATIVE_H_ + +#include +#include +#include + +struct Library_corlib_native_System_Object +{ + NANOCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + NANOCLR_NATIVE_DECLARE(GetHashCode___I4); + NANOCLR_NATIVE_DECLARE(GetType___SystemType); + NANOCLR_NATIVE_DECLARE(MemberwiseClone___OBJECT); + NANOCLR_NATIVE_DECLARE(ReferenceEquals___STATIC__BOOLEAN__OBJECT__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_ValueType +{ + NANOCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable +{ + static const int FIELD___buckets = 1; + static const int FIELD___numberOfBuckets = 2; + static const int FIELD___count = 3; + static const int FIELD___loadFactor = 4; + static const int FIELD___maxLoadFactor = 5; + static const int FIELD___growthFactor = 6; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable__Entry +{ + static const int FIELD__key = 1; + static const int FIELD__value = 2; + static const int FIELD__next = 3; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable__HashtableEnumerator +{ + static const int FIELD__ht = 1; + static const int FIELD__temp = 2; + static const int FIELD__index = 3; + static const int FIELD__returnType = 4; + + + //--// + +}; + +struct Library_corlib_native_System_Exception +{ + static const int FIELD___message = 1; + static const int FIELD___innerException = 2; + static const int FIELD___stackTrace = 3; + static const int FIELD__HResult = 4; + + NANOCLR_NATIVE_DECLARE(get_StackTrace___STRING); + + //--// + + struct StackTrace + { + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; + }; + + static HRESULT CreateInstance( CLR_RT_HeapBlock& ref, HRESULT hr, CLR_RT_StackFrame* stack ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& ref, const CLR_RT_TypeDef_Index& cls , HRESULT hr, CLR_RT_StackFrame* stack ); + static HRESULT SetStackTrace ( CLR_RT_HeapBlock& ref, CLR_RT_StackFrame* stack ); + + static CLR_RT_HeapBlock* GetTarget ( CLR_RT_HeapBlock& ref ); + static StackTrace* GetStackTrace( CLR_RT_HeapBlock* obj, CLR_UINT32& depth ); + + //--// + + static const char* GetMessage( CLR_RT_HeapBlock* obj ) { return obj[ Library_corlib_native_System_Exception::FIELD___message ].RecoverString() ; } + static CLR_UINT32 GetHResult( CLR_RT_HeapBlock* obj ) { return obj[ Library_corlib_native_System_Exception::FIELD__HResult ].NumericByRef().u4; } +}; + +struct Library_corlib_native_System_Collections_Hashtable__KeyCollection +{ + static const int FIELD__ht = 1; + + + //--// + +}; + +#if (NANOCLR_REFLECTION == TRUE) + +struct Library_corlib_native_System_AppDomain +{ + static const int FIELD___appDomain = 1; + static const int FIELD___friendlyName = 2; + + NANOCLR_NATIVE_DECLARE(GetAssemblies___SZARRAY_SystemReflectionAssembly); + NANOCLR_NATIVE_DECLARE(LoadInternal___SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(CreateDomain___STATIC__SystemAppDomain__STRING); + NANOCLR_NATIVE_DECLARE(Unload___STATIC__VOID__SystemAppDomain); + + //--// +#if defined(NANOCLR_APPDOMAINS) + static HRESULT GetAppDomain( CLR_RT_HeapBlock& ref, CLR_RT_AppDomain*& appDomain, CLR_RT_AppDomain*& appDomainSav, bool fCheckForUnloadingAppDomain ); +#endif +}; + +#endif // NANOCLR_REFLECTION + +struct Library_corlib_native_System_ArgumentException +{ + static const int FIELD___paramName = 5; + + + //--// + +}; + +struct Library_corlib_native_System_Array +{ + NANOCLR_NATIVE_DECLARE(System_Collections_IList_get_Item___OBJECT__I4); + NANOCLR_NATIVE_DECLARE(System_Collections_IList_set_Item___VOID__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(get_Length___I4); +#if (NANOCLR_REFLECTION == TRUE) + NANOCLR_NATIVE_DECLARE(CreateInstance___STATIC__SystemArray__SystemType__I4); +#endif // NANOCLR_REFLECTION + NANOCLR_NATIVE_DECLARE(Copy___STATIC__VOID__SystemArray__I4__SystemArray__I4__I4); + NANOCLR_NATIVE_DECLARE(Clear___STATIC__VOID__SystemArray__I4__I4); + NANOCLR_NATIVE_DECLARE(TrySzIndexOf___STATIC__BOOLEAN__SystemArray__I4__I4__OBJECT__BYREF_I4); + + //--// + + static HRESULT Clear ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg , int index , int length ); + static HRESULT Copy ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& argSrc, int indexSrc, CLR_RT_HeapBlock& argDst, int indexDst, int length ); + static HRESULT TrySzIndexOf( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& argSrc, CLR_RT_HeapBlock& match , int start , int stop , bool fForward, CLR_RT_HeapBlock& retValue ); +}; + +struct Library_corlib_native_System_Delegate +{ + NANOCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + NANOCLR_NATIVE_DECLARE(Combine___STATIC__SystemDelegate__SystemDelegate__SystemDelegate); + NANOCLR_NATIVE_DECLARE(Remove___STATIC__SystemDelegate__SystemDelegate__SystemDelegate); + NANOCLR_NATIVE_DECLARE(op_Equality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate); + NANOCLR_NATIVE_DECLARE(op_Inequality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate); + +#if (NANOCLR_REFLECTION == TRUE) + NANOCLR_NATIVE_DECLARE(GetInvocationList___SZARRAY_SystemDelegate); + NANOCLR_NATIVE_DECLARE(get_Method___SystemReflectionMethodInfo); + NANOCLR_NATIVE_DECLARE(get_Target___OBJECT); +#endif // NANOCLR_REFLECTION + + //--// + + static CLR_RT_HeapBlock_Delegate* GetLastDelegate( CLR_RT_HeapBlock_Delegate* dlg ); +}; + +struct Library_corlib_native_System_MulticastDelegate +{ + NANOCLR_NATIVE_DECLARE(op_Equality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate); + NANOCLR_NATIVE_DECLARE(op_Inequality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate); + + //--// + +}; + +struct Library_corlib_native_System_BitConverter +{ + NANOCLR_NATIVE_DECLARE(get_IsLittleEndian___STATIC__BOOLEAN); + NANOCLR_NATIVE_DECLARE(DoubleToInt64Bits___STATIC__I8__R8); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__BOOLEAN); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__CHAR); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__R8); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__R4); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__I8); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__I2); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__U4); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__U8); + NANOCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__U2); + NANOCLR_NATIVE_DECLARE(Int64BitsToDouble___STATIC__R8__I8); + NANOCLR_NATIVE_DECLARE(ToBoolean___STATIC__BOOLEAN__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToChar___STATIC__CHAR__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToDouble___STATIC__R8__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToInt16___STATIC__I2__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToInt32___STATIC__I4__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToInt64___STATIC__I8__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToSingle___STATIC__R4__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToString___STATIC__STRING__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(ToString___STATIC__STRING__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToString___STATIC__STRING__SZARRAY_U1__I4__I4); + NANOCLR_NATIVE_DECLARE(ToUInt16___STATIC__U2__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToUInt32___STATIC__U4__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(ToUInt64___STATIC__U8__SZARRAY_U1__I4); + + //--// + +}; + +struct Library_corlib_native_System_Boolean +{ + static const int FIELD_STATIC__FalseString = 0; + static const int FIELD_STATIC__TrueString = 1; + + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Byte +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Char +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_ArrayList +{ + static const int FIELD___items = 1; + static const int FIELD___size = 2; + + NANOCLR_NATIVE_DECLARE(get_Item___OBJECT__I4); + NANOCLR_NATIVE_DECLARE(set_Item___VOID__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(Add___I4__OBJECT); + NANOCLR_NATIVE_DECLARE(Clear___VOID); + NANOCLR_NATIVE_DECLARE(Insert___VOID__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(RemoveAt___VOID__I4); + NANOCLR_NATIVE_DECLARE(SetCapacity___VOID__I4); + + //--// + +}; + +struct Library_corlib_native_System_Console +{ + NANOCLR_NATIVE_DECLARE(OutNative___STATIC__VOID__STRING__BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Convert +{ + NANOCLR_NATIVE_DECLARE(NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4); + NANOCLR_NATIVE_DECLARE(NativeToDouble___STATIC__R8__STRING); + NANOCLR_NATIVE_DECLARE(ToBase64String___STATIC__STRING__SZARRAY_U1__I4__I4__BOOLEAN); + NANOCLR_NATIVE_DECLARE(FromBase64CharArray___STATIC__SZARRAY_U1__SZARRAY_CHAR__I4); + + //--// + + static double GetDoubleFractionalPart(char* str, int length); + static int64_t GetIntegerPart(char* str, int length); + static int64_t GetIntegerFromHexString(char* str); +}; + +struct Library_corlib_native_System_DateTime +{ + static const int FIELD_STATIC__MinValue = 2; + static const int FIELD_STATIC__MaxValue = 3; + static const int FIELD_STATIC__UnixEpoch = 4; + + static const int FIELD___ticks = 1; + + NANOCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(get_Day___I4); + NANOCLR_NATIVE_DECLARE(get_DayOfWeek___SystemDayOfWeek); + NANOCLR_NATIVE_DECLARE(get_DayOfYear___I4); + NANOCLR_NATIVE_DECLARE(get_Hour___I4); + NANOCLR_NATIVE_DECLARE(get_Millisecond___I4); + NANOCLR_NATIVE_DECLARE(get_Minute___I4); + NANOCLR_NATIVE_DECLARE(get_Month___I4); + NANOCLR_NATIVE_DECLARE(get_Second___I4); + NANOCLR_NATIVE_DECLARE(get_Year___I4); + NANOCLR_NATIVE_DECLARE(DaysInMonth___STATIC__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(get_UtcNow___STATIC__SystemDateTime); + NANOCLR_NATIVE_DECLARE(get_Today___STATIC__SystemDateTime); + + //--// + + static CLR_INT64* NewObject ( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_HeapBlock& ref ); + + static void Expand ( CLR_RT_StackFrame& stack, SYSTEMTIME& st ); + static void Compress( CLR_RT_StackFrame& stack, const SYSTEMTIME& st ); +}; + +struct Library_corlib_native_System_Diagnostics_Debugger +{ + NANOCLR_NATIVE_DECLARE(get_IsAttached___STATIC__BOOLEAN); + NANOCLR_NATIVE_DECLARE(Break___STATIC__VOID); + + //--// + +}; + +struct Library_corlib_native_System_Diagnostics_DebuggerBrowsableAttribute +{ + static const int FIELD___state = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Double +{ + static const int FIELD___value = 1; + + NANOCLR_NATIVE_DECLARE(CompareTo___STATIC__I4__R8__R8); + NANOCLR_NATIVE_DECLARE(IsInfinity___STATIC__BOOLEAN__R8); + NANOCLR_NATIVE_DECLARE(IsNaN___STATIC__BOOLEAN__R8); + NANOCLR_NATIVE_DECLARE(IsNegativeInfinity___STATIC__BOOLEAN__R8); + NANOCLR_NATIVE_DECLARE(IsPositiveInfinity___STATIC__BOOLEAN__R8); + + //--// + +}; + +struct Library_corlib_native_System_GC +{ + NANOCLR_NATIVE_DECLARE(AnyPendingFinalizers___STATIC__BOOLEAN); + NANOCLR_NATIVE_DECLARE(SuppressFinalize___STATIC__VOID__OBJECT); + NANOCLR_NATIVE_DECLARE(ReRegisterForFinalize___STATIC__VOID__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Globalization_CultureInfo +{ + static const int FIELD___numInfo = 1; + static const int FIELD___dateTimeInfo = 2; + static const int FIELD___cultureInfoName = 3; + static const int FIELD___name = 4; + static const int FIELD___parent = 5; + + NANOCLR_NATIVE_DECLARE(get_CurrentUICultureInternal___STATIC__SystemGlobalizationCultureInfo); + NANOCLR_NATIVE_DECLARE(set_CurrentUICultureInternal___STATIC__VOID__SystemGlobalizationCultureInfo); + + //--// + +}; + +struct Library_corlib_native_System_Globalization_DateTimeFormat +{ + NANOCLR_NATIVE_DECLARE(FormatDigits___STATIC__STRING__I4__I4); + + //--// + +}; + +struct Library_corlib_native_System_Globalization_DateTimeFormatInfo +{ + static const int FIELD___generalShortTimePattern = 1; + static const int FIELD___generalLongTimePattern = 2; + static const int FIELD___fullDateTimePattern = 3; + + + //--// + +}; + +struct Library_corlib_native_System_Globalization_NumberFormatInfo +{ + static const int FIELD___numberGroupSizes = 1; + static const int FIELD___positiveSign = 2; + static const int FIELD___negativeSign = 3; + static const int FIELD___numberDecimalSeparator = 4; + static const int FIELD___numberGroupSeparator = 5; + static const int FIELD___cultureInfo = 6; + + + //--// + +}; + +struct Library_corlib_native_System_Guid +{ + static const int FIELD_STATIC__Empty = 5; + + static const int FIELD___a = 1; + static const int FIELD___b = 2; + static const int FIELD___c = 3; + static const int FIELD___d = 4; + static const int FIELD___e = 5; + static const int FIELD___f = 6; + static const int FIELD___g = 7; + static const int FIELD___h = 8; + static const int FIELD___i = 9; + static const int FIELD___j = 10; + static const int FIELD___k = 11; + + NANOCLR_NATIVE_DECLARE(GenerateNewGuid___STATIC__SZARRAY_U1); + + //--// + +}; + +struct Library_corlib_native_System_Int16 +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Int32 +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Int64 +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_MathInternal +{ + NANOCLR_NATIVE_DECLARE(Abs___STATIC__I4__I4); + NANOCLR_NATIVE_DECLARE(Min___STATIC__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(Max___STATIC__I4__I4__I4); + + //--// + +}; + +struct Library_corlib_native_System_Number +{ + NANOCLR_NATIVE_DECLARE(FormatNative___STATIC__STRING__OBJECT__CHAR__I4); + + //--// + +}; + +struct Library_corlib_native_System_Random +{ + static const int FIELD___random = 1; + + NANOCLR_NATIVE_DECLARE(Next___I4); + NANOCLR_NATIVE_DECLARE(Next___I4__I4); + NANOCLR_NATIVE_DECLARE(NextDouble___R8); + NANOCLR_NATIVE_DECLARE(NextBytes___VOID__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(_ctor___VOID); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__I4); + + //--// + + static HRESULT GetRandom( CLR_RT_StackFrame& stack, CLR_RT_Random*& rand, bool create = false ); +}; + +struct Library_corlib_native_System_Reflection_Assembly +{ + NANOCLR_NATIVE_DECLARE(get_FullName___STRING); + NANOCLR_NATIVE_DECLARE(GetType___SystemType__STRING); + NANOCLR_NATIVE_DECLARE(GetTypes___SZARRAY_SystemType); + NANOCLR_NATIVE_DECLARE(GetVersion___VOID__BYREF_I4__BYREF_I4__BYREF_I4__BYREF_I4); + NANOCLR_NATIVE_DECLARE(GetManifestResourceNames___SZARRAY_STRING); + NANOCLR_NATIVE_DECLARE(GetExecutingAssembly___STATIC__SystemReflectionAssembly); + NANOCLR_NATIVE_DECLARE(LoadInternal___STATIC__SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(Load___STATIC__SystemReflectionAssembly__SZARRAY_U1); + + //--// + +#if (NANOCLR_REFLECTION == TRUE) + static HRESULT GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_Assembly_Instance& inst ); +#endif // NANOCLR_REFLECTION +}; + +struct Library_corlib_native_System_Reflection_AssemblyName +{ + static const int FIELD___assembly = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Reflection_MethodBase +{ + NANOCLR_NATIVE_DECLARE(get_Name___STRING); + NANOCLR_NATIVE_DECLARE(get_DeclaringType___SystemType); + NANOCLR_NATIVE_DECLARE(get_IsPublic___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsStatic___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsFinal___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsVirtual___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsAbstract___BOOLEAN); + NANOCLR_NATIVE_DECLARE(Invoke___OBJECT__OBJECT__SZARRAY_OBJECT); + + //--// + +#if (NANOCLR_REFLECTION == TRUE) + static HRESULT GetMethodDescriptor( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg, CLR_RT_MethodDef_Instance& inst ); + static HRESULT CheckFlags( CLR_RT_StackFrame& stack, CLR_UINT32 mask, CLR_UINT32 flag ); +#endif // NANOCLR_REFLECTION +}; + +struct Library_corlib_native_System_Reflection_ConstructorInfo +{ + NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN); + NANOCLR_NATIVE_DECLARE(Invoke___OBJECT__SZARRAY_OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Reflection_FieldInfo +{ + NANOCLR_NATIVE_DECLARE(SetValue___VOID__OBJECT__OBJECT); + NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN); + + //--// + +#if (NANOCLR_REFLECTION == TRUE) + static HRESULT Initialize( CLR_RT_StackFrame& stack, CLR_RT_FieldDef_Instance& instFD, CLR_RT_TypeDef_Instance& instTD, CLR_RT_HeapBlock*& obj ); +#endif // NANOCLR_REFLECTION +}; + +struct Library_corlib_native_System_Reflection_PropertyInfo +{ + NANOCLR_NATIVE_DECLARE(GetValue___OBJECT__OBJECT__SZARRAY_OBJECT); + NANOCLR_NATIVE_DECLARE(SetValue___VOID__OBJECT__OBJECT__SZARRAY_OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Reflection_RuntimeFieldInfo +{ + NANOCLR_NATIVE_DECLARE(get_Name___STRING); + NANOCLR_NATIVE_DECLARE(get_DeclaringType___SystemType); + NANOCLR_NATIVE_DECLARE(get_FieldType___SystemType); + NANOCLR_NATIVE_DECLARE(GetValue___OBJECT__OBJECT); + + //--// + +#if (NANOCLR_REFLECTION == TRUE) + static bool GetFieldDescriptor( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg, CLR_RT_FieldDef_Instance& inst ); +#endif // NANOCLR_REFLECTION +}; + +struct Library_corlib_native_System_Reflection_RuntimeMethodInfo +{ + NANOCLR_NATIVE_DECLARE(get_ReturnType___SystemType); + NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Runtime_CompilerServices_AccessedThroughPropertyAttribute +{ + static const int FIELD___propertyName = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers +{ + NANOCLR_NATIVE_DECLARE(InitializeArray___STATIC__VOID__SystemArray__SystemRuntimeFieldHandle); + NANOCLR_NATIVE_DECLARE(GetObjectValue___STATIC__OBJECT__OBJECT); + NANOCLR_NATIVE_DECLARE(RunClassConstructor___STATIC__VOID__SystemRuntimeTypeHandle); + NANOCLR_NATIVE_DECLARE(get_OffsetToStringData___STATIC__I4); + + //--// + +}; + +struct Library_corlib_native_System_Runtime_Remoting_RemotingServices +{ + NANOCLR_NATIVE_DECLARE(IsTransparentProxy___STATIC__BOOLEAN__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Runtime_Versioning_TargetFrameworkAttribute +{ + static const int FIELD___frameworkName = 1; + static const int FIELD___frameworkDisplayName = 2; + + + //--// + +}; + +#if (NANOCLR_REFLECTION == TRUE) + +struct Library_corlib_native_System_Type +{ + NANOCLR_NATIVE_DECLARE(get_DeclaringType___SystemType); + NANOCLR_NATIVE_DECLARE(GetMethod___SystemReflectionMethodInfo__STRING__SystemReflectionBindingFlags); + NANOCLR_NATIVE_DECLARE(IsInstanceOfType___BOOLEAN__OBJECT); + NANOCLR_NATIVE_DECLARE(InvokeMember___OBJECT__STRING__SystemReflectionBindingFlags__SystemReflectionBinder__OBJECT__SZARRAY_OBJECT); + NANOCLR_NATIVE_DECLARE(GetConstructor___SystemReflectionConstructorInfo__SZARRAY_SystemType); + NANOCLR_NATIVE_DECLARE(GetMethod___SystemReflectionMethodInfo__STRING__SZARRAY_SystemType); + NANOCLR_NATIVE_DECLARE(GetMethod___SystemReflectionMethodInfo__STRING); + NANOCLR_NATIVE_DECLARE(get_IsNotPublic___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsPublic___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsClass___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsInterface___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsValueType___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsAbstract___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsEnum___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsSerializable___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_IsArray___BOOLEAN); + NANOCLR_NATIVE_DECLARE(GetTypeInternal___STATIC__SystemType__STRING__STRING__BOOLEAN__SZARRAY_I4); + NANOCLR_NATIVE_DECLARE(GetTypeFromHandle___STATIC__SystemType__SystemRuntimeTypeHandle); + + //--// + + static const int c_BindingFlags_Default = 0x00000000; // a place holder for no flag specifed + + static const int c_BindingFlags_IgnoreCase = 0x00000001; // Ignore the case of Names while searching + static const int c_BindingFlags_DeclaredOnly = 0x00000002; // Only look at the members declared on the Type + static const int c_BindingFlags_Instance = 0x00000004; // Include Instance members in search + static const int c_BindingFlags_Static = 0x00000008; // Include Static members in search + static const int c_BindingFlags_Public = 0x00000010; // Include Public members in search + static const int c_BindingFlags_NonPublic = 0x00000020; // Include Non-Public members in search + static const int c_BindingFlags_FlattenHierarchy = 0x00000040; // Rollup the statics into the class. + + static const int c_BindingFlags_InvokeMethod = 0x00000100; + static const int c_BindingFlags_CreateInstance = 0x00000200; + static const int c_BindingFlags_GetField = 0x00000400; + static const int c_BindingFlags_SetField = 0x00000800; + static const int c_BindingFlags_GetProperty = 0x00001000; + static const int c_BindingFlags_SetProperty = 0x00002000; + + static const int c_BindingFlags_PutDispProperty = 0x00004000; + static const int c_BindingFlags_PutRefDispProperty = 0x00008000; + + static const int c_BindingFlags_ExactBinding = 0x00010000; // Bind with Exact Type matching, No Change type + static const int c_BindingFlags_SuppressChangeType = 0x00020000; + + static const int c_BindingFlags_OptionalParamBinding = 0x00040000; + static const int c_BindingFlags_IgnoreReturn = 0x01000000; // This is used in COM Interop + + //--// + + static const int c_BindingFlags_DefaultLookup = c_BindingFlags_Instance | c_BindingFlags_Static | c_BindingFlags_Public; + + //--// + + static HRESULT CheckFlags( CLR_RT_StackFrame& stack, CLR_UINT32 mask, CLR_UINT32 flag ); + + static HRESULT GetFields ( CLR_RT_StackFrame& stack, const char* szText, CLR_UINT32 attr , bool fAllMatches ); + static HRESULT GetMethods( CLR_RT_StackFrame& stack, const char* szText, CLR_UINT32 attr, CLR_RT_HeapBlock* pParams, int iParams, bool fAllMatches ); +}; +#endif // NANOCLR_REFLECTION + +#if (NANOCLR_REFLECTION == TRUE) +struct Library_corlib_native_System_RuntimeType +{ + NANOCLR_NATIVE_DECLARE(get_Assembly___SystemReflectionAssembly); + NANOCLR_NATIVE_DECLARE(get_Name___STRING); + NANOCLR_NATIVE_DECLARE(get_FullName___STRING); + NANOCLR_NATIVE_DECLARE(get_BaseType___SystemType); + NANOCLR_NATIVE_DECLARE(GetMethods___SZARRAY_SystemReflectionMethodInfo__SystemReflectionBindingFlags); + NANOCLR_NATIVE_DECLARE(GetField___SystemReflectionFieldInfo__STRING__SystemReflectionBindingFlags); + NANOCLR_NATIVE_DECLARE(GetFields___SZARRAY_SystemReflectionFieldInfo__SystemReflectionBindingFlags); + NANOCLR_NATIVE_DECLARE(GetInterfaces___SZARRAY_SystemType); + NANOCLR_NATIVE_DECLARE(GetElementType___SystemType); + NANOCLR_NATIVE_DECLARE(GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN); + + //--// + + static HRESULT GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_TypeDef_Instance& inst, CLR_UINT32* levels ); + static HRESULT GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_TypeDef_Instance& inst ); + static HRESULT GetName( CLR_RT_HeapBlock& arg, bool fFullName, CLR_RT_HeapBlock& res ); +}; +#endif // NANOCLR_REFLECTION + +struct Library_corlib_native_System_SByte +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Single +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_String +{ + static const int FIELD_STATIC__Empty = 6; + + NANOCLR_NATIVE_DECLARE(CompareTo___I4__OBJECT); + NANOCLR_NATIVE_DECLARE(get_Chars___CHAR__I4); + NANOCLR_NATIVE_DECLARE(ToCharArray___SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(ToCharArray___SZARRAY_CHAR__I4__I4); + NANOCLR_NATIVE_DECLARE(get_Length___I4); + NANOCLR_NATIVE_DECLARE(Split___SZARRAY_STRING__SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(Split___SZARRAY_STRING__SZARRAY_CHAR__I4); + NANOCLR_NATIVE_DECLARE(Substring___STRING__I4); + NANOCLR_NATIVE_DECLARE(Substring___STRING__I4__I4); + NANOCLR_NATIVE_DECLARE(Trim___STRING__SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(TrimStart___STRING__SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(TrimEnd___STRING__SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__SZARRAY_CHAR__I4__I4); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__CHAR__I4); + NANOCLR_NATIVE_DECLARE(CompareTo___I4__STRING); + NANOCLR_NATIVE_DECLARE(IndexOf___I4__CHAR); + NANOCLR_NATIVE_DECLARE(IndexOf___I4__CHAR__I4); + NANOCLR_NATIVE_DECLARE(IndexOf___I4__CHAR__I4__I4); + NANOCLR_NATIVE_DECLARE(IndexOfAny___I4__SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(IndexOfAny___I4__SZARRAY_CHAR__I4); + NANOCLR_NATIVE_DECLARE(IndexOfAny___I4__SZARRAY_CHAR__I4__I4); + NANOCLR_NATIVE_DECLARE(IndexOf___I4__STRING); + NANOCLR_NATIVE_DECLARE(IndexOf___I4__STRING__I4); + NANOCLR_NATIVE_DECLARE(IndexOf___I4__STRING__I4__I4); + NANOCLR_NATIVE_DECLARE(LastIndexOf___I4__CHAR); + NANOCLR_NATIVE_DECLARE(LastIndexOf___I4__CHAR__I4); + NANOCLR_NATIVE_DECLARE(LastIndexOf___I4__CHAR__I4__I4); + NANOCLR_NATIVE_DECLARE(LastIndexOfAny___I4__SZARRAY_CHAR); + NANOCLR_NATIVE_DECLARE(LastIndexOfAny___I4__SZARRAY_CHAR__I4); + NANOCLR_NATIVE_DECLARE(LastIndexOfAny___I4__SZARRAY_CHAR__I4__I4); + NANOCLR_NATIVE_DECLARE(LastIndexOf___I4__STRING); + NANOCLR_NATIVE_DECLARE(LastIndexOf___I4__STRING__I4); + NANOCLR_NATIVE_DECLARE(LastIndexOf___I4__STRING__I4__I4); + NANOCLR_NATIVE_DECLARE(ToLower___STRING); + NANOCLR_NATIVE_DECLARE(ToUpper___STRING); + NANOCLR_NATIVE_DECLARE(Trim___STRING); + NANOCLR_NATIVE_DECLARE(Equals___STATIC__BOOLEAN__STRING__STRING); + NANOCLR_NATIVE_DECLARE(op_Equality___STATIC__BOOLEAN__STRING__STRING); + NANOCLR_NATIVE_DECLARE(op_Inequality___STATIC__BOOLEAN__STRING__STRING); + NANOCLR_NATIVE_DECLARE(Compare___STATIC__I4__STRING__STRING); + NANOCLR_NATIVE_DECLARE(Concat___STATIC__STRING__STRING__STRING); + NANOCLR_NATIVE_DECLARE(Concat___STATIC__STRING__STRING__STRING__STRING); + NANOCLR_NATIVE_DECLARE(Concat___STATIC__STRING__STRING__STRING__STRING__STRING); + NANOCLR_NATIVE_DECLARE(Concat___STATIC__STRING__SZARRAY_STRING); + + //--// + + static const int c_IndexOf__SingleChar = 0x00000001; + static const int c_IndexOf__MultipleChars = 0x00000002; + static const int c_IndexOf__String = 0x00000004; + static const int c_IndexOf__StartIndex = 0x00000010; + static const int c_IndexOf__Count = 0x00000020; + static const int c_IndexOf__Last = 0x00000040; + static const int c_IndexOf__String_Last = 0x00000044; + + static HRESULT FromCharArray( CLR_RT_StackFrame& stack, int startIndex, int count ); + static HRESULT ToCharArray ( CLR_RT_StackFrame& stack, int startIndex, int count ); + static HRESULT IndexOf ( CLR_RT_StackFrame& stack, int mode ); + static HRESULT ChangeCase ( CLR_RT_StackFrame& stack, bool fToUpper ); + static HRESULT Substring ( CLR_RT_StackFrame& stack, int startIndex, int count ); + + + static HRESULT Trim( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_Array* arrayTrimChars, bool fStart, bool fEnd ); + + static HRESULT Split( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& chars, int maxStrings ); + + //--// + + static HRESULT Concat( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock* array, int num ); + + static HRESULT ConvertToCharArray( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ); + static HRESULT ConvertToCharArray( const char* szText , CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ); +}; + +struct Library_corlib_native_System_Text_StringBuilder +{ + static const int FIELD___maxCapacity = 1; + static const int FIELD___chunkChars = 2; + static const int FIELD___chunkLength = 3; + static const int FIELD___chunkPrevious = 4; + static const int FIELD___chunkOffset = 5; + + + //--// + +}; + +struct Library_corlib_native_System_Text_UTF8Decoder +{ + NANOCLR_NATIVE_DECLARE(Convert___VOID__SZARRAY_U1__I4__I4__SZARRAY_CHAR__I4__I4__BOOLEAN__BYREF_I4__BYREF_I4__BYREF_BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Text_UTF8Encoding +{ + NANOCLR_NATIVE_DECLARE(GetBytes___SZARRAY_U1__STRING); + NANOCLR_NATIVE_DECLARE(GetBytes___I4__STRING__I4__I4__SZARRAY_U1__I4); + NANOCLR_NATIVE_DECLARE(GetChars___SZARRAY_CHAR__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(GetChars___SZARRAY_CHAR__SZARRAY_U1__I4__I4); + + //--// + + static HRESULT Helper__GetChars(CLR_RT_StackFrame& stack, bool fIndexed); +}; + +struct Library_corlib_native_System_Threading_WaitHandle +{ + NANOCLR_NATIVE_DECLARE(WaitOne___BOOLEAN__I4__BOOLEAN); + NANOCLR_NATIVE_DECLARE(WaitMultiple___STATIC__I4__SZARRAY_SystemThreadingWaitHandle__I4__BOOLEAN__BOOLEAN); + + //--// + + static void Set ( CLR_RT_StackFrame& stack ); + static void Reset( CLR_RT_StackFrame& stack ); + + static HRESULT Wait( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& blkTimeout, CLR_RT_HeapBlock& blkExitContext, CLR_RT_HeapBlock* objects, int cObjects, bool fWaitAll ); +}; + +struct Library_corlib_native_System_Threading_AutoResetEvent +{ + NANOCLR_NATIVE_DECLARE(_ctor___VOID__BOOLEAN); + NANOCLR_NATIVE_DECLARE(Reset___BOOLEAN); + NANOCLR_NATIVE_DECLARE(Set___BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Threading_Interlocked +{ + NANOCLR_NATIVE_DECLARE(Increment___STATIC__I4__BYREF_I4); + NANOCLR_NATIVE_DECLARE(Decrement___STATIC__I4__BYREF_I4); + NANOCLR_NATIVE_DECLARE(Exchange___STATIC__I4__BYREF_I4__I4); + NANOCLR_NATIVE_DECLARE(CompareExchange___STATIC__I4__BYREF_I4__I4__I4); + + //--// + +}; + +struct Library_corlib_native_System_Threading_ManualResetEvent +{ + NANOCLR_NATIVE_DECLARE(_ctor___VOID__BOOLEAN); + NANOCLR_NATIVE_DECLARE(Reset___BOOLEAN); + NANOCLR_NATIVE_DECLARE(Set___BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Threading_Monitor +{ + NANOCLR_NATIVE_DECLARE(Enter___STATIC__VOID__OBJECT); + NANOCLR_NATIVE_DECLARE(Exit___STATIC__VOID__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Threading_Thread +{ + static const int FIELD___delegate = 1; + static const int FIELD___priority = 2; + static const int FIELD___thread = 3; + static const int FIELD___appDomain = 4; + static const int FIELD___id = 5; + + NANOCLR_NATIVE_DECLARE(_ctor___VOID__SystemThreadingThreadStart); + NANOCLR_NATIVE_DECLARE(Start___VOID); + NANOCLR_NATIVE_DECLARE(Abort___VOID); + NANOCLR_NATIVE_DECLARE(Suspend___VOID); + NANOCLR_NATIVE_DECLARE(Resume___VOID); + NANOCLR_NATIVE_DECLARE(get_Priority___SystemThreadingThreadPriority); + NANOCLR_NATIVE_DECLARE(set_Priority___VOID__SystemThreadingThreadPriority); + NANOCLR_NATIVE_DECLARE(get_ManagedThreadId___I4); + NANOCLR_NATIVE_DECLARE(get_IsAlive___BOOLEAN); + NANOCLR_NATIVE_DECLARE(Join___VOID); + NANOCLR_NATIVE_DECLARE(Join___BOOLEAN__I4); + NANOCLR_NATIVE_DECLARE(Join___BOOLEAN__SystemTimeSpan); + NANOCLR_NATIVE_DECLARE(get_ThreadState___SystemThreadingThreadState); + NANOCLR_NATIVE_DECLARE(Sleep___STATIC__VOID__I4); + NANOCLR_NATIVE_DECLARE(get_CurrentThread___STATIC__SystemThreadingThread); +#if (NANOCLR_REFLECTION == TRUE) + NANOCLR_NATIVE_DECLARE(GetDomain___STATIC__SystemAppDomain); +#endif // NANOCLR_REFLECTION + + //--// + + static CLR_RT_ObjectToEvent_Source* GetThreadReference ( CLR_RT_StackFrame& stack ); + static void ResetThreadReference( CLR_RT_StackFrame& stack ); + static HRESULT SetThread ( CLR_RT_StackFrame& stack, CLR_RT_Thread* th ); + static HRESULT GetThread ( CLR_RT_StackFrame& stack, CLR_RT_Thread*& th, bool mustBeStarted, bool noSystemThreads ); + + static HRESULT Join( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire ); +}; + +struct Library_corlib_native_System_Threading_Timeout +{ + static const int FIELD_STATIC__InfiniteTimeSpan = 7; + + + //--// + +}; + +struct Library_corlib_native_System_Threading_Timer +{ + static const int FIELD___timer = 1; + static const int FIELD___state = 2; + static const int FIELD___callback = 3; + + NANOCLR_NATIVE_DECLARE(Dispose___VOID); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__SystemThreadingTimerCallback__OBJECT__I4__I4); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__SystemThreadingTimerCallback__OBJECT__SystemTimeSpan__SystemTimeSpan); + NANOCLR_NATIVE_DECLARE(Change___BOOLEAN__I4__I4); + NANOCLR_NATIVE_DECLARE(Change___BOOLEAN__SystemTimeSpan__SystemTimeSpan); + + //--// + + static HRESULT SetValues ( CLR_RT_StackFrame& stack, CLR_UINT32 flags ); + static bool CheckDisposed( CLR_RT_StackFrame& stack ); +}; + +struct Library_corlib_native_System_TimeSpan +{ + static const int FIELD_STATIC__Zero = 8; + static const int FIELD_STATIC__MaxValue = 9; + static const int FIELD_STATIC__MinValue = 10; + + static const int FIELD___ticks = 1; + + NANOCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + NANOCLR_NATIVE_DECLARE(ToString___STRING); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(CompareTo___I4__OBJECT); + NANOCLR_NATIVE_DECLARE(Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan); + NANOCLR_NATIVE_DECLARE(Equals___STATIC__BOOLEAN__SystemTimeSpan__SystemTimeSpan); + + //--// + + static CLR_INT64* NewObject ( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_HeapBlock& ref ); + + static void ConstructTimeSpan( CLR_INT64* val, CLR_INT32 days, CLR_INT32 hours, CLR_INT32 minutes, CLR_INT32 seconds, CLR_INT32 ms ); +}; + +struct Library_corlib_native_System_UInt16 +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_UInt32 +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_UInt64 +{ + static const int FIELD___value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Version +{ + static const int FIELD___Major = 1; + static const int FIELD___Minor = 2; + static const int FIELD___Build = 3; + static const int FIELD___Revision = 4; + + + //--// + +}; + +struct Library_corlib_native_System_WeakReference +{ + NANOCLR_NATIVE_DECLARE(get_IsAlive___BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_Target___OBJECT); + NANOCLR_NATIVE_DECLARE(set_Target___VOID__OBJECT); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Array__SzArrayEnumerator +{ + static const int FIELD___array = 1; + static const int FIELD___index = 2; + static const int FIELD___endIndex = 3; + static const int FIELD___startIndex = 4; + static const int FIELD___arrayLength = 5; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable__ValueCollection +{ + static const int FIELD__ht = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib; + +#endif //_CORLIB_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_AppDomain.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_AppDomain.cpp new file mode 100644 index 00000000..ea354bd0 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_AppDomain.cpp @@ -0,0 +1,313 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +#if defined(NANOCLR_APPDOMAINS) + + + +HRESULT Library_corlib_native_System_AppDomain::GetAssemblies___SZARRAY_SystemReflectionAssembly( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav = NULL; + CLR_RT_AppDomain* appDomain; + + NANOCLR_CHECK_HRESULT(GetAppDomain( stack.ThisRef(), appDomain, appDomainSav, true )); + + NANOCLR_CHECK_HRESULT(appDomain->GetAssemblies( stack.PushValueAndClear() )); + + NANOCLR_CLEANUP(); + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_corlib_native_System_AppDomain::LoadInternal___SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_RT_AppDomain* appDomainSav; + CLR_RT_AppDomain* appDomain; + CLR_RT_Assembly* assembly; + CLR_RT_Assembly_Index idx; + bool fVersion; + CLR_INT16 maj, min, build, rev; + const char* szAssembly; + + NANOCLR_CHECK_HRESULT(GetAppDomain( stack.ThisRef(), appDomain, appDomainSav, true )); + + szAssembly = pArgs[ 0 ].RecoverString(); FAULT_ON_NULL(szAssembly); + fVersion = pArgs[ 1 ].NumericByRef().u8 != 0; + maj = pArgs[ 2 ].NumericByRef().s4; + min = pArgs[ 3 ].NumericByRef().s4; + build = pArgs[ 4 ].NumericByRef().s4; + rev = pArgs[ 5 ].NumericByRef().s4; + + if(fVersion && (maj == -1 || min == -1 || build == -1 || rev == -1)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if(fVersion) + { + CLR_RECORD_VERSION ver; + + ver.iMajorVersion = (CLR_UINT16) maj; + ver.iMinorVersion = (CLR_UINT16) min; + ver.iBuildNumber = (CLR_UINT16) build; + ver.iRevisionNumber = (CLR_UINT16) rev; + + assembly = g_CLR_RT_TypeSystem.FindAssembly( szAssembly, &ver, true ); FAULT_ON_NULL_HR(assembly, CLR_E_INVALID_PARAMETER); + } + else + { + assembly = g_CLR_RT_TypeSystem.FindAssembly( szAssembly, NULL, false ); FAULT_ON_NULL_HR(assembly, CLR_E_INVALID_PARAMETER); + } + + NANOCLR_CHECK_HRESULT(appDomain->LoadAssembly( assembly )); + + { + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + idx.Set( assembly->m_idx ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_Assembly)); + + hbObj = top.Dereference(); + hbObj->SetReflection( idx ); + } + + NANOCLR_CLEANUP(); + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_corlib_native_System_AppDomain::CreateDomain___STATIC__SystemAppDomain__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_AppDomain* appDomain = NULL; + CLR_RT_HeapBlock& pArgs = stack.Arg0(); + CLR_RT_HeapBlock res; res.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( res ); + const char* szName; + + szName = pArgs.RecoverString(); FAULT_ON_NULL(szName); + + NANOCLR_CHECK_HRESULT(CLR_RT_AppDomain::CreateInstance( szName, appDomain )); + + //load mscorlib + NANOCLR_CHECK_HRESULT(appDomain->LoadAssembly( g_CLR_RT_TypeSystem.m_assemblyMscorlib )); + + //load Runtime.Native + if(g_CLR_RT_TypeSystem.m_assemblyNative != NULL) + { + NANOCLR_CHECK_HRESULT(appDomain->LoadAssembly( g_CLR_RT_TypeSystem.m_assemblyNative )); + } + + NANOCLR_CHECK_HRESULT(appDomain->GetManagedObject( res )); + + //Marshal the new AD to the calling AD. + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->MarshalObject( res, res, appDomain )); + + stack.PushValueAndAssign( res ); + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(appDomain) + { + appDomain->DestroyInstance(); + } + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_corlib_native_System_AppDomain::Unload___STATIC__VOID__SystemAppDomain( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav; + CLR_RT_AppDomain* appDomain; + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool fRes; + + NANOCLR_CHECK_HRESULT(GetAppDomain( stack.ThisRef(), appDomain, appDomainSav, false )); + + hbTimeout.SetInteger( 5 * 1000 * TIME_CONVERSION__TO_MILLISECONDS); + + if(stack.m_customState == 0) + { + //Attempt to unload the AppDomain only once + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.UnloadAppDomain( appDomain, stack.m_owningThread )); + } + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + fRes = true; + while(fRes) + { + //Check to make sure this AppDomain is the one that caused the event to fire + if(appDomain->m_state == CLR_RT_AppDomain::AppDomainState_Unloaded) break; + + _ASSERTE(CLR_EE_IS(UnloadingAppDomain)); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_AppDomain, fRes )); + } + + if(!fRes) NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); + + appDomain->DestroyInstance(); + + stack.PopValue(); + + NANOCLR_CLEANUP(); + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + NANOCLR_CLEANUP_END(); +} + +//--// + +HRESULT Library_corlib_native_System_AppDomain::GetAppDomain( CLR_RT_HeapBlock& ref, CLR_RT_AppDomain*& appDomain, CLR_RT_AppDomain*& appDomainSav, bool fCheckForUnloadingAppDomain ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* obj; + CLR_RT_ObjectToEvent_Source* src; + + //Setting up appDomainSav is guaranteed to be initialized correctly by this function + appDomainSav = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + + _ASSERTE(ref.DataType() == DATATYPE_OBJECT); + + obj = ref.Dereference(); FAULT_ON_NULL(obj); + + if(obj->DataType() == DATATYPE_TRANSPARENT_PROXY) + { + appDomain = obj->TransparentProxyAppDomain(); + + if(!appDomain) NANOCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_EXITED); + + obj = obj->TransparentProxyDereference(); FAULT_ON_NULL(obj); + } + + _ASSERTE(obj->DataType() == DATATYPE_CLASS ); + _ASSERTE(obj->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_AppDomain.m_data); + + src = CLR_RT_ObjectToEvent_Source::ExtractInstance( obj[ FIELD___appDomain ] ); FAULT_ON_NULL(src); + appDomain = (CLR_RT_AppDomain*)src->m_eventPtr ; FAULT_ON_NULL(appDomain); + + _ASSERTE(appDomain->DataType() == DATATYPE_APPDOMAIN_HEAD); + + if(fCheckForUnloadingAppDomain) + { + if(!appDomain->IsLoaded()) NANOCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_EXITED); + } + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomain ); + + NANOCLR_NOCLEANUP(); +} + +#else //#if defined(NANOCLR_APPDOMAINS) + +#if (NANOCLR_REFLECTION == TRUE) + +HRESULT Library_corlib_native_System_AppDomain::GetAssemblies___SZARRAY_SystemReflectionAssembly( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + int count = 0; + CLR_RT_HeapBlock* pArray = NULL; + + for(int pass=0; pass<2; pass++) + { + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + if(pASSM->m_header->flags & CLR_RECORD_ASSEMBLY::c_Flags_Patch) continue; + + if(pass == 0) + { + count++; + } + else + { + CLR_RT_HeapBlock* hbObj; + CLR_RT_Assembly_Index idx; idx.Set( pASSM->m_idx ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*pArray, g_CLR_RT_WellKnownTypes.m_Assembly)); + hbObj = pArray->Dereference(); + + hbObj->SetReflection( idx ); + + pArray++; + } + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + if(pass == 0) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, count, g_CLR_RT_WellKnownTypes.m_Assembly )); + + pArray = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_AppDomain::LoadInternal___SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_AppDomain::CreateDomain___STATIC__SystemAppDomain__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_AppDomain::Unload___STATIC__VOID__SystemAppDomain( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +#endif // NANOCLR_REFLECTION + +#endif //#if defined(NANOCLR_APPDOMAINS) diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Array.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Array.cpp new file mode 100644 index 00000000..03eb5be5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Array.cpp @@ -0,0 +1,190 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Array::System_Collections_IList_get_Item___OBJECT__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& thisRef = stack.ThisRef(); + int index = stack.Arg1().NumericByRef().s4; + + CLR_RT_HeapBlock ref; NANOCLR_CHECK_HRESULT(ref.InitializeArrayReference( thisRef, index )); + + { + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + NANOCLR_CHECK_HRESULT(top.LoadFromReference ( ref )); + NANOCLR_CHECK_HRESULT(top.PerformBoxingIfNeeded( )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Array::System_Collections_IList_set_Item___VOID__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& thisRef = stack.ThisRef(); + int index = stack.Arg1().NumericByRef().s4; + + CLR_RT_HeapBlock ref; NANOCLR_CHECK_HRESULT(ref.InitializeArrayReference( thisRef, index )); + + NANOCLR_SET_AND_LEAVE(stack.Arg2().StoreToReference( ref, 0 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Array::get_Length___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyArrayReference( stack.Arg0() )); + + stack.SetResult_I4( stack.Arg0().DereferenceArray()->m_numOfElements ); + + NANOCLR_NOCLEANUP(); +} + +#if (NANOCLR_REFLECTION == TRUE) + +HRESULT Library_corlib_native_System_Array::CreateInstance___STATIC__SystemArray__SystemType__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor( *hbType, td )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( stack.PushValue(), stack.Arg1().NumericByRefConst().s4, td )); + + NANOCLR_NOCLEANUP(); +} + +#endif // NANOCLR_REFLECTION + +HRESULT Library_corlib_native_System_Array::Copy___STATIC__VOID__SystemArray__I4__SystemArray__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Copy( stack, stack.Arg0(), stack.Arg1().NumericByRef().s4, stack.Arg2(), stack.Arg3().NumericByRef().s4, stack.Arg4().NumericByRef().s4 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Array::Clear___STATIC__VOID__SystemArray__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Clear( stack, stack.Arg0(), stack.Arg1().NumericByRef().s4, stack.Arg2().NumericByRef().s4 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Array::TrySzIndexOf___STATIC__BOOLEAN__SystemArray__I4__I4__OBJECT__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT32 start = stack.Arg1().NumericByRefConst().s4; + CLR_INT32 count = stack.Arg2().NumericByRefConst().s4; + CLR_INT32 stop = start + count; + + NANOCLR_SET_AND_LEAVE(TrySzIndexOf( stack, stack.Arg0(), stack.Arg3(), start, stop, true, stack.Arg4() )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_Array::Clear( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg, int index, int length ) +{ + (void)stack; + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + int numElem; + + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyArrayReference( arg )); + + array = arg.DereferenceArray(); + numElem = array->m_numOfElements; + + if(length == -1) length = numElem; + + if(length < 0 || + index < 0 || + length + index > numElem ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + NANOCLR_SET_AND_LEAVE(array->ClearElements( index, length )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Array::Copy( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& argSrc, int indexSrc, CLR_RT_HeapBlock& argDst, int indexDst, int length ) +{ + (void)stack; + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(length) + { + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyArrayReference( argSrc )); + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyArrayReference( argDst )); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Array::Copy( argSrc.DereferenceArray(), indexSrc, argDst.DereferenceArray(), indexDst, length )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Array::TrySzIndexOf( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& argSrc, CLR_RT_HeapBlock& match, int start, int stop, bool fForward, CLR_RT_HeapBlock& retValue ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int index; + bool fRet; + CLR_RT_HeapBlock_Array* array = argSrc.DereferenceArray(); + + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyArrayReference( argSrc )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::IndexOf( array, match, start, stop, fForward, index )); + + _ASSERTE(retValue.DataType() == DATATYPE_BYREF); + + retValue.Dereference()->SetInteger( index ); + + fRet = (index >= 0); + + if(array->m_typeOfElement <= DATATYPE_LAST_PRIMITIVE) + { + //Primitives do not override Equals, so this check is good enough. + //If match is not found, index == -1, so the managed Array.IndexOf will + //skip the more expensive Object.Equals call. + + _ASSERTE(FIMPLIES(!fRet, index == -1)); + fRet = true; + } + + stack.SetResult_Boolean( fRet ); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Attribute.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Attribute.cpp new file mode 100644 index 00000000..488a22e7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Attribute.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +// no code generated for this class diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_BitConverter.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_BitConverter.cpp new file mode 100644 index 00000000..d257eed2 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_BitConverter.cpp @@ -0,0 +1,600 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +char DigitalToHex(unsigned char x) +{ + return x < 10 ? x + '0' : x - 10 + 'A'; +} + +char* ByteArrayToHex(unsigned char* pInput, int index, int length) +{ + char* pOutput = (char*) malloc(length * 3); + char* p = pOutput; + + pInput += index; + for(int i = 0; i < length; i++, pInput++) + { + *p++ = DigitalToHex(*pInput / 16); + *p++ = DigitalToHex(*pInput % 16); + *p++ = '-'; + } + *(--p) = 0; + + return pOutput; +} + + +HRESULT Library_corlib_native_System_BitConverter::get_IsLittleEndian___STATIC__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned long x = 0x12345678; + unsigned char* p = reinterpret_cast(&x); + stack.SetResult_Boolean(*p == 0x78); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_BitConverter::DoubleToInt64Bits___STATIC__I8__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + double input = stack.Arg0().NumericByRefConst().r8; +#else + CLR_INT64 input = stack.Arg0().NumericByRefConst().r8; +#endif + __int64* p = reinterpret_cast<__int64*>(&input); + stack.SetResult_I8(*p); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + bool input = stack.Arg0().NumericByRefConst().u1 != 0; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 1, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + wchar_t input = stack.Arg0().NumericByRefConst().u2; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 2, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + double input = stack.Arg0().NumericByRefConst().r8; +#else + CLR_INT64 input = stack.Arg0().NumericByRefConst().r8; +#endif + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 8, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + *reinterpret_cast(p) = input; +#else + *reinterpret_cast(p) = input; +#endif + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__R4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + float input = stack.Arg0().NumericByRefConst().r4; +#else + CLR_INT32 input = stack.Arg0().NumericByRefConst().r4; +#endif + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 4, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + *reinterpret_cast(p) = input; +#else + *reinterpret_cast(p) = input; +#endif + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int input = stack.Arg0().NumericByRefConst().s4; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 4, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + __int64 input = stack.Arg0().NumericByRefConst().s8; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 8, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast<__int64*>(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__I2( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + short input = stack.Arg0().NumericByRefConst().s2; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 2, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned int input = stack.Arg0().NumericByRefConst().u4; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 4, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned __int64 input = stack.Arg0().NumericByRefConst().u8; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 8, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::GetBytes___STATIC__SZARRAY_U1__U2( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned short input = stack.Arg0().NumericByRefConst().u2; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValueAndClear(), 2, g_CLR_RT_WellKnownTypes.m_UInt8)); + { + unsigned char* p = stack.TopValue().DereferenceArray()->GetFirstElement(); + *reinterpret_cast(p) = input; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::Int64BitsToDouble___STATIC__R8__I8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + __int64 input = stack.Arg0().NumericByRefConst().s8; +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + double* p = reinterpret_cast(&input); +#else + CLR_INT64* p = reinterpret_cast(&input); +#endif + stack.SetResult_R8(*p); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToBoolean___STATIC__BOOLEAN__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + unsigned char b=0; + int index = 0; + bool res = false; + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + p = pArray->GetFirstElement(); + b = *(p + index); + res = (b != 0); // assume any value not zero is true. Zero is false. + stack.SetResult_Boolean(res); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToChar___STATIC__CHAR__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + wchar_t value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 2 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + p = pArray->GetFirstElement(); + for (int i=0; i<2; ++i) + { + pValue[i] = p[index+i]; + } + + stack.SetResult(value, DATATYPE_CHAR); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToDouble___STATIC__R8__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + + double value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 8 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + // fetch unsigned char aligned values, and store in object that is correctly aligned for this system. + p = pArray->GetFirstElement(); + for (int i=0; i<8; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_R8(value); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToSingle___STATIC__R4__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + float value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 4 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + // fetch unsigned char aligned values, and store in object that is correctly aligned for this system. + p = pArray->GetFirstElement(); + + for (int i=0; i<4; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_R4(value); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToInt16___STATIC__I2__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + signed short value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 2 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + p = pArray->GetFirstElement(); + // big vs little endian? + for (int i=0; i<2; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_I4(value); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToInt32___STATIC__I4__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + + signed int value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 4 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + p = pArray->GetFirstElement(); + // big vs little endian? + for (int i=0; i<4; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_I4(value); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToInt64___STATIC__I8__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + + CLR_INT64 value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 8 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + p = pArray->GetFirstElement(); + + for (int i=0; i<8; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_I8(value) ; + + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToUInt16___STATIC__U2__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + CLR_UINT16 value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 2 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + p = pArray->GetFirstElement(); + for (int i=0; i<2; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_I4(value); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToUInt32___STATIC__U4__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + CLR_UINT32 value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 4 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + p = pArray->GetFirstElement(); + for (int i=0; i<4; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_U4(value) ; + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToUInt64___STATIC__U8__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + unsigned char *p = NULL; + int index = 0; + CLR_UINT64 value=0; + unsigned char *pValue = (unsigned char*)(&value); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + 8 > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + p = pArray->GetFirstElement(); + + for (int i=0; i<8; ++i) + { + pValue[i] = p[index+i]; + } + stack.SetResult_U8(value) ; + + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + if (pArray->m_numOfElements == 0) + { + NANOCLR_CHECK_HRESULT(stack.SetResult_String("")); + } + else + { + unsigned char* p = pArray->GetFirstElement(); + char* pOutput = ByteArrayToHex(p, 0, pArray->m_numOfElements); + NANOCLR_CHECK_HRESULT(stack.SetResult_String(pOutput)); + free(pOutput); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int index = 0; + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + if (pArray->m_numOfElements == 0 && index == 0) + { + NANOCLR_CHECK_HRESULT(stack.SetResult_String("")); + } + else + { + if (index < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + unsigned char* p = pArray->GetFirstElement(); + char* pOutput = ByteArrayToHex(p, index, pArray->m_numOfElements - index); + NANOCLR_CHECK_HRESULT(stack.SetResult_String(pOutput)); + free(pOutput); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_BitConverter::ToString___STATIC__STRING__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int index = 0; + int length = 0; + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); + FAULT_ON_NULL_ARG(pArray); + + index = stack.Arg1().NumericByRefConst().s4; + length = stack.Arg2().NumericByRefConst().s4; + if (pArray->m_numOfElements == 0 && index == 0 && length == 0) + { + NANOCLR_CHECK_HRESULT(stack.SetResult_String("")); + } + else + { + if (index < 0 || length < 0 || (unsigned int)index >= pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + if ((unsigned int)index + length > pArray->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + unsigned char* p = pArray->GetFirstElement(); + char* pOutput = ByteArrayToHex(p, index, length); + NANOCLR_CHECK_HRESULT(stack.SetResult_String(pOutput)); + free(pOutput); + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Collections_ArrayList.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Collections_ArrayList.cpp new file mode 100644 index 00000000..440a584e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Collections_ArrayList.cpp @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Collections_ArrayList::get_Item___OBJECT__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_ArrayList* pThis = (CLR_RT_HeapBlock_ArrayList*)stack.This(); FAULT_ON_NULL(pThis); + CLR_RT_HeapBlock* value; + + NANOCLR_CHECK_HRESULT(pThis->GetItem( stack.Arg1().NumericByRef().s4, value )); + + stack.SetResult_Object( value ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Collections_ArrayList::set_Item___VOID__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_ArrayList* pThis = (CLR_RT_HeapBlock_ArrayList*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->SetItem( stack.Arg1().NumericByRef().s4, stack.Arg2().Dereference() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Collections_ArrayList::Add___I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_ArrayList* pThis = (CLR_RT_HeapBlock_ArrayList*)stack.This(); FAULT_ON_NULL(pThis); + CLR_INT32 index; + + NANOCLR_CHECK_HRESULT(pThis->Add( stack.Arg1().Dereference(), index )); + + stack.SetResult_I4( index ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Collections_ArrayList::Clear___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_ArrayList* pThis = (CLR_RT_HeapBlock_ArrayList*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->Clear()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Collections_ArrayList::Insert___VOID__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_ArrayList* pThis = (CLR_RT_HeapBlock_ArrayList*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->Insert( stack.Arg1().NumericByRef().s4, stack.Arg2().Dereference() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Collections_ArrayList::RemoveAt___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_ArrayList* pThis = (CLR_RT_HeapBlock_ArrayList*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->RemoveAt( stack.Arg1().NumericByRef().s4 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Collections_ArrayList::SetCapacity___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_ArrayList* pThis = (CLR_RT_HeapBlock_ArrayList*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->SetCapacity( stack.Arg1().NumericByRef().s4 )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Console.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Console.cpp new file mode 100644 index 00000000..ff30e02d --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Console.cpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Console::OutNative___STATIC__VOID__STRING__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + const char * szText0 = stack.Arg0().RecoverString(); + bool addLineFeed = (bool)stack.Arg1().NumericByRef().u1; + + if(!szText0) szText0 = ""; + + CLR_Debug::Emit( szText0, -1 ); + + if(addLineFeed) + { + CLR_Debug::Emit( "\r\n" , -1 ); + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Convert.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Convert.cpp new file mode 100644 index 00000000..ae34fa14 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Convert.cpp @@ -0,0 +1,593 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "corlib_native.h" +#include +#include + +HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING__BOOLEAN__I8__I8__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int64_t result = 0; + + char* str = (char*)stack.Arg0().RecoverString(); + signed int radix = stack.Arg4().NumericByRef().s4; + +#if (SUPPORT_ANY_BASE_CONVERSION == TRUE) + // suport for conversion from any base + char* endptr = NULL; + + bool isUInt64 = false; + + bool isSigned = (bool)stack.Arg1().NumericByRef().u1; + long long minValue = stack.Arg2().NumericByRef().s8; + long long maxValue = stack.Arg3().NumericByRef().s8; + + // UInt64? => use also strtoull the result will be casted to Int64 + if (minValue == 0 && maxValue == 0) { + isUInt64 = true; + isSigned = false; + + //allow spaces before digits + while (*str == ' ') { + str++; + } + + //UInt64 can't begin with minus + if (*str == '-' ) { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + + // convert via strtoll / strtoull + result = isSigned ? strtoll(str, &endptr, radix) : (long long) strtoull(str, &endptr, radix); + + // TODO: + // If the value in input string is out of the range of representable values + // by a long long int / unsigned long int, the function returns + // LLONG_MAX or LLONG_MIN for signed conversion + // and ULONG_MAX for unsigned conversion + // It is necessary to add a check + + // if no valid conversion endptr is equal str + if (str == endptr) { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // allow spaces after digits + while (*endptr == ' ') { + endptr++; + } + + // should reach end of string no aditional chars + if (*endptr != 0) { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // the signed values for SByte, Int16 and Int32 are always positive for base 2, 8 or 16 conversions + // because the 64-bit function strtoll is used; need the post process the value + // if the result is greater max and smaller (max + 1) * 2 this value should be subtracted + if (radix == 2 || radix == 8 || radix == 16) { + if (isSigned && result > maxValue && result < (maxValue + 1) * 2) result -= (maxValue + 1) * 2; + } + + if (!isUInt64 && !isSigned && (uint64_t)result > (uint64_t)maxValue) { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } else if (!isUInt64 && (result > maxValue || result < minValue)) { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } else { + stack.SetResult_I8(result); + } + } + NANOCLR_NOCLEANUP(); +#else + // support for conversion from base 10 and 16 (partial) + + if(radix == 10) + { + // conversion from base 10 + + // check for minus sign + if(*str == '-') + { + // call GetIntegerPart() in 'guess' mode by throwing a crazy number for the length + result = GetIntegerPart((str + 1), 99); + + // is negative + result *= -1; + } + // check for plus sign + else if(*str == '+') + { + // call GetIntegerPart() in 'guess' mode by throwing a crazy number for the length + result = GetIntegerPart((str + 1), 99); + } + else + { + // call GetIntegerPart() in 'guess' mode by throwing a crazy number for the length + result = GetIntegerPart(str, 99); + } + + } + else if(radix == 16) + { + // conversion from base 16 + result = GetIntegerFromHexString(str); + } + else + { + // all other bases are not supported + return stack.NotImplementedStub(); + } + + stack.SetResult_I8(result); + } + NANOCLR_NOCLEANUP_NOLABEL(); +#endif // defined(SUPPORT_ANY_BASE_CONVERSION) + +} + +HRESULT Library_corlib_native_System_Convert::NativeToDouble___STATIC__R8__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + char* str = (char*)stack.Arg0().RecoverString(); + + #if (SUPPORT_ANY_BASE_CONVERSION == TRUE) + // suport for conversion from any base + + stack.SetResult_R8 (strtod(str, nullptr)); + } + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + // support for conversion from base 10 and 16 (partial) + // in this particular function the base isn't relevant + + int length = 0; + bool hasMinusSign = false; + bool hasPlusSign = false; + int decimalPoint = -1; + int exponentialSign = -1; + bool hasMinusExponentialSign = false; + bool hasPlusExponentialSign = false; + double returnValue = 0.0; + + // first pass, get count of decimal places, integer part and check for valid chars + char* temp = str; + while (*temp != '\0') + { + switch (*temp) + { + case '-': + if (exponentialSign == -1) + { + if (length == 0) + { + hasMinusSign = true; + } + else + { + // found a minus signal NOT at the start of the string + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + else + { + if (length == exponentialSign + 1) + { + hasMinusExponentialSign = true; + } + else + { + // found a minus signal NOT at the start of the exponent + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + break; + + case '+': + if (exponentialSign == -1) + { + if (length == 0) + { + hasPlusSign = true; + } + else + { + // found a plus signal NOT at the start of the string + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + else + { + if (length == exponentialSign + 1) + { + hasPlusExponentialSign = true; + } + else + { + // found a plus signal NOT at the start of the exponent + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + break; + + case '.': + if (decimalPoint == -1) + { + decimalPoint = length; + } + else + { + // already found a decimal point, can't have another + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + break; + + case 'e': + case 'E': + if (exponentialSign == -1) + { + exponentialSign = length; + } + else + { + // already found a exponential sign, can't have another + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + break; + + default: + if (*temp < '0' && *temp > '9') + { + // there is an invalid char in the string + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + length++; + temp++; + } + + // now parse the string according to it's format + int endOrExponentialPart = exponentialSign == -1 ? length : exponentialSign; + if (decimalPoint == -1) + { + // string doesn't have fractional part, treat as integer + returnValue = GetIntegerPart(str, endOrExponentialPart); + } + else if (decimalPoint == 0) + { + // string starts with the decimal point, only has fractional part + returnValue = GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1)); + } + else if (hasMinusSign || hasPlusSign) + { + // string starts with sign and... + + if(decimalPoint == 1) + { + // ... is followed by a decimal point, only has fractional part + returnValue = GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1)); + } + else + { + // ... has integer and fractional parts + returnValue = GetIntegerPart(str+1, decimalPoint-1); + returnValue = (returnValue + GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1))); + } + + if (hasMinusSign) + { + returnValue *= -1; + } + } + else + { + // string has integer and fractional parts + returnValue = GetIntegerPart(str, decimalPoint); + returnValue = returnValue + GetDoubleFractionalPart((str+decimalPoint+1), (endOrExponentialPart-decimalPoint-1)); + } + + // exponential part found? + if (exponentialSign != -1) + { + // advance by one if a sign (+ or -) is after the exponential sign + if (hasMinusExponentialSign || hasPlusExponentialSign) exponentialSign++; + // get the exponential part + int exponent = GetIntegerPart((str+exponentialSign+1), (length-exponentialSign-1)); + // each time multiply or divide by 10 + for (int i = 0; i < exponent; i++) + { + if (hasMinusExponentialSign) + { + returnValue /= 10; + } + else + { + returnValue *= 10; + } + } + } + + stack.SetResult_R8(returnValue); + } + NANOCLR_NOCLEANUP(); + + #endif // defined(SUPPORT_ANY_BASE_CONVERSION) + +} + +HRESULT Library_corlib_native_System_Convert::ToBase64String___STATIC__STRING__SZARRAY_U1__I4__I4__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + size_t outputLength; + char* outArray = NULL; + char* outArrayWitLineBreak = NULL; + uint8_t* inArrayPointer = NULL; + uint8_t lineBreakCount; + uint16_t offsetIndex = 0; + uint8_t count = 0; + uint16_t result; + + CLR_RT_HeapBlock_Array* inArray = stack.Arg0().DereferenceArray(); + size_t offset = (size_t)stack.Arg1().NumericByRef().s4; + size_t length = (size_t)stack.Arg2().NumericByRef().s4; + bool insertLineBreaks = (bool)stack.Arg3().NumericByRefConst().u1; + + if(inArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); + + inArrayPointer = (uint8_t*)inArray->GetFirstElement(); + inArrayPointer += (offset * sizeof(uint8_t)); + + // compute base64 string length + outputLength = 4 * ((length + 2) / 3); + + // need malloc with base64 string length plus string terminator (+1) + outArray = (char*)platform_malloc(outputLength + 1); + + // check if have allocation + if (outArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + + // perform the operation + // need to tweak the parameter with the output length because it includes room for the terminator + result = mbedtls_base64_encode( + (unsigned char*)outArray, + (outputLength + 1), + &outputLength, + inArrayPointer, + length ); + + if(result != 0) + { + // internal error occurred + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + if(insertLineBreaks) + { + // get line break count (line break every 76 chars) + lineBreakCount = outputLength / 76; + + // need malloc with base64 string length plus line breaks (line break is 2 char long: CR + LF) plus final line break + outArrayWitLineBreak = (char*)platform_malloc(outputLength + (lineBreakCount * 2) + 2); + + for(int i = 0; i <= lineBreakCount; i++) + { + // how many chars to copy + if(outputLength > 76) + { + // first/next 76 chars + count = 76; + } + else + { + // last outputLength chars + count = outputLength; + } + + // copy first/next count chars + // because we are using same offset for both arrays, we need to discount line break for tmp array + memcpy(outArrayWitLineBreak + offsetIndex, outArray + (offsetIndex - (i * 2)), count); + + // remove copied chars from original output length if more than 76 chars still to be copied + if(outputLength >= 76) + { + // more chars + + // adjust output length + outputLength -= 76; + + // add line break + outArrayWitLineBreak[count + offsetIndex] = '\r'; + outArrayWitLineBreak[count + offsetIndex + 1] = '\n'; + + // move offset for next copy (including line break +2) + offsetIndex += count + 2; + } + else + { + // move offset for last position + offsetIndex += count; + // reached end of array, add terminator + outArrayWitLineBreak[offsetIndex] = 0; + } + } + // set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + NANOCLR_CHECK_HRESULT(stack.SetResult_String(outArrayWitLineBreak)); + } + else + { + // set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + NANOCLR_CHECK_HRESULT(stack.SetResult_String(outArray)); + } + + // need to free memory from arrays + platform_free((void*)outArray); + + if(outArrayWitLineBreak != NULL) + { + platform_free((void*)outArrayWitLineBreak); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Convert::FromBase64CharArray___STATIC__SZARRAY_U1__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + size_t outputLength; + char* outArray = NULL; + uint16_t* inArrayPointerTmp = NULL; + uint8_t* inArrayPointer = NULL; + uint8_t charValue; + CLR_UINT8* returnArray; + int16_t i = 0; + uint16_t result; + + CLR_RT_HeapBlock_Array* inArray = stack.Arg0().DereferenceArray(); + size_t length = (size_t)stack.Arg1().NumericByRef().s4; + + if(inArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); + + outputLength = length / 4 * 3; + + // transform the 16 bits inArray to a 8 bits array so mbed knows how to convert it + inArrayPointerTmp = (uint16_t*)inArray->GetFirstElementUInt16(); + inArrayPointer = (uint8_t*)inArray->GetFirstElement(); + for(i = 0; i < (int16_t)length; i++) + { + *inArrayPointer = *inArrayPointerTmp; + inArrayPointer++; + inArrayPointerTmp++; + } + + // pointer is pointing to the end + // point to last char in array and get it + inArrayPointer--; + charValue = *inArrayPointer; + // adjust output length + if (charValue == '=') + { + outputLength--; + } + + // point to before last char and get it + inArrayPointer--; + charValue = *inArrayPointer; + // adjust output length + if (charValue == '=') + { + outputLength--; + } + + // reset pointer position (-2 because above we already went back two positions) + inArrayPointer -= length - 2; + + outArray = (char*)platform_malloc(outputLength + 1); + // check malloc success + if (outArray == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + + // perform the operation + // need to tweak the parameter with the output length because it includes room for the terminator + result = mbedtls_base64_decode( + (unsigned char*)outArray, + (outputLength + 1), + &outputLength, + inArrayPointer, + length ); + + if(result != 0) + { + // internal error occurred + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + // create heap block array instance with appropriate size (the length of the output array) and type (byte which is uint8_t) + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( stack.PushValueAndClear() , outputLength, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + // get a pointer to the array in the heap block array just created + returnArray = stack.TopValue().DereferenceArray()->GetFirstElement(); + + // copy outArray to the returnArray + memcpy(returnArray, outArray, outputLength); + + // need to free memory from outArray + platform_free(outArray); + + NANOCLR_NOCLEANUP(); +} + +double Library_corlib_native_System_Convert::GetDoubleFractionalPart(char* str, int length) +{ + double place = 1; + double returnValue = 0.0; + + for (int i = 0; i < length; i++) + { + // move decimal place to the right + place /= 10.0; + + returnValue += ((int)(*str++) - '0') * place; + } + + return returnValue; +} + +int64_t Library_corlib_native_System_Convert::GetIntegerPart(char* str, int length) +{ + int64_t returnValue = 0; + + for (int i = 0; i < length; i++) + { + returnValue = returnValue * 10 + (*str - '0'); + str++; + + // check for terminator, in case this is being called in 'guess' mode + if(*str == '\0') + { + break; + } + } + + return returnValue; +} + +int64_t Library_corlib_native_System_Convert::GetIntegerFromHexString(char* str) +{ + int64_t returnValue = 0; + + if ((*str == '0') && (*(str+1) == 'x')) + { + // there a 0x at the begining of the string, so move pointer forward 2 notches + str += 2; + } + + while (*str != '\0') + { + char c = toupper(*str++); + + if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A'))) + { + // there is an invalid char in the string + break; + } + + c -= '0'; + + if (c > 9) + { + c -= 7; + } + + returnValue = (returnValue << 4) + c; + } + + return returnValue; +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_DateTime.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_DateTime.cpp new file mode 100644 index 00000000..60b26107 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_DateTime.cpp @@ -0,0 +1,270 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "CorLib.h" + +HRESULT Library_corlib_native_System_DateTime::_ctor___VOID__I4__I4__I4__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pArg = &(stack.Arg1()); + SYSTEMTIME st; + + NANOCLR_CLEAR(st); + st.wYear = pArg[ 0 ].NumericByRef().s4; + st.wMonth = pArg[ 1 ].NumericByRef().s4; + st.wDay = pArg[ 2 ].NumericByRef().s4; + st.wHour = pArg[ 3 ].NumericByRef().s4; + st.wMinute = pArg[ 4 ].NumericByRef().s4; + st.wSecond = pArg[ 5 ].NumericByRef().s4; + st.wMilliseconds = pArg[ 6 ].NumericByRef().s4; + + /// Our current supported range is between 1601 and 3000. Years before 1582 requires different calculation (see explanation + /// in time_decl.h), same way years after 3000 will not hold the simple arithmetic which we are using. More complex calculations + /// outside these range are not worth the CPU cycle and codesize. + if ((st.wYear < 1601) || (st.wYear > 3000) || + (st.wMonth < 1) || (st.wMonth > 12) || + (st.wDay < 1) || (st.wDay > 31)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + + Compress( stack, st ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Day___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wDay ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_DayOfWeek___SystemDayOfWeek( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wDayOfWeek ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_DayOfYear___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st ; + signed int days; + Expand( stack, st ); + + NANOCLR_CHECK_HRESULT(HAL_Time_AccDaysInMonth( st.wYear, st.wMonth, &days )); + days += st.wDay; + + stack.SetResult_I4( days ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Hour___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wHour ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Millisecond___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wMilliseconds ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Minute___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wMinute ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Month___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wMonth ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Second___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wSecond ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Year___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wYear ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::DaysInMonth___STATIC__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT32 year = stack.Arg0().NumericByRef().s4; + CLR_INT32 month = stack.Arg1().NumericByRef().s4; + CLR_INT32 days = 0; + + HAL_Time_DaysInMonth( year, month, &days ); + + stack.SetResult_I4( days ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_UtcNow___STATIC__SystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64* pRes = NewObject( stack ); + + // request full date&time + *pRes = HAL_Time_CurrentDateTime(false); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Today___STATIC__SystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64* pRes = NewObject( stack ); + + // request date part only + *pRes = HAL_Time_CurrentDateTime(true); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +CLR_INT64* Library_corlib_native_System_DateTime::NewObject( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& ref = stack.PushValue(); + + ref.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_DATETIME, 0, 1) ); + ref.ClearData(); + + //return (CLR_INT64*)&ref.NumericByRef().s8; + // NOTE: reinterpret_cast is a test. It can be safely removed ;) + return reinterpret_cast(&ref.NumericByRef().s8); +} + +CLR_INT64* Library_corlib_native_System_DateTime::GetValuePtr( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return GetValuePtr( stack.Arg0() ); +} + +CLR_INT64* Library_corlib_native_System_DateTime::GetValuePtr( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = &ref; + CLR_DataType dt = obj->DataType(); + + if(dt == DATATYPE_OBJECT || dt == DATATYPE_BYREF) + { + obj = obj->Dereference(); if(!obj) return NULL; + dt = obj->DataType(); + } + + if(dt == DATATYPE_DATETIME) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_I8) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_VALUETYPE && obj->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_DateTime.m_data) + { + return (CLR_INT64*)&obj[ FIELD___ticks ].NumericByRef().s8; + } + + return NULL; +} + +void Library_corlib_native_System_DateTime::Expand( CLR_RT_StackFrame& stack, SYSTEMTIME& st ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_INT64* val = GetValuePtr( stack ); + + if(val) + { + CLR_INT64 ticks = *val; + HAL_Time_ToSystemTime( ticks, &st ); + } +} + +// Compress function always creates local time. +void Library_corlib_native_System_DateTime::Compress( CLR_RT_StackFrame& stack, const SYSTEMTIME& st ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_INT64* val = GetValuePtr( stack ); + + if(val) + { + *val = HAL_Time_ConvertFromSystemTime( &st ); + } +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Delegate.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Delegate.cpp new file mode 100644 index 00000000..fc08e48e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Delegate.cpp @@ -0,0 +1,184 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Delegate::Equals___BOOLEAN__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_Boolean( CLR_RT_HeapBlock::Compare_Unsigned_Values( stack.Arg0(), stack.Arg1() ) == 0 ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +#if (NANOCLR_REFLECTION == TRUE) + +HRESULT Library_corlib_native_System_Delegate::GetInvocationList___SZARRAY_SystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Delegate *dlg = stack.Arg0().DereferenceDelegate(); + CLR_RT_HeapBlock_Delegate_List *lst = (CLR_RT_HeapBlock_Delegate_List *)dlg; + + int delegatesCount = 0; + CLR_RT_HeapBlock *returnArray = NULL; + + // put the return array on the stack + CLR_RT_HeapBlock &top = stack.PushValueAndClear(); + + if (dlg) { + if (dlg->DataType() == DATATYPE_DELEGATELIST_HEAD) { + delegatesCount = lst->m_length; + } else { + delegatesCount = 1; + } + } + + // create the result array + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, delegatesCount, g_CLR_RT_WellKnownTypes.m_Delegate)); + + if (delegatesCount > 0) { + + // get the pointer to the first element + returnArray = (CLR_RT_HeapBlock *)top.DereferenceArray()->GetFirstElement(); + + if (delegatesCount > 1) { + CLR_RT_HeapBlock *ptr = lst->GetDelegates(); + // fill the array with the delegates + for (int i = 0; i < delegatesCount; i++) { + + // create an instance of delegate + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*returnArray, g_CLR_RT_WellKnownTypes.m_Delegate)); + + //fetch delegate from list + dlg = ptr[i].DereferenceDelegate(); + //set delegate reference to return element + returnArray->SetObjectReference(dlg); + + returnArray++; + } + } else { + // create an instance of delegate + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*returnArray, g_CLR_RT_WellKnownTypes.m_Delegate)); + //set delegate reference to return element + returnArray->SetObjectReference(dlg); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Delegate::get_Method___SystemReflectionMethodInfo( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Delegate* dlg = stack.Arg0().DereferenceDelegate(); + + dlg = GetLastDelegate( dlg ); if(!dlg) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + { + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_MethodInfo)); + hbObj = top.Dereference(); + + hbObj->SetReflection( dlg->DelegateFtn() ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Delegate::get_Target___OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Delegate* dlg = stack.Arg0().DereferenceDelegate(); + + dlg = GetLastDelegate( dlg ); if(!dlg) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + { + stack.PushValueAndAssign( dlg->m_object ); + } + + NANOCLR_NOCLEANUP(); +} + +#endif // NANOCLR_REFLECTION + +HRESULT Library_corlib_native_System_Delegate::Combine___STATIC__SystemDelegate__SystemDelegate__SystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Delegate_List::Combine( stack.PushValue(), stack.Arg0(), stack.Arg1(), false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Delegate::Remove___STATIC__SystemDelegate__SystemDelegate__SystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Delegate_List::Remove( stack.PushValue(), stack.Arg0(), stack.Arg1() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Delegate::op_Equality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Library_corlib_native_System_Delegate::Equals___BOOLEAN__OBJECT( stack )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Delegate::op_Inequality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Delegate::op_Equality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate( stack )); + + stack.NegateResult(); + + NANOCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_HeapBlock_Delegate* Library_corlib_native_System_Delegate::GetLastDelegate( CLR_RT_HeapBlock_Delegate* dlg ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(dlg) + { + if(dlg->DataType() == DATATYPE_DELEGATELIST_HEAD) + { + CLR_RT_HeapBlock_Delegate_List* lst = (CLR_RT_HeapBlock_Delegate_List*)dlg; + + if(lst->m_length == 0) + { + dlg = NULL; + } + else + { + CLR_RT_HeapBlock* ptr = lst->GetDelegates(); + + dlg = ptr[ lst->m_length-1 ].DereferenceDelegate(); + } + } + } + + return dlg; +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Diagnostics_Debugger.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Diagnostics_Debugger.cpp new file mode 100644 index 00000000..3a2e394f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Diagnostics_Debugger.cpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Diagnostics_Debugger::get_IsAttached___STATIC__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + stack.SetResult_Boolean( CLR_EE_DBG_IS( SourceLevelDebugging )); + +#else + + stack.SetResult_Boolean( false ); + +#endif + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Diagnostics_Debugger::Break___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(stack.m_customState == 0) + { + stack.m_customState++; + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Break( &stack ); + + hr = CLR_E_RESCHEDULE; NANOCLR_LEAVE(); + } + + NANOCLR_NOCLEANUP(); + +#else + (void)stack; + NANOCLR_NOCLEANUP_NOLABEL(); + +#endif + +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Double.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Double.cpp new file mode 100644 index 00000000..2c3ddcd3 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Double.cpp @@ -0,0 +1,112 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" +#include "nanoPAL_NativeDouble.h" + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + +HRESULT Library_corlib_native_System_Double::CompareTo___STATIC__I4__R8__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double val = stack.Arg1().NumericByRefConst().r8; + CLR_INT32 res = System::Double::CompareTo( d, val ); + + stack.PushValue().SetInteger( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Double::IsInfinity___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + bool res = System::Double::IsInfinity( d ); + + stack.SetResult_Boolean( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Double::IsNaN___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + bool res = System::Double::IsNaN( d ); + + stack.SetResult_Boolean( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Double::IsNegativeInfinity___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + bool res = System::Double::IsNegativeInfinity( d ); + + stack.SetResult_Boolean( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Double::IsPositiveInfinity___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + bool res = System::Double::IsPositiveInfinity( d ); + + stack.SetResult_Boolean( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +#else + +HRESULT Library_corlib_native_System_Double::CompareTo___STATIC__I4__R8__R8( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64 left = stack.Arg0().NumericByRef().s8; + CLR_INT64 right = stack.Arg1().NumericByRef().s8; + + stack.SetResult_I4((left < right) ? -1 : (left > right) ? 1 : 0); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Double::IsInfinity___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + stack.NotImplementedStub(); +} + +HRESULT Library_corlib_native_System_Double::IsNaN___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + stack.NotImplementedStub(); +} + +HRESULT Library_corlib_native_System_Double::IsNegativeInfinity___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + stack.NotImplementedStub(); +} + +HRESULT Library_corlib_native_System_Double::IsPositiveInfinity___STATIC__BOOLEAN__R8( CLR_RT_StackFrame& stack ) +{ + stack.NotImplementedStub(); +} + +#endif diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Enum.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Enum.cpp new file mode 100644 index 00000000..488a22e7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Enum.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +// no code generated for this class diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Exception.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Exception.cpp new file mode 100644 index 00000000..0205f404 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Exception.cpp @@ -0,0 +1,236 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +struct ExceptionLookup +{ + HRESULT hr; + CLR_RT_TypeDef_Index* ptr; +}; + +static const ExceptionLookup c_ExceptionLookup[] = +{ +#define EL(hr,fld) { hr, &g_CLR_RT_WellKnownTypes.fld } + EL(CLR_E_APPDOMAIN_EXITED , m_AppDomainUnloadedException ), + EL(CLR_E_INVALID_PARAMETER , m_ArgumentException ), + EL(CLR_E_ARGUMENT_NULL , m_ArgumentNullException ), + EL(CLR_E_OUT_OF_RANGE , m_ArgumentOutOfRangeException), + EL(CLR_E_INDEX_OUT_OF_RANGE , m_IndexOutOfRangeException ), + EL(CLR_E_INVALID_CAST , m_InvalidCastException ), + EL(CLR_E_INVALID_OPERATION , m_InvalidOperationException ), + EL(CLR_E_NOT_SUPPORTED , m_NotSupportedException ), + EL(CLR_E_NOTIMPL , m_NotImplementedException ), + EL(CLR_E_NULL_REFERENCE , m_NullReferenceException ), + EL(CLR_E_OUT_OF_MEMORY , m_OutOfMemoryException ), + EL(CLR_E_OBJECT_DISPOSED , m_ObjectDisposedException ), + EL(CLR_E_WATCHDOG_TIMEOUT , m_WatchdogException ), + +#undef EL +}; + +//--// + +HRESULT Library_corlib_native_System_Exception::get_StackTrace___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArray; + StackTrace* pStackTrace; + CLR_RT_HeapBlock* pBlkString; + char buf[ 512 ]; + char* strName; + size_t iName; + CLR_RT_HeapBlock tmpArray; tmpArray.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc(tmpArray); + int depth = 0; + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + pArray = pThis[ FIELD___stackTrace ].DereferenceArray(); + + if(pArray) + { + _ASSERTE(pArray->m_typeOfElement == DATATYPE_U1); + + depth = pArray->m_numOfElements / sizeof(StackTrace); + } + + if(depth == 0) NANOCLR_SET_AND_LEAVE(stack.SetResult_String(NULL)); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( tmpArray, depth, g_CLR_RT_WellKnownTypes.m_String )); + + pStackTrace = (StackTrace*)pArray->GetFirstElement(); + pBlkString = (CLR_RT_HeapBlock*)tmpArray.DereferenceArray()->GetFirstElement(); + + for(int i = 0; i < depth; i++) + { + strName = &buf[ 0 ]; + iName = MAXSTRLEN(buf) - 2 ; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.BuildMethodName( pStackTrace->m_md, strName, iName )); + + memcpy(strName, "\r\n\0", 3); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( *pBlkString, buf )); + + pStackTrace++; + pBlkString++; + } + + NANOCLR_SET_AND_LEAVE(Library_corlib_native_System_String::Concat( stack, (CLR_RT_HeapBlock*)tmpArray.DereferenceArray()->GetFirstElement(), depth )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +/* + This function will always succeed. + Return values + - S_OK. + - S_FALSE. ref points to the pre-allocated OutOfMemory exception +*/ +HRESULT Library_corlib_native_System_Exception::CreateInstance( CLR_RT_HeapBlock& ref, const CLR_RT_TypeDef_Index& cls, HRESULT hrIn, CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( stack->m_appDomain ); +#endif + + CLR_RT_HeapBlock* obj; + + _ASSERTE(CLR_RT_ExecutionEngine::IsInstanceOf( cls, g_CLR_RT_WellKnownTypes.m_Exception )); + + if(FAILED(hr = g_CLR_RT_ExecutionEngine.NewObjectFromIndex( ref, cls ))) + { +#if defined(NANOCLR_APPDOMAINS) + ref.SetObjectReference( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->m_outOfMemoryException ); +#else + ref.SetObjectReference( g_CLR_RT_ExecutionEngine.m_outOfMemoryException ); +#endif + + hrIn = CLR_E_OUT_OF_MEMORY; + hr = S_FALSE; + } + + obj = ref.Dereference(); + + obj[ FIELD__HResult ].SetInteger( (CLR_UINT32)hrIn ); + + if(hr == S_OK) + { + (void)SetStackTrace( ref, stack ); + } + +#if defined(NANOCLR_APPDOMAINS) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Exception::CreateInstance( CLR_RT_HeapBlock& ref, HRESULT hrIn, CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Index* cls = &g_CLR_RT_WellKnownTypes.m_Exception; + + _ASSERTE(FAILED(hrIn)); + + for(uint32_t i = 0; i < ARRAYSIZE(c_ExceptionLookup); i++) + { + if(c_ExceptionLookup[ i ].hr == hrIn) + { + cls = c_ExceptionLookup[ i ].ptr; + break; + } + } + + return CreateInstance( ref, *cls, hrIn, stack ); +} + +HRESULT Library_corlib_native_System_Exception::SetStackTrace( CLR_RT_HeapBlock& ref, CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(stack) + { + CLR_RT_HeapBlock* obj; + CLR_RT_HeapBlock_Array* array; + StackTrace* dst; + CLR_UINT32 depth; + + if(CLR_RT_ExecutionEngine::IsInstanceOf( ref, g_CLR_RT_WellKnownTypes.m_Exception ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + //--// + + obj = ref.Dereference(); + depth = 0; + + NANOCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,stackSub,stack) + { + depth++; + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + + //--// + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( obj[ FIELD___stackTrace ], depth * sizeof(StackTrace), g_CLR_RT_WellKnownTypes.m_UInt8 )); + + //--// + + array = obj[ FIELD___stackTrace ].DereferenceArray(); + dst = (StackTrace*)array->GetFirstElement(); + + NANOCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,stackSub,stack) + { + dst->m_md = stackSub->m_call; + dst->m_IP = (CLR_UINT32)(stackSub->m_IP - stackSub->m_IPstart); + + dst++; + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + +#if !defined(BUILD_RTM) + //shutting down the EE happens by Thread->Abort. These exceptions are by design, and + //don't need to be logged, or written to the console.... + if(!g_CLR_RT_ExecutionEngine.m_fShuttingDown) +#endif + { + CLR_RT_DUMP::EXCEPTION( *stack, ref ); + } + } + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock* Library_corlib_native_System_Exception::GetTarget( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + return CLR_RT_ExecutionEngine::IsInstanceOf( ref, g_CLR_RT_WellKnownTypes.m_Exception ) ? ref.Dereference() : NULL; +} + +Library_corlib_native_System_Exception::StackTrace* Library_corlib_native_System_Exception::GetStackTrace( CLR_RT_HeapBlock* obj, CLR_UINT32& depth ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(obj) + { + CLR_RT_HeapBlock_Array* array = obj[ FIELD___stackTrace ].DereferenceArray(); + + if(array) + { + depth = array->m_numOfElements / sizeof(StackTrace); + + return (StackTrace*)array->GetFirstElement(); + } + } + + depth = 0; + + return NULL; +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_GC.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_GC.cpp new file mode 100644 index 00000000..2f94e266 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_GC.cpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_GC::AnyPendingFinalizers___STATIC__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_Boolean( g_CLR_RT_ExecutionEngine.m_finalizersPending.IsEmpty() == false + || (g_CLR_RT_ExecutionEngine.m_finalizerThread != NULL && !g_CLR_RT_ExecutionEngine.m_finalizerThread->CanThreadBeReused())); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_GC::SuppressFinalize___STATIC__VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pObj = stack.Arg0().Dereference(); FAULT_ON_NULL(pObj); + + CLR_RT_HeapBlock_Finalizer::SuppressFinalize( pObj ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_GC::ReRegisterForFinalize___STATIC__VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDescriptor desc; + CLR_RT_HeapBlock* pObj = stack.Arg0().Dereference(); FAULT_ON_NULL(pObj); + + CLR_RT_HeapBlock_Finalizer::SuppressFinalize( pObj ); + + NANOCLR_CHECK_HRESULT(desc.InitializeFromObject( stack.Arg0() )); + + if(desc.m_handlerCls.HasFinalizer()) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Finalizer::CreateInstance( stack.Arg0().Dereference(), desc.m_handlerCls )); + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_CultureInfo.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_CultureInfo.cpp new file mode 100644 index 00000000..274c3db7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_CultureInfo.cpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Globalization_CultureInfo::get_CurrentUICultureInternal___STATIC__SystemGlobalizationCultureInfo( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.PushValue().SetObjectReference( g_CLR_RT_ExecutionEngine.m_currentUICulture ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Globalization_CultureInfo::set_CurrentUICultureInternal___STATIC__VOID__SystemGlobalizationCultureInfo( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + g_CLR_RT_ExecutionEngine.m_currentUICulture = stack.Arg0().Dereference(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_DateTimeFormat.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_DateTimeFormat.cpp new file mode 100644 index 00000000..a667560a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Globalization_DateTimeFormat.cpp @@ -0,0 +1,39 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Globalization_DateTimeFormat::FormatDigits___STATIC__STRING__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg0()); + + int value = pArgs[ 0 ].NumericByRef().s4; + int len = pArgs[ 1 ].NumericByRef().s4; + + char buffer[ 12 ]; // Enough to accommodate max int + + char fmt [10]; + + if(len >= 2) + { + sprintf( fmt, "%%0%dd", len ); + } + else + { + fmt[0] = '%'; + fmt[1] = 'd'; + fmt[2] = '\0'; + } + + sprintf( buffer, fmt, value ); + + NANOCLR_SET_AND_LEAVE(stack.SetResult_String( buffer )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Guid.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Guid.cpp new file mode 100644 index 00000000..ccadaf36 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Guid.cpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +// +// Generate a new GUID +// +// Based on the version 4 GUID (random) +// http://guid.one/guid/make + + +HRESULT Library_corlib_native_System_Guid::GenerateNewGuid___STATIC__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_Random rand; + CLR_UINT8* buf; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + // Create a array of 16 bytes on top of stack to return + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, 16, g_CLR_RT_WellKnownTypes.m_UInt8 )); + buf = top.DereferenceArray()->GetFirstElement(); + + rand.Initialize(); + rand.NextBytes(buf, 16); // fill with random numbers + + buf[7] = (buf[7] & 0x0f) | 0x40; // Set verion + buf[9] = (buf[7] & 0x3f) | 0x80; // Set variant + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MarshalByRefObject.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MarshalByRefObject.cpp new file mode 100644 index 00000000..488a22e7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MarshalByRefObject.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +// no code generated for this class diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MathInternal.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MathInternal.cpp new file mode 100644 index 00000000..335f396c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MathInternal.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +HRESULT Library_corlib_native_System_MathInternal::Abs___STATIC__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT32 d = stack.Arg0().NumericByRefConst().s4; + CLR_INT32 res = abs( d ); + + stack.SetResult_I4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_MathInternal::Max___STATIC__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT32 x = stack.Arg0().NumericByRefConst().s4; + CLR_INT32 y = stack.Arg1().NumericByRefConst().s4; + CLR_INT32 res = x >= y ? x : y; + + stack.SetResult_I4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_MathInternal::Min___STATIC__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT32 x = stack.Arg0().NumericByRefConst().s4; + CLR_INT32 y = stack.Arg1().NumericByRefConst().s4; + CLR_INT32 res = x <= y ? x : y; + + stack.SetResult_I4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MulticastDelegate.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MulticastDelegate.cpp new file mode 100644 index 00000000..7ee1daf5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_MulticastDelegate.cpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_MulticastDelegate::op_Equality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Library_corlib_native_System_Delegate::op_Equality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate( stack )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_MulticastDelegate::op_Inequality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Library_corlib_native_System_Delegate::op_Inequality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate( stack )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Number.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Number.cpp new file mode 100644 index 00000000..e67e1793 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Number.cpp @@ -0,0 +1,266 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +// compose sprintf format string according to requested parameters +void nf_GetFormatString(char* formatStr, char formatCh, int precision, bool isLong, bool isFloat, bool isSigned) +{ + if(formatCh == 'X' || formatCh=='x') + sprintf(formatStr, "%%0%d%sX", precision, isLong ? "ll" : ""); + else + sprintf(formatStr, "%%%s%d%s%s", isFloat ? "." : isSigned ? "-0" : "0", precision, isLong ? "ll" : isFloat ? "f" : "", isFloat ? "" : isSigned ? "d" : "u"); +} + +// remove the prepended zeros and (if possible) the decimal point in a float that's formated as string. e.g. "47.1100815000000" => "47.1100815" or "8.0000E-12" => "8E-12" +void nf_RemovePrependedZeros(char* floatStr) +{ + int length = hal_strlen_s(floatStr); + // flag for finding the decimal point + bool pointFound = false; + // if not -1 we found the first zero after the decimal point + int firstZero = -1; + // if not -1 we found an "e" or "E" after the last zero of this is the string length + int nextNonZero = length; + + // iterate thru all chars + for (int i = 0; i < length; i++) + { + // no decimal point found until now? + if (!pointFound) + { + // is it the decimal point? + if (floatStr[i] == '.') + { + pointFound = true; + } + + // next char + continue; + } + + // at this point we found the decimal point + // no zero found until now? + if (firstZero == -1) + { + // is it a zero? + if (floatStr[i] == '0') + { + // store the position of the first zero after the decimal point + firstZero = i; + } + + // next char + continue; + } + + // at this point we found the decimal point and the first zero + // an "e" or "E" char stops the sequence of zeros + if (floatStr[i] == 'e' || floatStr[i] == 'E') + { + // store the position of the e/E char + nextNonZero = i; + // done! we found the positions for the prepended zeros + break; + } + + // at this point we found the decimal point and the first zero and the current char is not the e/E char + // is this not a zero? + if (floatStr[i] != '0') + { + // reset! we need to find another zero + firstZero = -1; + } + } + + // something to remove? + if (pointFound && firstZero != -1 && nextNonZero != -1) + { + // is the char before the first zero the decimal point? => Remove the decimal point + int startIndex = floatStr[firstZero - 1] == '.' ? firstZero - 1 : firstZero; + // no e/E char after the last trailing zero? + if (nextNonZero == length) + { + // we can cut away the prepended zeros by terminating the string at first zero + floatStr[startIndex] = 0; + } + else + { + // otherwise we copy the last part over the prepended zeros and terminate the string + int lengthToCopy = length - nextNonZero; + memcpy(&floatStr[startIndex], &floatStr[nextNonZero], lengthToCopy); + floatStr[startIndex + lengthToCopy] = 0; + } + } +} + +HRESULT Library_corlib_native_System_Number::FormatNative___STATIC__STRING__OBJECT__CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg0()); + CLR_RT_HeapBlock* value = pArgs; + CLR_DataType dt; + CLR_RT_TypeDescriptor desc; + char result[ 24 ]; + // This is temporary buffer to create proper format string. + char formatStr[ 8 ]; + char formatCh = (char)pArgs[ 1 ].NumericByRef().u1; + int precision = pArgs[ 2 ].NumericByRef().s4; + bool shouldRemovePrependedZeros = false; + + NANOCLR_CHECK_HRESULT(desc.InitializeFromObject( *value )); + NANOCLR_CHECK_HRESULT(value->PerformUnboxing( desc.m_handlerCls )); + + dt = value->DataType(); + + if(formatCh == 'G' && precision == 0) + { + precision = 1; + shouldRemovePrependedZeros = true; + } + + switch(dt) + { + case DATATYPE_I1: + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, false, true); + sprintf(result, formatStr, value->NumericByRef().s1 ); + break; + + case DATATYPE_U1: + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, false, false); + sprintf(result, formatStr, value->NumericByRef().u1 ); + break; + + case DATATYPE_I2: + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, false, true); + sprintf(result, formatStr, value->NumericByRef().s2 ); + break; + + case DATATYPE_U2: + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, false, false); + sprintf(result, formatStr, value->NumericByRef().u2 ); + break; + + case DATATYPE_I4: + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, false, true); + sprintf(result, formatStr, value->NumericByRef().s4); + break; + + case DATATYPE_U4: + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, false, false); + sprintf(result, formatStr, value->NumericByRef().u4); + break; + + case DATATYPE_I8: + { + #if defined(_WIN32) + hal_snprintf( result, ARRAYSIZE(result), "%I64d",(CLR_INT64_TEMP_CAST)value->NumericByRef().s8 ); + #else + // get format string + nf_GetFormatString(formatStr, formatCh, precision, true, false, true); + sprintf(result, formatStr, (CLR_INT64_TEMP_CAST)value->NumericByRef().s8); + #endif // defined(_WIN32) + } + break; + + case DATATYPE_U8: + { + #if defined(_WIN32) + hal_snprintf( result, ARRAYSIZE(result), "%I64u",(CLR_UINT64_TEMP_CAST)value->NumericByRef().u8 ); + #else + // get format string + nf_GetFormatString(formatStr, formatCh, precision, true, false, false); + sprintf(result, formatStr, (CLR_UINT64_TEMP_CAST)value->NumericByRef().u8 ); + #endif // defined(_WIN32) + } + break; + + case DATATYPE_R4: + { + // All the formatCh have been converted to upper case in the managed layer + _ASSERTE(formatCh == 'G' || formatCh == 'N' || formatCh == 'F' || formatCh == 'D'); + + if (precision < 0 || precision > 99) + { + NANOCLR_SET_AND_LEAVE( CLR_E_INVALID_PARAMETER ); + } + + // DATATYPE_R4 is float and uses a precision of 9, standard sprintf format is "%.9g" + + #if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) + hal_snprintf( result, ARRAYSIZE(result), "%.9g", value->NumericByRef().r4 ); + #else + + #if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + // use default precision is none is specfied AND if format in not generic + precision = (formatCh == 'G' && precision == 1) ? 9 : precision; + + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, true, false); + + sprintf(result, formatStr, value->NumericByRef().r4); + if (shouldRemovePrependedZeros) + { + nf_RemovePrependedZeros(result); + } + #else + CLR_INT32 f = value->NumericByRef().r4; + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + #endif // !defined(NANOCLR_EMULATED_FLOATINGPOINT) + #endif // defined(_WIN32) + } + break; + + case DATATYPE_R8: + { + // All the formatCh have been converted to upper case in the managed layer + _ASSERTE(formatCh == 'G' || formatCh == 'N' || formatCh == 'F' || formatCh == 'D'); + + if (precision < 0 || precision > 99) + { + NANOCLR_SET_AND_LEAVE( CLR_E_INVALID_PARAMETER ); + } + + // DATATYPE_R8 is double and uses a precision of 15, standard sprintf format is "%.15g" + + #if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) + hal_snprintf( result, ARRAYSIZE(result), "%.15g", (CLR_DOUBLE_TEMP_CAST)value->NumericByRef().r8 ); + #else + #if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + // use default precision is none is specfied AND format is not generic + precision = (formatCh == 'G' && precision == 1) ? 15 : precision; + + // get format string + nf_GetFormatString(formatStr, formatCh, precision, false, true, false); + + sprintf(result, formatStr, (CLR_DOUBLE_TEMP_CAST)value->NumericByRef().r8); + if (shouldRemovePrependedZeros) + { + nf_RemovePrependedZeros(result); + } + #else + CLR_INT64 d = (CLR_DOUBLE_TEMP_CAST)value->NumericByRef().r8; + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + #endif // !defined(NANOCLR_EMULATED_FLOATINGPOINT) + #endif // defined(_WIN32) + } + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_SET_AND_LEAVE(stack.SetResult_String( result )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Object.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Object.cpp new file mode 100644 index 00000000..6f7dde24 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Object.cpp @@ -0,0 +1,91 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +//--// + +HRESULT Library_corlib_native_System_Object::Equals___BOOLEAN__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_Boolean( CLR_RT_HeapBlock::ObjectsEqual( stack.Arg0(), stack.Arg1(), true ) ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Object::GetHashCode___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_I4( CLR_RT_HeapBlock::GetHashCode( stack.This(), true, 0 ) ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +#if (NANOCLR_REFLECTION == TRUE) + +HRESULT Library_corlib_native_System_Object::GetType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDescriptor desc; + CLR_RT_ReflectionDef_Index idx; + CLR_RT_HeapBlock& arg0 = stack.Arg0(); + CLR_RT_HeapBlock* pObj; + + NANOCLR_CHECK_HRESULT(desc.InitializeFromObject( arg0 )); + + pObj = arg0.Dereference(); + + if(pObj && pObj->DataType() == DATATYPE_REFLECTION) + { + idx.m_kind = REFLECTION_TYPE; + idx.m_levels = 0; + idx.m_data.m_type.m_data = desc.m_handlerCls.m_data; + } + else + { + idx = desc.m_reflex; + } + + { + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + + hbObj = top.Dereference(); + hbObj->SetReflection( idx ); + } + + NANOCLR_NOCLEANUP(); +} + +#endif // NANOCLR_REFLECTION + +HRESULT Library_corlib_native_System_Object::MemberwiseClone___OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.CloneObject( stack.PushValueAndClear(), stack.Arg0() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Object::ReferenceEquals___STATIC__BOOLEAN__OBJECT__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_Boolean( CLR_RT_HeapBlock::ObjectsEqual( stack.Arg0(), stack.Arg1(), true ) ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Random.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Random.cpp new file mode 100644 index 00000000..233dd569 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Random.cpp @@ -0,0 +1,125 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Random::Next___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_Random* rand; + + NANOCLR_CHECK_HRESULT(GetRandom( stack, rand )); + + stack.SetResult_I4( rand->Next() & 0x7FFFFFFF ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Random::Next___I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_Random* rand; + CLR_INT32 maxValue; + + NANOCLR_CHECK_HRESULT(GetRandom( stack, rand )); + + maxValue = stack.Arg1().NumericByRef().s4; + + if(maxValue <= 0) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + stack.SetResult_I4( rand->Next() % maxValue ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Random::NextDouble___R8( CLR_RT_StackFrame& stack ) +{ + + + NANOCLR_HEADER(); + + CLR_RT_Random* rand; + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + + double nextDouble; +#else + CLR_INT64 nextDouble; + +#endif + + NANOCLR_CHECK_HRESULT(GetRandom( stack, rand )); + + nextDouble = rand->NextDouble(); + + stack.SetResult_R8( nextDouble ); + + NANOCLR_NOCLEANUP(); + + +} + +HRESULT Library_corlib_native_System_Random::NextBytes___VOID__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_Random* rand; + CLR_RT_HeapBlock_Array* buffer; + + NANOCLR_CHECK_HRESULT(GetRandom( stack, rand )); + + buffer = stack.Arg1().DereferenceArray(); FAULT_ON_NULL(buffer); + + rand->NextBytes( buffer->GetFirstElement(), buffer->m_numOfElements ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Random::_ctor___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_Random* rand; + + NANOCLR_CHECK_HRESULT(GetRandom( stack, rand, true )); + + rand->Initialize(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Random::_ctor___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_Random* rand; + + NANOCLR_CHECK_HRESULT(GetRandom( stack, rand, true )); + + rand->Initialize( stack.Arg1().NumericByRef().s4 ); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_Random::GetRandom( CLR_RT_StackFrame& stack, CLR_RT_Random*& rand, bool create ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(create) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_BinaryBlob::CreateInstance( pThis[ FIELD___random ], sizeof(CLR_RT_Random), NULL, NULL, 0 )); + } + + rand = (CLR_RT_Random*)pThis[ FIELD___random ].DereferenceBinaryBlob()->GetData(); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Assembly.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Assembly.cpp new file mode 100644 index 00000000..d1165947 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Assembly.cpp @@ -0,0 +1,324 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Reflection_Assembly::get_FullName___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + //The defines for maxFULLNAME and parameters for snprintf are currently not validated. + CLR_RT_Assembly_Instance instance; + CLR_RT_Assembly* assm; + char buffer[ NANOCLR_MAX_ASSEMBLY_NAME * 2 ]; + const CLR_RECORD_ASSEMBLY* header ; + CLR_RT_HeapBlock* hbAsm = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbAsm, instance )); + + assm = instance.m_assm; + header = assm->m_header; + + if(hal_strlen_s(assm->m_szName) > NANOCLR_MAX_ASSEMBLY_NAME) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + sprintf( buffer, + "%s, Version=%d.%d.%d.%d", + assm->m_szName, + header->version.iMajorVersion, + header->version.iMinorVersion, + header->version.iBuildNumber, + header->version.iRevisionNumber ); + + stack.SetResult_String( buffer ); + + NANOCLR_NOCLEANUP(); +#undef MAXFULLNAME +} + +HRESULT Library_corlib_native_System_Reflection_Assembly::GetType___SystemType__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly_Instance assm; + CLR_RT_TypeDef_Index td; + CLR_RT_HeapBlock* hbRef; + CLR_RT_HeapBlock* hbObj; + const char* szClass = stack.Arg1().RecoverString(); + CLR_RT_HeapBlock* hbAsm = stack.Arg0().Dereference(); + + FAULT_ON_NULL(szClass); + FAULT_ON_NULL(hbAsm); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbAsm, assm )); + + hbRef = &stack.PushValueAndClear(); + + if(g_CLR_RT_TypeSystem.FindTypeDef( szClass, assm.m_assm, td )) + { + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*hbRef, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + + hbObj = hbRef->Dereference(); + hbObj->SetReflection( td ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_Assembly::GetTypes___SZARRAY_SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly_Instance assm; + CLR_RT_HeapBlock* hbAsm = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbAsm, assm )); + + { + CLR_RT_Assembly* pASSM = assm.m_assm; + CLR_UINT32 num = pASSM->m_pTablesSize[ TBL_TypeDef ]; + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, num, g_CLR_RT_WellKnownTypes.m_TypeStatic )); + + if(num) + { + CLR_RT_HeapBlock* pArray = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + for(CLR_UINT32 i=0; im_idx, i ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*pArray, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + + hbObj = pArray->Dereference(); + hbObj->SetReflection( idx ); + } + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_Assembly::GetVersion___VOID__BYREF_I4__BYREF_I4__BYREF_I4__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* caller = stack.Caller(); + if(caller == NULL) + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + else + { + CLR_RT_Assembly_Instance assm; + CLR_RT_HeapBlock* hbAsm = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbAsm, assm )); + + const CLR_RECORD_VERSION& version = assm.m_assm->m_header->version; + + // we do not check for the reference not to be NULL because this is an internal method + stack.Arg1().Dereference()->NumericByRef().s4 = version.iMajorVersion; + stack.Arg2().Dereference()->NumericByRef().s4 = version.iMinorVersion; + stack.Arg3().Dereference()->NumericByRef().s4 = version.iBuildNumber; + stack.Arg4().Dereference()->NumericByRef().s4 = version.iRevisionNumber; + } + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_Reflection_Assembly::GetManifestResourceNames___SZARRAY_STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly_Instance assm; + CLR_RT_HeapBlock* hbAsm = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbAsm, assm )); + + { + CLR_RT_Assembly* pAssm = assm.m_assm; + CLR_RT_HeapBlock& result = stack.PushValue(); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( result, pAssm->m_pTablesSize[ TBL_ResourcesFiles ], g_CLR_RT_WellKnownTypes.m_String )); + + { + CLR_RT_HeapBlock* pArray = (CLR_RT_HeapBlock*)result.Array()->GetFirstElement(); + + for(int idxResourceFile = 0; idxResourceFile < pAssm->m_pTablesSize[ TBL_ResourcesFiles ]; idxResourceFile++) + { + const CLR_RECORD_RESOURCE_FILE* resourceFile = pAssm->GetResourceFile( idxResourceFile ); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( *pArray, pAssm->GetString( resourceFile->name ) )); + + pArray++; + } + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_Assembly::GetExecutingAssembly___STATIC__SystemReflectionAssembly( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* hbObj; + + CLR_RT_StackFrame* caller = stack.Caller(); if(caller == NULL) NANOCLR_SET_AND_LEAVE(S_OK); + + { + CLR_RT_Assembly_Index idx; idx.Set( caller->MethodCall().m_assm->m_idx ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_Assembly)); + + hbObj = top.Dereference(); + hbObj->SetReflection( idx ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_Assembly::LoadInternal___STATIC__SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + CLR_RT_HeapBlock* pArgs = &stack.Arg0(); + CLR_RT_HeapBlock* hbObj; + CLR_RT_Assembly* assembly; + const char* szAssembly; + CLR_RT_Assembly_Index idx; + bool fVersion; + CLR_INT16 maj, min, build, rev; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + szAssembly = pArgs[ 0 ].RecoverString(); FAULT_ON_NULL(szAssembly ); + fVersion = pArgs[ 1 ].NumericByRef().u1 != 0; + maj = pArgs[ 2 ].NumericByRef().s4; + min = pArgs[ 3 ].NumericByRef().s4; + build = pArgs[ 4 ].NumericByRef().s4; + rev = pArgs[ 5 ].NumericByRef().s4; + + if(fVersion && (maj == -1 || min == -1 || build == -1 || rev == -1)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if(fVersion) + { + CLR_RECORD_VERSION ver; + + ver.iMajorVersion = (CLR_UINT16)maj; + ver.iMinorVersion = (CLR_UINT16)min; + ver.iBuildNumber = (CLR_UINT16)build; + ver.iRevisionNumber = (CLR_UINT16)rev; + + assembly = g_CLR_RT_TypeSystem.FindAssembly( szAssembly, &ver, true ); FAULT_ON_NULL_HR(assembly, CLR_E_INVALID_PARAMETER); + } + else + { + assembly = g_CLR_RT_TypeSystem.FindAssembly( szAssembly, NULL, false ); FAULT_ON_NULL_HR(assembly, CLR_E_INVALID_PARAMETER); + } + +#if defined(NANOCLR_APPDOMAINS) + NANOCLR_CHECK_HRESULT(appDomain->LoadAssembly( assembly )); +#endif + idx.Set( assembly->m_idx ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_Assembly)); + + hbObj = top.Dereference(); + hbObj->SetReflection( idx ); + + NANOCLR_CLEANUP(); + + //Avoid exception handling in common case. Just return NULL on failure. + //Managed code decides to throw the exception or not. + hr = S_OK; + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_corlib_native_System_Reflection_Assembly::Load___STATIC__SystemReflectionAssembly__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = NULL; + CLR_RT_Assembly* assm = NULL; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* hbObj; + CLR_RECORD_ASSEMBLY* header; + + array = stack.Arg0().DereferenceArray(); FAULT_ON_NULL(array); + + header = (CLR_RECORD_ASSEMBLY*)array->GetFirstElement(); + + if(header->GoodAssembly()) + { + // + // Sorry, you'll have to reboot to load this assembly. + // + if(header->flags & CLR_RECORD_ASSEMBLY::c_Flags_NeedReboot) + { + NANOCLR_SET_AND_LEAVE(CLR_E_BUSY); + } + + NANOCLR_CHECK_HRESULT(CLR_RT_Assembly::CreateInstance( header, assm )); + + assm->m_pFile = array; + + g_CLR_RT_TypeSystem.Link( assm ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll ()); + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.PrepareForExecution()); + } + + if(assm) + { + CLR_RT_Assembly_Index idx; idx.Set( assm->m_idx ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_Assembly)); + + hbObj = top.Dereference(); + hbObj->SetReflection( idx ); + } + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(assm) + { + assm->DestroyInstance(); + } + } + + NANOCLR_CLEANUP_END(); +} + +//--// + +HRESULT Library_corlib_native_System_Reflection_Assembly::GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_Assembly_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + return CLR_RT_ReflectionDef_Index::Convert( arg, inst ) ? S_OK : CLR_E_NULL_REFERENCE; +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Binder.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Binder.cpp new file mode 100644 index 00000000..488a22e7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_Binder.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +// no code generated for this class diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_ConstructorInfo.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_ConstructorInfo.cpp new file mode 100644 index 00000000..3c05abc9 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_ConstructorInfo.cpp @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Reflection_ConstructorInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_ConstructorInfo::Invoke___OBJECT__SZARRAY_OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* thisRef = stack.ThisRef().Dereference(); + CLR_RT_MethodDef_Instance md; + CLR_RT_HeapBlock_Array* pArray = stack.Arg1().DereferenceArray(); + CLR_RT_HeapBlock* args = NULL; + int numArgs = 0; + + if(md.InitializeFromIndex( thisRef->ReflectionDataConst().m_data.m_method ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + + if(stack.m_customState == 0) + { + stack.m_customState = 1; + + if(pArray) + { + args = (CLR_RT_HeapBlock*)pArray->GetFirstElement(); + numArgs = pArray->m_numOfElements; + } + + NANOCLR_CHECK_HRESULT(stack.MakeCall( md, NULL, args, numArgs )); + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_FieldInfo.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_FieldInfo.cpp new file mode 100644 index 00000000..c6a2a0d2 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_FieldInfo.cpp @@ -0,0 +1,206 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Reflection_FieldInfo::SetValue___VOID__OBJECT__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_FieldDef_Instance instFD; + CLR_RT_TypeDef_Instance instTD; + CLR_RT_TypeDescriptor instTDescObj; + CLR_RT_TypeDef_Instance instTDField; + const CLR_RECORD_FIELDDEF* fd; + CLR_RT_HeapBlock* obj; + bool fValueType; + CLR_RT_HeapBlock& srcVal = stack.Arg2(); + CLR_RT_HeapBlock val; val.Assign( srcVal ); + CLR_RT_ProtectFromGC gc( val ); + + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_FieldInfo::Initialize( stack, instFD, instTD, obj )); + + fd = instFD.m_target; + + if(fd->flags & CLR_RECORD_FIELDDEF::FD_NoReflection) // don't allow reflection for fields with NoReflection attribute + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + NANOCLR_CHECK_HRESULT(instTDescObj.InitializeFromFieldDefinition(instFD)); + + // make sure the right side object is of the same type as the left side + if(NULL != val.Dereference() && !CLR_RT_ExecutionEngine::IsInstanceOf(val, instTDescObj.m_handlerCls)) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + fValueType = obj->IsAValueType(); + if(fValueType || (c_CLR_RT_DataTypeLookup[ obj->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType)) + { + if(val.Dereference() == NULL || !val.Dereference()->IsBoxed()) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + if(fValueType) + { + _ASSERTE(NULL != obj->Dereference()); + if(NULL == obj->Dereference()) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + instTDField.InitializeFromIndex( obj->Dereference()->ObjectCls() ); + } + else + { + instTDField.InitializeFromIndex( *c_CLR_RT_DataTypeLookup[ obj->DataType() ].m_cls ); + } + + NANOCLR_CHECK_HRESULT(val.PerformUnboxing( instTDField )); + } + else + { +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_HeapBlock& srcObj = stack.Arg1(); + + if(srcObj.IsTransparentProxy()) + { + _ASSERTE(srcObj.DataType() == DATATYPE_OBJECT); + _ASSERTE(srcObj.Dereference() != NULL && srcObj.Dereference()->DataType() == DATATYPE_TRANSPARENT_PROXY); + + NANOCLR_CHECK_HRESULT(srcObj.Dereference()->TransparentProxyValidate()); + NANOCLR_CHECK_HRESULT(srcObj.Dereference()->TransparentProxyAppDomain()->MarshalObject( val, val )); + } +#endif + } + + switch(obj->DataType()) + { + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + obj->NumericByRef().s8 = val.NumericByRefConst().s8; + break; + + default: + obj->Assign( val ); + break; + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_Reflection_FieldInfo::Initialize( CLR_RT_StackFrame& stack, CLR_RT_FieldDef_Instance& instFD, CLR_RT_TypeDef_Instance& instTD, CLR_RT_HeapBlock*& obj ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_HeapBlock* hbField = stack.Arg0().Dereference(); + + if(CLR_RT_ReflectionDef_Index::Convert( *hbField, instFD ) == false || + instTD.InitializeFromField ( instFD ) == false ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if(instFD.m_target->flags & CLR_RECORD_FIELDDEF::FD_Static) + { + obj = CLR_RT_ExecutionEngine::AccessStaticField( instFD ); + + if(obj == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + NANOCLR_CHECK_HRESULT(stack.Arg1().EnsureObjectReference( obj )); + + if(CLR_RT_ExecutionEngine::IsInstanceOf( *obj, instTD ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + obj = &obj[ instFD.CrossReference().m_offset ]; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_FieldInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* callerField; + CLR_RT_HeapBlock* returnArray = NULL; + CLR_RT_FieldDef_Instance fieldDefinition; + int count = 0; + + // put the return array on the stack + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + // get the caller field + callerField = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_RuntimeFieldInfo::GetFieldDescriptor( stack, *callerField, fieldDefinition )); + + // setup attribute enumerator + CLR_RT_AttributeEnumerator attributeEnumerator; + attributeEnumerator.Initialize( fieldDefinition ); + + // 1st pass: count attributes + do + { + // move to the next attribute in the collection, if any + if(attributeEnumerator.Advance()) + { + count++; + } + else + { + // done sweeping attributes + + // create the result array + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, count, g_CLR_RT_WellKnownTypes.m_TypeStatic )); + + // use this to skip the 2nd pass if no attribute was found + if (count == 0) break; + + // get the pointer to the first element + returnArray = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // reset attribute enumerator + attributeEnumerator.Initialize( fieldDefinition ); + + break; + } + } + while(true); + + // 2nd pass: fill the array with the attributes types, if any + while(count > 0) + { + // move to the next attribute in the collection, if any + if(attributeEnumerator.Advance()) + { + CLR_RT_TypeDef_Instance instanceTypeDef; + CLR_RT_HeapBlock* hbObj; + + // get the type def for the current attribute + attributeEnumerator.GetCurrent(&instanceTypeDef); + + CLR_RT_TypeDef_Index attributeType; + attributeType.Set(instanceTypeDef.Assembly(), instanceTypeDef.Type()); + + // create a new object for the attribute type and put it on the return array + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*returnArray, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = returnArray->Dereference(); + // make sure the reflection is pointing to the attribute type + hbObj->SetReflection( attributeType ); + + returnArray++; + count--; + } + else + { + // no more attributes + break; + } + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MemberInfo.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MemberInfo.cpp new file mode 100644 index 00000000..488a22e7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MemberInfo.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +// no code generated for this class diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MethodBase.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MethodBase.cpp new file mode 100644 index 00000000..a77af234 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_MethodBase.cpp @@ -0,0 +1,184 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + + + +HRESULT Library_corlib_native_System_Reflection_MethodBase::get_Name___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance md; + CLR_RT_HeapBlock* hbMeth = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetMethodDescriptor( stack, *hbMeth, md )); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( stack.PushValue(), md.m_target->name, md.m_assm )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::get_DeclaringType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance md; + CLR_RT_TypeDef_Instance cls; + CLR_RT_HeapBlock* hbMeth = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetMethodDescriptor( stack, *hbMeth, md )); + + if(cls.InitializeFromMethod( md ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + { + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + + hbObj = top.Dereference(); + hbObj->SetReflection( cls ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::get_IsPublic___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_METHODDEF::MD_Scope_Mask, CLR_RECORD_METHODDEF::MD_Scope_Public )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::get_IsStatic___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_METHODDEF::MD_Static, CLR_RECORD_METHODDEF::MD_Static )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::get_IsFinal___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_METHODDEF::MD_Final, CLR_RECORD_METHODDEF::MD_Final )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::get_IsVirtual___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_METHODDEF::MD_Virtual, CLR_RECORD_METHODDEF::MD_Virtual )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::get_IsAbstract___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_METHODDEF::MD_Abstract, CLR_RECORD_METHODDEF::MD_Abstract )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::Invoke___OBJECT__OBJECT__SZARRAY_OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& obj = stack.Arg1(); + CLR_RT_MethodDef_Instance md; + const CLR_RECORD_METHODDEF* mdR; + CLR_RT_HeapBlock_Array* pArray = stack.Arg2().DereferenceArray(); + CLR_RT_HeapBlock* args = NULL; + int numArgs = 0; + CLR_RT_HeapBlock* hbMeth = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetMethodDescriptor( stack, *hbMeth, md )); + + mdR = md.m_target; + + if(stack.m_customState == 0) + { + stack.m_customState = 1; + + if(pArray) + { + args = (CLR_RT_HeapBlock*)pArray->GetFirstElement(); + numArgs = pArray->m_numOfElements; + } + + NANOCLR_CHECK_HRESULT(stack.MakeCall( md, &obj, args, numArgs )); + } + else + { + if(mdR->retVal != DATATYPE_VOID) + { + if(mdR->retVal < DATATYPE_I4) + { + stack.TopValue().ChangeDataType( mdR->retVal ); + } + + NANOCLR_CHECK_HRESULT(stack.TopValue().PerformBoxingIfNeeded()); + } + else + { + stack.SetResult_Object( NULL ); + } + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_Reflection_MethodBase::GetMethodDescriptor( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg, CLR_RT_MethodDef_Instance& inst ) +{ + (void)stack; + + NATIVE_PROFILE_CLR_CORE(); + return CLR_RT_ReflectionDef_Index::Convert( arg, inst ) ? S_OK : CLR_E_NULL_REFERENCE; +} + +HRESULT Library_corlib_native_System_Reflection_MethodBase::CheckFlags( CLR_RT_StackFrame& stack, CLR_UINT32 mask, CLR_UINT32 flag ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance md; + bool fRes; + CLR_RT_HeapBlock* hbMeth = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetMethodDescriptor( stack, *hbMeth, md )); + + if((md.m_target->flags & mask) == flag) + { + fRes = true; + } + else + { + fRes = false; + } + + stack.SetResult_Boolean( fRes ); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_PropertyInfo.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_PropertyInfo.cpp new file mode 100644 index 00000000..8c58f62a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_PropertyInfo.cpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Reflection_PropertyInfo::GetValue___OBJECT__OBJECT__SZARRAY_OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_PropertyInfo::SetValue___VOID__OBJECT__OBJECT__SZARRAY_OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeFieldInfo.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeFieldInfo.cpp new file mode 100644 index 00000000..a47a8cf1 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeFieldInfo.cpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Reflection_RuntimeFieldInfo::get_Name___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_HeapBlock* hbField = stack.Arg0().Dereference(); + + CLR_RT_FieldDef_Instance fd; if(GetFieldDescriptor( stack, *hbField, fd ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( stack.PushValue(), fd.m_target->name, fd.m_assm )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_RuntimeFieldInfo::get_DeclaringType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_FieldDef_Instance fd; + CLR_RT_TypeDef_Instance cls; + CLR_RT_HeapBlock* hbField = stack.Arg0().Dereference(); + + if(GetFieldDescriptor( stack, *hbField, fd ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + + if(cls.InitializeFromField( fd ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + { + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + + hbObj = top.Dereference(); + hbObj->SetReflection( cls ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_RuntimeFieldInfo::get_FieldType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDescriptor desc; + CLR_RT_FieldDef_Instance fd; + CLR_RT_HeapBlock* hbField = stack.Arg0().Dereference(); + + if(GetFieldDescriptor( stack, *hbField, fd ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + + NANOCLR_CHECK_HRESULT(desc.InitializeFromFieldDefinition( fd )); + + { + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( desc.m_handlerCls ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_RuntimeFieldInfo::GetValue___OBJECT__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_FieldDef_Instance instFD; + CLR_RT_TypeDef_Instance instTD; + const CLR_RECORD_FIELDDEF* fd; + CLR_RT_HeapBlock* obj; + CLR_RT_HeapBlock dst; + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_FieldInfo::Initialize( stack, instFD, instTD, obj )); + + fd = instFD.m_target; + if(fd->flags & CLR_RECORD_FIELDDEF::FD_NoReflection) // don't allow reflection for fields with NoReflection attribute + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + { + dst.Assign( *obj ); + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_HeapBlock* argObj = &stack.Arg1(); + + //Marshal if necessary. + if(argObj->IsTransparentProxy()) + { + _ASSERTE(argObj->DataType() == DATATYPE_OBJECT); + + argObj = argObj->Dereference(); + + _ASSERTE(argObj != NULL && argObj->DataType() == DATATYPE_TRANSPARENT_PROXY); + + NANOCLR_CHECK_HRESULT(argObj->TransparentProxyValidate()); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->MarshalObject( *obj, dst, argObj->TransparentProxyAppDomain() )); + } +#endif + + CLR_RT_HeapBlock& res = stack.PushValueAndAssign( dst ); + + NANOCLR_CHECK_HRESULT(res.PerformBoxingIfNeeded()); + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +bool Library_corlib_native_System_Reflection_RuntimeFieldInfo::GetFieldDescriptor( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg, CLR_RT_FieldDef_Instance& inst ) +{ + (void)stack; + + NATIVE_PROFILE_CLR_CORE(); + return CLR_RT_ReflectionDef_Index::Convert( arg, inst ); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeMethodInfo.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeMethodInfo.cpp new file mode 100644 index 00000000..1a0e6176 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Reflection_RuntimeMethodInfo.cpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Reflection_RuntimeMethodInfo::get_ReturnType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance md; + CLR_RT_SignatureParser parser; + CLR_RT_TypeDescriptor desc; + CLR_RT_HeapBlock* hbMeth = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_MethodBase::GetMethodDescriptor( stack, *hbMeth, md )); + + parser.Initialize_MethodSignature( md.m_assm, md.m_target ); + + NANOCLR_CHECK_HRESULT(desc.InitializeFromSignatureParser( parser )); + + { + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( desc.m_reflex ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Reflection_RuntimeMethodInfo::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* returnArray = NULL; + CLR_RT_MethodDef_Instance methodDefinition; + CLR_RT_SignatureParser signatureParser; + CLR_RT_TypeDescriptor desc; + CLR_RT_HeapBlock* callerMethod; + int count = 0; + + // put the return array on the stack + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + // get the caller method + callerMethod = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_MethodBase::GetMethodDescriptor( stack, *callerMethod, methodDefinition )); + + signatureParser.Initialize_MethodSignature( methodDefinition.m_assm, methodDefinition.m_target ); + + NANOCLR_CHECK_HRESULT(desc.InitializeFromSignatureParser( signatureParser )); + + // setup attribute enumerator + CLR_RT_AttributeEnumerator attributeEnumerator; + attributeEnumerator.Initialize( methodDefinition ); + + // 1st pass: count attributes + do + { + // move to the next attribute in the collection, if any + if(attributeEnumerator.Advance()) + { + count++; + } + else + { + // done sweeping attributes + + // create the result array + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, count, g_CLR_RT_WellKnownTypes.m_TypeStatic )); + + // use this to skip the 2nd pass if no attribute was found + if (count == 0) break; + + // get the pointer to the first element + returnArray = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // reset attribute enumerator + attributeEnumerator.Initialize( methodDefinition ); + + break; + } + } + while(true); + + // 2nd pass: fill the array with the attributes types, if any + while(count > 0) + { + // move to the next attribute in the collection, if any + if(attributeEnumerator.Advance()) + { + CLR_RT_TypeDef_Instance instanceTypeDef; + CLR_RT_HeapBlock* hbObj; + + // get the type def for the current attribute + attributeEnumerator.GetCurrent(&instanceTypeDef); + + CLR_RT_TypeDef_Index attributeType; + attributeType.Set(instanceTypeDef.Assembly(), instanceTypeDef.Type()); + + // create a new object for the attribute type and put it on the return array + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*returnArray, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = returnArray->Dereference(); + // make sure the reflection is pointing to the attribute type + hbObj->SetReflection( attributeType ); + + returnArray++; + count--; + } + else + { + // no more attributes + break; + } + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_RuntimeType.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_RuntimeType.cpp new file mode 100644 index 00000000..02fa4bad --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_RuntimeType.cpp @@ -0,0 +1,325 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_RuntimeType::get_Assembly___SystemReflectionAssembly( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbType, td, NULL )); + + { + CLR_RT_Assembly_Index idx; idx.Set( td.Assembly() ); + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_Assembly)); + hbObj = top.Dereference(); + hbObj->SetReflection( idx ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_RuntimeType::get_Name___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetName( *hbType, false, stack.PushValueAndClear() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_RuntimeType::get_FullName___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetName( *hbType, true, stack.PushValueAndClear() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_RuntimeType::get_BaseType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_UINT32 levels; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbType, td, &levels )); + + if(levels > 0) + { + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( g_CLR_RT_WellKnownTypes.m_Array ); + } + else if(td.SwitchToParent()) + { + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( td ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_RuntimeType::GetMethods___SZARRAY_SystemReflectionMethodInfo__SystemReflectionBindingFlags( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Library_corlib_native_System_Type::GetMethods( stack, NULL, stack.Arg1().NumericByRef().s4, NULL, 0, true ); +} + +HRESULT Library_corlib_native_System_RuntimeType::GetField___SystemReflectionFieldInfo__STRING__SystemReflectionBindingFlags( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Library_corlib_native_System_Type::GetFields( stack, stack.Arg1().RecoverString(), stack.Arg2().NumericByRef().s4, false ); +} + +HRESULT Library_corlib_native_System_RuntimeType::GetFields___SZARRAY_SystemReflectionFieldInfo__SystemReflectionBindingFlags( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Library_corlib_native_System_Type::GetFields( stack, NULL, stack.Arg1().NumericByRef().s4, true ); +} + +HRESULT Library_corlib_native_System_RuntimeType::GetInterfaces___SZARRAY_SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* ptr = NULL; + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + int count = 0; + + // 2-pass algorithm. 1. count the interfaces; 2. store the interfaces in an array + for (int pass = 1; pass <= 2; pass++) + { + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *hbType, td )); + + do + { + // Scan the list of interfaces. + CLR_RT_SignatureParser parser; parser.Initialize_Interfaces( td.m_assm, td.m_target ); + CLR_RT_SignatureParser::Element res; + + // 1. pass count + if (pass == 1) + { + count += parser.Available(); + } + else + { + // 2. pass fill the data into the array + while(parser.Available() > 0) + { + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(parser.Advance( res )); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*ptr, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = ptr->Dereference(); + hbObj->SetReflection( res.m_cls ); + + ptr++; + count--; + } + + // array full? => Done + if (count == 0) + { + break; + } + } + } + while(td.SwitchToParent()); + + if (pass == 1) + { + // create the result array + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, count, g_CLR_RT_WellKnownTypes.m_TypeStatic )); + // don't need the second pass if nothing found + if (count == 0) break; + // get the pointer to the first element + ptr = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_RuntimeType::GetElementType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor descSub; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(desc.InitializeFromReflection( hbType->ReflectionDataConst() )); + + if(desc.GetElementType( descSub )) + { + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( descSub.m_reflex ); + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_RuntimeType::GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_TypeDef_Instance& inst, CLR_UINT32* levels ) +{ + NATIVE_PROFILE_CLR_CORE(); + return CLR_RT_ReflectionDef_Index::Convert( arg, inst, levels ) ? S_OK : CLR_E_NULL_REFERENCE; +} + +HRESULT Library_corlib_native_System_RuntimeType::GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT32 levels; + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( arg, inst, &levels )); + + if(levels > 0) + { + inst.InitializeFromIndex( g_CLR_RT_WellKnownTypes.m_Array ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_RuntimeType::GetName( CLR_RT_HeapBlock& arg, bool fFullName, CLR_RT_HeapBlock& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_UINT32 levels; + char rgBuffer[ 256 ]; + char* szBuffer; + size_t iBuffer; + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( arg, td, &levels )); + + szBuffer = rgBuffer; + iBuffer = MAXSTRLEN(rgBuffer); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.BuildTypeName( td, szBuffer, iBuffer, fFullName ? CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL : 0, levels )); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( res, rgBuffer )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_RuntimeType::GetCustomAttributes___SZARRAY_OBJECT__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* returnArray = NULL; + CLR_RT_HeapBlock* callerType = NULL; + CLR_RT_TypeDef_Instance instanceTypeDef; + CLR_RT_TypeDef_Instance typeDefinition; + CLR_RT_HeapBlock* hbObj; + int count = 0; + + // put the return array on the stack + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + // get the caller type + callerType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(GetTypeDescriptor( *callerType, typeDefinition )); + + // setup attribute enumerator + CLR_RT_AttributeEnumerator attributeEnumerator; + attributeEnumerator.Initialize( typeDefinition ); + + // 1st pass: count attributes + do + { + // move to the next attribute in the collection, if any + if(attributeEnumerator.Advance()) + { + count++; + } + else + { + // done sweeping attributes + + // create the result array + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, count, g_CLR_RT_WellKnownTypes.m_TypeStatic )); + + // use this to skip the 2nd pass if no attribute was found + if (count == 0) break; + + // get the pointer to the first element + returnArray = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // reset attribute enumerator + attributeEnumerator.Initialize( typeDefinition ); + + break; + } + } + while(true); + + // 2nd pass: fill the array with the attributes types, if any + while(count > 0) + { + // move to the next attribute in the collection, if any + if(attributeEnumerator.Advance()) + { + // get the type def for the current attribute + attributeEnumerator.GetCurrent(&instanceTypeDef); + + CLR_RT_TypeDef_Index attributeType; + attributeType.Set(instanceTypeDef.Assembly(), instanceTypeDef.Type()); + + // create a new object for the attribute type and put it on the return array + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*returnArray, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = returnArray->Dereference(); + // make sure the reflection is pointing to the attribute type + hbObj->SetReflection( attributeType ); + + returnArray++; + count--; + } + else + { + // no more attributes + break; + } + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_CompilerServices_RuntimeHelpers.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_CompilerServices_RuntimeHelpers.cpp new file mode 100644 index 00000000..69f9ac19 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_CompilerServices_RuntimeHelpers.cpp @@ -0,0 +1,217 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::InitializeArray___STATIC__VOID__SystemArray__SystemRuntimeFieldHandle( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_FieldDef_Instance inst; + CLR_RT_HeapBlock_Array* array = stack.Arg0().DereferenceArray(); FAULT_ON_NULL(array); + + if(array->m_fReference) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if(CLR_RT_ReflectionDef_Index::Convert( stack.Arg1(), inst ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if((inst.m_target->flags & CLR_RECORD_FIELDDEF::FD_HasFieldRVA) == 0 || inst.m_target->defaultValue == CLR_EmptyIndex) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + { + CLR_PMETADATA ptrSrc = inst.m_assm->GetSignature( inst.m_target->defaultValue ); + CLR_UINT32 lenSrc; NANOCLR_READ_UNALIGNED_UINT16( lenSrc, ptrSrc ); + + CLR_UINT8* ptrDst = array->GetFirstElement(); + CLR_UINT32 lenDst = array->m_numOfElements; + CLR_UINT32 sizeDst = array->m_sizeOfElement; + + lenSrc /= sizeDst; if(lenSrc > lenDst) lenSrc = lenDst; +#if !defined(NETMF_TARGET_BIG_ENDIAN) + memcpy( ptrDst, ptrSrc, lenSrc * sizeDst ); + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + switch(array->m_typeOfElement) + { + case DATATYPE_R4: + { + CLR_RT_HeapBlock tmp; + CLR_UINT32* ptr = (CLR_UINT32*)ptrDst; + + for(;lenSrc; lenSrc--, ptr++) + { + NANOCLR_CHECK_HRESULT(tmp.SetFloatIEEE754( *ptr )); + + *ptr = tmp.NumericByRef().u4; + } + } + break; + + case DATATYPE_R8: + { + CLR_RT_HeapBlock tmp; + CLR_UINT64* ptr = (CLR_UINT64*)ptrDst; + + for(;lenSrc; lenSrc--, ptr++) + { + NANOCLR_CHECK_HRESULT(tmp.SetDoubleIEEE754( *ptr )); + + *ptr = tmp.NumericByRef().u8; + } + } + break; + } +#endif + +#else + // FIXME GJS - WOuld it be possible to move the endian swap to pe compile time to get rid of this? + // If this is a numeric dataype of datatype size other than a byte then byteswap the entries + // Unaligned reads handle endianess, just use them. FIXME GJS - this could be the subject of much optimization + switch(array->m_typeOfElement) + { + case DATATYPE_CHAR: + case DATATYPE_I2: + case DATATYPE_U2: + { + CLR_UINT32 count=0; + CLR_UINT16 d; + CLR_UINT16 *p16 = (CLR_UINT16*)ptrDst; + while( count < lenDst ) + { + NANOCLR_READ_UNALIGNED_UINT16( d, ptrSrc ); + *p16++ = SwapEndian(d); + count++; + } + } + break; + + case DATATYPE_I4: + case DATATYPE_U4: + case DATATYPE_R4: + { + CLR_UINT32 count=0; + CLR_UINT32 d; + CLR_UINT32 *p32 = (CLR_UINT32*)ptrDst; + while( count < lenDst ) + { + NANOCLR_READ_UNALIGNED_UINT32( d, ptrSrc ); + *p32++ = SwapEndian(d); + count++; + } + } + break; + case DATATYPE_I8: + case DATATYPE_U8: + case DATATYPE_R8: + { + CLR_UINT32 count=0; + CLR_UINT64 d; + CLR_UINT64 *p64 = (CLR_UINT64*)ptrDst; + + while( count < lenDst ) + { + NANOCLR_READ_UNALIGNED_UINT64( d, ptrSrc ); + *p64++ = SwapEndian( d ); + count++; + } + } + break; + default: + memcpy( ptrDst, ptrSrc, lenSrc * sizeDst ); + break; + } + + + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + switch(array->m_typeOfElement) + { + case DATATYPE_R4: + { + CLR_RT_HeapBlock tmp; + CLR_UINT32* ptr = (CLR_UINT32*)ptrDst; + + for(;lenSrc; lenSrc--, ptr++) + { + NANOCLR_CHECK_HRESULT(tmp.SetFloatIEEE754( *ptr )); + + *ptr = tmp.NumericByRef().u4; + } + } + break; + + case DATATYPE_R8: + { + CLR_RT_HeapBlock tmp; + CLR_UINT64* ptr = (CLR_UINT64*)ptrDst; + + for(;lenSrc; lenSrc--, ptr++) + { + NANOCLR_CHECK_HRESULT(tmp.SetDoubleIEEE754( *ptr )); + + *ptr = tmp.NumericByRef().u8; + } + } + break; + } +#endif +#endif //NETMF_TARGET_BIG_ENDIAN + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::GetObjectValue___STATIC__OBJECT__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* src = stack.Arg0().Dereference(); + + if(src && src->DataType() == DATATYPE_VALUETYPE && src->IsBoxed()) + { + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( top, *src )); + } + else + { + top.SetObjectReference( src ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::RunClassConstructor___STATIC__VOID__SystemRuntimeTypeHandle( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers::get_OffsetToStringData___STATIC__I4( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_Remoting_RemotingServices.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_Remoting_RemotingServices.cpp new file mode 100644 index 00000000..be4d82a6 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Runtime_Remoting_RemotingServices.cpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Runtime_Remoting_RemotingServices::IsTransparentProxy___STATIC__BOOLEAN__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + bool fProxy = false; + + #if defined(NANOCLR_APPDOMAINS) + CLR_RT_HeapBlock& obj = stack.Arg0(); + fProxy = obj.IsTransparentProxy(); + #endif + + stack.SetResult_Boolean( fProxy ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_String.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_String.cpp new file mode 100644 index 00000000..2a9d4e27 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_String.cpp @@ -0,0 +1,1182 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +static const CLR_UINT16 c_WhiteSpaces[] = +{ + 0x0009, + 0x000A, + 0x000B, + 0x000C, + 0x000D, + 0x0020, + 0x00A0, + 0x2000, + 0x2001, + 0x2002, + 0x2003, + 0x2004, + 0x2005, + 0x2006, + 0x2007, + 0x2008, + 0x2009, + 0x200A, + 0x200B, + 0x3000, + 0xFEFF, +}; + +//--// + +HRESULT Library_corlib_native_System_String::CompareTo___I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Library_corlib_native_System_String::CompareTo___I4__STRING( stack )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::get_Chars___CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* szText; + CLR_RT_UnicodeHelper uh; + CLR_UINT16 buf[ 3 ]; + int len; + int index; + + szText = stack.Arg0().RecoverString(); FAULT_ON_NULL(szText); + + uh.SetInputUTF8( szText ); + + len = uh.CountNumberOfCharacters() ; if(len < 0 ) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + index = stack.Arg1().NumericByRef().s4; if(index < 0 || index >= len) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + uh.m_outputUTF16 = buf; + uh.m_outputUTF16_size = MAXSTRLEN(buf); + + // + // First move to the character, then read it. + // + uh.ConvertFromUTF8( index, true ); + uh.ConvertFromUTF8( 1 , false ); + + stack.SetResult( buf[ 0 ], DATATYPE_CHAR ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(ToCharArray( stack, 0, -1 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(ToCharArray( stack, stack.Arg1().NumericByRef().s4, stack.Arg2().NumericByRef().s4 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::get_Length___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* szText = stack.Arg0().RecoverString(); FAULT_ON_NULL(szText); + + CLR_RT_UnicodeHelper uh; uh.SetInputUTF8( szText ); + + stack.SetResult_I4( uh.CountNumberOfCharacters() ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Split( stack, stack.Arg1(), 0x7FFFFFFF )); /// Sending INT_MAX instead of -1. + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Split( stack, stack.Arg1(), stack.Arg2().NumericByRef().s4 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Substring___STRING__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Substring( stack, stack.Arg1().NumericByRef().s4, -1 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Substring___STRING__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT32 length = stack.Arg2().NumericByRef().s4; + + if(length < 0) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + NANOCLR_SET_AND_LEAVE(Substring( stack, stack.Arg1().NumericByRef().s4, length )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Trim___STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Trim( stack, stack.Arg1().DereferenceArray(), true, true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::TrimStart___STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Trim( stack, stack.Arg1().DereferenceArray(), true, false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::TrimEnd___STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Trim( stack, stack.Arg1().DereferenceArray(), false, true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(FromCharArray( stack, stack.Arg2().NumericByRef().s4, stack.Arg3().NumericByRef().s4 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(FromCharArray( stack, 0, -1 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::_ctor___VOID__CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT16 ch = stack.Arg1().NumericByRef().u2; + int len = stack.Arg2().NumericByRef().s4; if(len < 0) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + { + CLR_RT_HeapBlock tmp; tmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( tmp ); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( tmp, len, g_CLR_RT_WellKnownTypes.m_Char )); + + { + CLR_RT_HeapBlock_Array* tmpArray = tmp.DereferenceArray(); + CLR_UINT16* pTmp = (CLR_UINT16*)tmpArray->GetFirstElement(); + CLR_UINT16* p; + + p = pTmp; while(len--) *p++ = ch; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( stack.Arg0(), pTmp, tmpArray->m_numOfElements )); + } + } + + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_String::CompareTo___I4__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& pThis = stack.Arg0(); // String references are special, they don't point to an object, they are the object. So use stack.Arg0() instead of stack.This() + CLR_RT_HeapBlock& pArg = stack.Arg1(); + + stack.SetResult_I4( CLR_RT_HeapBlock::Compare_Unsigned_Values( pThis, pArg ) ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__StartIndex )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__StartIndex | c_IndexOf__Count )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__StartIndex )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__StartIndex | c_IndexOf__Count )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__STRING__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__StartIndex )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__STRING__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__StartIndex | c_IndexOf__Count )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__Last )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__Last | c_IndexOf__StartIndex )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__Last | c_IndexOf__StartIndex | c_IndexOf__Count )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__Last )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__Last | c_IndexOf__StartIndex )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__Last | c_IndexOf__StartIndex | c_IndexOf__Count )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__Last )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__Last | c_IndexOf__StartIndex )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__Last | c_IndexOf__StartIndex | c_IndexOf__Count )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToLower___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(ChangeCase( stack, false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToUpper___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(ChangeCase( stack, true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Trim___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Trim( stack, NULL, true, true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_Boolean( CLR_RT_HeapBlock::Compare_Unsigned_Values( stack.Arg0(), stack.Arg1() ) == 0 ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_String::op_Equality___STATIC__BOOLEAN__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING( stack )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::op_Inequality___STATIC__BOOLEAN__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING( stack )); + + stack.NegateResult(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Compare___STATIC__I4__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_I4( CLR_RT_HeapBlock::Compare_Unsigned_Values( stack.Arg0(), stack.Arg1() ) ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Concat( stack, &stack.Arg0(), 2 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Concat( stack, &stack.Arg0(), 3 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Concat( stack, &stack.Arg0(), 4 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__SZARRAY_STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); FAULT_ON_NULL(pArray); + + NANOCLR_SET_AND_LEAVE(Concat( stack, (CLR_RT_HeapBlock*)pArray->GetFirstElement(), pArray->m_numOfElements )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_String::FromCharArray( CLR_RT_StackFrame& stack, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + CLR_UINT32 len; + + array = stack.Arg1().DereferenceArray(); + if (!array || array->m_numOfElements == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance(stack.Arg0(), "")); + } + else + { + len = array->m_numOfElements; + + if (length == -1) + length = len - startIndex; + + if (CLR_RT_HeapBlock_Array::CheckRange(startIndex, length, len) == false) + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance(stack.Arg0(), (CLR_UINT16*)array->GetElement(startIndex), length)); + } + + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_String::ToCharArray( CLR_RT_StackFrame& stack, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + + NANOCLR_SET_AND_LEAVE(ConvertToCharArray( stack, stack.PushValueAndClear(), array, startIndex, length )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf( CLR_RT_StackFrame& stack, int mode ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* szText; + int startIndex; + int count; + int pos; + const char* pString; + const CLR_UINT16* pChars; + int iChars = 0; + CLR_RT_UnicodeHelper inputIterator; + int inputLen; + int searchLen = 1; + + szText = stack.Arg0().RecoverString(); if(!szText) szText = ""; + pos = -1; + pString = NULL; + pChars = NULL; + + if(mode & c_IndexOf__SingleChar) + { + pChars = (CLR_UINT16*)&stack.Arg1().NumericByRefConst().u2; + iChars = 1; + } + else if(mode & c_IndexOf__MultipleChars) + { + CLR_RT_HeapBlock_Array* array = stack.Arg1().DereferenceArray(); FAULT_ON_NULL(array); + + pChars = (const CLR_UINT16*)array->GetFirstElement(); + iChars = array->m_numOfElements; + } + else if(mode & c_IndexOf__String) + { + pString = stack.Arg1().RecoverString(); FAULT_ON_NULL(pString); + // how long is the search string? + inputIterator.SetInputUTF8( pString ); + searchLen = inputIterator.CountNumberOfCharacters(); + } + + // calculate input string length + inputIterator.SetInputUTF8( szText ); + inputLen = inputIterator.CountNumberOfCharacters(); + + // calculate start index + if(mode & c_IndexOf__StartIndex) + { + startIndex = stack.Arg2().NumericByRefConst().s4; + } + else + { + // for mode LastIndex... we are searching backwards toward the start of the string + if(mode & c_IndexOf__Last) + { + startIndex = inputLen - 1; + } + else + { + startIndex = 0; + } + } + + // check the start index + if(startIndex < 0 || startIndex > inputLen) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + // for mode LastIndex... with string we move the start index back by the search string length -1 + if((mode & c_IndexOf__String_Last) == c_IndexOf__String_Last) + { + startIndex -= searchLen - 1; + // check the start index; if not in range skip the search + if(startIndex < 0 || startIndex > inputLen) goto Exit; + } + + // calculate the iteration count + if(mode & c_IndexOf__Count) + { + // count form parameter + count = stack.Arg3().NumericByRefConst().s4; + } + else + { + // for mode LastIndex... we are searching from start index backwards toward the start of the string + if(mode & c_IndexOf__Last) + { + // backward until the start of string + // one more time than the startIndex because we should iterate until zero + count = startIndex + 1; + } + else + { + // forward until the end of string + count = inputLen - startIndex; + } + } + + // for mode with string we reduce the count by the search string length -1 + // if we search foreward + if((mode & c_IndexOf__String_Last) == c_IndexOf__String) + { + count -= searchLen - 1; + } + + // check the count + if(mode & c_IndexOf__Last) + { + // check for backward mode; no exception; just exit + if(count > startIndex + 1) goto Exit; + } + else + { + // check for forward mode + if(startIndex + count > inputLen) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + // First move to the character, then read it. + if(inputIterator.ConvertFromUTF8( startIndex, true )) + { + // string mode? + if(pString) + { + // iterate thru all positions + while(count-- > 0) + { + CLR_RT_UnicodeHelper inputString; inputString.SetInputUTF8( (const char*)inputIterator.m_inputUTF8 ); + CLR_RT_UnicodeHelper searchString; searchString.SetInputUTF8( pString ); + bool finished = false; + + while(true) + { + CLR_UINT16 bufInput[ 3 ]; + CLR_UINT16 bufSearch[ 3 ]; + + inputString.m_outputUTF16 = bufInput; + inputString.m_outputUTF16_size = MAXSTRLEN(bufInput); + + searchString.m_outputUTF16 = bufSearch; + searchString.m_outputUTF16_size = MAXSTRLEN(bufSearch); + + // read next char from search string; if no more chars to read (false) + // then we are done and found the search string in the input string + if(searchString.ConvertFromUTF8( 1, false ) == false) + { + pos = startIndex; + finished = true; + break; + } + + // read the next char from the input string; if no more chars to read (false) + // we didn't found the search string in the input string; we abort the search now + if(inputString.ConvertFromUTF8( 1, false ) == false) + { + finished = true; + break; + } + + // does the char from input not match the char from the search string + if(bufInput[ 0 ] != bufSearch[ 0 ]) + { + // next iteration round but not finished + break; + } + } + + // finished (with or without a found) then break + if (finished) + { + break; + } + + // reading forward or backward + if(mode & c_IndexOf__Last) + { + startIndex--; + // move one chars backward + if(inputIterator.MoveBackwardInUTF8( szText, 1 ) == false) + { + break; + } + } + else + { + startIndex++; + // move to the next char + if(inputIterator.ConvertFromUTF8( 1, true ) == false) + { + break; + } + } + } + } + + // char mode? + if(pChars) + { + // iterate thru all positions + while(count-- > 0) + { + CLR_UINT16 buf[ 3 ]; + + inputIterator.m_outputUTF16 = buf; + inputIterator.m_outputUTF16_size = MAXSTRLEN(buf); + + // read the next char from the input string; if no more chars to read (false) + // we didn't found the search chars in the input string + if(inputIterator.ConvertFromUTF8( 1, false ) == false) + { + break; + } + + // test each search char if it's a match + for(int i=0; i break + if (pos != -1) + { + break; + } + + // for mode LastIndex... we are searching from start index backwards toward the start of the string + if(mode & c_IndexOf__Last) + { + // in backward mode + startIndex--; + // move two chars backward, because the current char is already read + if(inputIterator.MoveBackwardInUTF8( szText, 2 ) == false) + { + break; + } + } + else + { + // forward mode; simple advance the start index + startIndex++; + } + } + } + } + +Exit: + stack.SetResult_I4( pos ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ChangeCase( CLR_RT_StackFrame& stack, bool fToUpper ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock refTmp; refTmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refTmp ); + CLR_RT_HeapBlock_Array* arrayTmp; + CLR_UINT16* ptr; + + NANOCLR_CHECK_HRESULT(ConvertToCharArray( stack, refTmp, arrayTmp, 0, -1 )); + + ptr = (CLR_UINT16*)arrayTmp->GetFirstElement(); + + for(CLR_UINT32 i=0; im_numOfElements; i++) + { + CLR_UINT16 c = *ptr; + + if(fToUpper) + { + if(c >= 'a' && c <= 'z') c += 'A' - 'a'; + } + else + { + if(c >= 'A' && c <= 'Z') c -= 'A' - 'a'; + } + + *ptr++ = c; + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( stack.PushValue(), (CLR_UINT16*)arrayTmp->GetFirstElement(), arrayTmp->m_numOfElements )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Substring( CLR_RT_StackFrame& stack, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock refTmp; refTmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refTmp ); + CLR_RT_HeapBlock_Array* arrayTmp; + + NANOCLR_CHECK_HRESULT(ConvertToCharArray( stack, refTmp, arrayTmp, 0, -1 )); + + if(startIndex < 0 || startIndex > (int)arrayTmp->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(length == -1) + { + length = arrayTmp->m_numOfElements - startIndex; + } + else + { + if(length < 0 || (startIndex + length) > (int)arrayTmp->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( stack.PushValue(), (CLR_UINT16*)arrayTmp->GetElement( startIndex ), length )); + + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_String::Trim( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_Array* arrayTrimChars, bool fStart, bool fEnd ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock refTmp; refTmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refTmp ); + CLR_RT_HeapBlock_Array* arrayTmp; + CLR_UINT16* pSrcStart; + CLR_UINT16* pSrcEnd; + + NANOCLR_CHECK_HRESULT(ConvertToCharArray( stack, refTmp, arrayTmp, 0, -1 )); + + pSrcStart = (CLR_UINT16*)arrayTmp->GetFirstElement(); + pSrcEnd = &pSrcStart[ arrayTmp->m_numOfElements ]; + + const CLR_UINT16* pTrim; + CLR_UINT32 iTrim; + + if(arrayTrimChars && arrayTrimChars->m_numOfElements) + { + pTrim = (const CLR_UINT16*)arrayTrimChars->GetFirstElement(); + iTrim = arrayTrimChars->m_numOfElements; + } + else + { + pTrim = c_WhiteSpaces; + iTrim = ARRAYSIZE(c_WhiteSpaces); + } + + //--// + + if(fStart) + { + while(pSrcStart < pSrcEnd) + { + const CLR_UINT16* p = pTrim; + CLR_UINT32 i; + + for(i=0; im_numOfElements > 0) + { + pChars = (CLR_UINT16*)arrayChars->GetFirstElement(); + cChars = arrayChars->m_numOfElements; + } + else + { + pChars = &c_WhiteSpaces[ 0 ]; + cChars = ARRAYSIZE(c_WhiteSpaces); + } + + arrayDst = NULL; + + { + CLR_RT_HeapBlock refSrc; refSrc.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refSrc ); + + NANOCLR_CHECK_HRESULT(ConvertToCharArray( stack, refSrc, arraySrc, 0, -1 )); + + for(int pass=0; pass<2; pass++) + { + CLR_UINT16* pSrcStart = (CLR_UINT16*)arraySrc->GetFirstElement(); + CLR_UINT16* pSrc = pSrcStart; + int count = 0; + bool fFound = false; + bool fContinueSearching = true; + + for(CLR_UINT32 iSrc=0; iSrc <= arraySrc->m_numOfElements; iSrc++, pSrc++) + { + if(iSrc == arraySrc->m_numOfElements) + { + fFound = true; + } + else if ((count + 1) >= maxStrings) + { + fContinueSearching = false; + } + else if (fContinueSearching) + { + const CLR_UINT16* pCharsT = pChars; + + for(CLR_UINT32 iChars=0; iCharsGetElement( count ); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( *str, pSrcStart, (CLR_UINT32)(pSrc - pSrcStart) )); + + pSrcStart = pSrc + 1; + } + + count++; + fFound = false; + } + } + + if(pass == 0) + { + CLR_RT_HeapBlock& refTarget = stack.PushValue(); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( refTarget, count, g_CLR_RT_WellKnownTypes.m_String )); + + arrayDst = refTarget.DereferenceArray(); + } + } + } + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_String::Concat( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock* array, int num ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* ptrSrc; + const char* szTextSrc; + char* szTextDst = NULL; + CLR_UINT32 totLen; + CLR_UINT32 len; + + totLen = 0; + + for(int i=0; i<2; i++) + { + ptrSrc = array; + + for(int iStr=0; iStrDataType() == DATATYPE_OBJECT); + _ASSERTE(FIMPLIES(ptrSrc->Dereference(), ptrSrc->Dereference()->DataType() == DATATYPE_STRING)); + + szTextSrc = ptrSrc->RecoverString(); + if(szTextSrc) + { + len = (CLR_UINT32)hal_strlen_s( szTextSrc ); + + if(i==0) + { + totLen += len; + } + else + { + memcpy( szTextDst, szTextSrc, len ); + + szTextDst += len; + } + } + + ptrSrc++; + } + + if(i==0) + { + //push return value + CLR_RT_HeapBlock& blkResult = stack.PushValue(); + CLR_RT_HeapBlock_String* str = CLR_RT_HeapBlock_String::CreateInstance( blkResult, totLen ); CHECK_ALLOCATION(str); + + szTextDst = (char*)str->StringText(); + szTextDst[ totLen ] = 0; + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ConvertToCharArray( const char* szText, CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_UnicodeHelper uh; + int totLength; + + FAULT_ON_NULL(szText); + + uh.SetInputUTF8( szText ); + + totLength = uh.CountNumberOfCharacters(); if(totLength < 0) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + if(length == -1) length = totLength; + + if(CLR_RT_HeapBlock_Array::CheckRange( startIndex, length, totLength ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, length, g_CLR_RT_WellKnownTypes.m_Char )); + + array = ref.DereferenceArray(); + + uh.m_outputUTF16 = (CLR_UINT16*)array->GetFirstElement(); + uh.m_outputUTF16_size = array->m_numOfElements; + + // + // First move to the character, then read it. + // + uh.ConvertFromUTF8( startIndex , true ); + uh.ConvertFromUTF8( array->m_numOfElements, false ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ConvertToCharArray( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + return ConvertToCharArray( stack.Arg0().RecoverString(), ref, array, startIndex, length ); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Decoder.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Decoder.cpp new file mode 100644 index 00000000..ddbf11fb --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Decoder.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Text_UTF8Decoder::Convert___VOID__SZARRAY_U1__I4__I4__SZARRAY_CHAR__I4__I4__BOOLEAN__BYREF_I4__BYREF_I4__BYREF_BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_UTF8_DECODER(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArrayBytes; + CLR_INT32 byteIndex; + CLR_INT32 byteCount; + CLR_RT_HeapBlock_Array* pArrayChars; + CLR_INT32 charIndex; + CLR_INT32 charCount; + CLR_INT32 byteUsed; + CLR_INT32 charUsed; + bool completed; + + CLR_RT_UnicodeHelper uh; + CLR_UINT8* byteStart; + + // Get all the parameters + pArrayBytes = stack.Arg1().DereferenceArray(); FAULT_ON_NULL(pArrayBytes); + byteIndex = stack.Arg2().NumericByRef().s4; + byteCount = stack.Arg3().NumericByRef().s4; + + pArrayChars = stack.Arg4( ).DereferenceArray(); FAULT_ON_NULL(pArrayChars); + charIndex = stack.ArgN( 5 ).NumericByRef().s4; + charCount = stack.ArgN( 6 ).NumericByRef().s4; + + // Parameters error checking + if (byteIndex < 0 || + byteCount < 0 || + charIndex < 0 || + charCount < 0 || + (CLR_INT32)pArrayBytes->m_numOfElements - byteIndex < byteCount || + (CLR_INT32)pArrayChars->m_numOfElements - charIndex < charCount ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + _ASSERTE(pArrayBytes->m_typeOfElement == DATATYPE_U1); + _ASSERTE(pArrayChars->m_typeOfElement == DATATYPE_CHAR); + + _ASSERTE(stack.ArgN( 8 ).DataType() == DATATYPE_BYREF); + _ASSERTE(stack.ArgN( 9 ).DataType() == DATATYPE_BYREF); + _ASSERTE(stack.ArgN( 10 ).DataType() == DATATYPE_BYREF); + + + // Setup the UnicodeHelper + byteStart = pArrayBytes->GetElement( byteIndex ); + uh.SetInputUTF8( (const char*)byteStart ); + + uh.m_outputUTF16 = (CLR_UINT16*)pArrayChars->GetElement( charIndex ); + uh.m_outputUTF16_size = charCount; + + uh.ConvertFromUTF8( charCount, false, byteCount ); + + // Calculate return values + byteUsed = (CLR_INT32)(uh.m_inputUTF8 - byteStart); + charUsed = charCount - uh.m_outputUTF16_size; + completed = (byteUsed == byteCount); + + stack.ArgN(8).Dereference()->SetInteger( byteUsed ); + stack.ArgN(9).Dereference()->SetInteger( charUsed ); + stack.ArgN(10).Dereference()->SetBoolean( completed ); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Encoding.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Encoding.cpp new file mode 100644 index 00000000..a1f14888 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Text_UTF8Encoding.cpp @@ -0,0 +1,127 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Text_UTF8Encoding::GetBytes___SZARRAY_U1__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + size_t cBytes; + CLR_RT_HeapBlock_Array* arr; + const char* str; + CLR_RT_HeapBlock& ret = stack.PushValueAndClear(); + + str = stack.Arg1().RecoverString(); FAULT_ON_NULL(str); + cBytes = hal_strlen_s(str); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ret, (CLR_UINT32)cBytes, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + arr = ret.DereferenceArray(); + + memcpy( arr->GetFirstElement(), str, cBytes ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Text_UTF8Encoding::GetBytes___I4__STRING__I4__I4__SZARRAY_U1__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* str = stack.Arg1().RecoverString(); + CLR_INT32 strIdx = stack.Arg2().NumericByRef().s4; + CLR_INT32 strCnt = stack.Arg3().NumericByRef().s4; + CLR_RT_HeapBlock_Array* pArrayBytes = stack.Arg4().DereferenceArray(); + CLR_INT32 byteIdx = stack.Arg5().NumericByRef().s4; + + const CLR_UINT8* i; + const CLR_UINT8* j; + CLR_RT_UnicodeHelper uh; + int strLength; + + FAULT_ON_NULL(str); + FAULT_ON_NULL(pArrayBytes); + + uh.SetInputUTF8(str); + strLength = uh.CountNumberOfCharacters(); + if (strLength < 0) + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + if ((strIdx + strCnt) > (CLR_INT32)strLength) + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + uh.ConvertFromUTF8(strIdx, true); + i = uh.m_inputUTF8; + uh.ConvertFromUTF8(strCnt, true); + j = uh.m_inputUTF8; + + if ((byteIdx + j - i) > (CLR_INT32)pArrayBytes->m_numOfElements) + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + memcpy(pArrayBytes->GetElement(byteIdx), i, j - i); + + stack.SetResult_I4(j - i); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Text_UTF8Encoding::GetChars___SZARRAY_CHAR__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(Helper__GetChars( stack, false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Text_UTF8Encoding::GetChars___SZARRAY_CHAR__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(Helper__GetChars( stack, true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Text_UTF8Encoding::Helper__GetChars(CLR_RT_StackFrame& stack, bool fIndexed) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* szText; + CLR_RT_HeapBlock ref; ref.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( ref ); + CLR_RT_HeapBlock_Array* pArrayBytes = stack.Arg1().DereferenceArray(); + CLR_INT32 byteIdx = fIndexed ? stack.Arg2().NumericByRef().s4 : 0; + CLR_INT32 byteCnt = fIndexed ? stack.Arg3().NumericByRef().s4 : pArrayBytes->m_numOfElements; + CLR_RT_HeapBlock_Array* pArrayBytesCopy; + CLR_RT_HeapBlock_Array* arrTmp; + int cBytesCopy; + + FAULT_ON_NULL(pArrayBytes); + + _ASSERTE(pArrayBytes->m_typeOfElement == DATATYPE_U1); + + if((byteIdx + byteCnt) > (CLR_INT32)pArrayBytes->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + cBytesCopy = byteCnt+1; + + /* Copy the array to a temporary buffer to create a zero-terminated string */ + NANOCLR_CHECK_HRESULT( CLR_RT_HeapBlock_Array::CreateInstance( ref, cBytesCopy, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + pArrayBytesCopy = ref.DereferenceArray(); + szText = (const char*)pArrayBytesCopy->GetFirstElement(); + + hal_strncpy_s( (char*) szText, cBytesCopy, (const char*)pArrayBytes->GetElement(byteIdx), byteCnt ); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_String::ConvertToCharArray( szText, stack.PushValueAndClear(), arrTmp, 0, -1 )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_AutoResetEvent.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_AutoResetEvent.cpp new file mode 100644 index 00000000..1037e1d3 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_AutoResetEvent.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Threading_AutoResetEvent::_ctor___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + + pThis->SetFlags( CLR_RT_HeapBlock::HB_SignalAutoReset ); + + if(stack.Arg1().NumericByRef().s4) + { + pThis->SetFlags( CLR_RT_HeapBlock::HB_Signaled ); + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Threading_AutoResetEvent::Reset___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + Library_corlib_native_System_Threading_WaitHandle::Reset( stack ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Threading_AutoResetEvent::Set___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + Library_corlib_native_System_Threading_WaitHandle::Set( stack ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Interlocked.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Interlocked.cpp new file mode 100644 index 00000000..54bb9322 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Interlocked.cpp @@ -0,0 +1,92 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Threading_Interlocked::Increment___STATIC__I4__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock heapLocation; + NANOCLR_CHECK_HRESULT(heapLocation.LoadFromReference( stack.Arg0() )); + signed int &location = heapLocation.NumericByRef().s4; + + // Increment the value passed by reference + location++; + + SetResult_INT32( stack, location ); + + NANOCLR_CHECK_HRESULT(heapLocation.StoreToReference( stack.Arg0(), 0 )); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Interlocked::Decrement___STATIC__I4__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock heapLocation; + NANOCLR_CHECK_HRESULT(heapLocation.LoadFromReference( stack.Arg0() )); + signed int &location = heapLocation.NumericByRef().s4; + + // Decrement the value passed by reference + location--; + + SetResult_INT32( stack, location ); + + NANOCLR_CHECK_HRESULT(heapLocation.StoreToReference( stack.Arg0(), 0 )); + } + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_Threading_Interlocked::Exchange___STATIC__I4__BYREF_I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock heapLocation; + NANOCLR_CHECK_HRESULT(heapLocation.LoadFromReference( stack.Arg0() )); + signed int &location = heapLocation.NumericByRef().s4; + + // Always return value of first parameter + signed int retVal = location; + // Move second parameter into the first. + location = stack.Arg1().NumericByRef().s4; + + SetResult_INT32( stack, retVal ); + + NANOCLR_CHECK_HRESULT(heapLocation.StoreToReference( stack.Arg0(), 0 )); + } + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_Threading_Interlocked::CompareExchange___STATIC__I4__BYREF_I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock heapLocation; + NANOCLR_CHECK_HRESULT(heapLocation.LoadFromReference( stack.Arg0() )); + signed int &location = heapLocation.NumericByRef().s4; + + // Always return value of first parameter + signed int retVal = location; + // Exchange value if first and third parameters has equal value. + if (stack.Arg2().NumericByRef().s4 == location) + { + location = stack.Arg1().NumericByRef().s4; + } + + SetResult_INT32( stack, retVal ); + + NANOCLR_CHECK_HRESULT(heapLocation.StoreToReference( stack.Arg0(), 0 )); + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_ManualResetEvent.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_ManualResetEvent.cpp new file mode 100644 index 00000000..8482a43d --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_ManualResetEvent.cpp @@ -0,0 +1,42 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Threading_ManualResetEvent::_ctor___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + + if(stack.Arg1().NumericByRef().s4) + { + pThis->SetFlags( CLR_RT_HeapBlock::HB_Signaled ); + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Threading_ManualResetEvent::Reset___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + Library_corlib_native_System_Threading_WaitHandle::Reset( stack ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Threading_ManualResetEvent::Set___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + Library_corlib_native_System_Threading_WaitHandle::Set( stack ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Monitor.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Monitor.cpp new file mode 100644 index 00000000..0a1c43fb --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Monitor.cpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Threading_Monitor::Enter___STATIC__VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* caller = NULL; + + if(stack.Arg0().Dereference() == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); + } + + switch(stack.m_customState) + { + case 0: + { + caller = stack.Caller(); FAULT_ON_NULL(caller); // We need to set the constraint on the caller, not on us... + + hr = g_CLR_RT_ExecutionEngine.LockObject( stack.Arg0(), caller->m_owningSubThread, TIMEOUT_INFINITE, false ); + if(hr == CLR_E_THREAD_WAITING) + { + stack.m_customState = 1; + } + + NANOCLR_LEAVE(); + } + break; + + case 1: + NANOCLR_SET_AND_LEAVE(S_OK); + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Monitor::Exit___STATIC__VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* caller = NULL; + + if(stack.Arg0().Dereference() == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL); + } + + caller = stack.Caller(); FAULT_ON_NULL(caller); // We need to set the constraint on the caller, not on us... + + NANOCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.UnlockObject( stack.Arg0(), caller->m_owningSubThread )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Thread.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Thread.cpp new file mode 100644 index 00000000..add106ca --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Thread.cpp @@ -0,0 +1,575 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +//--// + +HRESULT Library_corlib_native_System_Threading_Thread::_ctor___VOID__SystemThreadingThreadStart( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + + pThis[ FIELD___delegate ].Assign ( stack.Arg1() ); + + // Thread is always constructed with normal priority. + pThis[ FIELD___priority ].NumericByRef().s4 = ThreadPriority::Normal; + + // Book a Thread ID + pThis[ FIELD___id ].NumericByRef().s4 = g_CLR_RT_ExecutionEngine.GetNextThreadId(); + + +#if defined(NANOCLR_APPDOMAINS) + NANOCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(), *pThis, pThis[ FIELD___appDomain ] )); + NANOCLR_NOCLEANUP(); +#else + NANOCLR_NOCLEANUP_NOLABEL(); +#endif + +} + +HRESULT Library_corlib_native_System_Threading_Thread::Start___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th; + CLR_RT_HeapBlock* pThis; + CLR_RT_HeapBlock_Delegate* dlg; + int pri; + + // + // Don't start twice... + // + NANOCLR_CHECK_HRESULT(GetThread( stack, th, false, false )); + if(th != NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + pThis = stack.This(); FAULT_ON_NULL(pThis); + dlg = pThis[ FIELD___delegate ].DereferenceDelegate(); FAULT_ON_NULL(dlg ); + + // Set priority of new sub-thread to the priority stored in the thread C# object. + // The new sub-thread becames the current one, it should always match priority stored in Thread C# object + + pri = pThis[ FIELD___priority ].NumericByRef().s4; + + pThis->ResetFlags( CLR_RT_HeapBlock::HB_Signaled ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewThread( th, dlg, pri, pThis[ FIELD___id ].NumericByRef().s4 )); + + NANOCLR_SET_AND_LEAVE(SetThread( stack, th )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Abort___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th; + + NANOCLR_CHECK_HRESULT(GetThread( stack, th, true, true )); + + if(th == stack.m_owningThread) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + th->Abort(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Suspend___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + // Test if this the call from managed Thread.Suspend() or second call on resume. + switch( stack.m_customState ) + { + // This is the normal call from managed code. + case 0: + { + CLR_RT_Thread* th; + + NANOCLR_CHECK_HRESULT(GetThread( stack, th, true, true )); + + NANOCLR_CHECK_HRESULT(th->Suspend()); + + // If the thread suspends itself, then we need to re-schedule. + if ( stack.m_owningThread == th ) + { // Set flag in thread stack that thread is re-scheduled. + stack.m_customState = 1; + + // Call to th->Suspend() was successful and moved thread to suspended list. + // Now the threads should be re-scheduled to make suspension effective immidiately. + // In order to do it we return CLR_E_RESCHEDULE from this function - Suspend___VOID + NANOCLR_SET_AND_LEAVE( CLR_E_RESCHEDULE ); + } + } + break; + + // This is the case when thread is resumed, brought back from suspended state. + case 1: + { + stack.m_customState = 0; + NANOCLR_SET_AND_LEAVE(S_OK); + } + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + break; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Resume___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th; + + NANOCLR_CHECK_HRESULT(GetThread( stack, th, true, true )); + + NANOCLR_SET_AND_LEAVE(th->Resume()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_Priority___SystemThreadingThreadPriority( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th; + int pri; + + // Get C# thread object + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Reads priority stored in C# object. + pri = pThis[ FIELD___priority ].NumericByRef().s4; + + // Here we check consistency of values stored in C# and internal thread objects. + // Get thread associated with C# thread object. It might be NULL if thread was not started. + NANOCLR_CHECK_HRESULT(GetThread( stack, th, false, false )); + + // If thread was started, then we use priority from the CLR_RT_Thread. + // There are 2 reasons it might be different from priority from C# object: + // 1. The manager C# object was garbage collected and then re-created. + // 2. Sub-thread with different priority may have been created in Library_spot_native_Microsoft_SPOT_ExecutionConstraint::Install___STATIC__VOID__I4__I4 + + if ( th != NULL ) + { + pri = th->GetThreadPriority(); + + // We store it back to managed object to keep values consistent. + pThis[ FIELD___priority ].NumericByRef().s4 = pri; + } + + // Zero priority correspond is equal to managed. ThreadPriority.Lowest. + // The highest value should be 4 ( ThreadPriority.highest ), but we allow higher values. + // Users cannot create threads with values outside the Lowest-Highest range; we exceed that + // range internally, but we can't expose those values to managed code. + if (pri < ThreadPriority::Lowest ) pri = ThreadPriority::Lowest; + else if (pri > ThreadPriority::Highest) pri = ThreadPriority::Highest; + + // Return value back to C# code. + stack.SetResult_I4( pri ); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::set_Priority___VOID__SystemThreadingThreadPriority( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if ( stack.m_customState == 0 ) + { + CLR_RT_Thread* th; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get argument for priority. Check the range - should be between ThreadPriority::Highest and ThreadPriority::Lowest ( 0 - 4 ) + int pri = stack.Arg1().NumericByRef().s4; + if ( pri < ThreadPriority::Lowest || pri > ThreadPriority::Highest ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Get CLR thread. The object exists if thread was started. + NANOCLR_CHECK_HRESULT(GetThread( stack, th, false, true )); + + // Save priority to managed C# object + pThis[ FIELD___priority ].NumericByRef().s4 = pri; + + if ( th ) + { + // Priority of current sub-thread is set the thread priority. + th->SetThreadPriority( pri ); + + stack.m_customState = 1; + + // If we set high priority to another thread, then we need to swtich to another thread. + if ( pri > stack.m_owningThread->GetThreadPriority() ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_RESCHEDULE); + } + } + } + + NANOCLR_NOCLEANUP(); + +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_ManagedThreadId___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int id; + + // Get C# thread object + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Reads priority stored in C# object. + id = pThis[ FIELD___id ].NumericByRef().s4; + + // Return value back to C# code. + stack.SetResult_I4( id ); + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_Threading_Thread::get_IsAlive___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th; + + GetThread( stack, th, false, false ); + + stack.SetResult_Boolean( th != NULL && th->m_status != CLR_RT_Thread::TH_S_Terminated ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Join( stack, TIMEOUT_INFINITE )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64 timeExpire; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpire, stack.Arg1().NumericByRef().s4 )); + + NANOCLR_SET_AND_LEAVE(Join( stack, timeExpire )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64* timeExpireIn; + CLR_INT64 timeExpireOut; + + timeExpireIn = Library_corlib_native_System_TimeSpan::GetValuePtr( stack.Arg1() ); FAULT_ON_NULL(timeExpireIn); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpireOut, *timeExpireIn )); + + NANOCLR_SET_AND_LEAVE(Join( stack, timeExpireOut )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_ThreadState___SystemThreadingThreadState( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + CLR_RT_Thread* th; + int val = 0; + + NANOCLR_CHECK_HRESULT(GetThread( stack, th, false, false )); + + if(th == NULL) + { + val = 8; //Unstarted + } + else + { + switch(th->m_status) + { + case CLR_RT_Thread::TH_S_Ready : val = 0; break; // Running + case CLR_RT_Thread::TH_S_Waiting : val = 32; break; // WaitSleepJoin + case CLR_RT_Thread::TH_S_Terminated: val = 16; break; // Stopped + default : _ASSERTE(false); break; + } + + // Suspended thread. Add ThreadState.Suspended to the return value + if(th->m_flags & CLR_RT_Thread::TH_F_Suspended) + { + val |= 64; // ThreadState.Suspended = 64 + } + // Aborted thread. Add ThreadState.Aborted to the return value + if(th->m_flags & CLR_RT_Thread::TH_F_Aborted) + { + val |= 256; // ThreadState.Aborted = 256 + } + + } + + stack.SetResult_I4( val ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Sleep___STATIC__VOID__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64 timeExpire; + CLR_INT32 timeSleep; + + switch(stack.m_customState) + { + case 0: + + timeSleep = stack.m_arguments[ 0 ].NumericByRef().s4; + if ( timeSleep != 0 ) + { + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpire, stack.m_arguments[ 0 ].NumericByRef().s4 )); + + hr = g_CLR_RT_ExecutionEngine.Sleep( stack.m_owningThread, timeExpire ); + if(hr == CLR_E_THREAD_WAITING) + { + stack.m_customState = 1; + } + } + else + { + // In case of Sleep(0) call the threads should be re-scheduled . + // This function updates execution counter in pThread and makes it last to execute. + // Used to Thread.Sleep(0) imlementation. The thread is still ready, but is last to execute. + g_CLR_RT_ExecutionEngine.UpdateToLowestExecutionCounter( stack.m_owningThread ); + // In order to do it we return CLR_E_RESCHEDULE from this function. + stack.m_customState = 1; + NANOCLR_SET_AND_LEAVE( CLR_E_RESCHEDULE ); + } + + + NANOCLR_LEAVE(); + + case 1: + NANOCLR_SET_AND_LEAVE(S_OK); + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_CurrentThread___STATIC__SystemThreadingThread( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* thread = stack.m_owningThread; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* pRes; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + //If we are a thread spawned by the debugger to perform evaluations, + //return the thread object that correspond to thread that has focus in debugger. + thread = thread->m_realThread; +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Find an existing managed thread, if it exists + //making sure to only return the managed object association with the current appdomain + //to prevent leaking of managed Thread objects across AD boundaries. + NANOCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,src,thread->m_references) + { + CLR_RT_HeapBlock* pManagedThread = src->m_objectPtr; + bool fFound = false; + _ASSERTE(pManagedThread != NULL); + +#if defined(NANOCLR_APPDOMAINS) + { + CLR_RT_ObjectToEvent_Source* appDomainSrc = CLR_RT_ObjectToEvent_Source::ExtractInstance( pManagedThread[ FIELD___appDomain ] ); + + FAULT_ON_NULL_HR(appDomainSrc, CLR_E_FAIL); + + fFound = (appDomainSrc->m_eventPtr == g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()); + } +#else + fFound = true; +#endif + + if(fFound) + { + top.SetObjectReference( pManagedThread ); + + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + NANOCLR_FOREACH_NODE_END(); + + + //Create the managed thread. + //This implies that there is no state in the managed object. This is not exactly true, as the managed thread + //contains the priority as well as the delegate to start. However, that state is really just used as a placeholder for + //the data before the thread is started. Once the thread is started, they are copied over to the unmanaged thread object + //and no longer used. The managed object is then used simply as a wrapper for the unmanaged thread. Therefore, it is safe + //to simply make another managed thread here. + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( top, g_CLR_RT_WellKnownTypes.m_Thread )); + + pRes = top.Dereference(); + + NANOCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( thread, *pRes, pRes[ FIELD___thread ] )); + +#if defined(NANOCLR_APPDOMAINS) + NANOCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(), *pRes, pRes[ FIELD___appDomain ] )); +#endif + + NANOCLR_NOCLEANUP(); +} + +#if (NANOCLR_REFLECTION == TRUE) + +HRESULT Library_corlib_native_System_Threading_Thread::GetDomain___STATIC__SystemAppDomain( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if !defined(NANOCLR_APPDOMAINS) + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); +#else + CLR_RT_AppDomain* appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + + NANOCLR_CHECK_HRESULT(appDomain->GetManagedObject( stack.PushValue() )); +#endif + + NANOCLR_NOCLEANUP(); +} +#endif // NANOCLR_REFLECTION + +//--// + +CLR_RT_ObjectToEvent_Source* Library_corlib_native_System_Threading_Thread::GetThreadReference( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* pThis = stack.This(); + + return CLR_RT_ObjectToEvent_Source::ExtractInstance( pThis[ FIELD___thread ] ); +} + +void Library_corlib_native_System_Threading_Thread::ResetThreadReference( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_ObjectToEvent_Source* src = GetThreadReference( stack ); + if(src) + { + src->Detach(); + } +} + +HRESULT Library_corlib_native_System_Threading_Thread::SetThread( CLR_RT_StackFrame& stack, CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + + ResetThreadReference( stack ); + + NANOCLR_SET_AND_LEAVE(CLR_RT_ObjectToEvent_Source::CreateInstance( th, *pThis, pThis[ FIELD___thread ] )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::GetThread( CLR_RT_StackFrame& stack, CLR_RT_Thread*& th, bool mustBeStarted, bool noSystemThreads ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_ObjectToEvent_Source* src = GetThreadReference( stack ); + + th = (src == NULL) ? NULL : (CLR_RT_Thread*)src->m_eventPtr; + if(th == NULL) + { + if (mustBeStarted) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else if (noSystemThreads && th->m_flags & CLR_RT_Thread::TH_F_System) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th; + bool fRes = true; + + NANOCLR_CHECK_HRESULT(GetThread( stack, th, true, false )); + + //Don't let programs join from system threads like interrupts or finalizers + if ( stack.m_owningThread->m_flags & CLR_RT_Thread::TH_F_System ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + + // + // You cannot join yourself. + // + if(th == stack.m_owningThread) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if(th->m_status != CLR_RT_Thread::TH_S_Terminated) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_WaitForObject::WaitForSignal( stack, timeExpire, stack.ThisRef() )); + + fRes = (stack.m_owningThread->m_waitForObject_Result != CLR_RT_Thread::TH_WAIT_RESULT_TIMEOUT); + } + + stack.SetResult_Boolean( fRes ); + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Timer.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Timer.cpp new file mode 100644 index 00000000..6f5aa716 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_Timer.cpp @@ -0,0 +1,91 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Threading_Timer::Dispose___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + (void)SetValues( stack, CLR_RT_HeapBlock_Timer::c_ACTION_Destroy ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Threading_Timer::_ctor___VOID__SystemThreadingTimerCallback__OBJECT__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(SetValues( stack, CLR_RT_HeapBlock_Timer::c_ACTION_Create | CLR_RT_HeapBlock_Timer::c_INPUT_Int32 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Timer::_ctor___VOID__SystemThreadingTimerCallback__OBJECT__SystemTimeSpan__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(SetValues( stack, CLR_RT_HeapBlock_Timer::c_ACTION_Create | CLR_RT_HeapBlock_Timer::c_INPUT_TimeSpan )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Timer::Change___BOOLEAN__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(CheckDisposed( stack )) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + stack.SetResult_Boolean( true ); + + NANOCLR_SET_AND_LEAVE(SetValues( stack, CLR_RT_HeapBlock_Timer::c_ACTION_Change | CLR_RT_HeapBlock_Timer::c_INPUT_Int32 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Timer::Change___BOOLEAN__SystemTimeSpan__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(CheckDisposed( stack )) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + stack.SetResult_Boolean( true ); + + NANOCLR_SET_AND_LEAVE(SetValues( stack, CLR_RT_HeapBlock_Timer::c_ACTION_Change | CLR_RT_HeapBlock_Timer::c_INPUT_TimeSpan )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +bool Library_corlib_native_System_Threading_Timer::CheckDisposed( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + return CLR_RT_HeapBlock_Timer::CheckDisposed( stack ); +} + + +HRESULT Library_corlib_native_System_Threading_Timer::SetValues( CLR_RT_StackFrame& stack, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Timer::ConfigureObject( stack, flags )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_WaitHandle.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_WaitHandle.cpp new file mode 100644 index 00000000..abf735d6 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Threading_WaitHandle.cpp @@ -0,0 +1,71 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Threading_WaitHandle::WaitOne___BOOLEAN__I4__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(Wait( stack, stack.Arg1(), stack.Arg2(), &stack.ThisRef(), 1, false )); + + stack.SetResult_Boolean( stack.m_owningThread->m_waitForObject_Result != CLR_RT_Thread::TH_WAIT_RESULT_TIMEOUT ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_WaitHandle::WaitMultiple___STATIC__I4__SZARRAY_SystemThreadingWaitHandle__I4__BOOLEAN__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* arr = stack.Arg0().DereferenceArray(); FAULT_ON_NULL(arr); + + NANOCLR_CHECK_HRESULT(Wait( stack, stack.Arg1(), stack.Arg2(), (CLR_RT_HeapBlock*)arr->GetFirstElement(), arr->m_numOfElements, stack.Arg3().NumericByRef().s1 == 1 )); + + stack.SetResult_I4( stack.m_owningThread->m_waitForObject_Result ); + + NANOCLR_NOCLEANUP(); +} + +//--// + +void Library_corlib_native_System_Threading_WaitHandle::Set( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* pThis = stack.This(); + + CLR_RT_HeapBlock_WaitForObject::SignalObject( *pThis ); + + stack.SetResult_Boolean( true ); +} + +void Library_corlib_native_System_Threading_WaitHandle::Reset( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* pThis = stack.This(); + + pThis->ResetFlags( CLR_RT_HeapBlock::HB_Signaled ); + + stack.SetResult_Boolean( true ); +} + +HRESULT Library_corlib_native_System_Threading_WaitHandle::Wait( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& blkTimeout, CLR_RT_HeapBlock& blkExitContext, CLR_RT_HeapBlock* objects, int cObjects, bool fWaitAll ) +{ + (void)blkExitContext; + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64 timeExpire; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpire, blkTimeout.NumericByRef().s4 )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_WaitForObject::WaitForSignal( stack, timeExpire, objects, cObjects, fWaitAll )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_TimeSpan.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_TimeSpan.cpp new file mode 100644 index 00000000..71c1a076 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_TimeSpan.cpp @@ -0,0 +1,193 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_TimeSpan::Equals___BOOLEAN__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(CompareTo___I4__OBJECT( stack )); + + { + CLR_RT_HeapBlock& res = stack.TopValue(); + + res.SetBoolean( res.NumericByRef().s4 == 0 ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::ToString___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + char rgBuffer[ 128 ]; + char* szBuffer = rgBuffer; + size_t iBuffer = ARRAYSIZE(rgBuffer); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + HAL_Time_TimeSpanToStringEx( *val, szBuffer, iBuffer ); + + NANOCLR_SET_AND_LEAVE(stack.SetResult_String( rgBuffer )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + ConstructTimeSpan( val, 0, pArgs[ 0 ].NumericByRef().s4, pArgs[ 1 ].NumericByRef().s4, pArgs[ 2 ].NumericByRef().s4, 0 ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + ConstructTimeSpan( val, pArgs[ 0 ].NumericByRef().s4, pArgs[ 1 ].NumericByRef().s4, pArgs[ 2 ].NumericByRef().s4, pArgs[ 3 ].NumericByRef().s4, 0 ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + ConstructTimeSpan( val, pArgs[ 0 ].NumericByRef().s4, pArgs[ 1 ].NumericByRef().s4, pArgs[ 2 ].NumericByRef().s4, pArgs[ 3 ].NumericByRef().s4, pArgs[ 4 ].NumericByRef().s4 ); + + NANOCLR_NOCLEANUP(); +} + +void Library_corlib_native_System_TimeSpan::ConstructTimeSpan( CLR_INT64* val, CLR_INT32 days, CLR_INT32 hours, CLR_INT32 minutes, CLR_INT32 seconds, CLR_INT32 msec ) + +{ + *val = ((CLR_INT64)days) * TIME_CONVERSION__ONEDAY + + hours * TIME_CONVERSION__ONEHOUR + + minutes * TIME_CONVERSION__ONEMINUTE + + seconds * TIME_CONVERSION__ONESECOND; + + *val *= 1000; + *val += msec; + *val *= TIME_CONVERSION__TICKUNITS; +} + +HRESULT Library_corlib_native_System_TimeSpan::CompareTo___I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pRight = stack.Arg1().Dereference(); + + if(pRight) + { + NANOCLR_SET_AND_LEAVE(Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan( stack )); + } + + stack.SetResult_I4( 1 ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64* pLeft; + CLR_INT64* pRight; + CLR_RT_HeapBlock resLeft; + CLR_RT_HeapBlock resRight; + + pLeft = Library_corlib_native_System_TimeSpan::GetValuePtr( stack ); FAULT_ON_NULL(pLeft); + pRight = Library_corlib_native_System_TimeSpan::GetValuePtr( stack.Arg1() ); FAULT_ON_NULL(pRight); + + resLeft .SetInteger( *pLeft ); + resRight.SetInteger( *pRight ); + + stack.SetResult_I4( CLR_RT_HeapBlock::Compare_Signed_Values( resLeft, resRight ) ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::Equals___STATIC__BOOLEAN__SystemTimeSpan__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan( stack )); + + stack.ConvertResultToBoolean(); + + NANOCLR_NOCLEANUP(); +} + +//--// + +CLR_INT64* Library_corlib_native_System_TimeSpan::NewObject( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& ref = stack.PushValue(); + + ref.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID( DATATYPE_TIMESPAN, 0, 1 ) ); + ref.ClearData( ); + + return (CLR_INT64*)&ref.NumericByRef().s8; +} + +CLR_INT64* Library_corlib_native_System_TimeSpan::GetValuePtr( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return GetValuePtr( stack.Arg0() ); +} + +CLR_INT64* Library_corlib_native_System_TimeSpan::GetValuePtr( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = &ref; + CLR_DataType dt = obj->DataType(); + + if(dt == DATATYPE_OBJECT || dt == DATATYPE_BYREF) + { + obj = obj->Dereference(); if(!obj) return NULL; + + dt = obj->DataType(); + } + + if(dt == DATATYPE_TIMESPAN) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_I8) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_VALUETYPE && obj->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_TimeSpan.m_data) + { + return (CLR_INT64*)&obj[ FIELD___ticks ].NumericByRef().s8; + } + + return NULL; +} + diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Type.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Type.cpp new file mode 100644 index 00000000..0e47acd7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_Type.cpp @@ -0,0 +1,660 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_Type::get_DeclaringType___SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor( *hbType, td )); + + if(td.m_target->enclosingType != CLR_EmptyIndex) + { + CLR_RT_HeapBlock* hbObj; + td.Set( td.Assembly(), td.m_target->enclosingType ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( td ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetMethod___SystemReflectionMethodInfo__STRING__SystemReflectionBindingFlags( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* szText = stack.Arg1().RecoverString(); FAULT_ON_NULL(szText); + + NANOCLR_SET_AND_LEAVE(GetMethods( stack, szText, stack.Arg2().NumericByRef().s4, NULL, 0, false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::IsInstanceOfType___BOOLEAN__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDescriptor descTarget; + CLR_RT_TypeDescriptor desc; + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + if(hbType->DataType() != DATATYPE_REFLECTION) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_CHECK_HRESULT(descTarget.InitializeFromReflection( hbType->ReflectionDataConst() )); + NANOCLR_CHECK_HRESULT(desc .InitializeFromObject ( stack.Arg1() )); + + stack.SetResult_Boolean( CLR_RT_ExecutionEngine::IsInstanceOf( desc, descTarget ) ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::InvokeMember___OBJECT__STRING__SystemReflectionBindingFlags__SystemReflectionBinder__OBJECT__SZARRAY_OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetConstructor___SystemReflectionConstructorInfo__SZARRAY_SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = stack.Arg1().DereferenceArray(); FAULT_ON_NULL(array); + CLR_RT_HeapBlock* pParams; + int iParams; + + pParams = (CLR_RT_HeapBlock*)array->GetFirstElement(); + iParams = array->m_numOfElements; + + NANOCLR_SET_AND_LEAVE(GetMethods( stack, NULL, c_BindingFlags_CreateInstance | c_BindingFlags_Instance | c_BindingFlags_Public | c_BindingFlags_NonPublic, pParams, iParams, false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetMethod___SystemReflectionMethodInfo__STRING__SZARRAY_SystemType( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = stack.Arg2().DereferenceArray(); + CLR_RT_HeapBlock* pParams; + int iParams; + + if(array) + { + pParams = (CLR_RT_HeapBlock*)array->GetFirstElement(); + iParams = array->m_numOfElements; + } + else + { + pParams = NULL; + iParams = 0; + } + + const char* szText = stack.Arg1().RecoverString(); FAULT_ON_NULL(szText); + + NANOCLR_SET_AND_LEAVE(GetMethods( stack, szText, c_BindingFlags_DefaultLookup, pParams, iParams, false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetMethod___SystemReflectionMethodInfo__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* szText = stack.Arg1().RecoverString(); FAULT_ON_NULL(szText); + + NANOCLR_SET_AND_LEAVE(GetMethods( stack, szText, c_BindingFlags_DefaultLookup, NULL, 0, false )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsNotPublic___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Scope_Mask, CLR_RECORD_TYPEDEF::TD_Scope_NotPublic )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsPublic___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Scope_Mask, CLR_RECORD_TYPEDEF::TD_Scope_Public )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsClass___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Semantics_Mask, CLR_RECORD_TYPEDEF::TD_Semantics_Class )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsInterface___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Semantics_Mask, CLR_RECORD_TYPEDEF::TD_Semantics_Interface )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsValueType___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Semantics_Mask, CLR_RECORD_TYPEDEF::TD_Semantics_ValueType )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsAbstract___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Abstract, CLR_RECORD_TYPEDEF::TD_Abstract )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsEnum___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Semantics_Mask, CLR_RECORD_TYPEDEF::TD_Semantics_Enum )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsSerializable___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Serializable, CLR_RECORD_TYPEDEF::TD_Serializable )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::get_IsArray___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor( *hbType, td )); + + stack.SetResult_Boolean(td.m_data == g_CLR_RT_WellKnownTypes.m_Array.m_data); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetTypeInternal___STATIC__SystemType__STRING__STRING__BOOLEAN__SZARRAY_I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const char* szClass; + const char* szAssembly; + CLR_RT_HeapBlock_Array* verArray; + CLR_RT_Assembly* assm; + CLR_RT_TypeDef_Index td; + CLR_INT32* ver; + bool fVersion; + + CLR_RECORD_VERSION version; + + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* hbObj; + szClass = stack.Arg0().RecoverString(); FAULT_ON_NULL(szClass); + szAssembly = stack.Arg1().RecoverString(); + + fVersion = stack.Arg2().NumericByRef().u1 != 0; + + if(fVersion) + { + verArray = stack.Arg3().DereferenceArray(); FAULT_ON_NULL(verArray); + ver = (CLR_INT32*)verArray->GetFirstElement(); + + version.iMajorVersion = ver[0]; + version.iMinorVersion = ver[1]; + version.iBuildNumber = ver[2]; + version.iRevisionNumber = ver[3]; + } + else + { + memset( &version, 0, sizeof(CLR_RECORD_VERSION)); + } + + if(szAssembly) + { + assm = g_CLR_RT_TypeSystem.FindAssembly( szAssembly, fVersion ? &version : NULL, fVersion ); + } + else + { + assm = NULL; + } + + if(g_CLR_RT_TypeSystem.FindTypeDef( szClass, assm, td )) + { +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_TypeDef_Instance inst; + + inst.InitializeFromIndex( td ); + if(!g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( inst.m_assm )) NANOCLR_SET_AND_LEAVE(S_OK); +#endif + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( td ); + } + else + { + CLR_RT_ReflectionDef_Index reflex; + if(g_CLR_RT_TypeSystem.FindTypeDef( szClass, assm, reflex )) + { +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_TypeDef_Instance inst; + + inst.InitializeFromIndex( reflex.m_data.m_type ); + if(!g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( inst.m_assm )) NANOCLR_SET_AND_LEAVE(S_OK); +#endif + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->SetReflection( reflex ); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetTypeFromHandle___STATIC__SystemType__SystemRuntimeTypeHandle( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& pThis = stack.Arg0(); + CLR_RT_HeapBlock& top = stack.PushValue(); + CLR_RT_HeapBlock* hbObj; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_TypeStatic)); + hbObj = top.Dereference(); + hbObj->Assign(pThis); // RuntimeTypeHandle and Type have the same representation. + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_Type::CheckFlags( CLR_RT_StackFrame& stack, CLR_UINT32 mask, CLR_UINT32 flag ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + bool fRes; + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor( *hbType, td )); + + if((td.m_target->flags & mask) == flag) + { + fRes = true; + } + // + // Special case, an enum is a valuetype, so let's check for that one. + // + else if(mask == CLR_RECORD_TYPEDEF::TD_Semantics_Mask && flag == CLR_RECORD_TYPEDEF::TD_Semantics_ValueType) + { + NANOCLR_SET_AND_LEAVE(CheckFlags( stack, CLR_RECORD_TYPEDEF::TD_Semantics_Mask, CLR_RECORD_TYPEDEF::TD_Semantics_Enum )); + } + else + { + fRes = false; + } + + stack.SetResult_Boolean( fRes ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetFields( CLR_RT_StackFrame& stack, const char* szText, CLR_UINT32 bindingFlags, bool fAllMatches ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance td; + CLR_RT_TypeDef_Instance tdArg; + int iField; + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + + if(bindingFlags == c_BindingFlags_Default) bindingFlags = c_BindingFlags_DefaultLookup; + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor( *hbType, tdArg )); + + { + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + for(int pass=0; pass < 2; pass++) + { + td = tdArg; + iField = 0; + + do + { + CLR_RT_Assembly* assm = td.m_assm; + const CLR_RECORD_TYPEDEF* tdR = td.m_target; + const CLR_RECORD_FIELDDEF* fd = td.m_assm->GetFieldDef( tdR->sFields_First ); + int iTot = tdR->iFields_Num + tdR->sFields_Num; + int i; + CLR_RT_FieldDef_Index idx; + + for(i=0; iGetString( fd->name ); + + if(fd->flags & CLR_RECORD_FIELDDEF::FD_NoReflection) + { + continue; + } + + if(fd->flags & CLR_RECORD_FIELDDEF::FD_Static) + { + if((bindingFlags & c_BindingFlags_Static) == 0) continue; + } + else + { + if((bindingFlags & c_BindingFlags_Instance) == 0) continue; + } + + if((fd->flags & CLR_RECORD_FIELDDEF::FD_Scope_Mask) == CLR_RECORD_FIELDDEF::FD_Scope_Public) + { + if((bindingFlags & c_BindingFlags_Public) == 0) continue; + } + else + { + if((bindingFlags & c_BindingFlags_NonPublic) == 0) continue; + } + + // In this block we check if requested name szText is the same as examined field name. + // We check if compare is case insensitive. + if (bindingFlags & c_BindingFlags_IgnoreCase) + { + // If strings are not eqaul - continue + if(szText != NULL && hal_stricmp( fieldName, szText )) continue; + } + else // Case sensitive compare + { + // If strings are not eqaul - continue + if(szText != NULL && strcmp( fieldName, szText )) continue; + } + + idx.Set( td.Assembly(), i + tdR->sFields_First ); + + if(!fAllMatches) + { + CLR_RT_HeapBlock* hbObj; + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_FieldInfo)); + hbObj = top.Dereference(); + hbObj->SetReflection( idx ); + + NANOCLR_SET_AND_LEAVE(S_OK); + } + else if(pass == 1) + { + CLR_RT_HeapBlock* elem = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetElement(iField); + CLR_RT_HeapBlock* hbObj; + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*elem, g_CLR_RT_WellKnownTypes.m_FieldInfo)); + hbObj = elem->Dereference(); + NANOCLR_CHECK_HRESULT(hbObj->SetReflection( idx )); + } + + iField++; + } + + if(bindingFlags & c_BindingFlags_DeclaredOnly) break; + } + while(td.SwitchToParent()); + + if(pass == 0) + { + if(!fAllMatches) NANOCLR_SET_AND_LEAVE(S_OK); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, iField, g_CLR_RT_WellKnownTypes.m_FieldInfo )); + } + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Type::GetMethods( CLR_RT_StackFrame& stack, const char* szText, CLR_UINT32 bindingFlags, CLR_RT_HeapBlock* pParams, int iParams, bool fAllMatches ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance inst; inst.Clear(); + CLR_RT_TypeDef_Instance td; + CLR_RT_TypeDef_Instance tdArg; + int iMethod; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* hbType = stack.Arg0().Dereference(); + bool staticInstanceOnly = false; + + if(bindingFlags == c_BindingFlags_Default) bindingFlags = c_BindingFlags_DefaultLookup; + // in default lookup mode we want the static methods only from the instance not from the base classes + if(bindingFlags == c_BindingFlags_DefaultLookup) staticInstanceOnly = true; + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_RuntimeType::GetTypeDescriptor( *hbType, tdArg )); + + for(int pass = 0; pass < 2; pass++) + { + td = tdArg; + iMethod = 0; + bool isInstance = true; + + do + { + CLR_RT_Assembly* assm = td.m_assm; + const CLR_RECORD_TYPEDEF* tdR = td.m_target; + const CLR_RECORD_METHODDEF* md = assm->GetMethodDef( tdR->methods_First ); + int iTot = tdR->sMethods_Num + tdR->iMethods_Num + tdR->vMethods_Num; + int i; + + if (staticInstanceOnly) + { + if (isInstance) + { + // for the instance we use DefaultLookup + bindingFlags = c_BindingFlags_DefaultLookup; + // goto the else block in the next round + isInstance = false; + } + else + { + // otherwise (for the base classes) we use Instance+Public + bindingFlags = c_BindingFlags_Instance | c_BindingFlags_Public; + } + } + + for(i=0; iflags & CLR_RECORD_METHODDEF::MD_Static) + { + if((bindingFlags & c_BindingFlags_Static) == 0) continue; + } + else + { + if((bindingFlags & c_BindingFlags_Instance) == 0) continue; + } + + if((md->flags & CLR_RECORD_METHODDEF::MD_Scope_Mask) == CLR_RECORD_METHODDEF::MD_Scope_Public) + { + if((bindingFlags & c_BindingFlags_Public) == 0) continue; + } + else + { + if((bindingFlags & c_BindingFlags_NonPublic) == 0) continue; + } + + //--// + + if(md->flags & CLR_RECORD_METHODDEF::MD_Constructor) + { + if((bindingFlags & c_BindingFlags_CreateInstance) == 0) continue; + } + else + { + if((bindingFlags & c_BindingFlags_CreateInstance) != 0) continue; + + if(szText != NULL && !strcmp( assm->GetString( md->name ), szText ) == false) continue; + } + + if(pParams) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_MethodSignature( assm, md ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_Objects ( pParams, iParams, true ); + CLR_RT_SignatureParser::Element res; + + // + // Skip return value. + // + NANOCLR_CHECK_HRESULT(parserLeft.Advance( res )); + + if(CLR_RT_TypeSystem::MatchSignatureDirect( parserLeft, parserRight, true ) == false) continue; + } + + CLR_RT_MethodDef_Index idx; idx.Set( td.Assembly(), i + tdR->methods_First ); + CLR_RT_MethodDef_Instance inst2; inst2.InitializeFromIndex( idx ); + + if(fAllMatches) + { + if(pass==1) + { + CLR_RT_HeapBlock* elem = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetElement(iMethod); + CLR_RT_HeapBlock* hbObj; + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*elem, g_CLR_RT_WellKnownTypes.m_MethodInfo)); + hbObj = elem->Dereference(); + NANOCLR_CHECK_HRESULT(hbObj->SetReflection( idx )); + } + + iMethod++; + } + else + { + CLR_RT_HeapBlock* hbObj; + + if(NANOCLR_INDEX_IS_VALID(inst)) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_MethodSignature( inst .m_assm, inst .m_target ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_MethodSignature( inst2.m_assm, inst2.m_target ); + + CLR_RT_SignatureParser::Element resLeft; + CLR_RT_SignatureParser::Element resRight; + + // + // Skip return value. + // + NANOCLR_CHECK_HRESULT(parserLeft.Advance ( resLeft )); + NANOCLR_CHECK_HRESULT(parserRight.Advance( resRight )); + + if(!pParams) + { + if(CLR_RT_TypeSystem::MatchSignatureDirect( parserLeft, parserRight, false ) == false) + { + //Two methods with different signatures, we cannot distinguish between the two. + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + //If they are identical signatures, the first one wins (subclass takes precendence) + continue; + } + else + { + bool fLeftBetterMatch = false; + bool fRightBetterMatch = false; + + while(parserLeft.Available() > 0) + { + NANOCLR_CHECK_HRESULT(parserLeft.Advance ( resLeft )); + NANOCLR_CHECK_HRESULT(parserRight.Advance( resRight )); + + bool fRightBetterMatchT = CLR_RT_TypeSystem::MatchSignatureElement( resLeft , resRight, true ); + bool fLeftBetterMatchT = CLR_RT_TypeSystem::MatchSignatureElement( resRight, resLeft , true ); + + //If fLeftBetterMatchT && fRightBetterMatchT, one is assignable from the other, they must be the same + // !fLeftBetterMatchT && !fRightBetterMatchT cannot happen, since this signature matches pParams + + if(fLeftBetterMatchT && !fRightBetterMatchT) fLeftBetterMatch = true; + if(!fLeftBetterMatchT && fRightBetterMatchT) fRightBetterMatch = true; + } + + if(fLeftBetterMatch && fRightBetterMatch) + { + //If the params match both Foo(Super, Sub) and Foo(Sub, Super) + //we cannot choose between the two + NANOCLR_SET_AND_LEAVE( CLR_E_INVALID_PARAMETER ); + } + + //If they are identical signatures, the first one wins (subclass takes precendence) + //Only if Right is better do we have a strictly better match + if(!fRightBetterMatch) continue; + + //Found a better match + } + } + + inst.InitializeFromIndex( idx ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_MethodInfo)); + hbObj = top.Dereference(); + hbObj->SetReflection( inst ); + } + } + + if(bindingFlags & (c_BindingFlags_DeclaredOnly | c_BindingFlags_CreateInstance)) break; + } + while(td.SwitchToParent()); + + if(pass == 0) + { + if(!fAllMatches) NANOCLR_SET_AND_LEAVE(S_OK); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, iMethod, g_CLR_RT_WellKnownTypes.m_MethodInfo )); + } + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_ValueType.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_ValueType.cpp new file mode 100644 index 00000000..fe06deaf --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_ValueType.cpp @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_ValueType::Equals___BOOLEAN__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stack.SetResult_Boolean( CLR_RT_HeapBlock::ObjectsEqual( stack.Arg0(), stack.Arg1(), false ) ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_WeakReference.cpp b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_WeakReference.cpp new file mode 100644 index 00000000..edc390bb --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/CorLib/corlib_native_System_WeakReference.cpp @@ -0,0 +1,181 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +void CLR_RT_HeapBlock_WeakReference::InsertInPriorityOrder() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + this->Unlink(); // Remove from the list before looking for a spot, to avoid comparing against ourselves. + + g_CLR_RT_ExecutionEngine.m_weakReferences.LinkAtBack( this ); +} + +void CLR_RT_HeapBlock_WeakReference::Relocate() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_RT_HeapBlock_Node::Relocate(); + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_targetDirect ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_targetSerialized ); +} + +CLR_UINT32 CLR_RT_HeapBlock_WeakReference_Identity::ComputeCRC( const CLR_UINT8* ptr, CLR_UINT32 len ) const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_UINT32 hash; + + hash = SUPPORT_ComputeCRC( ptr , len , g_buildCRC ); + hash = SUPPORT_ComputeCRC( &m_selectorHash, sizeof(m_selectorHash), hash ); + hash = SUPPORT_ComputeCRC( &m_id , sizeof(m_id ), hash ); + + return hash; +} + +void CLR_RT_HeapBlock_WeakReference::RecoverObjects( CLR_RT_DblLinkedList& lstHeap ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,lstHeap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + while(ptr < end) + { + if(ptr->DataType() == DATATYPE_WEAKCLASS) + { + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)ptr; + CLR_RT_HeapBlock* target = weak->m_targetSerialized; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc2,lstHeap) + { + CLR_RT_HeapBlock_Node* ptr2 = hc2->m_payloadStart; + CLR_RT_HeapBlock_Node* end2 = hc2->m_payloadEnd; + + if(ptr2 <= target && target < end2) + { + while(ptr2 < end2) + { + if(ptr2 == target) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr2; + + if(array->m_numOfElements == weak->m_identity.m_length) + { + if(weak->m_identity.m_crc == weak->m_identity.ComputeCRC( array->GetFirstElement(), weak->m_identity.m_length )) + { + weak->m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_Restored; + + weak->InsertInPriorityOrder(); + + weak = NULL; + } + } + + break; + } + + ptr2 += ptr2->DataSize(); + } + + if(ptr2 < end2) break; + } + } + NANOCLR_FOREACH_NODE_END(); + + if(weak) + { + weak->ChangeDataType( DATATYPE_FREEBLOCK ); + } + } + + ptr += ptr->DataSize(); + } + } + NANOCLR_FOREACH_NODE_END(); +} + +HRESULT CLR_RT_HeapBlock_WeakReference::GetTarget( CLR_RT_HeapBlock& targetReference ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + NANOCLR_HEADER(); + + targetReference.SetObjectReference( m_targetDirect ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock_WeakReference::SetTarget( CLR_RT_HeapBlock& targetReference ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + NANOCLR_HEADER(); + + // + // Only classes and value types can be associated with a weak reference! + // + if(targetReference.DataType() != DATATYPE_OBJECT) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + m_targetDirect = targetReference.Dereference(); + + InsertInPriorityOrder(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_WeakReference::get_IsAlive___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_WeakReference* weak; + + weak = (CLR_RT_HeapBlock_WeakReference*)stack.This(); FAULT_ON_NULL(weak); + + stack.SetResult_Boolean( weak->m_targetDirect != NULL ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_WeakReference::get_Target___OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_WeakReference* weak; + + weak = (CLR_RT_HeapBlock_WeakReference*)stack.This(); FAULT_ON_NULL(weak); + + NANOCLR_SET_AND_LEAVE(weak->GetTarget( stack.PushValue() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_WeakReference::set_Target___VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_WeakReference* weak; + + weak = (CLR_RT_HeapBlock_WeakReference*)stack.This(); FAULT_ON_NULL(weak); + + NANOCLR_SET_AND_LEAVE(weak->SetTarget( stack.Arg1() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_WeakReference::_ctor___VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)stack.This(); FAULT_ON_NULL(weak); + + NANOCLR_SET_AND_LEAVE(weak->SetTarget( stack.Arg1() )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_DblLinkedList.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_DblLinkedList.cpp new file mode 100644 index 00000000..c5ab184c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_DblLinkedList.cpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_DblLinkedList::DblLinkedList_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + m_first = Tail(); + m_null = NULL; + m_last = Head(); +} + +void CLR_RT_DblLinkedList::DblLinkedList_PushToCache() +{ + NATIVE_PROFILE_CLR_CORE(); + ValidateList(); + + while(true) + { + CLR_RT_HeapBlock_Node* node = ExtractFirstNode(); if(!node) break; + + g_CLR_RT_EventCache.Append_Node( node ); + } +} + +void CLR_RT_DblLinkedList::DblLinkedList_Release() +{ + NATIVE_PROFILE_CLR_CORE(); + ValidateList(); + + while(true) + { + CLR_RT_HeapBlock_Node* node = ExtractFirstNode(); if(!node) break; + + CLR_RT_Memory::Release( node ); + } +} + +int CLR_RT_DblLinkedList::NumOfNodes() +{ + NATIVE_PROFILE_CLR_CORE(); + ValidateList(); + + int num = 0; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,node,(*this)) + { + num++; + } + NANOCLR_FOREACH_NODE_END(); + + return num; +} + +void CLR_RT_DblLinkedList::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_first ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_last ); +} + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_2_DblLinkedList + +void CLR_RT_DblLinkedList::ValidateList() +{ + NATIVE_PROFILE_CLR_CORE(); + + if(m_null != NULL) NANOCLR_DEBUG_STOP(); + + CLR_RT_HeapBlock_Node* prev = Head(); + CLR_RT_HeapBlock_Node* node = prev->Next(); + + while(node) + { + if(node->Prev() != prev) NANOCLR_DEBUG_STOP(); + + prev = node; + node = prev->Next(); + } +} + +#endif + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock.cpp new file mode 100644 index 00000000..94000db1 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock.cpp @@ -0,0 +1,2003 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapBlock::InitializeToZero() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Memory::ZeroFill( &m_data, this->DataSize() * sizeof(*this) - offsetof(CLR_RT_HeapBlock,m_data) ); +} + +//--//--//--//--//--// + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + +HRESULT CLR_RT_HeapBlock::SetFloatIEEE754( const CLR_UINT32 arg ) +{ + + CLR_INT32 res; + CLR_UINT32 mantissa = ( arg & 0x007FFFFF) | 0x00800000; + int exponent = (int)((arg >> 23) & 0x000000FF) - 127; + + exponent -= (23 - CLR_RT_HeapBlock::HB_FloatShift); + + if(arg == 0) + { + res = 0; + } + else if(exponent <= -31) + { + res = 0; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else if(exponent >= 31) + { + res = 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + if(exponent > 0) + { + CLR_UINT64 tmpRes; + + tmpRes = ((CLR_UINT64)mantissa) << exponent; + + if(0 != (tmpRes >> 31)) + { + res = 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + res = (CLR_UINT32)tmpRes; + } + } + else if(exponent < 0) res = mantissa >> (-exponent); + else res = mantissa; + } + + if(arg & 0x80000000) res = -res; + + SetFloat( res ); + + return S_OK; +} + +HRESULT CLR_RT_HeapBlock::SetDoubleIEEE754( const CLR_UINT64& arg ) +{ + + CLR_INT64 res; + CLR_UINT64 mantissa = ( arg & ULONGLONGCONSTANT(0x000FFFFFFFFFFFFF)) | ULONGLONGCONSTANT(0x0010000000000000); + int exponent = (int)((arg >> 52) & ULONGLONGCONSTANT(0x00000000000007FF)) - 1023; + + CLR_UINT64 mask = ULONGLONGCONSTANT(0xFFFFFFFFFFFFFFFF); + + exponent -= (52 - CLR_RT_HeapBlock::HB_DoubleShift); + + if(arg == 0) + { + res = 0; + } + else if(exponent <= -63) + { + res = 0; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else if(exponent >= 63) + { + res = ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + if(exponent > 0) + { + mask <<= (63 - exponent); + + if(0 != (mask & mantissa)) + { + res = ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + res = mantissa << exponent; + } + } + else if(exponent < 0) res = mantissa >> (-exponent); + else res = mantissa; + } + + if(arg & ULONGLONGCONSTANT(0x8000000000000000)) res = -res; + + SetDouble( res ); + + return S_OK; +} + +#endif + + + +HRESULT CLR_RT_HeapBlock::EnsureObjectReference( CLR_RT_HeapBlock*& obj ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(this->DataType()) + { + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + { + obj = Dereference(); FAULT_ON_NULL(obj); + + #if defined(NANOCLR_APPDOMAINS) + if(obj->DataType() == DATATYPE_TRANSPARENT_PROXY) + { + NANOCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + obj = obj->TransparentProxyDereference(); FAULT_ON_NULL(obj); + } + #endif + switch(obj->DataType()) + { + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + NANOCLR_SET_AND_LEAVE(S_OK); + + default: + // the remaining data types aren't to be handled + break; + } + } + break; + + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + obj = this; + NANOCLR_SET_AND_LEAVE(S_OK); + + default: + // the remaining data types aren't to be handled + break; + } + + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection = reflex; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_Assembly_Index& assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = REFLECTION_ASSEMBLY; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_assm = assm; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_TypeSpec_Index& sig ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDescriptor desc; + + NANOCLR_CHECK_HRESULT(desc.InitializeFromTypeSpec( sig )); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection = desc.m_reflex; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = REFLECTION_TYPE; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_type = cls; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_FieldDef_Index& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = REFLECTION_FIELD; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_field = fd; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance inst; + + if(inst.InitializeFromIndex( md ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = (inst.m_target->flags & CLR_RECORD_METHODDEF::MD_Constructor) ? REFLECTION_CONSTRUCTOR : REFLECTION_METHOD; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_method = md; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::SetObjectCls( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( cls ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + m_data.objectHeader.cls = cls; + m_data.objectHeader.lock = NULL; + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_HeapBlock::InitializeArrayReference( CLR_RT_HeapBlock& ref, int index ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + + if(ref.DataType() != DATATYPE_OBJECT) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + array = ref.DereferenceArray(); FAULT_ON_NULL(array); + + if(array->DataType() != DATATYPE_SZARRAY) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if(index < 0 || index >= (CLR_INT32)array->m_numOfElements) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); + } + + InitializeArrayReferenceDirect( *array, index ); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock::InitializeArrayReferenceDirect( CLR_RT_HeapBlock_Array& array, int index ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_ARRAY_BYREF,0,1); + m_data.arrayReference.array = &array; + m_data.arrayReference.index = index; +} + +void CLR_RT_HeapBlock::FixArrayReferenceForValueTypes() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Array* array = m_data.arrayReference.array; + + // + // ValueTypes are implemented as pointers to objects, + // so getting an array reference to a ValueType has to be treated like assigning a pointer! + // + // DateTime and TimeSpan are optimized as primitive types, + // so getting an array reference to them is like getting a reference to them. + // + switch(array->m_typeOfElement) + { + case DATATYPE_VALUETYPE: + this->SetReference( *(CLR_RT_HeapBlock*)array->GetElement( m_data.arrayReference.index ) ); + break; + + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_BYREF,0,1); + m_data.objectReference.ptr = (CLR_RT_HeapBlock*)array->GetElement( m_data.arrayReference.index ); + break; + } +} + +HRESULT CLR_RT_HeapBlock::LoadFromReference( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock* obj; + CLR_DataType dt = ref.DataType(); + + if(dt == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock_Array* array = ref.m_data.arrayReference.array; FAULT_ON_NULL(array); + CLR_UINT8* src = array->GetElement( ref.m_data.arrayReference.index ); + CLR_UINT32 size = array->m_sizeOfElement; + + if(!array->m_fReference) + { + CLR_UINT32 second = 0; + CLR_UINT32 first; + + SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(array->m_typeOfElement,0,1) ); + + if (size == 4) { first = ((CLR_UINT32*)src)[ 0 ]; } + else if(size == 8) { first = ((CLR_UINT32*)src)[ 0 ]; second = ((CLR_UINT32*)src)[ 1 ]; } + else if(size == 1) { first = ((CLR_UINT8 *)src)[ 0 ]; } + else { first = ((CLR_UINT16*)src)[ 0 ]; } + + ((CLR_UINT32*)&NumericByRef())[ 0 ] = first; + ((CLR_UINT32*)&NumericByRef())[ 1 ] = second; + + NANOCLR_SET_AND_LEAVE(S_OK); + } + + // + // It's a pointer to a full CLR_RT_HeapBlock. + // + obj = (CLR_RT_HeapBlock*)src; + } + else if(dt == DATATYPE_BYREF) + { + obj = ref.Dereference(); FAULT_ON_NULL(obj); + + if(obj->DataType() == DATATYPE_VALUETYPE) + { + tmp.SetObjectReference( obj ); + + obj = &tmp; + } + } + else if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Direct) + { + obj = &ref; + + if(dt == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* objT = ref.Dereference(); + + if(objT && objT->IsBoxed()) + { + CLR_RT_TypeDef_Instance inst; + if (objT->DataType() != DATATYPE_VALUETYPE) { NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } + + if(!inst.InitializeFromIndex( objT->ObjectCls() )) { NANOCLR_SET_AND_LEAVE(CLR_E_TYPE_UNAVAILABLE); } + + if(inst.m_target->dataType != DATATYPE_VALUETYPE) // It's a boxed primitive/enum type. + { + obj = &objT[ 1 ]; + } + } + } + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if(obj->IsAValueType()) + { + NANOCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.CloneObject( *this, *obj )); + } + + this->Assign( *obj ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::StoreToReference( CLR_RT_HeapBlock& ref, int size ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* obj; + CLR_DataType dt = ref.DataType(); + + if(dt == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock_Array* array = ref.m_data.arrayReference.array; FAULT_ON_NULL(array); + CLR_UINT8* dst = array->GetElement( ref.m_data.arrayReference.index ); + + if(!array->m_fReference) + { + CLR_INT32 sizeArray = array->m_sizeOfElement; + + // + // Cannot copy NULL reference to a primitive type array. + // + obj = FixBoxingReference(); FAULT_ON_NULL(obj); + + if(size == -1) + { + //size == -1 tells StoreToReference to allow the value 'this' to have more precision than the dest + //array. This fixes the following bug. + // : conv.u1 + // : stobj [mscorlib]System.Byte + // The conv.u1 will convert the top of the eval stack to a u1. But since the eval stack is required + // to contain at least 4 byte values, this heap block will be promoted to an I4. + // stobj ignores the type token (System.Byte) and calls Reassign, which calls StoreToReference. + + if(c_CLR_RT_DataTypeLookup[ this->DataType() ].m_sizeInBytes < sizeArray) + { + //Not enough precision here. + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + +#if defined(_DEBUG) + { + CLR_DataType dtElem = (CLR_DataType)array->m_typeOfElement; + CLR_RT_HeapBlock blk; blk.Assign( *this ); + + NANOCLR_CHECK_HRESULT(blk.Convert( dtElem, false, (c_CLR_RT_DataTypeLookup[ dtElem ].m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0)); + + switch(sizeArray) + { + case 1: _ASSERTE(blk.NumericByRefConst().u1 == this->NumericByRefConst().u1); break; + case 2: _ASSERTE(blk.NumericByRefConst().u2 == this->NumericByRefConst().u2); break; + case 4: _ASSERTE(blk.NumericByRefConst().u4 == this->NumericByRefConst().u4); break; + case 8: _ASSERTE(blk.NumericByRefConst().u8 == this->NumericByRefConst().u8); break; + } + } +#endif + } + else if(size == 0) + { + if(obj->DataType() != array->m_typeOfElement) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else + { + if(size != sizeArray) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + CLR_UINT32 first = ((CLR_UINT32*)&obj->NumericByRef())[ 0 ]; + CLR_UINT32 second = ((CLR_UINT32*)&obj->NumericByRef())[ 1 ]; + + if (sizeArray == 4) { ((CLR_UINT32*)dst)[ 0 ] = (CLR_UINT32)first; } + else if(sizeArray == 8) { ((CLR_UINT32*)dst)[ 0 ] = (CLR_UINT32)first; ((CLR_UINT32*)dst)[ 1 ] = (CLR_UINT32)second; } + else if(sizeArray == 1) { ((CLR_UINT8 *)dst)[ 0 ] = (CLR_UINT8 )first; } + else { ((CLR_UINT16*)dst)[ 0 ] = (CLR_UINT16)first; } + + NANOCLR_SET_AND_LEAVE(S_OK); + } + else + { + // + // If the source is not null, make sure the types are compatible. + // + if(this->DataType() == DATATYPE_OBJECT && this->Dereference()) + { + CLR_RT_TypeDescriptor descSrc; + CLR_RT_TypeDescriptor descDst; + CLR_RT_TypeDescriptor descDstSub; + + NANOCLR_CHECK_HRESULT(descSrc.InitializeFromObject( *this )); + NANOCLR_CHECK_HRESULT(descDst.InitializeFromObject( *array )); descDst.GetElementType( descDstSub ); + + if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDstSub ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + obj = (CLR_RT_HeapBlock*)dst; + + NANOCLR_SET_AND_LEAVE(obj->Reassign( *this )); + } + } + else if(dt == DATATYPE_BYREF) + { + obj = ref.Dereference(); FAULT_ON_NULL(obj); + + if(obj->DataType() == DATATYPE_VALUETYPE) + { + NANOCLR_SET_AND_LEAVE(ref.Reassign( *this )); + } + } + else if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Direct) + { + obj = &ref; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + obj->Assign( *this ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::Reassign( const CLR_RT_HeapBlock& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* obj; + CLR_RT_HeapBlock ref; + + if(this->DataType() == DATATYPE_BYREF) + { + obj = this->Dereference(); FAULT_ON_NULL(obj); + + // + // Real value types can be passed as references. + // + if(obj->DataType() == DATATYPE_VALUETYPE) + { + ref.SetObjectReference( obj ); + + obj = &ref; + } + + NANOCLR_SET_AND_LEAVE(obj->Reassign( value )); + } + else if(value.DataType() == DATATYPE_BYREF) + { + obj = value.Dereference(); FAULT_ON_NULL(obj); + + // + // Real value types can be passed as references. + // + if(obj->DataType() == DATATYPE_VALUETYPE) + { + ref.SetObjectReference( obj ); + + obj = &ref; + } + + NANOCLR_SET_AND_LEAVE(this->Reassign( *obj )); + } + else if(this->DataType() == DATATYPE_ARRAY_BYREF) + { + NANOCLR_CHECK_HRESULT(ref.LoadFromReference( *this )); + NANOCLR_CHECK_HRESULT(ref.Reassign ( value )); + NANOCLR_SET_AND_LEAVE(ref.StoreToReference ( *this, -1 )); + } + else if(value.DataType() == DATATYPE_ARRAY_BYREF) + { + _ASSERTE( false ); //not tested + + CLR_RT_HeapBlock valueT; valueT.Assign( value ); + + NANOCLR_CHECK_HRESULT(ref.LoadFromReference( valueT )); + NANOCLR_SET_AND_LEAVE(this->Reassign ( ref )); + } + else + { + bool fDestination = this->IsAValueType(); + bool fSource = value.IsAValueType(); + + if(fSource != fDestination) + { + // For value type objects we don't care if the source item is boxed because + // CopyValueType will take care of the boxing/unboxing + if(fDestination != value.IsAReferenceOfThisType(DATATYPE_VALUETYPE)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + if(fDestination) + { + NANOCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.CopyValueType( this->Dereference(), value.Dereference() )); + } + + this->Assign( value ); + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock::AssignAndPinReferencedObject( const CLR_RT_HeapBlock& value ) +{ + // This is very special case that we have local variable with pinned attribute in metadata. + // This code is called only if "fixed" keyword is present in the managed code. Executed on assignment to "fixed" pointer. + // First check if there is object referenced by the local var. We unpin it, since the reference is replaced. + if ((m_data.objectReference.ptr != NULL && m_id.type.dataType == DATATYPE_ARRAY_BYREF) || m_id.type.dataType == DATATYPE_BYREF) + { + // Unpin the object that has been pointed by local variable. + m_data.objectReference.ptr->Unpin(); + } + + // Move the data. + m_data = value.m_data; + + // Leave the same logic as in AssignAndPreserveType + if(DataType() > DATATYPE_LAST_PRIMITIVE_TO_PRESERVE) + { + m_id.type.dataType = value.m_id.type.dataType; + m_id.type.size = value.m_id.type.size; + // We take new flags, but preserve "pinned" attribute + m_id.type.flags = m_id.type.flags | HB_Pinned; + } + + // Pin the object referenced by local variable. + if ((m_data.objectReference.ptr != NULL && m_id.type.dataType == DATATYPE_ARRAY_BYREF) || m_id.type.dataType == DATATYPE_BYREF) + { + m_data.objectReference.ptr->Pin(); + } +} + + +HRESULT CLR_RT_HeapBlock::PerformBoxingIfNeeded() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + + // we need to box the optimized value types... + bool fBox = (c_CLR_RT_DataTypeLookup[ this->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) != 0; + + // ... but also the value types under object types + if(!fBox && this->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* src = this->Dereference(); + + if(src && src->DataType() == DATATYPE_VALUETYPE && !src->IsBoxed()) + { + fBox = true; + } + } + + if(fBox) + { + CLR_RT_TypeDescriptor desc; + + NANOCLR_CHECK_HRESULT(desc.InitializeFromObject( *this )); + + NANOCLR_CHECK_HRESULT(PerformBoxing( desc.m_handlerCls )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::PerformBoxing( const CLR_RT_TypeDef_Instance& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock* obj = this; + CLR_DataType dt = obj->DataType(); + + // + // System.DateTime and System.TimeSpan are real value types, so sometimes they are passed by reference. + // + if(dt == DATATYPE_BYREF) + { + obj = obj->Dereference(); FAULT_ON_NULL(obj); + dt = obj->DataType(); + + // + // Real value types can be passed as references. + // + if(dt == DATATYPE_VALUETYPE) + { + tmp.SetObjectReference( obj ); obj = &tmp; + + dt = DATATYPE_OBJECT; + } + } + + { + CLR_DataType dataType = (CLR_DataType)cls.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dataType ]; + + if(dtl.m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + CLR_RT_HeapBlock* ptr = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForClassOrValueTypes( DATATYPE_VALUETYPE, HB_Boxed, cls, 2 ); FAULT_ON_NULL(ptr); + + switch(dataType) + { + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + dataType = DATATYPE_I8; + break; + + default: + // the remaining data types aren't to be handled + break; + } + + ptr[ 1 ].SetDataId ( CLR_RT_HEAPBLOCK_RAW_ID(dataType,0,1) ); + ptr[ 1 ].AssignData( *this ); + + this->SetObjectReference( ptr ); + } + else if(dt == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = this->Dereference(); + + if(ptr->IsBoxed() || ptr->DataType() != DATATYPE_VALUETYPE) + { + NANOCLR_SET_AND_LEAVE(S_FALSE); // Don't box twice... + } + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *this, *ptr )); + + this->Dereference()->Box(); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + NANOCLR_NOCLEANUP(); +} + +/******************************************************************************************* +* Thefunction CLR_RT_HeapBlock::PerformUnboxing is used during processing of unbox.any IL instruction. +* Example +* unbox.any [mscorlib]System.Int32 +* unbox.any takes the value at the top of evaluation stack and performs unboxing into the type +* specified after the instruction. In this case the type is [mscorlib]System.Int32. +* Function parameters: +* 1. this - Heap block at the top of evaluation stack. +* 2. cls - Runtime Type Definition of the type specified after instruction. +* The functoin takes the object pointed by top of ev. stack. Then it does 3 operatioins: +* 1. Dereferences the object +* 2. Validates the type of data kept by object corresponds to type in cls. +* 3. Moves de-referenced date to top of evaluation stack. +*******************************************************************************************/ + +HRESULT CLR_RT_HeapBlock::PerformUnboxing( const CLR_RT_TypeDef_Instance& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* src; + + if(this->DataType() != DATATYPE_OBJECT) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // Finds the object that keeps the boxed type. + src = this->Dereference(); FAULT_ON_NULL(src); + + // Validates that src keeps something boxed and the boxed value is VALUE type. + if(src->IsBoxed() == false || src->DataType() != DATATYPE_VALUETYPE) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // Validates the type of data kept by object corresponds to type in cls. + // If typedef indexes are the same, then skip and go to assigment of objects. + if(src->ObjectCls().m_data != cls.m_data) + { + // The typedef indexes are different, but src and cls may have identical basic data type. + // Need to check it. If identical - the unboxing is allowed. + // This "if" compares underlying type in object and cls. Should be equal in order to continue. + if ( !( src->DataSize() > 1 && ( src[ 1 ].DataType() == cls.m_target->dataType ) ) ) + { + // No luck. The types in src object and specified by cls are different. Need to throw exceptioin. + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + } + } + + if(cls.m_target->dataType == DATATYPE_VALUETYPE) + { + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *this, *this )); + + this->Dereference()->Unbox(); + } + else // It's a boxed primitive/enum type. + { + this->Assign( src[ 1 ] ); + + this->ChangeDataType( cls.m_target->dataType ); + } + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock* CLR_RT_HeapBlock::FixBoxingReference() +{ + NATIVE_PROFILE_CLR_CORE(); + // + // Not boxed, nothing to do. + // + if(this->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* src = this->Dereference(); if(!src) return src; + + if(src->DataType() == DATATYPE_VALUETYPE && src->IsBoxed()) + { + CLR_RT_TypeDef_Instance inst; + + if(!inst.InitializeFromIndex( src->ObjectCls() )) return NULL; + + if(inst.m_target->dataType != DATATYPE_VALUETYPE) // It's a boxed primitive/enum type. + { + return &src[ 1 ]; + } + } + } + + return this; +} + +//--// + +bool CLR_RT_HeapBlock::IsZero() const +{ + NATIVE_PROFILE_CLR_CORE(); + switch(DataType()) + { + case DATATYPE_OBJECT: return (m_data.objectReference.ptr == NULL); + + case DATATYPE_I8 : + case DATATYPE_U8 : return (m_data.numeric.u8 == 0); + + + case DATATYPE_R4 : return (m_data.numeric.r4 == 0); + case DATATYPE_R8 : return (m_data.numeric.r8 == 0); + + + default : return (m_data.numeric.u4 == 0); + } +} + +//--// + +void CLR_RT_HeapBlock::Promote() +{ + NATIVE_PROFILE_CLR_CORE(); + + switch(DataType()) + { + case DATATYPE_I1 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.s4 = (CLR_INT32 )m_data.numeric.s1; break; + + case DATATYPE_I2 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.s4 = (CLR_INT32 )m_data.numeric.s2; break; + + case DATATYPE_BOOLEAN: + case DATATYPE_U1 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.u4 = (CLR_UINT32)m_data.numeric.u1; break; + + case DATATYPE_CHAR : + case DATATYPE_U2 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.u4 = (CLR_UINT32)m_data.numeric.u2; break; + + default: + // this data type is not to be promoted + break; + } +} + +//--// + +CLR_UINT32 CLR_RT_HeapBlock::GetHashCode( CLR_RT_HeapBlock* ptr, bool fRecurse, CLR_UINT32 crc = 0 ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(!ptr) return 0; + + switch(ptr->DataType()) + { + case DATATYPE_OBJECT: + crc = GetHashCode( ptr->Dereference(), fRecurse, crc ); + break; + + case DATATYPE_STRING: + { + const char* szText = ptr->StringText(); + + crc = SUPPORT_ComputeCRC( szText, (int)hal_strlen_s( szText ), crc ); + } + break; + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + if(fRecurse) + { + CLR_RT_TypeDef_Instance cls; cls.InitializeFromIndex( ptr->ObjectCls() ); + int totFields = cls.CrossReference().m_totalFields; + + if (totFields > 0) + { + while(totFields-- > 0) + { + crc = GetHashCode( ++ptr, false, crc ); + } + } + else + { + crc = SUPPORT_ComputeCRC( &ptr, sizeof(ptr), crc ); + } + } + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + const CLR_RT_MethodDef_Index& ftn = dlg->DelegateFtn(); + + crc = GetHashCode( &dlg->m_object, false, crc ); + + crc = SUPPORT_ComputeCRC( &ftn, sizeof(ftn), crc ); + } + break; + + case DATATYPE_OBJECT_TO_EVENT: + { + CLR_RT_ObjectToEvent_Source* evtSrc = (CLR_RT_ObjectToEvent_Source*)ptr; + + crc = GetHashCode(evtSrc->m_eventPtr, false, crc); + crc = GetHashCode(evtSrc->m_objectPtr, false, crc); + } + break; + + default: + crc = SUPPORT_ComputeCRC( &ptr->DataByRefConst(), ptr->GetAtomicDataUsedBytes(), crc ); + break; + } + + return crc; +} + +CLR_UINT32 CLR_RT_HeapBlock::GetAtomicDataUsedBytes() const + +{ + switch( DataType() ) + { + case DATATYPE_BOOLEAN : // Fall through, hashDataSize = 1 + case DATATYPE_U1 : // Fall through, hashDataSize = 1 + case DATATYPE_CHAR : return 1; + + case DATATYPE_I2 : // Fall through, hashDataSize = 2 + case DATATYPE_U2 : return 2; break; + + case DATATYPE_I4 : + case DATATYPE_U4 : + case DATATYPE_R4 : return 4; break; + + case DATATYPE_I8 : // Fall through, hashDataSize = 8 + case DATATYPE_U8 : // Fall through, hashDataSize = 8 + case DATATYPE_R8 : // Fall through, hashDataSize = 8 + case DATATYPE_DATETIME: // Fall through, hashDataSize = 8 + case DATATYPE_TIMESPAN: return 8; break; + + // Default full size of CLR_RT_HeapBlock_AtomicData + default : return sizeof(CLR_RT_HeapBlock_AtomicData); + } + // The same as default. This is never reached, but I put it to avoid potential compiler warning. + return sizeof(CLR_RT_HeapBlock_AtomicData); +} + +bool CLR_RT_HeapBlock::ObjectsEqual( const CLR_RT_HeapBlock& pArgLeft, const CLR_RT_HeapBlock& pArgRight, bool fSameReference ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(&pArgLeft == &pArgRight) return true; + + if(pArgLeft.DataType() == pArgRight.DataType()) + { + switch(pArgLeft.DataType()) + { + case DATATYPE_VALUETYPE: + if(pArgLeft.ObjectCls().m_data == pArgRight.ObjectCls().m_data) + { + const CLR_RT_HeapBlock* objLeft = &pArgLeft ; + const CLR_RT_HeapBlock* objRight = &pArgRight; + CLR_UINT32 num = pArgLeft.DataSize(); + + while(--num) + { + if(ObjectsEqual( *++objLeft, *++objRight, false ) == false) return false; + } + + return true; + } + break; + +#if defined(NANOCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: +#endif + case DATATYPE_OBJECT: + { + CLR_RT_HeapBlock* objLeft = pArgLeft .Dereference(); + CLR_RT_HeapBlock* objRight = pArgRight.Dereference(); + if(objLeft == objRight) return true; + + if(objLeft && objRight) + { + if(!fSameReference || (objLeft->DataType() == DATATYPE_REFLECTION)) return ObjectsEqual( *objLeft, *objRight, false ); + } + } + break; + + case DATATYPE_SZARRAY: + if(fSameReference == false) + { + _ASSERTE(false); //can this code path ever be executed? + + CLR_RT_HeapBlock_Array* objLeft = (CLR_RT_HeapBlock_Array*)&pArgLeft; + CLR_RT_HeapBlock_Array* objRight = (CLR_RT_HeapBlock_Array*)&pArgRight; + + if(objLeft->m_numOfElements == objRight->m_numOfElements && + objLeft->m_sizeOfElement == objRight->m_sizeOfElement && + objLeft->m_typeOfElement == objRight->m_typeOfElement ) + { + if(!objLeft->m_fReference) + { + if(memcmp( objLeft->GetFirstElement(), objRight->GetFirstElement(), objLeft->m_numOfElements * objLeft->m_sizeOfElement ) == 0) + { + return true; + } + } + } + } + break; + case DATATYPE_REFLECTION: + if(pArgLeft.SameHeader( pArgRight )) return true; + break; + default: + if(fSameReference == false) + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ pArgLeft.DataType() ]; + + if((dtl.m_flags & CLR_RT_DataTypeLookup::c_Reference) == 0) + { + CLR_UINT32 size = (dtl.m_sizeInBits + 7) / 8; + + if(memcmp( &pArgLeft.DataByRefConst(), &pArgRight.DataByRefConst(), size ) == 0) + { + return true; + } + } + } + break; + } + } + + return false; +} + +//--// + +static const CLR_RT_HeapBlock* FixReflectionForType( const CLR_RT_HeapBlock& src, CLR_RT_HeapBlock& tmp ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RT_ReflectionDef_Index& rd = src.ReflectionDataConst(); + + if(rd.m_kind == REFLECTION_TYPE) + { + CLR_RT_TypeDef_Instance inst; + CLR_UINT32 levels; + + if(inst.InitializeFromReflection( rd, &levels ) && levels == 0) + { + tmp.Assign( src ); + + CLR_RT_ReflectionDef_Index& rd2 = tmp.ReflectionData(); + + rd2.InitializeFromHash( inst.CrossReference().m_hash ); + + return &tmp; + } + } + + return &src; +} + +//--// + +static inline int CompareValues_Numeric( CLR_INT32 left, CLR_INT32 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static inline int CompareValues_Numeric( CLR_UINT32 left, CLR_UINT32 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static int CompareValues_Numeric( const CLR_INT64 left, const CLR_INT64 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static int CompareValues_Numeric( const CLR_UINT64 left, const CLR_UINT64 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static int CompareValues_Numeric( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSigned, int bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + + switch(bytes) + { + case 4: + if(fSigned) return CompareValues_Numeric( (CLR_INT32 )left.NumericByRefConst().s4, (CLR_INT32 )right.NumericByRefConst().s4 ); + else return CompareValues_Numeric( (CLR_UINT32)left.NumericByRefConst().u4, (CLR_UINT32)right.NumericByRefConst().u4 ); + + case 8: + if(fSigned) return CompareValues_Numeric( (CLR_INT64 )left.NumericByRefConst().s8, (CLR_INT64 )right.NumericByRefConst().s8 ); + else return CompareValues_Numeric( (CLR_UINT64)left.NumericByRefConst().u8, (CLR_UINT64)right.NumericByRefConst().u8 ); + + case 2: + if(fSigned) return CompareValues_Numeric( (CLR_INT32 )left.NumericByRefConst().s2, (CLR_INT32 )right.NumericByRefConst().s2 ); + else return CompareValues_Numeric( (CLR_UINT32)left.NumericByRefConst().u2, (CLR_UINT32)right.NumericByRefConst().u2 ); + + case 1: + if(fSigned) return CompareValues_Numeric( (CLR_INT32 )left.NumericByRefConst().s1, (CLR_INT32 )right.NumericByRefConst().s1 ); + else return CompareValues_Numeric( (CLR_UINT32)left.NumericByRefConst().u1, (CLR_UINT32)right.NumericByRefConst().u1 ); + + default: + return -1; + } +} + + + +static inline int CompareValues_Pointers( const CLR_RT_HeapBlock* left, const CLR_RT_HeapBlock* right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + + +CLR_INT32 CLR_RT_HeapBlock::Compare_Values( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSigned ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DataType leftDataType = left .DataType(); + CLR_DataType rightDataType = right.DataType(); + + if(leftDataType == rightDataType) + { + switch(leftDataType) + { + #if defined(NANOCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + #endif + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + { + CLR_RT_HeapBlock* leftObj = left .Dereference(); + CLR_RT_HeapBlock* rightObj = right.Dereference(); + + if(!leftObj) + { + return !rightObj ? 0 : -1; // NULL references always compare smaller than non-NULL ones. + } + else if(!rightObj) + { + return 1; // NULL references always compare smaller than non-NULL ones. + } + + return Compare_Values( *leftObj, *rightObj, fSigned ); + } + + case DATATYPE_STRING: + { + CLR_RT_HeapBlock_String* leftStr = (CLR_RT_HeapBlock_String*)&left ; + CLR_RT_HeapBlock_String* rightStr = (CLR_RT_HeapBlock_String*)&right; + + return strcmp( leftStr->StringText(), rightStr->StringText() ); + } + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* leftDlg = (CLR_RT_HeapBlock_Delegate_List*)&left ; + CLR_RT_HeapBlock_Delegate_List* rightDlg = (CLR_RT_HeapBlock_Delegate_List*)&right; + CLR_RT_HeapBlock* leftPtr = leftDlg ->GetDelegates(); + CLR_RT_HeapBlock* rightPtr = rightDlg->GetDelegates(); + CLR_UINT32 leftLen = leftDlg ->m_length; + CLR_UINT32 rightLen = rightDlg->m_length; + + while(leftLen > 0 && rightLen > 0) + { + int res = CLR_RT_HeapBlock::Compare_Values( *leftPtr++, *rightPtr++, fSigned ); if(res) return res; + + leftLen--; + rightLen--; + } + + if(!leftLen) + { + return !rightLen ? 0 : -1; // NULL references always compare smaller than non-NULL ones. + } + else // rightLen != 0 for sure. + { + return 1; // NULL references always compare smaller than non-NULL ones. + } + } + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* leftDlg = (CLR_RT_HeapBlock_Delegate*)&left ; + CLR_RT_HeapBlock_Delegate* rightDlg = (CLR_RT_HeapBlock_Delegate*)&right; + CLR_UINT32 leftData = leftDlg ->DelegateFtn().m_data; + CLR_UINT32 rightData = rightDlg->DelegateFtn().m_data; + + if(leftData > rightData) return 1; + if(leftData < rightData) return -1; + + return Compare_Values( leftDlg->m_object, rightDlg->m_object, fSigned ); + } + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + case DATATYPE_SZARRAY: + case DATATYPE_WEAKCLASS: + return CompareValues_Pointers( &left, &right ); + + case DATATYPE_REFLECTION: + { + const CLR_RT_HeapBlock* ptrLeft; + const CLR_RT_HeapBlock* ptrRight; + CLR_RT_HeapBlock hbLeft; + CLR_RT_HeapBlock hbRight; + + if(left.ReflectionDataConst().m_kind != right.ReflectionDataConst().m_kind) + { + ptrLeft = FixReflectionForType( left , hbLeft ); + ptrRight = FixReflectionForType( right, hbRight ); + } + else + { + ptrLeft = &left; + ptrRight = &right; + } + + return CompareValues_Numeric( *ptrLeft, *ptrRight, false, 8 ); + } + + //--// + #if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + + case DATATYPE_R4: + if(left.NumericByRefConst().r4 > right.NumericByRefConst().r4) return 1; + if(left.NumericByRefConst().r4 < right.NumericByRefConst().r4) return -1; + /************************************************************/ return 0; + + case DATATYPE_R8: + + if(left.NumericByRefConst().r8 > right.NumericByRefConst().r8) return 1; + if(left.NumericByRefConst().r8 < right.NumericByRefConst().r8) return -1; + /************************************************************/ return 0; + + #else + case DATATYPE_R4 : + case DATATYPE_R8 : + fSigned = true; + #endif + + case DATATYPE_BOOLEAN : + case DATATYPE_I1 : + case DATATYPE_U1 : + + case DATATYPE_CHAR : + case DATATYPE_I2 : + case DATATYPE_U2 : + + case DATATYPE_I4 : + case DATATYPE_U4 : + + case DATATYPE_I8 : + case DATATYPE_U8 : + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + return CompareValues_Numeric( left, right, fSigned, c_CLR_RT_DataTypeLookup[ leftDataType ].m_sizeInBytes ); + + default: + // the remaining data types aren't to be handled + break; + } + } + else + { + if(leftDataType == DATATYPE_STRING && rightDataType == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* rightObj = right.Dereference(); + + if(!rightObj) + { + return 1; // NULL references always compare smaller than non-NULL ones. + } + + return Compare_Values( left, *rightObj, fSigned ); + } + + if(leftDataType == DATATYPE_OBJECT && rightDataType == DATATYPE_STRING) + { + CLR_RT_HeapBlock* leftObj = left.Dereference(); + + if(!leftObj) + { + return -1; // NULL references always compare smaller than non-NULL ones. + } + + return Compare_Values( *leftObj, right, fSigned ); + } + + //--// + + const CLR_RT_DataTypeLookup& leftDtl = c_CLR_RT_DataTypeLookup[ leftDataType ]; + const CLR_RT_DataTypeLookup& rightDtl = c_CLR_RT_DataTypeLookup[ rightDataType ]; + + if((leftDtl .m_flags & CLR_RT_DataTypeLookup::c_Numeric) && + (rightDtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) ) + { + if(leftDtl.m_sizeInBytes == rightDtl.m_sizeInBytes) + { + return CompareValues_Numeric( left, right, fSigned, leftDtl.m_sizeInBytes ); + } + else + { + CLR_Debug::Printf( "\r\n\r\nRUNTIME ERROR: comparing two values of different size: %d vs. %d!!!\r\n\r\n\r\n", leftDataType, rightDataType ); +#if defined(NANOCLR_PROFILE_NEW) + g_CLR_PRF_Profiler.DumpHeap(); +#endif + } + } + } + + return -1; // Not comparable... +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock::NumericAdd( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_I4: m_data.numeric.s4 += right.m_data.numeric.s4; break; + + case DATATYPE_U4: m_data.numeric.u4 += right.m_data.numeric.u4; break; + + case DATATYPE_I8: m_data.numeric.s8 += right.m_data.numeric.s8; break; + + case DATATYPE_U8: m_data.numeric.u8 += right.m_data.numeric.u8; break; + + case DATATYPE_R4: +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT32 orig = (CLR_INT32)m_data.numeric.r4; + CLR_INT32 rhs = (CLR_INT32)right.m_data.numeric.r4; +#endif + m_data.numeric.r4 += right.m_data.numeric.r4; + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + if(rhs > 0 && orig > 0 && orig > (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = 0x7FFFFFFF; /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs < 0 && orig < 0 && orig < (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = (CLR_INT32)(CLR_UINT32)0x80000000; /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + break; + + case DATATYPE_R8: +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT64 orig = (CLR_INT64)m_data.numeric.r8; + CLR_INT64 rhs = (CLR_INT64)right.m_data.numeric.r8; +#endif + m_data.numeric.r8 += right.m_data.numeric.r8; + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + if(rhs > 0 && orig > 0 && orig > (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs < 0 && orig < 0 && orig < (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x8000000000000000); /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + break; + + + // Adding of value to array reference is like advancing the index in array. + case DATATYPE_ARRAY_BYREF: + { + // Retrieve refernced array. Test if it is not NULL + CLR_RT_HeapBlock_Array* array = m_data.arrayReference.array; FAULT_ON_NULL(array); + // Advance current index. C# on pointer operations multiplies the offset by object size. We need to reverse it. + m_data.arrayReference.index += right.m_data.numeric.s4 / array->m_sizeOfElement; + } + break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericSub( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 -= right.m_data.numeric.u4; break; + + case DATATYPE_I4: m_data.numeric.s4 -= right.m_data.numeric.s4; break; + + case DATATYPE_U8: m_data.numeric.u8 -= right.m_data.numeric.u8; break; + + case DATATYPE_I8: m_data.numeric.s8 -= right.m_data.numeric.s8; break; + + case DATATYPE_R4: +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT32 orig = (CLR_INT32)m_data.numeric.r8; + CLR_INT32 rhs = (CLR_INT32)right.m_data.numeric.r4; +#endif + m_data.numeric.r4 -= right.m_data.numeric.r4; + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + if(rhs < 0 && orig > 0 && orig > (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = 0x7FFFFFFF; /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs > 0 && orig < 0 && orig < (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = (CLR_INT32)(CLR_UINT32)0x80000000; /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + + break; + + case DATATYPE_R8: +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT64 orig = (CLR_INT64)m_data.numeric.r8; + CLR_INT64 rhs = (CLR_INT64)right.m_data.numeric.r8; +#endif + + m_data.numeric.r8 -= right.m_data.numeric.r8; + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + if(rhs < 0 && orig > 0 && orig > (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs > 0 && orig < 0 && orig < (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x8000000000000000); /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + + break; + + + // Substructing of value to array reference is like decreasing the index in array. + case DATATYPE_ARRAY_BYREF: + { + // Retrieve refernced array. Test if it is not NULL + CLR_RT_HeapBlock_Array* array = m_data.arrayReference.array; FAULT_ON_NULL(array); + // Advance current index. C# on pointer operations multiplies the offset by object size. We need to reverse it. + m_data.arrayReference.index -= right.m_data.numeric.s4 / array->m_sizeOfElement; + } + break; + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericMul( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 = m_data.numeric.u4 * right.m_data.numeric.u4; break; + + case DATATYPE_I4: m_data.numeric.s4 = m_data.numeric.s4 * right.m_data.numeric.s4; break; + + case DATATYPE_U8: m_data.numeric.u8 = m_data.numeric.u8 * right.m_data.numeric.u8; break; + + case DATATYPE_I8: m_data.numeric.s8 = m_data.numeric.s8 * right.m_data.numeric.s8; break; + + case DATATYPE_R4: +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT32 orig = (CLR_INT32)m_data.numeric.r4; + CLR_INT32 rhs; +#endif + m_data.numeric.r4 = m_data.numeric.r4 * right.m_data.numeric.r4; + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + rhs = (CLR_INT32)right.m_data.numeric.r4; + + if(orig != 0 && rhs != 0) + { + CLR_INT32 ret_value = (CLR_INT32)m_data.numeric.r4; + bool isNeg = orig < 0; + + if(rhs < 0) isNeg = !isNeg; + + if(!isNeg && (ret_value < 0 || ret_value < orig || ret_value < rhs)) { m_data.numeric.r4 = 0x7FFFFFFF; /* return CLR_E_OUT_OF_RANGE; */ } + else if( isNeg && (ret_value > 0 || ret_value > orig || ret_value > rhs)) { m_data.numeric.r4 = (CLR_INT32)(CLR_UINT32)0x80000000; /* return CLR_E_OUT_OF_RANGE; */ } + } + } +#endif + break; + + case DATATYPE_R8: +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT64 orig = (CLR_INT64)m_data.numeric.r8; + CLR_INT64 rhs; +#endif + m_data.numeric.r8 = m_data.numeric.r8 * right.m_data.numeric.r8; + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) + rhs = (CLR_INT64)right.m_data.numeric.r8; + + if(orig != 0 && rhs != 0) + { + CLR_INT64 ret_value = (CLR_INT64)m_data.numeric.r8; + bool isNeg = orig < 0; + + if(rhs < 0) isNeg = !isNeg; + + if(!isNeg && (ret_value < 0 || ret_value < orig || ret_value < rhs)) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); /* return CLR_E_OUT_OF_RANGE; */ } + else if( isNeg && (ret_value > 0 || ret_value > orig || ret_value > rhs)) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x8000000000000000); /* return CLR_E_OUT_OF_RANGE; */ } + } + } +#endif + break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericDiv( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(right.IsZero()) NANOCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_U4: + case DATATYPE_I4: m_data.numeric.s4 = m_data.numeric.s4 / right.m_data.numeric.s4; break; + + case DATATYPE_U8: + case DATATYPE_I8: m_data.numeric.s8 = m_data.numeric.s8 / right.m_data.numeric.s8; break; + + case DATATYPE_R4: m_data.numeric.r4 = m_data.numeric.r4 / right.m_data.numeric.r4; break; + + case DATATYPE_R8: m_data.numeric.r8 = m_data.numeric.r8 / right.m_data.numeric.r8; break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericDivUn( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(right.IsZero()) NANOCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 = m_data.numeric.u4 / right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8:m_data.numeric.u8 = m_data.numeric.u8 / right.m_data.numeric.u8; break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericRem( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(right.IsZero()) NANOCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 %= right.m_data.numeric.u4 ; break; + + case DATATYPE_I4: m_data.numeric.s4 %= right.m_data.numeric.s4 ; break; + + case DATATYPE_U8: m_data.numeric.u8 %= right.m_data.numeric.u8 ; break; + + case DATATYPE_I8: m_data.numeric.s8 %= right.m_data.numeric.s8 ; break; + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + + case DATATYPE_R4: m_data.numeric.r4 = fmod( m_data.numeric.r4, right.m_data.numeric.r4 ); break; + + case DATATYPE_R8: m_data.numeric.r8 = fmod( (CLR_DOUBLE_TEMP_CAST)m_data.numeric.r8,(CLR_DOUBLE_TEMP_CAST) right.m_data.numeric.r8 ); break; + +#else + + case DATATYPE_R4: m_data.numeric.r4 %= right.m_data.numeric.r4; break; + + case DATATYPE_R8: m_data.numeric.r8 %= right.m_data.numeric.r8; break; + +#endif + + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericRemUn( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(right.IsZero()) NANOCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 %= right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8: m_data.numeric.u8 %= right.m_data.numeric.u8; break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericShl( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 <<= right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8: m_data.numeric.u8 <<= right.m_data.numeric.u4; break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericShr( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 >>= right.m_data.numeric.u4; break; + + case DATATYPE_I4: m_data.numeric.s4 >>= right.m_data.numeric.u4; break; + + case DATATYPE_U8: m_data.numeric.u8 >>= right.m_data.numeric.u4; break; + + case DATATYPE_I8: m_data.numeric.s8 >>= right.m_data.numeric.u4; break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericShrUn( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 >>= right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8: m_data.numeric.u8 >>= right.m_data.numeric.u4; break; + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericNeg() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: + case DATATYPE_I4: m_data.numeric.s4 = -m_data.numeric.s4; break; + + case DATATYPE_U8: + case DATATYPE_I8: m_data.numeric.s8 = -m_data.numeric.s8; break; + + case DATATYPE_R4: m_data.numeric.r4 = -m_data.numeric.r4; break; + + case DATATYPE_R8: m_data.numeric.r8 = -m_data.numeric.r8; break; + + + + default : NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_HeapBlock* CLR_RT_HeapBlock::ExtractValueBlock( int offset ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* ptr = Dereference(); + + if(ptr) + { + ptr = &ptr[ offset ]; + } + + return ptr; +} + +void CLR_RT_HeapBlock::ReadValue( CLR_INT64& val, int offset ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* ptr = ExtractValueBlock( offset ); + + if(ptr) + { + val = ptr->NumericByRefConst().s8; + } + else + { + CLR_INT32 val2 = 0; + + val = val2; + } +} + +void CLR_RT_HeapBlock::WriteValue( const CLR_INT64& val, int offset ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* ptr = ExtractValueBlock( offset ); + + if(ptr) ptr->NumericByRef().s8 = val; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(NANOCLR_APPDOMAINS) + +void CLR_RT_HeapBlock::SetTransparentProxyReference( CLR_RT_AppDomain* appDomain, CLR_RT_HeapBlock* ptr) + { +#if defined(_DEBUG) + if(ptr) + { + //Make sure the data points to a MBRO. + CLR_RT_TypeDef_Instance inst; + + _ASSERTE(ptr->DataType() == DATATYPE_CLASS); + + inst.InitializeFromIndex( ptr->ObjectCls() ); + _ASSERTE((inst.CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject) != 0); + } +#endif + + m_data.transparentProxy.appDomain = appDomain; + m_data.transparentProxy.ptr = ptr; + } + +HRESULT CLR_RT_HeapBlock::TransparentProxyValidate() const +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_AppDomain* appDomain = TransparentProxyAppDomain (); + CLR_RT_HeapBlock* obj = TransparentProxyDereference(); + + if(appDomain == NULL || !appDomain->IsLoaded()) NANOCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_EXITED); + + FAULT_ON_NULL(obj); + + NANOCLR_NOCLEANUP(); +} + +#endif //NANOCLR_APPDOMAINS +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapBlock::Relocate__HeapBlock() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HEAPBLOCK_RELOCATE(this); +} + + +void CLR_RT_HeapBlock::Relocate_String() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.string.m_text ); +#if !defined(NANOCLR_NO_ASSEMBLY_STRINGS) + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.string.m_assm ); +#endif +} + +void CLR_RT_HeapBlock::Relocate_Obj() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.objectReference.ptr ); +} + +void CLR_RT_HeapBlock::Relocate_Cls() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.objectHeader.lock ); + + CLR_RT_GarbageCollector::Heap_Relocate( this + 1, DataSize() - 1 ); +} + +void CLR_RT_HeapBlock::Relocate_Ref() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.objectReference.ptr ); +} + +void CLR_RT_HeapBlock::Relocate_ArrayRef() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.arrayReference.array ); +} + +#if defined(NANOCLR_APPDOMAINS) +void CLR_RT_HeapBlock::Relocate_TransparentProxy() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.transparentProxy.ptr ); +} +#endif + +//--// + +#if defined(NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + +void CLR_RT_HeapBlock::Debug_CheckPointer() const +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_id.type.dataType == DATATYPE_OBJECT) + { + Debug_CheckPointer( Dereference() ); + } +} + +void CLR_RT_HeapBlock::Debug_CheckPointer( void* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + switch((size_t)ptr) + { + case 0xCFCFCFCF: + case 0xCBCBCBCB: + case 0xABABABAB: + case 0xADADADAD: + case 0xDFDFDFDF: + NANOCLR_STOP(); + break; + } +} + +void CLR_RT_HeapBlock::Debug_ClearBlock( int data ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 size = DataSize(); + + if(size > 1) + { + CLR_RT_HeapBlock_Raw* ptr = (CLR_RT_HeapBlock_Raw*)this; + CLR_UINT32 raw1 = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_OBJECT,0,1); + CLR_UINT32 raw2; + + raw2 = data & 0xFF; + raw2 = raw2 | (raw2 << 8); + raw2 = raw2 | (raw2 << 16); + + while(--size) + { + ptr++; + + ptr->data[ 0 ] = raw1; + ptr->data[ 1 ] = raw2; + ptr->data[ 2 ] = raw2; + } + } +} + +#endif + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp new file mode 100644 index 00000000..4f2c8dde --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp @@ -0,0 +1,375 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Array::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArray; + CLR_RT_TypeDef_Index cls; + CLR_RT_TypeDef_Instance inst; + + reference.SetObjectReference( NULL ); + + if((CLR_INT32)length < 0) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(reflex.m_kind != REFLECTION_TYPE) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if(reflex.m_levels == 1) + { + cls = reflex.m_data.m_type; + } + else + { + cls = g_CLR_RT_WellKnownTypes.m_Array; + } + + if(inst.InitializeFromIndex( cls ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + CLR_DataType dt = (CLR_DataType)inst.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + if(dtl.m_sizeInBytes == CLR_RT_DataTypeLookup::c_NA) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + pArray = (CLR_RT_HeapBlock_Array*)g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForArray( inst, length, reflex ); CHECK_ALLOCATION(pArray); + + reference.SetObjectReference( pArray ); + + NANOCLR_SET_AND_LEAVE(pArray->ClearElements( 0, length )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_ReflectionDef_Index reflex; + + reflex.m_kind = REFLECTION_TYPE; + reflex.m_levels = 1; + reflex.m_data.m_type = cls; + + NANOCLR_SET_AND_LEAVE(CreateInstance( reference, length, reflex )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, CLR_RT_Assembly* assm, CLR_UINT32 tk ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock ref; + CLR_RT_TypeDef_Instance cls; + CLR_RT_TypeSpec_Instance def; + + if(cls.ResolveToken( tk, assm )) + { + ref.SetReflection( cls ); + } + else if(def.ResolveToken( tk, assm )) + { + NANOCLR_CHECK_HRESULT(ref.SetReflection( def )); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + ref.ReflectionData().m_levels++; + + NANOCLR_SET_AND_LEAVE(CreateInstance( reference, length, ref.ReflectionData() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::ClearElements( int index, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_RT_ReflectionDef_Index& reflex = ReflectionDataConst(); + CLR_UINT8* data = GetElement( index ); + + CLR_RT_Memory::ZeroFill( data, length * m_sizeOfElement ); + + if(m_fReference) + { + CLR_DataType dt = (CLR_DataType)m_typeOfElement; + bool fAllocate = (reflex.m_levels == 1 && dt == DATATYPE_VALUETYPE); + CLR_RT_HeapBlock* ptr = (CLR_RT_HeapBlock*)data; + + switch(dt) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS: + case DATATYPE_WEAKCLASS: + dt = DATATYPE_OBJECT; + break; + + default: + // the remaining data types aren't to be handled + break; + } + + while(length > 0) + { + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt,0,1) ); + + if(fAllocate) + { + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *ptr, reflex.m_data.m_type )); + } + + ptr++; length--; + } + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Array::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + // + // If the array is full of reference types, relocate each of them. + // + if(m_fReference) + { + CLR_RT_GarbageCollector::Heap_Relocate( (CLR_RT_HeapBlock*)GetFirstElement(), m_numOfElements ); + } +} + +bool CLR_RT_HeapBlock_Array::CheckRange( int index, int length, int numOfElements ) +{ + NATIVE_PROFILE_CLR_CORE(); + if( length < 0 ) return false; + if( index < 0 || index > numOfElements) return false; + if((index + length) < 0 || (index + length) > numOfElements) return false; + + return true; +} + +/* + This is not the same functionality as System.Array.IndexOf. CLR_RT_HeapBlock_Array::IndexOf does the search analogous + to calling Object.ReferenceEquals, not Object.Equals, as System.Array.IndexOf demands. This function is used by + TrySzIndexOf +*/ +HRESULT CLR_RT_HeapBlock_Array::IndexOf( CLR_RT_HeapBlock_Array* array, CLR_RT_HeapBlock& match, int start, int stop, bool fForward, int& index ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int numElem = array->m_numOfElements; + int count; + + if(stop == -1) stop = numElem; + + count = stop - start; + + if(CheckRange( start, count, numElem ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(count > 0) + { + CLR_UINT8* data = array->GetFirstElement(); + CLR_UINT8 sizeElem = array->m_sizeOfElement; + int pos; + int incr; + + if(fForward) { pos = start ; incr = 1; } + else { pos = stop-1; incr = -1; } + + data += pos * sizeElem; + + if(!array->m_fReference) + { + CLR_RT_HeapBlock* matchPtr = match.FixBoxingReference(); FAULT_ON_NULL(matchPtr); + + if(matchPtr->DataType() <= DATATYPE_LAST_PRIMITIVE) + { + int incrElem = incr * sizeElem; + + while(true) + { + if(memcmp( data, &matchPtr->NumericByRef(), sizeElem ) == 0) + { + index = pos; + NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(--count == 0) break; + + pos += incr; + data += incrElem; + } + } + } + else + { + CLR_RT_HeapBlock* dataPtr = (CLR_RT_HeapBlock*)data; + + while(true) + { + if(CLR_RT_HeapBlock::Compare_Unsigned_Values( *dataPtr, match ) == 0) + { + index = pos; + NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(--count == 0) break; + + pos += incr; + dataPtr += incr; + } + } + } + + index = -1; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::Copy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(length) + { + int numElemSrc = arraySrc->m_numOfElements; + int numElemDst = arrayDst->m_numOfElements; + + if(length < 0 || + indexSrc < 0 || + indexDst < 0 || + length + indexSrc > numElemSrc || + length + indexDst > numElemDst ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + // + // Copy of an array on itself. + // + if(arraySrc == arrayDst && indexSrc == indexDst) NANOCLR_SET_AND_LEAVE(S_OK); + + if(arraySrc->SameHeader( *arrayDst )) + { + CLR_UINT8* dataSrc = arraySrc->GetFirstElement(); + CLR_UINT8* dataDst = arrayDst->GetFirstElement(); + CLR_UINT8 sizeElem = arraySrc->m_sizeOfElement; + + dataSrc += indexSrc * sizeElem; + dataDst += indexDst * sizeElem; + + if(!arraySrc->m_fReference) + { + memmove( dataDst, dataSrc, length * sizeElem ); + } + else + { + CLR_RT_HeapBlock* ptrSrc = (CLR_RT_HeapBlock*)dataSrc; + CLR_RT_HeapBlock* ptrDst = (CLR_RT_HeapBlock*)dataDst; + int incr; + + if(arraySrc == arrayDst && ptrSrc < ptrDst) + { + incr = -1; + ptrSrc += length-1; + ptrDst += length-1; + } + else + { + incr = 1; + } + + for(int i=0; iReassign( *ptrSrc )); + } + } + } + else if(arraySrc->m_fReference && arrayDst->m_fReference) + { + CLR_RT_TypeDescriptor descSrc; + CLR_RT_TypeDescriptor descDst; + CLR_RT_HeapBlock* ptrSrc = (CLR_RT_HeapBlock*)arraySrc->GetElement( indexSrc ); + CLR_RT_HeapBlock* ptrDst = (CLR_RT_HeapBlock*)arrayDst->GetElement( indexDst ); + + NANOCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst ); + + for(int i=0; iDataType() == DATATYPE_OBJECT && ptrSrc->Dereference() == NULL) + { + ; + } + else + { + NANOCLR_CHECK_HRESULT(descSrc.InitializeFromObject( *ptrSrc )); + + if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDst ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + } + } + + NANOCLR_CHECK_HRESULT(ptrDst->Reassign( *ptrSrc )); + } + } + else + { + CLR_RT_TypeDescriptor descSrc; + CLR_RT_TypeDescriptor descDst; + CLR_RT_HeapBlock ref; + CLR_RT_HeapBlock elem; elem.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( elem ); + + NANOCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst ); + + for(int i=0; i= GetSize()) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + value = ((CLR_RT_HeapBlock*)GetItems()->GetElement( index ))->Dereference(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_ArrayList::SetItem( CLR_INT32 index, CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(index < 0 || index >= GetSize()) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + ((CLR_RT_HeapBlock*)GetItems()->GetElement( index ))->SetObjectReference( value ); + + NANOCLR_NOCLEANUP(); +} + +// May Trigger GC, but parameter value will be protected +HRESULT CLR_RT_HeapBlock_ArrayList::Add( CLR_RT_HeapBlock* value, CLR_INT32& index ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* items = GetItems(); + CLR_INT32 size = GetSize(); + CLR_INT32 capacity = items->m_numOfElements; + + if(size == capacity) + { + // Protect value from GC, in case EnsureCapacity triggers one + CLR_RT_HeapBlock valueHB; valueHB.SetObjectReference( value ); + CLR_RT_ProtectFromGC gc( valueHB ); + + NANOCLR_CHECK_HRESULT(EnsureCapacity( size + 1, capacity )); + + // needs to update the reference to the new array + items = GetItems(); + } + + SetSize( size + 1 ); + + ((CLR_RT_HeapBlock*)items->GetElement( size ))->SetObjectReference( value ); + + index = size; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_ArrayList::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(GetItems()->ClearElements( 0, GetSize() )); + + SetSize( 0 ); + + NANOCLR_NOCLEANUP(); +} + +// May Trigger GC, but parameter value will be protected +HRESULT CLR_RT_HeapBlock_ArrayList::Insert( CLR_INT32 index, CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* items = GetItems(); + CLR_INT32 size = GetSize(); + CLR_INT32 capacity = items->m_numOfElements; + + if(index < 0 || index > size) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(size == capacity) + { + // Protect value from GC, in case EnsureCapacity triggers one + CLR_RT_HeapBlock valueHB; valueHB.SetObjectReference( value ); + CLR_RT_ProtectFromGC gc( valueHB ); + + NANOCLR_CHECK_HRESULT(EnsureCapacity( size + 1, capacity )); + + // needs to update the reference to the new array + items = GetItems(); + } + + if(index < size) + { + // Move everything up one slot. + CLR_RT_HeapBlock* current = (CLR_RT_HeapBlock*)items->GetElement( size ); + CLR_RT_HeapBlock* end = (CLR_RT_HeapBlock*)items->GetElement( index ); + + do + { + current->Assign( *(current - 1) ); + } + while(--current != end); + } + + ((CLR_RT_HeapBlock*)items->GetElement( index ))->SetObjectReference( value ); + + SetSize( size + 1 ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_ArrayList::RemoveAt( CLR_INT32 index ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* items = GetItems(); + CLR_INT32 size = GetSize(); + + if(index < 0 || index >= size) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + // Need to shift everything, if it's not the last item + if(index < size - 1) + { + // Move everything down one slot. + CLR_RT_HeapBlock* current = (CLR_RT_HeapBlock*)items->GetElement( index ); + CLR_RT_HeapBlock* end = (CLR_RT_HeapBlock*)items->GetElement( size - 1 ); + + do + { + current->Assign( *(current + 1) ); + } + while(++current != end); + } + + size--; + + ((CLR_RT_HeapBlock*)items->GetElement( size ))->SetObjectReference( NULL ); + + SetSize( size ); + + NANOCLR_NOCLEANUP(); +} + +// May Trigger GC +HRESULT CLR_RT_HeapBlock_ArrayList::SetCapacity( CLR_UINT32 newCapacity ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* items = GetItems(); + CLR_UINT32 size = GetSize(); + + if(newCapacity != items->m_numOfElements) // if capacity is changing + { + CLR_RT_HeapBlock newItemsHB; + CLR_RT_HeapBlock_Array* newItems; + + if(newCapacity < size) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(newCapacity < c_DefaultCapacity) + { + newCapacity = c_DefaultCapacity; + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( newItemsHB, newCapacity, g_CLR_RT_WellKnownTypes.m_Object )); + + newItems = newItemsHB.DereferenceArray(); + + if(size > 0) + { + memcpy( newItems->GetFirstElement(), items->GetFirstElement(), size * sizeof(CLR_RT_HeapBlock) ); + } + + SetItems( newItems ); + } + + NANOCLR_NOCLEANUP(); +} + +// May Trigger GC +HRESULT CLR_RT_HeapBlock_ArrayList::EnsureCapacity( CLR_INT32 min, CLR_INT32 currentCapacity ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(currentCapacity < min) + { + CLR_INT32 newCapacity = currentCapacity * 3 / 2; + + if(newCapacity < min) newCapacity = min; + + NANOCLR_SET_AND_LEAVE(SetCapacity( newCapacity )); + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +CT_ASSERT(Library_corlib_native_System_Collections_ArrayList__FIELD___items == Library_corlib_native_System_Collections_ArrayList::FIELD___items); +CT_ASSERT(Library_corlib_native_System_Collections_ArrayList__FIELD___size == Library_corlib_native_System_Collections_ArrayList::FIELD___size ); diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_BinaryBlob.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_BinaryBlob.cpp new file mode 100644 index 00000000..e871bc86 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_BinaryBlob.cpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_BinaryBlob::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, CLR_RT_MarkingHandler mark, CLR_RT_RelocationHandler relocate, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_BinaryBlob* obj = Allocate( length, flags ); CHECK_ALLOCATION(obj); + + reference.SetObjectReference( obj ); + + obj->SetBinaryBlobHandlers( mark, relocate ); + obj->m_assembly = NULL; + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock_BinaryBlob* CLR_RT_HeapBlock_BinaryBlob::Allocate( CLR_UINT32 length, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 totLength = (CLR_UINT32)( sizeof(CLR_RT_HeapBlock_BinaryBlob) + length ); + + CLR_RT_HeapBlock_BinaryBlob* obj; + + if(flags & CLR_RT_HeapBlock::HB_Event) + { + obj = EVENTCACHE_EXTRACT_NODE_AS_BYTES(g_CLR_RT_EventCache,CLR_RT_HeapBlock_BinaryBlob,DATATYPE_BINARY_BLOB_HEAD,flags,totLength); + } + else + { + obj = (CLR_RT_HeapBlock_BinaryBlob*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_BINARY_BLOB_HEAD, flags, totLength ); + } + + if(obj) + { + obj->SetBinaryBlobHandlers( NULL, NULL ); + } + + return obj; +} + +void CLR_RT_HeapBlock_BinaryBlob::Release( bool fEvent ) +{ + NATIVE_PROFILE_CLR_CORE(); + SetBinaryBlobHandlers( NULL, NULL ); + + if(fEvent) g_CLR_RT_EventCache.Append_Node( this ); +} + +void CLR_RT_HeapBlock_BinaryBlob::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_RelocationHandler relocate = BinaryBlobRelocationHandler(); + + if(relocate) + { + relocate( this ); + } +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp new file mode 100644 index 00000000..5af4e0b5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Delegate::CreateInstance( CLR_RT_HeapBlock& reference, const CLR_RT_MethodDef_Index& ftn, CLR_RT_StackFrame* call ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + reference.SetObjectReference( NULL ); + + CLR_UINT32 length = 0; + + #if defined(NANOCLR_DELEGATE_PRESERVE_STACK) + if(call) + { + NANOCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,ptr,call) + { + length++; + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + } + + // + // Limit depth to three callers. + // + if(length > 3) length = 3; + #else + (void)call; + #endif + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_Delegate) + length * sizeof(CLR_RT_MethodDef_Index)); + + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_DELEGATE_HEAD, 0, totLength ); CHECK_ALLOCATION(dlg); + + reference.SetObjectReference( dlg ); + + dlg->ClearData(); + dlg->m_cls.Clear(); + dlg->m_ftn = ftn; +#if defined(NANOCLR_DELEGATE_PRESERVE_STACK) + dlg->m_numOfStackFrames = length; +#endif + + dlg->m_object.SetObjectReference( NULL ); + +#if defined(NANOCLR_APPDOMAINS) + dlg->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + +#if defined(NANOCLR_DELEGATE_PRESERVE_STACK) + if(call) + { + CLR_RT_MethodDef_Index* callStack = dlg->GetStackFrames(); + + NANOCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,ptr,call) + { + if(length-- == 0) break; + + *callStack++ = ptr->m_call; + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + } +#endif + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Delegate::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + m_object.Relocate__HeapBlock(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp new file mode 100644 index 00000000..e9a199b5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp @@ -0,0 +1,232 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Delegate_List::CreateInstance( CLR_RT_HeapBlock_Delegate_List*& list, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_Delegate_List) + length * sizeof(CLR_RT_HeapBlock)); + + list = (CLR_RT_HeapBlock_Delegate_List*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_DELEGATELIST_HEAD, 0, totLength ); CHECK_ALLOCATION(list); + + list->ClearData(); + list->m_cls.Clear(); + list->m_length = length; + list->m_flags = 0; + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock* CLR_RT_HeapBlock_Delegate_List::CopyAndCompress( CLR_RT_HeapBlock* src, CLR_RT_HeapBlock* dst, CLR_UINT32 num ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(num--) + { + CLR_RT_HeapBlock_Delegate* dlg = src->DereferenceDelegate(); + if(dlg) + { + dst->SetObjectReference( dlg ); + + dst++; + } + else + { + m_length--; + } + + src++; + } + + return dst; +} + +HRESULT CLR_RT_HeapBlock_Delegate_List::Change( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateTarget, bool fCombine, bool fWeak ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Delegate_List* dlgListSrc; + CLR_RT_HeapBlock_Delegate_List* dlgListDst; + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock* newDlgs; + CLR_RT_HeapBlock* oldDlgs; + CLR_UINT32 oldNum; + CLR_UINT32 newNum; + + CLR_UINT32 num = 0; + + reference.SetObjectReference( NULL ); + + if(delegateSrc .DataType() != DATATYPE_OBJECT || + delegateTarget.DataType() != DATATYPE_OBJECT ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + dlg = delegateTarget.DereferenceDelegate(); + + if(dlg == NULL) + { + reference.SetObjectReference( delegateSrc.DereferenceDelegate() ); + NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(dlg->DataType() == DATATYPE_DELEGATELIST_HEAD) + { + CLR_RT_HeapBlock intermediate; intermediate.Assign( delegateSrc ); + CLR_RT_ProtectFromGC gc( intermediate ); + + dlgListDst = (CLR_RT_HeapBlock_Delegate_List*)dlg; + newDlgs = dlgListDst->GetDelegates(); + + for(num=0; numm_length; num++, newDlgs++) + { + if(newDlgs->DataType() == DATATYPE_OBJECT && newDlgs->DereferenceDelegate() != NULL) // The delegate could have been GC'ed. + { + NANOCLR_CHECK_HRESULT(Change( reference, intermediate, *newDlgs, fCombine, fWeak )); + + intermediate.Assign( reference ); + } + } + } + else + { + dlgListSrc = delegateSrc.DereferenceDelegateList(); + if(dlgListSrc == NULL) + { + oldDlgs = NULL; + oldNum = 0; + } + else + { + switch(dlgListSrc->DataType()) + { + case DATATYPE_DELEGATE_HEAD: + oldDlgs = &delegateSrc; + oldNum = 1; + break; + + case DATATYPE_DELEGATELIST_HEAD: + oldDlgs = dlgListSrc->GetDelegates(); + oldNum = dlgListSrc->m_length; + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + if(fCombine) + { + if(oldNum == 0 && fWeak == false) + { + // + // Empty input list, copy the delegate. + // + reference.Assign( delegateTarget ); + NANOCLR_SET_AND_LEAVE(S_OK); + } + + //--// + + newNum = oldNum + 1; + } + else + { + for(num=0, newDlgs=oldDlgs; numDereferenceDelegate(); + if(ptr) + { + if( ptr->DelegateFtn().m_data == dlg->DelegateFtn().m_data && + ptr->m_object.Dereference() == dlg->m_object.Dereference() ) + { + break; + } + } + } + + if(num == oldNum) + { + reference.Assign( delegateSrc ); // Nothing to remove. + NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(oldNum == 2 && (dlgListSrc->m_flags & CLR_RT_HeapBlock_Delegate_List::c_Weak) == 0) + { + reference.Assign( oldDlgs[ 1-num ] ); // Convert from a list to delegate. + NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(oldNum == 1) + { + reference.SetObjectReference( NULL ); // Oops, empty delegate... + NANOCLR_SET_AND_LEAVE(S_OK); + } + + //--// + + newNum = oldNum - 1; + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate_List::CreateInstance( dlgListDst, newNum )); + + dlgListDst->m_cls = dlg->m_cls; + + newDlgs = dlgListDst->GetDelegates(); + + if(fCombine) + { + newDlgs = dlgListDst->CopyAndCompress( oldDlgs, newDlgs, oldNum ); + + newDlgs->Assign( delegateTarget ); + } + else + { + newDlgs = dlgListDst->CopyAndCompress( oldDlgs , newDlgs, num++ ); + newDlgs = dlgListDst->CopyAndCompress( oldDlgs + num, newDlgs, oldNum - num ); + } + + dlgListDst->m_flags = (dlgListSrc && oldNum > 1) ? dlgListSrc->m_flags : 0; + + if(fWeak) dlgListDst->m_flags |= CLR_RT_HeapBlock_Delegate_List::c_Weak; + + reference.SetObjectReference( dlgListDst ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Delegate_List::Combine( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateNew, bool fWeak ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Change( reference, delegateSrc, delegateNew, true, fWeak )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Delegate_List::Remove( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateOld ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(Change( reference, delegateSrc, delegateOld, false, false )); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Delegate_List::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( GetDelegates(), m_length ); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp new file mode 100644 index 00000000..c06cee13 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp @@ -0,0 +1,80 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Finalizer::CreateInstance( CLR_RT_HeapBlock* object, const CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst2 = inst; + + do + { + if(inst2.m_target->flags & CLR_RECORD_TYPEDEF::TD_HasFinalizer) + { + int pos = inst2.m_target->methods_First; + int end = pos + inst2.m_target->vMethods_Num + inst2.m_target->iMethods_Num; + const CLR_RECORD_METHODDEF* md = inst2.m_assm->GetMethodDef( pos ); + + for(; posflags & CLR_RECORD_METHODDEF::MD_Finalizer) break; + } + + if(pos < end) + { + CLR_RT_HeapBlock_Finalizer* fin = EVENTCACHE_EXTRACT_NODE_NOALLOC(g_CLR_RT_EventCache,CLR_RT_HeapBlock_Finalizer,DATATYPE_FINALIZER_HEAD); CHECK_ALLOCATION(fin); + + fin->m_object = object; + + fin->m_md.Set( inst2.Assembly(), pos ); + +#if defined(NANOCLR_APPDOMAINS) + fin->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + g_CLR_RT_ExecutionEngine.m_finalizersAlive.LinkAtBack( fin ); + + break; + } + } + } + while(inst2.SwitchToParent()); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Finalizer::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_object ); +} + +void CLR_RT_HeapBlock_Finalizer::SuppressFinalize( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_CORE(); + RemoveInstance( object, g_CLR_RT_ExecutionEngine.m_finalizersAlive ); + RemoveInstance( object, g_CLR_RT_ExecutionEngine.m_finalizersPending ); +} + +void CLR_RT_HeapBlock_Finalizer::RemoveInstance( CLR_RT_HeapBlock* object, CLR_RT_DblLinkedList& lst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,lst) + { + if(fin->m_object == object) + { + g_CLR_RT_EventCache.Append_Node( fin ); + + break; + } + } + NANOCLR_FOREACH_NODE_END(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp new file mode 100644 index 00000000..99a040c7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp @@ -0,0 +1,228 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Lock::CreateInstance( CLR_RT_HeapBlock_Lock*& lock, CLR_RT_Thread* th, CLR_RT_HeapBlock& resource ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + lock = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_Lock,DATATYPE_LOCK_HEAD); CHECK_ALLOCATION(lock); + + lock->m_owningThread = th; // CLR_RT_Thread* m_owningThread; + // + lock->m_resource.Assign( resource ); // CLR_RT_HeapBlock m_resource; + // + lock->m_owners .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_owners; + lock->m_requests.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_requests; + +#if defined(NANOCLR_APPDOMAINS) + lock->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + //--// + + if(resource.DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = resource.Dereference(); + + if(ptr) + { + switch(ptr->DataType()) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS : + ptr->SetObjectLock( lock ); + break; + + default: + // the remaining data types aren't to be handled + break; + } + } + } + + th->m_locks.LinkAtBack( lock ); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Lock::DestroyOwner( CLR_RT_SubThread* sth ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock::Owner,owner,m_owners) + { + if(owner->m_owningSubThread == sth) + { + g_CLR_RT_EventCache.Append_Node( owner ); + } + } + NANOCLR_FOREACH_NODE_END(); + + if(m_owners.IsEmpty()) + { + ChangeOwner(); + } +} + +void CLR_RT_HeapBlock_Lock::ChangeOwner() +{ + NATIVE_PROFILE_CLR_CORE(); + m_owners.DblLinkedList_PushToCache(); + + while(true) + { + CLR_RT_HeapBlock_LockRequest* req = (CLR_RT_HeapBlock_LockRequest*)m_requests.ExtractFirstNode(); if(!req) break; + + CLR_RT_SubThread* sth = req->m_subthreadWaiting; + CLR_RT_Thread* th = sth->m_owningThread; + + g_CLR_RT_EventCache.Append_Node( req ); + + sth->ChangeLockRequestCount( -1 ); + + th->m_locks.LinkAtBack( this ); + + m_owningThread = th; + + CLR_RT_HeapBlock_Lock::IncrementOwnership( this, sth, TIMEOUT_INFINITE, false ); + + // + // If the new owner was waiting on something, update the flags. + // + { + CLR_RT_StackFrame* stack = th->CurrentFrame(); + + if(stack->m_flags & CLR_RT_StackFrame::c_PendingSynchronizeGlobally) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_PendingSynchronizeGlobally; + stack->m_flags |= CLR_RT_StackFrame::c_SynchronizedGlobally; + } + + if(stack->m_flags & CLR_RT_StackFrame::c_PendingSynchronize) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_PendingSynchronize; + stack->m_flags |= CLR_RT_StackFrame::c_Synchronized; + } + } + + return; + } + + // + // None is listening for this object, unlock it. + // + if(m_resource.DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = m_resource.Dereference(); + + if(ptr) + { + switch(ptr->DataType()) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS : + ptr->SetObjectLock( NULL ); + break; + + default: + // the remaining data types aren't to be handled + break; + } + } + } + + g_CLR_RT_EventCache.Append_Node( this ); +} + +HRESULT CLR_RT_HeapBlock_Lock::IncrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th = sth ->m_owningThread; + CLR_RT_Thread* thOwner = lock->m_owningThread; + + if(thOwner == th) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock::Owner,owner,lock->m_owners) + { + if(owner->m_owningSubThread == sth) + { + owner->m_recursion++; + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + NANOCLR_FOREACH_NODE_END(); + + { + CLR_RT_HeapBlock_Lock::Owner* owner = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,Owner,DATATYPE_LOCK_OWNER_HEAD); CHECK_ALLOCATION(owner); + + owner->m_owningSubThread = sth; + owner->m_recursion = 1; + + lock->m_owners.LinkAtFront( owner ); + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + + // + // Create a request and stop the calling thread. + // + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_LockRequest::CreateInstance( lock, sth, timeExpire, fForce )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Lock::DecrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th = sth->m_owningThread; + + if(lock && lock->m_owningThread == th) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock::Owner,owner,lock->m_owners) + { + if(owner->m_owningSubThread == sth) + { + if(--owner->m_recursion == 0) + { + g_CLR_RT_EventCache.Append_Node( owner ); + } + + //--// + + if(lock->m_owners.IsEmpty()) + { + lock->ChangeOwner(); + } + + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + NANOCLR_FOREACH_NODE_END(); + } + + NANOCLR_SET_AND_LEAVE(CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Lock::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + m_resource.Relocate__HeapBlock(); +} + +void CLR_RT_HeapBlock_Lock::Relocate_Owner() +{ + NATIVE_PROFILE_CLR_CORE(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp new file mode 100644 index 00000000..807f4fcb --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_LockRequest::CreateInstance( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_LockRequest* req = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_LockRequest,DATATYPE_LOCK_REQUEST_HEAD); CHECK_ALLOCATION(req); + + req->m_subthreadWaiting = sth; + req->m_timeExpire = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + req->m_fForce = fForce; + + lock->m_requests.LinkAtBack( req ); + + sth->ChangeLockRequestCount( +1 ); + + NANOCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Node.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Node.cpp new file mode 100644 index 00000000..1ece5611 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Node.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapBlock_Node::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.nodeLink.prevBlock ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.nodeLink.nextBlock ); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Queue.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Queue.cpp new file mode 100644 index 00000000..85b6c176 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Queue.cpp @@ -0,0 +1,173 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +#if (NANOCLR_SYSTEM_COLLECTIONS == TRUE) +#include + +HRESULT CLR_RT_HeapBlock_Queue::Dequeue( CLR_RT_HeapBlock*& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_INT32 head = Head(); + CLR_RT_HeapBlock* removed; + + if(size == 0) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + + removed = (CLR_RT_HeapBlock*)array->GetElement( head ); + + value = removed->Dereference(); + + removed->SetObjectReference( NULL ); + + SetHead( (head + 1) % array->m_numOfElements ); + + SetSize( size - 1 ); + + NANOCLR_NOCLEANUP(); +} + +// May Trigger GC, but parameter value will be protected +HRESULT CLR_RT_HeapBlock_Queue::Enqueue( CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_INT32 tail = GetTail(); + CLR_INT32 capacity = array->m_numOfElements; + + if(size == capacity) + { + // Set new capacity + CLR_RT_HeapBlock newArrayHB; + + // Protect value from GC, in case CreateInstance triggers one + CLR_RT_HeapBlock valueHB; valueHB.SetObjectReference( value ); + CLR_RT_ProtectFromGC gc( valueHB ); + + capacity *= 2; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( newArrayHB, capacity, g_CLR_RT_WellKnownTypes.m_Object )); + + array = newArrayHB.DereferenceArray(); + + CopyTo( array, 0 ); + + tail = size; + + SetArray( array ); + SetHead ( 0 ); + SetTail ( tail ); + } + + ((CLR_RT_HeapBlock*)array->GetElement( tail ))->SetObjectReference( value ); + + SetTail( (tail + 1) % capacity ); + + SetSize( size + 1 ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Queue::Peek( CLR_RT_HeapBlock*& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(GetSize() == 0) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + + value = ((CLR_RT_HeapBlock*)GetArray()->GetElement( Head() ))->Dereference(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Queue::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_INT32 head = Head(); + CLR_INT32 tail = GetTail(); + + if(size > 0) + { + if(head < tail) + { + NANOCLR_CHECK_HRESULT(array->ClearElements( head, size )); + } + else + { + NANOCLR_CHECK_HRESULT(array->ClearElements( head, array->m_numOfElements - head )); + NANOCLR_CHECK_HRESULT(array->ClearElements( 0 , tail )); + } + + SetSize( 0 ); + } + + SetHead( 0 ); + SetTail( 0 ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Queue::ObjArrayMemcpy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length ) +{ + NANOCLR_HEADER(); + + memcpy( arraySrc->GetElement( indexSrc ), arrayDst->GetElement( indexDst ), length * sizeof(CLR_RT_HeapBlock) ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock_Queue::CopyTo( CLR_RT_HeapBlock_Array* toArray, CLR_INT32 index ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_INT32 head = Head(); + CLR_INT32 tail = GetTail(); + + // if the target array is of type Object, we don't need to call the complex Array::Copy() since there will be no casting involved + HRESULT (*arrayCopy)( CLR_RT_HeapBlock_Array*, int, CLR_RT_HeapBlock_Array*, int, int ) = + (toArray->m_typeOfElement == DATATYPE_OBJECT) ? ObjArrayMemcpy : CLR_RT_HeapBlock_Array::Copy; + + if(((CLR_INT32)toArray->m_numOfElements) - index < size) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + if(size > 0) + { + if(head < tail) + { + NANOCLR_SET_AND_LEAVE(arrayCopy( array, head, toArray, index, size )); + } + else + { + CLR_INT32 firstPart = array->m_numOfElements - head; + + NANOCLR_CHECK_HRESULT(arrayCopy( array, head, toArray, index , firstPart )); + NANOCLR_SET_AND_LEAVE(arrayCopy( array, 0 , toArray, index + firstPart, tail )); + } + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +CT_ASSERT(Library_nf_system_collections_System_Collections_Queue__FIELD___array == Library_nf_system_collections_System_Collections_Queue::FIELD___array); +CT_ASSERT(Library_nf_system_collections_System_Collections_Queue__FIELD___head == Library_nf_system_collections_System_Collections_Queue::FIELD___head ); +CT_ASSERT(Library_nf_system_collections_System_Collections_Queue__FIELD___tail == Library_nf_system_collections_System_Collections_Queue::FIELD___tail ); +CT_ASSERT(Library_nf_system_collections_System_Collections_Queue__FIELD___size == Library_nf_system_collections_System_Collections_Queue::FIELD___size ); + +#endif diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp new file mode 100644 index 00000000..0b64745a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp @@ -0,0 +1,111 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "Core.h" + +#if (NANOCLR_SYSTEM_COLLECTIONS == TRUE) +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CLR_RT_HeapBlock_Stack::Pop( CLR_RT_HeapBlock*& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_RT_HeapBlock* removed; + + if(size == 0) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + + removed = (CLR_RT_HeapBlock*)array->GetElement( array->m_numOfElements - size ); + + value = removed->Dereference(); + + removed->SetObjectReference( NULL ); + + SetSize( size - 1 ); + + NANOCLR_NOCLEANUP(); +} + +// May Trigger GC, but parameter value will be protected +HRESULT CLR_RT_HeapBlock_Stack::Push( CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_INT32 capacity = array->m_numOfElements; + + if(size == capacity) + { + // Set new capacity + CLR_RT_HeapBlock newArrayHB; + CLR_RT_HeapBlock_Array* newArray; + + // Protect value from GC, in case CreateInstance triggers one + CLR_RT_HeapBlock valueHB; valueHB.SetObjectReference( value ); + CLR_RT_ProtectFromGC gc( valueHB ); + + capacity *= 2; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( newArrayHB, capacity, g_CLR_RT_WellKnownTypes.m_Object )); + + newArray = newArrayHB.DereferenceArray(); + + memcpy( newArray->GetElement( size ), array->GetFirstElement(), size * sizeof(CLR_RT_HeapBlock) ); + + SetArray( newArray ); + array = newArray; + } + + size++; + + ((CLR_RT_HeapBlock*)array->GetElement( capacity - size ))->SetObjectReference( value ); + + SetSize( size ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Stack::Peek( CLR_RT_HeapBlock*& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + + if(size == 0) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + + value = ((CLR_RT_HeapBlock*)array->GetElement( array->m_numOfElements - size ))->Dereference(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Stack::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + + NANOCLR_CHECK_HRESULT(array->ClearElements( array->m_numOfElements - size, size )); + + SetSize( 0 ); + + NANOCLR_NOCLEANUP(); +} + +//--// + +CT_ASSERT(Library_nf_system_collections_System_Collections_Stack__FIELD___array == Library_nf_system_collections_System_Collections_Stack::FIELD___array); +CT_ASSERT(Library_nf_system_collections_System_Collections_Stack__FIELD___size == Library_nf_system_collections_System_Collections_Stack::FIELD___size ); + +#endif diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_String.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_String.cpp new file mode 100644 index 00000000..69b849df --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_String.cpp @@ -0,0 +1,116 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_HeapBlock_String* CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 totLength = sizeof(CLR_RT_HeapBlock_String) + length + 1; + CLR_RT_HeapBlock_String* str; + + reference.SetObjectReference( NULL ); + + str = (CLR_RT_HeapBlock_String*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_STRING, 0, totLength ); + if(str) + { + char* szText = (char*)&str[ 1 ]; szText[ 0 ] = 0; + +#if defined(NANOCLR_NO_ASSEMBLY_STRINGS) + str->SetStringText( szText ); +#else + str->SetStringText( szText, NULL ); +#endif + + reference.SetObjectReference( str ); + } + + return str; +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, const char* szText ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(!szText) szText = ""; + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( reference, szText, (CLR_UINT32)hal_strlen_s( szText ) )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, const char* szText, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_String* str; + char* szTextDst; + + str = CreateInstance( reference, length ); CHECK_ALLOCATION(str); + + szTextDst = (char*)str->StringText(); + + memcpy( szTextDst, szText, length ); szTextDst[ length ] = 0; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_String* str; + + reference.SetObjectReference( NULL ); + + str = (CLR_RT_HeapBlock_String*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_STRING, 0, sizeof(CLR_RT_HeapBlock_String) ); CHECK_ALLOCATION(str); + + reference.SetObjectReference( str ); + +#if defined(NANOCLR_NO_ASSEMBLY_STRINGS) + (void)szText; + (void)assm; + + NANOCLR_CHECK_HRESULT( CLR_RT_HeapBlock_String::CreateInstance( reference, szText ) ); +#else + str->SetStringText( szText, assm ); +#endif + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 token, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + return CreateInstance( reference, assm->GetString( CLR_DataFromTk( token ) ), assm ); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT16* szText, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_UnicodeHelper uh; uh.SetInputUTF16 ( szText ); + CLR_UINT32 lengthInBytes = uh.CountNumberOfBytes( length ); + CLR_RT_HeapBlock_String* str = CreateInstance( reference, lengthInBytes ); CHECK_ALLOCATION(str); + + uh.m_outputUTF8 = (CLR_UINT8*)str->StringText(); + uh.m_outputUTF8_size = lengthInBytes + 1; + + uh.ConvertToUTF8( length, false ); + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock_String* CLR_RT_HeapBlock_String::GetStringEmpty() +{ + return g_CLR_RT_TypeSystem.m_assemblyMscorlib->GetStaticField( Library_corlib_native_System_String::FIELD_STATIC__Empty )->DereferenceString(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp new file mode 100644 index 00000000..f04bccb0 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp @@ -0,0 +1,327 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + HRESULT CLR_RT_HeapBlock_Timer::CreateInstance( CLR_UINT32 flags, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& tmRef ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Timer* timer = NULL; + + // + // Create a request and stop the calling thread. + // + timer = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_Timer,DATATYPE_TIMER_HEAD); CHECK_ALLOCATION(timer); + + { + CLR_RT_ProtectFromGC gc( *timer ); + + timer->Initialize(); + + timer->m_flags = flags; + timer->m_timeExpire = TIMEOUT_INFINITE; + timer->m_timeFrequency = TIMEOUT_INFINITE; + timer->m_timeLastExpiration = 0; + timer->m_ticksLastExpiration = 0; + + g_CLR_RT_ExecutionEngine.m_timers.LinkAtBack( timer ); + + NANOCLR_SET_AND_LEAVE(CLR_RT_ObjectToEvent_Source::CreateInstance( timer, owner, tmRef )); + } + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(timer) timer->ReleaseWhenDead(); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_HeapBlock_Timer::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Timer*& timer ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* src = CLR_RT_ObjectToEvent_Source::ExtractInstance( ref ); FAULT_ON_NULL(src); + + timer = (CLR_RT_HeapBlock_Timer*)src->m_eventPtr; + + NANOCLR_NOCLEANUP(); +} + +//--// + +void CLR_RT_HeapBlock_Timer::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + CheckAll(); + + ReleaseWhenDead(); +} + +//--// + +void CLR_RT_HeapBlock_Timer::Trigger() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_references.IsEmpty()) return; + + if(m_flags & CLR_RT_HeapBlock_Timer::c_Executing) + { + return; + } + + m_flags |= CLR_RT_HeapBlock_Timer::c_Triggered; +} + +void CLR_RT_HeapBlock_Timer::SpawnTimer( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + //Only one managed timer max + _ASSERTE(m_references.NumOfNodes() == 1); + + CLR_RT_ObjectToEvent_Source* ref = (CLR_RT_ObjectToEvent_Source*)m_references.FirstValidNode(); + CLR_RT_HeapBlock* managedTimer = ref->m_objectPtr; + CLR_RT_HeapBlock* callback = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD___callback ]; + CLR_RT_HeapBlock* state = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD___state ]; + CLR_RT_HeapBlock_Delegate* delegate = callback->DereferenceDelegate(); + CLR_RT_ProtectFromGC gc( *managedTimer ); + + _ASSERTE(delegate != NULL); if(delegate == NULL) return; + _ASSERTE(delegate->DataType() == DATATYPE_DELEGATE_HEAD); + + m_ticksLastExpiration = HAL_Time_CurrentTime(); + m_timeLastExpiration = m_timeExpire; + m_timeExpire = TIMEOUT_INFINITE; + + if(SUCCEEDED(th->PushThreadProcDelegate( delegate ))) + { + CLR_RT_StackFrame* stack = th->FirstFrame(); + if(stack->Next() != NULL) + { + int numArgs = stack->m_call.m_target->numArgs; + if(numArgs > 0) + { + stack->m_arguments[ numArgs-1 ].Assign( *state ); + } + } + + // + // Associate the timer with the thread. + // + m_flags |= CLR_RT_HeapBlock_Timer::c_Executing; + m_flags &= ~CLR_RT_HeapBlock_Timer::c_Triggered; + + th->m_terminationCallback = CLR_RT_HeapBlock_Timer::ThreadTerminationCallback; + th->m_terminationParameter = this; + } +} + +void CLR_RT_HeapBlock_Timer::ThreadTerminationCallback( void* param ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Timer* pThis = (CLR_RT_HeapBlock_Timer*)param; + + pThis->m_flags &= ~CLR_RT_HeapBlock_Timer::c_Executing; + + pThis->Reschedule(); + + g_CLR_RT_ExecutionEngine.SpawnTimer(); +} + +void CLR_RT_HeapBlock_Timer::Reschedule() +{ + NATIVE_PROFILE_CLR_CORE(); + if((m_flags & CLR_RT_HeapBlock_Timer::c_Recurring ) && + (m_flags & CLR_RT_HeapBlock_Timer::c_EnabledTimer) ) + { + CLR_UINT64 expire = m_timeLastExpiration + m_timeFrequency; + + // + // Normally, adding the 'timeFrequency' will put the expiration in the future. + // + // If we fall back too much, we need to compute the next expiration in the future, to avoid an avalanche effect. + // + if(expire < HAL_Time_CurrentTime()) + { + expire = HAL_Time_CurrentTime() - ((HAL_Time_CurrentTime() - expire) % m_timeFrequency) + m_timeFrequency; + } + + m_timeExpire = expire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + } +} + +//--// + +void CLR_RT_HeapBlock_Timer::AdjustNextFixedExpire( const SYSTEMTIME& systemTime, bool fNext ) +{ + NATIVE_PROFILE_CLR_CORE(); + SYSTEMTIME st = systemTime; + CLR_INT64 baseTime; + CLR_INT64 add; + + CLR_RT_ExecutionEngine::InvalidateTimerCache(); + + switch(m_flags & CLR_RT_HeapBlock_Timer::c_AnyChange) + { + case CLR_RT_HeapBlock_Timer::c_SecondChange: add = TIME_CONVERSION__ONESECOND * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; break; + case CLR_RT_HeapBlock_Timer::c_MinuteChange: add = TIME_CONVERSION__ONEMINUTE * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; st.wSecond = 0; break; + case CLR_RT_HeapBlock_Timer::c_HourChange : add = TIME_CONVERSION__ONEHOUR * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; st.wSecond = 0; st.wMinute = 0; break; + case CLR_RT_HeapBlock_Timer::c_DayChange : add = TIME_CONVERSION__ONEDAY * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; st.wSecond = 0; st.wMinute = 0; st.wHour = 0; break; + + default : return; + } + + st.wMilliseconds = 0; + baseTime = HAL_Time_ConvertFromSystemTime( &st ); + + m_timeExpire = fNext ? baseTime + add : baseTime; + m_timeFrequency = add; + m_flags |= CLR_RT_HeapBlock_Timer::c_Recurring; +} + +bool CLR_RT_HeapBlock_Timer::CheckDisposed( CLR_RT_StackFrame& stack ) +{ + CLR_RT_HeapBlock* pThis = stack.This(); + CLR_RT_HeapBlock_Timer* timer; + + if(!FAILED(CLR_RT_HeapBlock_Timer::ExtractInstance( pThis[ Library_corlib_native_System_Threading_Timer::FIELD___timer ], timer ))) + { + if((timer->m_flags & CLR_RT_HeapBlock_Timer::c_ACTION_Destroy) == 0) + { + return false; + } + } + + return true; +} + +HRESULT CLR_RT_HeapBlock_Timer::ConfigureObject( CLR_RT_StackFrame& stack, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + CLR_RT_HeapBlock* args = &(stack.Arg1()); + CLR_RT_HeapBlock_Timer* timer; + + const CLR_INT64 maxTime = (CLR_INT64)0x7FFFFFFF * (CLR_INT64)TIME_CONVERSION__TO_MILLISECONDS; + const CLR_INT64 minTime = 0; + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Create) + { + FAULT_ON_NULL(args[ 0 ].DereferenceDelegate()); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Timer::CreateInstance( 0, *pThis, pThis[ Library_corlib_native_System_Threading_Timer::FIELD___timer ] )); + + pThis[ Library_corlib_native_System_Threading_Timer::FIELD___callback ].Assign( args[ 0 ] ); + pThis[ Library_corlib_native_System_Threading_Timer::FIELD___state ].Assign( args[ 1 ] ); + + args += 2; + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Timer::ExtractInstance( pThis[ Library_corlib_native_System_Threading_Timer::FIELD___timer ], timer )); + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Create) + { + CLR_UINT32 anyChange = (flags & CLR_RT_HeapBlock_Timer::c_AnyChange); + + if(anyChange) + { + SYSTEMTIME systemTime; HAL_Time_ToSystemTime( HAL_Time_CurrentTime(), &systemTime ); + + timer->m_flags |= anyChange | CLR_RT_HeapBlock_Timer::c_EnabledTimer; + + timer->AdjustNextFixedExpire( systemTime, true ); + } + else + { + flags |= CLR_RT_HeapBlock_Timer::c_ACTION_Change; + } + } + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Destroy) + { + timer->m_flags &= ~CLR_RT_HeapBlock_Timer::c_EnabledTimer; + } + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Change) + { + // + // You cannot change a fixed timer after creation. + // + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_AnyChange) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Int32) + { + timer->m_timeExpire = args[ 0 ].NumericByRef().s4; + timer->m_timeFrequency = args[ 1 ].NumericByRef().s4; + + if (timer->m_timeExpire == -1) timer->m_timeExpire = TIMEOUT_INFINITE; + if (timer->m_timeFrequency == -1) timer->m_timeFrequency = TIMEOUT_INFINITE; + } + else if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_TimeSpan) + { + CLR_INT64* pVal; + + pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( args[ 0 ] ); FAULT_ON_NULL(pVal); + if (*pVal == -c_TickPerMillisecond) timer->m_timeExpire = TIMEOUT_INFINITE; + else timer->m_timeExpire = *pVal; + + pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( args[ 1 ] ); FAULT_ON_NULL(pVal); + if (*pVal == -c_TickPerMillisecond) timer->m_timeFrequency = TIMEOUT_INFINITE; + else timer->m_timeFrequency = *pVal; + } + + if(timer->m_timeExpire == TIMEOUT_INFINITE) + { + timer->m_flags &= ~CLR_RT_HeapBlock_Timer::c_EnabledTimer; + } + else + { + if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Int32) timer->m_timeExpire *= TIME_CONVERSION__TO_MILLISECONDS; + + if (minTime <= timer->m_timeExpire && timer->m_timeExpire <= maxTime) + { + timer->m_timeExpire += HAL_Time_CurrentTime(); + + timer->m_flags |= CLR_RT_HeapBlock_Timer::c_EnabledTimer; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + + if(timer->m_timeFrequency == 0 || timer->m_timeFrequency == TIMEOUT_INFINITE) + { + timer->m_flags &= ~CLR_RT_HeapBlock_Timer::c_Recurring; + } + else + { + if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Int32) timer->m_timeFrequency *= TIME_CONVERSION__TO_MILLISECONDS; + + if(minTime <= timer->m_timeFrequency && timer->m_timeFrequency <= maxTime ) + { + timer->m_flags |= CLR_RT_HeapBlock_Timer::c_Recurring; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + } + + CLR_RT_ExecutionEngine::InvalidateTimerCache(); + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp new file mode 100644 index 00000000..aa42285f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp @@ -0,0 +1,189 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// CreateInstance - Creates a wait object +// +// Result - returns S_OK - if the target object is in the signaled state - indicating no wait is needed +// - returns CLR_E_THREAD_WAITING - if the target object is not signaled - indicating that the caller thread is waiting +// for the object to be signaled +// +HRESULT CLR_RT_HeapBlock_WaitForObject::CreateInstance( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + // + // Create a request and stop the calling thread. + // + + _ASSERTE( sizeof(CLR_RT_HeapBlock_WaitForObject) % 4 == 0 ); + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_WaitForObject) + cObjects * sizeof(CLR_RT_HeapBlock)); + + CLR_RT_HeapBlock_WaitForObject* wait = EVENTCACHE_EXTRACT_NODE_AS_BYTES(g_CLR_RT_EventCache,CLR_RT_HeapBlock_WaitForObject,DATATYPE_WAIT_FOR_OBJECT_HEAD,0,totLength); CHECK_ALLOCATION(wait); + + wait->m_timeExpire = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + wait->m_cObjects = cObjects; + wait->m_fWaitAll = fWaitAll; + + memcpy( wait->GetWaitForObjects(), objects, sizeof(CLR_RT_HeapBlock) * cObjects ); + + caller->m_waitForObject = wait; + caller->m_status = CLR_RT_Thread::TH_S_Waiting; + caller->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_INIT; + + NANOCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_WaitForObject* wait = th->m_waitForObject; + + if(wait) + { + if (CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal( th, wait->GetWaitForObjects(), wait->m_cObjects, wait->m_fWaitAll )) + { + th->Restart( true ); + } + } +} + +bool CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal(CLR_RT_Thread* caller, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* blk; + CLR_RT_HeapBlock* obj; + + if(fWaitAll) + { + //first time through, find out whether or not the requested objects are signaled + //second time through, reset the signalled objects + for(int phase = 0; phase < 2; phase++) + { + blk = objects; + for(CLR_UINT32 i = 0; i < cObjects; i++) + { + obj = blk->Dereference(); + _ASSERTE(obj != NULL); + + if(phase == 0) + { + if(!obj->IsFlagSet( CLR_RT_HeapBlock::HB_Signaled )) + { + return false; + } + } + else + { + if(obj->IsFlagSet( CLR_RT_HeapBlock::HB_SignalAutoReset )) + { + obj->ResetFlags( CLR_RT_HeapBlock::HB_Signaled ); + } + } + + blk++; + } + } + + caller->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_HANDLE_ALL; + return true; + } + else + { + blk = objects; + for(CLR_UINT32 i = 0; i < cObjects; i++) + { + obj = blk->Dereference(); + _ASSERTE(obj != NULL); + + if(obj->IsFlagSet( CLR_RT_HeapBlock::HB_Signaled )) + { + if(obj->IsFlagSet( CLR_RT_HeapBlock::HB_SignalAutoReset )) + { + obj->ResetFlags( CLR_RT_HeapBlock::HB_Signaled ); + } + + caller->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_HANDLE_0 + i; + return true; + } + + blk++; + } + } + + return false; +} + +void CLR_RT_HeapBlock_WaitForObject::SignalObject( CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + object.SetFlags( CLR_RT_HeapBlock::HB_Signaled ); + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal( th ); + + if(!object.IsFlagSet( CLR_RT_HeapBlock::HB_Signaled )) + { + _ASSERTE(object.IsFlagSet( CLR_RT_HeapBlock::HB_SignalAutoReset )); + //This is an AutoResetEvent. Since the event got unsignaled, we can break out of + //the loop early, as this object can only free one thread. + break; + } + } + NANOCLR_FOREACH_NODE_END(); +} + +HRESULT CLR_RT_HeapBlock_WaitForObject::WaitForSignal( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(stack.m_customState == 0) + { + CLR_RT_HeapBlock* objectsT = objects; + + stack.m_customState = 1; + + if(cObjects > 64) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + for(CLR_UINT32 i = 0; i < cObjects; i++) + { + _ASSERTE(objects->DataType() == DATATYPE_OBJECT); + + FAULT_ON_NULL(objectsT->Dereference()); + + objectsT++; + } + + if(!TryWaitForSignal( stack.m_owningThread, objects, cObjects, fWaitAll )) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_WaitForObject::CreateInstance( stack.m_owningThread, timeExpire, objects, cObjects, fWaitAll )); + } + } + + NANOCLR_NOCLEANUP(); +} + + +HRESULT CLR_RT_HeapBlock_WaitForObject::WaitForSignal ( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + return WaitForSignal( stack, timeExpire, &object, 1, false ); +} + +void CLR_RT_HeapBlock_WaitForObject::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( GetWaitForObjects(), m_cObjects ); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapCluster.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapCluster.cpp new file mode 100644 index 00000000..bacf114f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_HeapCluster.cpp @@ -0,0 +1,340 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapCluster::HeapCluster_Initialize( CLR_UINT32 size, CLR_UINT32 blockSize ) +{ + NATIVE_PROFILE_CLR_CORE(); + GenericNode_Initialize(); + + size = (size - sizeof(*this)) / sizeof(CLR_RT_HeapBlock); + + m_freeList.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_freeList; + m_payloadStart = (CLR_RT_HeapBlock_Node*)&this[ 1 ]; // CLR_RT_HeapBlock_Node* m_payloadStart; + m_payloadEnd = &m_payloadStart[ size ]; // CLR_RT_HeapBlock_Node* m_payloadEnd; + + // + // Scan memory looking for possible objects to salvage. This method returns false if HeapPersistence is stubbed + // which requires us to set up the free list. + // + // used to be CLR_RT_HeapBlock_WeakReference::PrepareForRecovery( CLR_RT_HeapBlock_Node* ptr, CLR_RT_HeapBlock_Node* end, CLR_UINT32 blockSize ) + + CLR_RT_HeapBlock_Node* ptr = m_payloadStart; + CLR_RT_HeapBlock_Node* end = m_payloadEnd; + + while(ptr < end) + { + if(ptr->DataType() == DATATYPE_WEAKCLASS) + { + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)ptr; + + if(weak->DataSize() == CONVERTFROMSIZETOHEAPBLOCKS(sizeof(*weak)) && weak->m_targetSerialized != NULL && (weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_SurviveBoot)) + { + weak->SetNext( NULL ); + weak->SetPrev( NULL ); + + weak->m_identity.m_flags &= ~CLR_RT_HeapBlock_WeakReference::WR_Persisted; + + weak->m_targetDirect = NULL; + + weak->MarkAlive(); + + ptr += ptr->DataSize(); + continue; + } + } + else if(ptr->DataType() == DATATYPE_SZARRAY) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + if(array->m_typeOfElement == DATATYPE_U1 && array->m_fReference == 0) + { + CLR_UINT32 tot = sizeof(*array) + array->m_sizeOfElement * array->m_numOfElements; + + if(array->DataSize() == CONVERTFROMSIZETOHEAPBLOCKS(tot) && (ptr + ptr->DataSize()) <= end) + { + array->MarkAlive(); + + ptr += ptr->DataSize(); + continue; + } + } + } + + if((unsigned int)(ptr + blockSize) > (unsigned int)end) + { + blockSize = (CLR_UINT32)(end - ptr); + } + + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,0,blockSize) ); + ptr += blockSize; + } + + while(ptr < m_payloadEnd) + { + if((unsigned int)(ptr + blockSize) > (unsigned int)m_payloadEnd) + { + blockSize = (CLR_UINT32)(m_payloadEnd - ptr); + } + + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,0,blockSize) ); + ptr += blockSize; + } + + RecoverFromGC(); + + m_freeList.ValidateList(); +} + +CLR_RT_HeapBlock* CLR_RT_HeapCluster::ExtractBlocks( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* res = NULL; + CLR_UINT32 available = 0; + + m_freeList.ValidateList(); + + if(flags & CLR_RT_HeapBlock::HB_Event) + { + NANOCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_Node,ptr,m_freeList) + { + available = ptr->DataSize(); + + if(available >= length) + { + res = ptr; + break; + } + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + } + else + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,m_freeList) + { + available = ptr->DataSize(); + + if(available >= length) + { + res = ptr; + break; + } + } + NANOCLR_FOREACH_NODE_END(); + } + + if(res) + { + CLR_RT_HeapBlock_Node* next = res->Next(); + CLR_RT_HeapBlock_Node* prev = res->Prev(); + + available -= length; + + if(available != 0) + { + if(flags & CLR_RT_HeapBlock::HB_Event) + { + res->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,available) ); + + res += available; + } + else + { + CLR_RT_HeapBlock_Node* ptr = &res[ length ]; + + // + // Relink to the new free block. + // + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,available) ); + + ptr->SetNext( next ); + ptr->SetPrev( prev ); + + prev->SetNext( ptr ); + next->SetPrev( ptr ); + } + } + else + { + // + // Unlink the whole block. + // + prev->SetNext( next ); + next->SetPrev( prev ); + } + + res->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dataType,flags,length) ); + + if(flags & CLR_RT_HeapBlock::HB_InitializeToZero) + { + res->InitializeToZero(); + } + else + { + res->Debug_ClearBlock( 0xCB ); + } + } + + m_freeList.ValidateList(); + + return res; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapCluster::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_RT_HeapBlock_Node* ptr = m_payloadStart; + CLR_RT_HeapBlock_Node* end = m_payloadEnd; + + // + // Open the free list. + // + CLR_RT_HeapBlock_Node* last = m_freeList.Head(); last->SetPrev( NULL ); + + while(ptr < end) + { + + ValidateBlock( ptr ); + + if(ptr->IsAlive() == false) + { + CLR_RT_HeapBlock_Node* next = ptr; + CLR_UINT32 lenTot = 0; + + do + { + ValidateBlock( next ); + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectDeletion( next ); +#endif + + NANOCLR_CHECK_EARLY_COLLECTION(next); + + int len = next->DataSize(); + + next += len; + lenTot += len; + + } while(next < end && next->IsAlive() == false); + + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,lenTot) ); + + // + // Link to the free list. + // + last->SetNext( ptr ); + ptr ->SetPrev( last ); + last = ptr; + + ptr->Debug_ClearBlock( 0xDF ); + + ptr = next; + } + else + { + if(ptr->IsEvent() == false) ptr->MarkDead(); + + ptr += ptr->DataSize(); + } + } + + // + // Close the free list. + // + last ->SetNext( m_freeList.Tail() ); + m_freeList.Tail()->SetPrev( last ); + m_freeList.Tail()->SetNext( NULL ); +} + +CLR_RT_HeapBlock_Node* CLR_RT_HeapCluster::InsertInOrder( CLR_RT_HeapBlock_Node* node, CLR_UINT32 size ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr; + + NANOCLR_FOREACH_NODE__NODECL(CLR_RT_HeapBlock_Node,ptr,m_freeList) + { + if(ptr > node) break; + } + NANOCLR_FOREACH_NODE_END(); + + node->ClearData(); m_freeList.InsertBeforeNode( ptr, node ); + + // + // Try to coalesce with the following free block. + // + ptr = node->Next(); + if(ptr->Next() && (node + size) == ptr) + { + size += ptr->DataSize(); ptr->Unlink(); + } + + // + // Try to coalesce with the preceding free block. + // + ptr = node->Prev(); + if(ptr->Prev() && (ptr + ptr->DataSize()) == node) + { + size += ptr->DataSize(); node->Unlink(); node = ptr; + } + + node->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,size ) ); + node->Debug_ClearBlock( 0xCF ); + + return node; +} + +//--// + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink + +void CLR_RT_HeapCluster::ValidateBlock( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + + while(true) + { + if(ptr < m_payloadStart || ptr >= m_payloadEnd) + { + CLR_Debug::Printf( "Block beyond cluster limits: %08x [%08x : %08x-%08x]\r\n", (size_t)ptr, (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + if(ptr->DataType() >= DATATYPE_FIRST_INVALID) + { + CLR_Debug::Printf( "Bad Block Type: %08x %02x [%08x : %08x-%08x]\r\n", (size_t)ptr, ptr->DataType(), (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + if(ptr->DataSize() == 0) + { + CLR_Debug::Printf( "Bad Block null-size: %08x [%08x : %08x-%08x]\r\n", (size_t)ptr, (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + if(ptr + ptr->DataSize() > m_payloadEnd) + { + CLR_Debug::Printf( "Bad Block size: %d %08x [%08x : %08x-%08x]\r\n", ptr->DataSize(), (size_t)ptr, (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + return; + } + + NANOCLR_DEBUG_STOP(); +} + +#endif + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_Interop.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_Interop.cpp new file mode 100644 index 00000000..b49ac2e5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_Interop.cpp @@ -0,0 +1,813 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "Core.h" + + +/********************************************************************** +** Macro: NANOCLR_INTEROP_CHECK_ARG_TYPE +** This macro is specific for Interop_Marshal_ functions. +** It checks that data type corresponds to the data type stored in heapblock +** in parameter paramIndex. +** In release mode macro does nothing. +**********************************************************************/ + + +// For the final product we disable checking of the argument types +// NANOCLR_INTEROP_CHECK_ARG_TYPE is reduced to nothing. +#define NANOCLR_INTEROP_CHECK_ARG_TYPE( arg_type ) +#define NANOCLR_INTEROP_NOCLEANUP() return S_OK; + + +HRESULT Interop_Marshal_bool( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, bool ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4); +// The comparison with 0 converts numeric type "u1" to boolean type. + param = stackFrame.ArgN( paramIndex ).NumericByRef().u1 != 0; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT8( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, unsigned char ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4); + param = stackFrame.ArgN( paramIndex ).NumericByRef().u1; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT16( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed short ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4) + param = stackFrame.ArgN( paramIndex ).NumericByRef().u2; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT32( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed int ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4) + param = stackFrame.ArgN( paramIndex ).NumericByRef().u4; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT64( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, unsigned __int64 ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I8); + param = stackFrame.ArgN( paramIndex ).NumericByRef().u8; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_CHAR( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, char ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4) + param = stackFrame.ArgN( paramIndex ).NumericByRef().s1; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT8( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed char ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4) + param = stackFrame.ArgN( paramIndex ).NumericByRef().s1; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT16( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed short ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4); + param = stackFrame.ArgN( paramIndex ).NumericByRef().s2; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT32( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed int ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4); + param = stackFrame.ArgN( paramIndex ).NumericByRef().s4; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT64( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed __int64 ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I8); + param = stackFrame.ArgN( paramIndex ).NumericByRef().s8; + NANOCLR_INTEROP_NOCLEANUP(); +} + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + +HRESULT Interop_Marshal_float( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, float ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_R4); + param = stackFrame.ArgN( paramIndex ).NumericByRef().r4; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_double( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, double ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_R8); + param = stackFrame.ArgN( paramIndex ).NumericByRef().r8; + NANOCLR_INTEROP_NOCLEANUP(); +} +#else +HRESULT Interop_Marshal_float( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed int ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_R4); + param = stackFrame.ArgN( paramIndex ).NumericByRef().r4; + NANOCLR_INTEROP_NOCLEANUP(); +} + +HRESULT Interop_Marshal_double( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed __int64 ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_R8); + param = stackFrame.ArgN( paramIndex ).NumericByRef().r8; + NANOCLR_INTEROP_NOCLEANUP(); +} + +#endif + +HRESULT Interop_Marshal_LPCSTR( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, const char* ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + // Check the type of passed varialble - should be object for strings. + if ( stackFrame.ArgN( paramIndex ).DataType() != DATATYPE_OBJECT ) + { NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // Checks that the string was actually present in managed code, not a NULL reference to sting. + param = stackFrame.ArgN( paramIndex ).RecoverString(); FAULT_ON_NULL(param); + + NANOCLR_NOCLEANUP(); +} + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +// For unsupported types we set param to zero and always return S_OK. +HRESULT Interop_Marshal_UNSUPPORTED_TYPE( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, UNSUPPORTED_TYPE ¶m ) +{ + NATIVE_PROFILE_CLR_CORE(); + param = NULL; + return S_OK; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +#undef NANOCLR_INTEROP_CHECK_ARG_TYPE +/********************************************************************** +** +** Function: Interop_Marshal_NUMERIC_ARRAY +** +** Synopsis: This function is used marshal arrays of basic types created by managed code. +** The native code can access and update array data. +** Thus the data can be exchanged between managed and native code in both directions. +** The native code cannot change size of array. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** [pByteParam] - Reference of pointer to buffer with array data. Filled by the function +** [arraySize] - Count of elements in array. Filled by the function +** [elementSize] - Size of array element in bytes. +** +** Returns: S_OK on success or error from StoreToReference. Error return would cause exception thrown in managed code. +**********************************************************************/ +template +static HRESULT Interop_Marshal_NUMERIC_ARRAY +( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, T *&pByteParam, unsigned int &arraySize, unsigned int elementSize ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array *pHeapBlockArray = NULL; + + if ( stackFrame.ArgN( paramIndex ).DataType() != DATATYPE_OBJECT ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + pHeapBlockArray = stackFrame.ArgN( paramIndex ).DereferenceArray(); FAULT_ON_NULL(pHeapBlockArray); + + if ( pHeapBlockArray->m_sizeOfElement != elementSize ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + arraySize = pHeapBlockArray->m_numOfElements; + pByteParam = (T *)pHeapBlockArray->GetFirstElement(); + + NANOCLR_NOCLEANUP(); +} + +/********************************************************************** +** Group of function that retrive array of values from managed stack frame. +** All these functions are wrappers around Interop_Marshal_NUMERIC_ARRAY, +** they create type safe interface for users of Interop library. +**********************************************************************/ +HRESULT Interop_Marshal_bool_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT8 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( unsigned char ) ); +} + +HRESULT Interop_Marshal_UINT8_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT8 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( unsigned char ) ); +} + +HRESULT Interop_Marshal_UINT16_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT16 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( unsigned short ) ); +} + +HRESULT Interop_Marshal_UINT32_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT32 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( unsigned int ) ); +} + +HRESULT Interop_Marshal_UINT64_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT64 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( unsigned __int64 ) ); +} + +HRESULT Interop_Marshal_CHAR_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_CHAR &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( char ) ); +} + +HRESULT Interop_Marshal_INT8_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT8 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( signed char ) ); +} + +HRESULT Interop_Marshal_INT16_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT16 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( signed short ) ); +} + +HRESULT Interop_Marshal_INT32_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT32 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( signed int ) ); +} + +HRESULT Interop_Marshal_INT64_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT64 &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( signed __int64 ) ); +} + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +HRESULT Interop_Marshal_float_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_float &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( float ) ); +} + +HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_double &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( double ) ); +} +#else + +HRESULT Interop_Marshal_float_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_float &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( signed int ) ); +} + +HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_double &typedArray ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Interop_Marshal_NUMERIC_ARRAY( stackFrame, paramIndex, typedArray.m_pData, typedArray.m_ElemCount, sizeof( signed __int64 ) ); +} + +#endif + + +/********************************************************************** +** +** Functions: SetResult_* +** +** Synopsis: This group of functions set result returned by native function to managed stack frame. +** It stores data from heap block pointed by pVoidHeapBlock back to the managed stack frame. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [pVoidHeapBlock] - Pointer to heap block that keeps updated basic type value +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** +** Returns: S_OK on success or error from StoreToReference. Error return would cause exception thrown in managed code. +**********************************************************************/ + +void SetResult_bool( CLR_RT_StackFrame &stackFrame, bool value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_Boolean( value ); +} + +void SetResult_CHAR( CLR_RT_StackFrame &stackFrame, char value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult( value, DATATYPE_I1 ); +} + +void SetResult_INT8( CLR_RT_StackFrame &stackFrame, signed char value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult( value, DATATYPE_I1 ); +} + +void SetResult_INT16( CLR_RT_StackFrame &stackFrame, signed short value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult( value, DATATYPE_I2 ); +} + +void SetResult_INT32( CLR_RT_StackFrame &stackFrame, signed int value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult( value, DATATYPE_I4 ); +} + +void SetResult_INT64( CLR_RT_StackFrame &stackFrame, signed __int64 value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_I8( value ); +} + +void SetResult_UINT8( CLR_RT_StackFrame &stackFrame, unsigned char value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult( value, DATATYPE_U1 ); +} + +void SetResult_UINT16( CLR_RT_StackFrame &stackFrame, signed short value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult( value, DATATYPE_U2 ); +} + +void SetResult_UINT32( CLR_RT_StackFrame &stackFrame, signed int value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult( value, DATATYPE_U4 ); +} + +void SetResult_UINT64( CLR_RT_StackFrame &stackFrame, unsigned __int64 value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_U8( value ); +} +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +void SetResult_float( CLR_RT_StackFrame &stackFrame, float value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_R4( value ); +} + +void SetResult_double( CLR_RT_StackFrame &stackFrame, double value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_R8( value ); +} +#else +void SetResult_float( CLR_RT_StackFrame &stackFrame, CLR_INT32 value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_R4( value ); +} + +void SetResult_double( CLR_RT_StackFrame &stackFrame, CLR_INT64& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_R8( value ); +} +#endif + +void SetResult_LPCSTR( CLR_RT_StackFrame &stackFrame, const char* lpszString ) +{ + NATIVE_PROFILE_CLR_CORE(); + stackFrame.SetResult_String( lpszString ); +} + +/********************************************************************** +** +** Group of function that retrive reference to particular type from managed stack frame. +** This function hides CLR_RT_HeapBlock structure. +** +** Functions: Interop_Marshal_*_ByRef +** +** Synopsis: For paramenters passed by reference gets the +** reference to basic type parameter. +** After the call the pParam points to variable passed by reference from managed code. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [pHeapBlock] - Pointer to heap block that keeps reference type extracted from managed stack frame +** [paramIndex] - Index of parameter passed from managed code. +** [pParam] - Pointer to variable passed by reference from managed code. Filled by function. +** +** Returns: S_OK on success or error from LoadFromReference of CLR_E_WRONG_TYPE if type invalid. Error return would cause exception thrown in managed code. +**********************************************************************/ + +/********************************************************************** +** Macro: NANOCLR_INTEROP_CHECK_REF_TYPE +** This macro is specific for Interop_Marshal_*_ByRef functions. +** It checks that retrived type corresponds to the data type stored in heapblock +** in parameter paramIndex. +** In release mode macro does nothing. +**********************************************************************/ + +#if defined(_DEBUG) + +// In debug mode check reference type. +#define NANOCLR_INTEROP_CHECK_REF_TYPE( ref_type ) \ +if ( ((CLR_RT_HeapBlock *)pHeapBlock)->DataType() != ref_type ) \ +{ \ + NANOCLR_SET_AND_LEAVE( CLR_E_WRONG_TYPE ); \ +} + +#else // Not defined _DEBUG, means we are in release mode - do nothing. + +#define NANOCLR_INTEROP_CHECK_REF_TYPE( ref_type ) + +#endif + +//------------------ Unsigned Integral types ---------------------------------------------------------------------------- +HRESULT Interop_Marshal_bool_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned char *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + // Declare hRes ( #define NANOCLR_HEADER() HRESULT hr ) + NANOCLR_HEADER(); + + // Loads heapblock data from heapblock in managed stack frame + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + + // Validates that data in heapblock correspond to requested parameter. + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_U1) + + // Now we have initialized pHeapBlock with reference paramenter. + // Need to cast the pointer because &s1 is "CLR_INT8 *", while we need "bool *" + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().u1; + + // Return S_OK or error if there is "go to" from NANOCLR_CHECK_HRESULT or NANOCLR_SET_AND_LEAVE + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT8_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned char *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_U1) + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().u1; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT16_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned short *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_U2) + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().u2; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT32_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned int *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_U4) + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().u4; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_UINT64_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned __int64 *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_U8) + pParam = (unsigned __int64 *)&((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().u8; + NANOCLR_NOCLEANUP(); +} + +//------------------ Signed Integral types ---------------------------------------------------------------------------- +HRESULT Interop_Marshal_CHAR_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, char *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_CHAR) + pParam = (char *)&((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().s1; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT8_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed char *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + // signed char servers for both boolean and sbyte types. So we check for either of them. +#if defined(_DEBUG) + if ( !( ((CLR_RT_HeapBlock *)pHeapBlock)->DataType() == DATATYPE_I1 || + ((CLR_RT_HeapBlock *)pHeapBlock)->DataType() == DATATYPE_BOOLEAN ) + ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } +#endif + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().s1; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT16_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed short *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_I2) + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().s2; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT32_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed int *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_I4) + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().s4; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_INT64_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed __int64 *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_I8) + pParam = (signed __int64 *)&((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().s8; + NANOCLR_NOCLEANUP(); +} + +//----------------- Float point types - float and double +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + +HRESULT Interop_Marshal_float_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, float *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_R4) + pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().r4; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_double_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, double *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_R8) + pParam = (double *)&((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().r8; + NANOCLR_NOCLEANUP(); +} + + +//----------------- Non Float point types - float and double +#else +HRESULT Interop_Marshal_float_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed int *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_R4) + pParam = (signed int *)&((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().r4; + NANOCLR_NOCLEANUP(); +} + +HRESULT Interop_Marshal_double_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed __int64* &pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + NANOCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_R8) + pParam = (signed __int64 *)&((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().r8; + NANOCLR_NOCLEANUP(); +} + +#endif +HRESULT Interop_Marshal_UNSUPPORTED_TYPE_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, UNSUPPORTED_TYPE *&pParam ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + NANOCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) )); + pParam = NULL; + NANOCLR_NOCLEANUP(); +} + + +#undef NANOCLR_INTEROP_CHECK_REF_TYPE + + +/********************************************************************** +** +** Function: Interop_Marshal_StoreRef +** +** Synopsis: Stores data from the heap block passed in pVoidHeapBlock back to managed stack frame. +** Thus the managed stack frame and application may receive modified value of variable passed by reference.. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [pVoidHeapBlock] - Pointer to heap block that keeps updated value of variable passed by reference. +** [paramIndex] - Index of parameter passed from managed code. +** +** Returns: S_OK on success or error from StoreToReference. Error return would cause exception thrown in managed code. +**********************************************************************/ + +HRESULT Interop_Marshal_StoreRef( CLR_RT_StackFrame &stackFrame, void *pVoidHeapBlock, unsigned int paramIndex ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_HeapBlock *pHeapBlock = (CLR_RT_HeapBlock *)pVoidHeapBlock; + NANOCLR_CHECK_HRESULT(pHeapBlock->StoreToReference( stackFrame.ArgN(paramIndex), 0 )); + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock* Interop_Marshal_RetrieveManagedObject( CLR_RT_StackFrame &stackFrame ) + +{ + return stackFrame.This(); +} + +/********************************************************************** +** +** Functions: Interop_Marshal_GetField_ +** +** Synopsis: Retrieves C++ reference ( pointer ) to the field in managed object. +** +** Arguments: [pThis] - Pointer to the managed object retrieved by Interop_Marshal_RetrieveManagedObject. +** [fieldIndex] - Field index. +** +** Returns: Reference to the field. +**********************************************************************/ + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + +bool &Interop_Marshal_GetField_bool( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (bool&)pThis[ fieldIndex ].NumericByRef().u1; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +unsigned char &Interop_Marshal_GetField_UINT8( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return pThis[ fieldIndex ].NumericByRef().u1; +} + +unsigned short &Interop_Marshal_GetField_UINT16( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return pThis[ fieldIndex ].NumericByRef().u2; +} + +unsigned int &Interop_Marshal_GetField_UINT32( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return pThis[ fieldIndex ].NumericByRef().u4; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + +unsigned __int64 &Interop_Marshal_GetField_UINT64( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (unsigned __int64 &)pThis[ fieldIndex ].NumericByRef().u8; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +char &Interop_Marshal_GetField_CHAR( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (char &)pThis[ fieldIndex ].NumericByRef().s1; +} + +signed char &Interop_Marshal_GetField_INT8( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return pThis[ fieldIndex ].NumericByRef().s1; +} + +signed short &Interop_Marshal_GetField_INT16( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return pThis[ fieldIndex ].NumericByRef().s2; +} + +signed int &Interop_Marshal_GetField_INT32( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return pThis[ fieldIndex ].NumericByRef().s4; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + +signed __int64 &Interop_Marshal_GetField_INT64( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (signed __int64 &)pThis[ fieldIndex ].NumericByRef().s8; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +//----------------- Float point types - float and double +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + +float &Interop_Marshal_GetField_float( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return pThis[ fieldIndex ].NumericByRef().r4; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + +double &Interop_Marshal_GetField_double( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (double &)pThis[ fieldIndex ].NumericByRef().r8; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +#else + +signed int &Interop_Marshal_GetField_float( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (signed int &) pThis[ fieldIndex ].NumericByRef().r4; +} + +signed __int64 &Interop_Marshal_GetField_double( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (signed __int64 &)pThis[ fieldIndex ].NumericByRef().r8; +} + + +#endif + +#if defined(__arm) +#pragma push +#pragma diag_suppress 284 +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +UNSUPPORTED_TYPE &Interop_Marshal_GetField_UNSUPPORTED_TYPE( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ) +{ + return (UNSUPPORTED_TYPE &)(*((UNSUPPORTED_TYPE *)NULL)); +} +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#if defined(__arm) +#pragma pop +#endif + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_Memory.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_Memory.cpp new file mode 100644 index 00000000..493bf048 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_Memory.cpp @@ -0,0 +1,208 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_TRACE_MALLOC) +static CLR_UINT32 s_TotalAllocated; +#endif + +CLR_RT_MemoryRange s_CLR_RT_Heap = { 0, 0 }; + +static int s_PreHeapInitIndex = 0; + +//////////////////////////////////////////////////////////// + + + +//--// + +void CLR_RT_Memory::Reset() +{ + NATIVE_PROFILE_CLR_CORE(); + ::HeapLocation( s_CLR_RT_Heap.m_location, s_CLR_RT_Heap.m_size ); + +#if defined(NANOCLR_TRACE_MALLOC) + s_TotalAllocated = 0; +#endif +} + +void* CLR_RT_Memory::SubtractFromSystem( size_t len ) +{ + NATIVE_PROFILE_CLR_CORE(); + len = ROUNDTOMULTIPLE(len,CLR_UINT32); + + if(len <= s_CLR_RT_Heap.m_size) + { + s_CLR_RT_Heap.m_size -= (CLR_UINT32)len; + + return &s_CLR_RT_Heap.m_location[ s_CLR_RT_Heap.m_size ]; + } + + return NULL; +} + +//--// + +#if defined(NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + +#define DEBUG_POINTER_INCREMENT(ptr,size) ptr = (void*)((char*)ptr + (size)) +#define DEBUG_POINTER_DECREMENT(ptr,size) ptr = (void*)((char*)ptr - (size)) + +const CLR_UINT32 c_extra = sizeof(CLR_RT_HeapBlock) * 2; + +#endif + + +void CLR_RT_Memory::Release( void* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + + // CLR heap not initialized yet, return (this is not an error condition because we allow pre + if(s_CLR_RT_Heap.m_size == 0) + { + return; + } + + if(ptr) + { +#if defined(NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + DEBUG_POINTER_DECREMENT(ptr,c_extra+sizeof(CLR_UINT32)); +#endif + + CLR_RT_HeapBlock_BinaryBlob* pThis = CLR_RT_HeapBlock_BinaryBlob::GetBlob( ptr ); + + if(pThis->DataType() != DATATYPE_BINARY_BLOB_HEAD) + { + NANOCLR_STOP(); + } + else + { +#if defined(NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + CLR_UINT32 len = *(CLR_UINT32*)ptr; + CLR_UINT8* blk; + CLR_UINT32 pos; + + for(pos=0, blk=(CLR_UINT8*)ptr + sizeof(len); posDataSize(); + CLR_Debug::Printf( "CLR_RT_Memory::Release : %08x = %3d blocks (tot %4d)\r\n", ptr, pThis->DataSize(), s_TotalAllocated ); +#endif + + pThis->Release( true ); + } + } +} + +void* CLR_RT_Memory::Allocate( size_t len, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(s_CLR_RT_Heap.m_size == 0) + { + unsigned char* heapStart = NULL; + unsigned int heapSize = 0; + + ::HeapLocation( heapStart, heapSize ); + + if(len > heapSize) + { + ASSERT(false); + return NULL; + + } + + // use the current index to prevent heap thrashing before initialization + heapStart = &heapStart[ s_PreHeapInitIndex ]; + + s_PreHeapInitIndex += len; + + return heapStart; + } + + flags |= CLR_RT_HeapBlock::HB_Event; + +#if defined(NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + len += c_extra * 2 + sizeof(CLR_UINT32); +#endif + + CLR_RT_HeapBlock_BinaryBlob* obj = CLR_RT_HeapBlock_BinaryBlob::Allocate( (CLR_UINT32)len, flags ); + if(obj) + { + void* res = obj->GetData(); + +#if defined(NANOCLR_TRACE_MALLOC) + s_TotalAllocated += obj->DataSize(); + CLR_Debug::Printf( "CLR_RT_Memory::Allocate: %08x = %3d blocks (tot %4d), %d bytes\r\n", res, obj->DataSize(), s_TotalAllocated, len ); +#endif + +#if defined(NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + memset( res, 0xDD, len ); + + *(CLR_UINT32*)res = (CLR_UINT32)len; + + DEBUG_POINTER_INCREMENT(res,c_extra+sizeof(CLR_UINT32)); +#endif + + return res; + } + + return NULL; +} + +void* CLR_RT_Memory::Allocate_And_Erase( size_t len, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + void* ptr = CLR_RT_Memory::Allocate( len, flags ); + + if(ptr) ZeroFill( ptr, len ); + + return ptr; +} + + +void* CLR_RT_Memory::ReAllocate( void* ptr, size_t len ) +{ + NATIVE_PROFILE_CLR_CORE(); + + // allocate always as an event but do not run GC on failure + void* p = CLR_RT_Memory::Allocate( len, CLR_RT_HeapBlock::HB_Event | CLR_RT_HeapBlock::HB_NoGcOnFailedAllocation); if(!p) return NULL; + + if(ptr) + { + CLR_RT_HeapBlock_BinaryBlob* pThis = CLR_RT_HeapBlock_BinaryBlob::GetBlob( ptr ); + + size_t prevLen = pThis->DataSize() * sizeof(CLR_RT_HeapBlock); + + memcpy( p, ptr, len > prevLen ? prevLen : len ); + + CLR_RT_Memory::Release( ptr ); + + ptr = p; + } + + return p; +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp new file mode 100644 index 00000000..6f11dad9 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_ObjectToEvent_Destination::Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + m_references.DblLinkedList_Initialize(); +} + +void CLR_RT_ObjectToEvent_Destination::CheckAll() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,m_references) + { + ref->EnsureObjectIsAlive(); + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ObjectToEvent_Destination::SignalAll() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,m_references) + { + if(ref->m_objectPtr) + { + CLR_RT_HeapBlock_WaitForObject::SignalObject( *ref->m_objectPtr ); + } + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ObjectToEvent_Destination::DetachAll() +{ + NATIVE_PROFILE_CLR_CORE(); + while(true) + { + CLR_RT_ObjectToEvent_Source* ref = (CLR_RT_ObjectToEvent_Source*)m_references.ExtractFirstNode(); if(!ref) break; + + ref->Detach(); + } +} + +bool CLR_RT_ObjectToEvent_Destination::IsReadyForRelease() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_references.IsEmpty()) + { + if(IsForcedAlive() == false) + { + return true; + } + } + + return false; +} + +bool CLR_RT_ObjectToEvent_Destination::ReleaseWhenDead() +{ + NATIVE_PROFILE_CLR_CORE(); + bool res = IsReadyForRelease(); + + if(res) g_CLR_RT_EventCache.Append_Node( this ); + + return res; +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp new file mode 100644 index 00000000..57dbe957 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_ObjectToEvent_Source::CreateInstance( CLR_RT_ObjectToEvent_Destination* event, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock& reference ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* oe = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_ObjectToEvent_Source,DATATYPE_OBJECT_TO_EVENT); CHECK_ALLOCATION(oe); + + oe->m_eventPtr = event; // Pointer to the event referenced. + + oe->m_objectPtr = &object; // Pointer to the object to keep alive. + oe->m_referencePtr = &reference; // Pointer to the HeapBlock referencing this structure. + + reference.SetObjectReference( oe ); + + event->m_references.LinkAtBack( oe ); + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_ObjectToEvent_Source* CLR_RT_ObjectToEvent_Source::ExtractInstance( CLR_RT_HeapBlock& reference ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(reference.IsAReferenceOfThisType( DATATYPE_OBJECT_TO_EVENT ) == false) return NULL; + + return (CLR_RT_ObjectToEvent_Source*)reference.Dereference(); +} + + +void CLR_RT_ObjectToEvent_Source::EnsureObjectIsAlive() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_objectPtr && m_objectPtr->IsAlive()) return; + + Detach(); +} + +void CLR_RT_ObjectToEvent_Source::Detach() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_referencePtr) + { + m_referencePtr->SetObjectReference( NULL ); + } + + g_CLR_RT_EventCache.Append_Node( this ); +} + +void CLR_RT_ObjectToEvent_Source::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_objectPtr ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_referencePtr ); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_RuntimeMemory.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_RuntimeMemory.cpp new file mode 100644 index 00000000..0a5902e2 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_RuntimeMemory.cpp @@ -0,0 +1,136 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "nanoCLR_Interop.h" + +//////////////////////////////////////// +// !!! DO NOT EDIT THIS FILE !!! + +#define LINK_SIZE_BYTES 4 +#define PAYLOAD_SIZE_BYTES 12 +#define INTERRUPT_RECORD_SIZE_BYTES 24 +#define INLINE_SIZE_BYTES (8 * sizeof(int*) + sizeof(int)) + +#define ENTRY_SIZE__extrasmall 32 +#define HASH_TABLE_ENTRY__extrasmall 9 +#define INTERRUPT_RECORDS__extrasmall 16 +#define INLINE_BUFFER__extrasmall 16 + +#define ENTRY_SIZE__small 128 +#define HASH_TABLE_ENTRY__small 33 +#define INTERRUPT_RECORDS__small 64 +#define INLINE_BUFFER__small 32 + +#define ENTRY_SIZE__medium 512 +#define HASH_TABLE_ENTRY__medium 129 +#define INTERRUPT_RECORDS__medium 128 +#define INLINE_BUFFER__medium 64 + +#define ENTRY_SIZE__large 2048 +#define HASH_TABLE_ENTRY__large 521 +#define INTERRUPT_RECORDS__large 512 +#define INLINE_BUFFER__large 128 + +///////////////////////////////////////////// +// undefine everything and define defaults +#ifdef PLATFORM_DEPENDENT_ENTRY_SIZE +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#endif +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__medium + +#ifdef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#endif +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__medium + +#ifdef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#endif +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__medium + +#ifdef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#endif +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__medium + +// undefine everything and define defaults +///////////////////////////////////////////// + +//////////////////////////////////////////////////////// +// apply user selection from platform_selector.h file +#ifdef RUNTIME_MEMORY_PROFILE__extrasmall +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__extrasmall +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__extrasmall +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__extrasmall +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__extrasmall +#endif + +#ifdef RUNTIME_MEMORY_PROFILE__small +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__small +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__small +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__small +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__small +#endif + +#ifdef RUNTIME_MEMORY_PROFILE__medium +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__medium +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__medium +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__medium +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__medium +#endif + +#ifdef RUNTIME_MEMORY_PROFILE__large +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__large +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__large +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__large +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__large +#endif +// apply user selection from platform_selector.h file +//////////////////////////////////////////////////////// + +//--// + +size_t LinkArraySize () { return (PLATFORM_DEPENDENT_ENTRY_SIZE + PLATFORM_DEPENDENT_HASH_TABLE_SIZE); } +size_t LinkMRUArraySize() { return (PLATFORM_DEPENDENT_ENTRY_SIZE + 1 ); } +size_t PayloadArraySize() { return PLATFORM_DEPENDENT_ENTRY_SIZE; } +#ifndef CLR_NO_IL_INLINE +size_t InlineBufferCount() { return PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE; } +#endif + +unsigned int g_scratchVirtualMethodTableLink [ LINK_SIZE_BYTES * (PLATFORM_DEPENDENT_ENTRY_SIZE + PLATFORM_DEPENDENT_HASH_TABLE_SIZE) / sizeof(unsigned int) + 1 ]; +unsigned int g_scratchVirtualMethodTableLinkMRU[ LINK_SIZE_BYTES * (PLATFORM_DEPENDENT_ENTRY_SIZE + 1 ) / sizeof(unsigned int) + 1 ]; +unsigned int g_scratchVirtualMethodPayload [ PAYLOAD_SIZE_BYTES * PLATFORM_DEPENDENT_ENTRY_SIZE / sizeof(unsigned int) + 1 ]; + +#ifndef CLR_NO_IL_INLINE +unsigned int g_scratchInlineBuffer[ INLINE_SIZE_BYTES * PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE / sizeof(unsigned int) + 1 ]; +#endif + +//--// + +size_t InterruptRecords() { return PLATFORM_DEPENDENT_INTERRUPT_RECORDS; } + +unsigned int g_scratchInterruptDispatchingStorage[ (PLATFORM_DEPENDENT_INTERRUPT_RECORDS * INTERRUPT_RECORD_SIZE_BYTES) / sizeof(unsigned int) + 1 ]; + +//--// + +// !!! DO NOT EDIT THIS FILE !!! +//////////////////////////////////////// + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_StackFrame.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_StackFrame.cpp new file mode 100644 index 00000000..d52684a3 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_StackFrame.cpp @@ -0,0 +1,1208 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_StackFrame::Push( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_INT32 extraBlocks ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* stack; + CLR_RT_StackFrame* caller; + CLR_RT_Assembly* assm; + const CLR_RECORD_METHODDEF* md; + const CLR_RT_MethodDef_Instance* callInstPtr = &callInst; + CLR_UINT32 sizeLocals; + CLR_UINT32 sizeEvalStack; + +#if defined(PLATFORM_WINDOWS_EMULATOR) + if(s_CLR_RT_fTrace_SimulateSpeed > c_CLR_RT_Trace_None) + { + CLR_PROF_Handler::SuspendTime(); + + HAL_Windows_FastSleep( g_HAL_Configuration_Windows.TicksPerMethodCall ); + + CLR_PROF_Handler::ResumeTime(); + } +#endif + + assm = callInstPtr->m_assm; + md = callInstPtr->m_target; + + sizeLocals = md->numLocals; +#ifndef CLR_NO_IL_INLINE + sizeEvalStack = md->lengthEvalStack + CLR_RT_StackFrame::c_OverheadForNewObjOrInteropMethod + 1; +#else + sizeEvalStack = md->lengthEvalStack + CLR_RT_StackFrame::c_OverheadForNewObjOrInteropMethod; +#endif + + //--// + + caller = th->CurrentFrame(); + + //--// + + // + // Allocate memory for the runtime state. + // + { + CLR_UINT32 memorySize = sizeLocals + sizeEvalStack; + + if(extraBlocks > 0 ) memorySize += extraBlocks; +#ifndef CLR_NO_IL_INLINE + if(memorySize < c_MinimumStack) + { + sizeEvalStack += c_MinimumStack - memorySize; + memorySize = c_MinimumStack; + } +#else + if(memorySize < c_MinimumStack) memorySize = c_MinimumStack; +#endif + + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Winvalid-offsetof" + #endif + + memorySize += CONVERTFROMSIZETOHEAPBLOCKS(offsetof(CLR_RT_StackFrame,m_extension)); + + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + + stack = EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(g_CLR_RT_EventCache,CLR_RT_StackFrame,DATATYPE_STACK_FRAME,0,memorySize); CHECK_ALLOCATION(stack); + } + + //--// + + { // + stack->m_owningSubThread = th->CurrentSubThread(); // CLR_RT_SubThread* m_owningSubThread; // EVENT HEAP - NO RELOCATION - + stack->m_owningThread = th; // CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + // CLR_UINT32 m_flags; + // + stack->m_call = *callInstPtr; // CLR_RT_MethodDef_Instance m_call; + // + // CLR_RT_MethodHandler m_nativeMethod; + // CLR_PMETADATA m_IPstart; // ANY HEAP - DO RELOCATION - + // CLR_PMETADATA m_IP; // ANY HEAP - DO RELOCATION - + // + stack->m_locals = stack->m_extension; // CLR_RT_HeapBlock* m_locals; // EVENT HEAP - NO RELOCATION - + stack->m_evalStack = stack->m_extension + sizeLocals; // CLR_RT_HeapBlock* m_evalStack; // EVENT HEAP - NO RELOCATION - + stack->m_evalStackPos = stack->m_evalStack; // CLR_RT_HeapBlock* m_evalStackPos; // EVENT HEAP - NO RELOCATION - + stack->m_evalStackEnd = stack->m_evalStack + sizeEvalStack; // CLR_RT_HeapBlock* m_evalStackEnd; // EVENT HEAP - NO RELOCATION - + stack->m_arguments = NULL; // CLR_RT_HeapBlock* m_arguments; // EVENT HEAP - NO RELOCATION - + // + // union + // { + stack->m_customState = 0; // CLR_UINT32 m_customState; + // void* m_customPointer; + // }; + // +#ifndef CLR_NO_IL_INLINE + stack->m_inlineFrame = NULL; +#endif +#if defined(NANOCLR_PROFILE_NEW_CALLS) + stack->m_callchain.Enter( stack ); // CLR_PROF_CounterCallChain m_callchain; +#endif + // + // CLR_RT_HeapBlock m_extension[1]; + // +#if defined(ENABLE_NATIVE_PROFILER) + stack->m_fNativeProfiled = stack->m_owningThread->m_fNativeProfiled; +#endif + CLR_RT_MethodHandler impl; + +#if defined(NANOCLR_APPDOMAINS) + stack->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + if(md->flags & CLR_RECORD_METHODDEF::MD_DelegateInvoke) // Special case for delegate calls. + { + stack->m_nativeMethod = (CLR_RT_MethodHandler)CLR_RT_Thread::Execute_DelegateInvoke; + + stack->m_flags = CLR_RT_StackFrame::c_MethodKind_Native; + stack->m_IPstart = NULL; + } + else if(assm->m_nativeCode && (impl = assm->m_nativeCode[ stack->m_call.Method() ]) != NULL) + { + stack->m_nativeMethod = impl; + + stack->m_flags = CLR_RT_StackFrame::c_MethodKind_Native; + stack->m_IPstart = NULL; + stack->m_IP = NULL; + } + else + { + stack->m_nativeMethod = (CLR_RT_MethodHandler)CLR_RT_Thread::Execute_IL; + + if(md->RVA == CLR_EmptyIndex) NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + stack->m_flags = CLR_RT_StackFrame::c_MethodKind_Interpreted; + stack->m_IPstart = assm->GetByteCode( md->RVA ); + stack->m_IP = stack->m_IPstart; + } + + #if defined(ENABLE_NATIVE_PROFILER) + if(stack->m_owningThread->m_fNativeProfiled == false && md->flags & CLR_RECORD_METHODDEF::MD_NativeProfiled) + { + stack->m_flags |= CLR_RT_StackFrame::c_NativeProfiled; + stack->m_owningThread->m_fNativeProfiled = true; + } + #endif + + //--// + + th->m_stackFrames.LinkAtBack( stack ); + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + g_CLR_PRF_Profiler.RecordFunctionCall( th, callInst ); +#endif + } + + if(md->numLocals) + { + g_CLR_RT_ExecutionEngine.InitializeLocals( stack->m_locals, assm, md ); + } + + { + CLR_UINT32 flags = md->flags & (md->MD_Synchronized | md->MD_GloballySynchronized); + + if(flags) + { + if(flags & md->MD_Synchronized ) stack->m_flags |= c_NeedToSynchronize; + if(flags & md->MD_GloballySynchronized) stack->m_flags |= c_NeedToSynchronizeGlobally; + } + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + stack->m_depth = stack->Caller()->Prev() ? stack->Caller()->m_depth + 1 : 0; + + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + if(stack->m_call.DebuggingInfo().HasBreakpoint()) + { + stack->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + + if(stack->m_owningThread->m_fHasJMCStepper || (stack->m_flags & c_HasBreakpoint) || (caller->Prev() != NULL && (caller->m_flags & c_HasBreakpoint))) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Push( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_CALL ); + } + } +#endif + + //--// + + if(caller->Prev() != NULL && caller->m_nativeMethod == stack->m_nativeMethod) + { + if(stack->m_flags & CLR_RT_StackFrame::c_ProcessSynchronize) + { + stack->m_flags |= CLR_RT_StackFrame::c_CallerIsCompatibleForRet; + } + else + { + stack->m_flags |= CLR_RT_StackFrame::c_CallerIsCompatibleForCall | CLR_RT_StackFrame::c_CallerIsCompatibleForRet; + } + } + + // + // If the arguments are in the caller's stack frame (var == 0), let's link the two. + // + if(extraBlocks < 0) + { +#if defined(_WIN32) + if(caller->m_evalStackPos > caller->m_evalStackEnd) + { + NANOCLR_SET_AND_LEAVE(CLR_E_STACK_OVERFLOW); + } +#endif + + // + // Everything is set up correctly, pop the operands. + // + stack->m_arguments = &caller->m_evalStackPos[ -md->numArgs ]; + + caller->m_evalStackPos = stack->m_arguments; + +#if defined(_WIN32) + if(stack->m_arguments < caller->m_evalStack) + { + NANOCLR_SET_AND_LEAVE(CLR_E_STACK_UNDERFLOW); + } +#endif + } + else + { + stack->m_arguments = stack->m_evalStackEnd; + } + + NANOCLR_CLEANUP(); + + + NANOCLR_CLEANUP_END(); +} + +#ifndef CLR_NO_IL_INLINE +bool CLR_RT_StackFrame::PushInline( CLR_PMETADATA& ip, CLR_RT_Assembly*& assm, CLR_RT_HeapBlock*& evalPos, CLR_RT_MethodDef_Instance& calleeInst, CLR_RT_HeapBlock* pThis) +{ + const CLR_RECORD_METHODDEF* md = calleeInst.m_target; + + if( (m_inlineFrame != NULL) || // We can only support one inline at a time per stack call + (m_evalStackEnd - evalPos) <= (md->numArgs + md->numLocals + md->lengthEvalStack + 2) || // We must have enough space on the current stack for the inline method + (m_nativeMethod != (CLR_RT_MethodHandler)CLR_RT_Thread::Execute_IL) || // We only support IL inlining + (md->flags & ~CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) >= CLR_RECORD_METHODDEF::MD_Constructor || // Do not try to inline constructors, etc because they require special processing + (0 != (md->flags & CLR_RECORD_METHODDEF::MD_Static)) || // Static methods also requires special processing + (calleeInst.m_assm->m_nativeCode != NULL && (calleeInst.m_assm->m_nativeCode[ calleeInst.Method() ] != NULL)) || // Make sure the callee is not an internal method + (md->RVA == CLR_EmptyIndex) || // Make sure we have a valid IP address for the method + !g_CLR_RT_EventCache.GetInlineFrameBuffer(&m_inlineFrame)) // Make sure we have an extra slot in the inline cache + { + return false; + } + + CLR_PMETADATA ipTmp = calleeInst.m_assm->GetByteCode( md->RVA ); + +#if defined(PLATFORM_WINDOWS_EMULATOR) + if(s_CLR_RT_fTrace_SimulateSpeed > c_CLR_RT_Trace_None) + { + CLR_PROF_Handler::SuspendTime(); + + HAL_Windows_FastSleep( g_HAL_Configuration_Windows.TicksPerMethodCall ); + + CLR_PROF_Handler::ResumeTime(); + } +#endif + + // make backup + m_inlineFrame->m_frame.m_IP = ip; + m_inlineFrame->m_frame.m_IPStart = m_IPstart; + m_inlineFrame->m_frame.m_locals = m_locals; + m_inlineFrame->m_frame.m_args = m_arguments; + m_inlineFrame->m_frame.m_call = m_call; + m_inlineFrame->m_frame.m_evalStack = m_evalStack; + m_inlineFrame->m_frame.m_evalPos = pThis; + + // increment the evalPos pointer so that we don't corrupt the real stack + evalPos++; + assm = calleeInst.m_assm; + ip = ipTmp; + + m_arguments = pThis; + m_locals = &m_evalStackEnd[-md->numLocals]; + m_call = calleeInst; + m_evalStackEnd = m_locals; + m_evalStack = evalPos; + m_evalStackPos = evalPos + 1; + m_IPstart = ip; + m_IP = ip; + + if(md->numLocals) + { + g_CLR_RT_ExecutionEngine.InitializeLocals( m_locals, calleeInst.m_assm, md ); + } + + m_flags |= CLR_RT_StackFrame::c_MethodKind_Inlined; + + if(md->retVal != DATATYPE_VOID) + { + m_flags |= CLR_RT_StackFrame::c_InlineMethodHasReturnValue; + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + m_depth++; + + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + if(m_call.DebuggingInfo().HasBreakpoint()) + { + m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + + if(m_owningThread->m_fHasJMCStepper || (m_flags & CLR_RT_StackFrame::c_HasBreakpoint)) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Push( this, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_CALL ); + } + } +#endif + + return true; +} + +void CLR_RT_StackFrame::PopInline() +{ + + CLR_RT_HeapBlock& src = m_evalStackPos[0]; + + RestoreFromInlineStack(); + + if(m_flags & CLR_RT_StackFrame::c_InlineMethodHasReturnValue) + { + if(m_owningThread->m_currentException.Dereference() == NULL) + { + CLR_RT_HeapBlock& dst = PushValueAndAssign( src ); + + dst.Promote(); + } + } + + g_CLR_RT_EventCache.FreeInlineBuffer(m_inlineFrame); + m_inlineFrame = NULL; + m_flags &= ~(CLR_RT_StackFrame::c_MethodKind_Inlined | CLR_RT_StackFrame::c_InlineMethodHasReturnValue); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(m_owningThread->m_fHasJMCStepper || (m_flags & CLR_RT_StackFrame::c_HasBreakpoint)) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( this, false ); + } + m_depth--; +#endif +} + +void CLR_RT_StackFrame::RestoreFromInlineStack() +{ + m_arguments = m_inlineFrame->m_frame.m_args; + m_locals = m_inlineFrame->m_frame.m_locals; + m_evalStackEnd += m_call.m_target->numLocals; + m_call = m_inlineFrame->m_frame.m_call; + m_IP = m_inlineFrame->m_frame.m_IP; + m_IPstart = m_inlineFrame->m_frame.m_IPStart; + m_evalStack = m_inlineFrame->m_frame.m_evalStack; + m_evalStackPos = m_inlineFrame->m_frame.m_evalPos; +} + +void CLR_RT_StackFrame::RestoreStack(CLR_RT_InlineFrame& frame) +{ + m_arguments = frame.m_args; + m_locals = frame.m_locals; + m_call = frame.m_call; + m_IP = frame.m_IP; + m_IPstart = frame.m_IPStart; + m_evalStack = frame.m_evalStack; + m_evalStackPos = frame.m_evalPos; + m_evalStackEnd -= m_call.m_target->numLocals; +} + +void CLR_RT_StackFrame::SaveStack(CLR_RT_InlineFrame& frame) +{ + frame.m_args = m_arguments; + frame.m_locals = m_locals; + frame.m_call = m_call; + frame.m_IP = m_IP; + frame.m_IPStart = m_IPstart; + frame.m_evalPos = m_evalStackPos; + frame.m_evalStack = m_evalStack; +} +#endif + +#if defined(NANOCLR_APPDOMAINS) +HRESULT CLR_RT_StackFrame::PopAppDomainTransition() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + bool fException = false; + CLR_RT_HeapBlock exception; + CLR_RT_StackFrame* caller = this->Caller(); + + exception.SetObjectReference( NULL ); + + if(m_flags & CLR_RT_StackFrame::c_AppDomainInjectException) + { + //this is the last frame on the thread in a doomed AppDomain + //Convert the current ThreadAbortException into an AppDomainUnloaded exception + + _ASSERTE(m_owningThread->m_flags & CLR_RT_Thread::TH_F_Aborted); + _ASSERTE(m_owningThread->m_flags & CLR_RT_Thread::TH_F_ContainsDoomedAppDomain); + _ASSERTE(m_owningThread->m_currentException.Dereference() != NULL); + _ASSERTE(m_owningThread->m_currentException.Dereference()->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_ThreadAbortException.m_data); + _ASSERTE(!m_appDomain->IsLoaded()); + + m_owningThread->m_flags &= ~(CLR_RT_Thread::TH_F_Aborted | CLR_RT_Thread::TH_F_ContainsDoomedAppDomain); + + hr = CLR_E_APPDOMAIN_EXITED; + } + else if(m_owningThread->m_currentException.Dereference() == NULL) + { + _ASSERTE((m_flags & CLR_RT_StackFrame::c_AppDomainInjectException) == 0); + + //Normal return. No exception is in flight + + if(m_flags & CLR_RT_StackFrame::c_AppDomainMethodInvoke) + { + // For dynamic invoke, + // we do not marshal byRef parameters back to the calling AppDomain + // The caller is a native method (MethodBase::Invoke), and does not have the args on it's eval stack. + } + else + { + int cArgs = m_call.m_target->numArgs; + + //First marshal the ref parameters + NANOCLR_CHECK_HRESULT(caller->m_appDomain->MarshalParameters( &caller->m_evalStackPos[ -cArgs ], m_arguments, cArgs, true )); + + //Now, pop the caller's arguments off the eval stack + caller->m_evalStackPos -= cArgs; + } + + // Now, push the return, if any. + if(m_call.m_target->retVal != DATATYPE_VOID) + { + CLR_RT_HeapBlock& dst = caller->PushValueAndClear(); + CLR_RT_HeapBlock& src = this ->TopValue (); + + NANOCLR_CHECK_HRESULT(caller->m_appDomain->MarshalObject( src, dst )); + + dst.Promote(); + } + } + else //Exception + { + //Normal exceptions must be marshaled to the caller's AppDomain + NANOCLR_CHECK_HRESULT(caller->m_appDomain->MarshalObject( m_owningThread->m_currentException, exception )); + fException = true; + } + + NANOCLR_CLEANUP(); + + if(FAILED(hr) || fException) + { + if(FAILED(hr)) + { + (void)Library_corlib_native_System_Exception::CreateInstance( exception, hr, caller ); + } + + m_owningThread->m_currentException.Assign( exception ); + } + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( caller->m_appDomain ); + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_StackFrame::PushAppDomainTransition( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_RT_HeapBlock* pThis, CLR_RT_HeapBlock* pArgs ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* frame = NULL; + int cArgs = callInst.m_target->numArgs; + CLR_RT_HeapBlock* proxy; + + _ASSERTE(pThis->IsTransparentProxy()); + + proxy = pThis->Dereference(); + + NANOCLR_CHECK_HRESULT(proxy->TransparentProxyValidate()); + + NANOCLR_CHECK_HRESULT(Push( th, callInst, cArgs )); + + frame = th->CurrentFrame(); + + frame->m_appDomain = proxy->TransparentProxyAppDomain(); + frame->m_flags |= CLR_RT_StackFrame::c_AppDomainTransition; + frame->m_flags &= ~CLR_RT_StackFrame::c_CallerIsCompatibleForRet; + + //Marshal the arguments from the caller (on the eval stack) to the callee, unitialized heapblocks that + //are set up by the extra blocks in CLR_RT_StackFrame::Push + NANOCLR_CHECK_HRESULT(frame->m_appDomain->MarshalObject ( *pThis, frame->m_arguments[ 0 ] )); + NANOCLR_CHECK_HRESULT(frame->m_appDomain->MarshalParameters( pArgs, &frame->m_arguments[ 1 ], cArgs-1, false )); + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( frame->m_appDomain ); + + NANOCLR_NOCLEANUP(); +} + +#endif //NANOCLR_APPDOMAINS + +HRESULT CLR_RT_StackFrame::MakeCall( CLR_RT_MethodDef_Instance md, CLR_RT_HeapBlock* obj, CLR_RT_HeapBlock* args, int nArgs ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_RECORD_METHODDEF* mdR = md.m_target; + bool fStatic =(mdR->flags & CLR_RECORD_METHODDEF::MD_Static) != 0; + int numArgs = mdR->numArgs; + int argsOffset = 0; + CLR_RT_StackFrame* stackSub; + CLR_RT_HeapBlock tmp; tmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc(tmp); + + if(mdR->flags & CLR_RECORD_METHODDEF::MD_Constructor) + { + CLR_RT_TypeDef_Instance owner; owner.InitializeFromMethod( md ); + + _ASSERTE(obj == NULL); + + _SIDE_ASSERTE(owner.InitializeFromMethod( md )); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObject( tmp, owner )); + + obj = &tmp; + + // + // Make a copy of the object pointer. + // + PushValueAndAssign( tmp ); + } + + if(!fStatic) + { + FAULT_ON_NULL(obj); + numArgs--; + argsOffset = 1; + } + + if(numArgs != nArgs) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + // + // In case the invoked method is abstract or virtual, resolve it to the correct method implementation. + // + if(mdR->flags & (CLR_RECORD_METHODDEF::MD_Abstract | CLR_RECORD_METHODDEF::MD_Virtual)) + { + CLR_RT_TypeDef_Index cls; + CLR_RT_MethodDef_Index mdReal; + + _ASSERTE(obj); + _ASSERTE(!fStatic); + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( *obj, cls )); + + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, md, mdReal ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + md.InitializeFromIndex( mdReal ); + + mdR = md.m_target; + } + +#if defined(NANOCLR_APPDOMAINS) + + if(!fStatic && obj->IsTransparentProxy()) + { + NANOCLR_CHECK_HRESULT(CLR_RT_StackFrame::PushAppDomainTransition( m_owningThread, md, obj, args )); + + stackSub = m_owningThread->CurrentFrame(); + + stackSub->m_flags |= CLR_RT_StackFrame::c_AppDomainMethodInvoke; + } + else +#endif + { + NANOCLR_CHECK_HRESULT(CLR_RT_StackFrame::Push( m_owningThread, md, md.m_target->numArgs )); + + stackSub = m_owningThread->CurrentFrame(); + + if(!fStatic) + { + stackSub->m_arguments[ 0 ].Assign( *obj ); + } + + if(numArgs) + { + memcpy( &stackSub->m_arguments[ argsOffset ], args, sizeof(CLR_RT_HeapBlock) * numArgs ); + } + } + + NANOCLR_CHECK_HRESULT(stackSub->FixCall()); + + NANOCLR_SET_AND_LEAVE(CLR_E_RESTART_EXECUTION); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_StackFrame::FixCall() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_RECORD_METHODDEF* target = m_call.m_target; + CLR_UINT8 numArgs = target->numArgs; + + // + // The copy of ValueTypes is delayed as much as possible. + // + // If an argument is a ValueType, now it's a good time to clone it. + // + if(numArgs) + { + CLR_RT_SignatureParser parser; parser.Initialize_MethodSignature( m_call.m_assm, target ); + CLR_RT_SignatureParser::Element res; + CLR_RT_HeapBlock* args = m_arguments; + + if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) + { + args++; + } + + // + // Skip return value. + // + NANOCLR_CHECK_HRESULT(parser.Advance( res )); + + for(;parser.Available() > 0;args++) + { + NANOCLR_CHECK_HRESULT(parser.Advance( res )); + + if(res.m_levels > 0) continue; // Array, no need to fix. + + if(args->DataType() == DATATYPE_OBJECT) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( res.m_cls ); + CLR_DataType dtT = (CLR_DataType)inst.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dtT ]; + + if(dtl.m_flags & (CLR_RT_DataTypeLookup::c_OptimizedValueType | CLR_RT_DataTypeLookup::c_ValueType)) + { + CLR_RT_HeapBlock* value = args->FixBoxingReference(); FAULT_ON_NULL(value); + + if(value->DataType() == dtT) + { + // It's a boxed primitive/enum type. + args->Assign( *value ); + } + else if(args->Dereference()->ObjectCls().m_data == res.m_cls.m_data) + { + NANOCLR_CHECK_HRESULT(args->PerformUnboxing( inst )); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + + if(res.m_dt == DATATYPE_VALUETYPE && res.m_fByRef == false) + { + if(args->IsAReferenceOfThisType( DATATYPE_VALUETYPE )) + { + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *args, *args )); + } + } + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_StackFrame::HandleSynchronized( bool fAcquire, bool fGlobal ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock refType; + CLR_RT_HeapBlock* obj; + CLR_RT_HeapBlock ref; + CLR_RT_HeapBlock** ppGlobalLock; + CLR_RT_HeapBlock* pGlobalLock; + + if(fGlobal) + { + obj = &ref; + +#if defined(NANOCLR_APPDOMAINS) + //With AppDomains enabled, the global lock is no longer global. It is only global wrt the AppDomain/ + //Do we need a GlobalGlobalLock? (an attribute on GloballySynchronized (GlobalAcrossAppDomain?) + ppGlobalLock = &g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->m_globalLock; +#else + ppGlobalLock = &g_CLR_RT_ExecutionEngine.m_globalLock; +#endif + + pGlobalLock = *ppGlobalLock; + + if(pGlobalLock) + { + obj->SetObjectReference( pGlobalLock ); + } + else + { + // + // Create an private object to implement global locks. + // + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *obj, g_CLR_RT_WellKnownTypes.m_Object )); + + *ppGlobalLock = obj->Dereference(); + } + } + else if(m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) + { + CLR_RT_TypeDef_Index idx; + + idx.Set( m_call.Assembly(), m_call.CrossReference().GetOwner() ); + + refType.SetReflection( idx ); + + obj = &refType; + } + else + { + obj = &Arg0(); + } + + if(fAcquire) + { + NANOCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.LockObject( *obj, m_owningSubThread, TIMEOUT_INFINITE, false )); + } + else + { + NANOCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.UnlockObject( *obj, m_owningSubThread )); + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_StackFrame::Pop() +{ + NATIVE_PROFILE_CLR_CORE(); + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + { + // + // This passivates any outstanding handler. + // + CLR_PROF_HANDLER_CALLCHAIN(pm2,m_callchain); + + m_callchain.Leave(); + } +#endif + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + g_CLR_PRF_Profiler.RecordFunctionReturn( m_owningThread, m_callchain ); +#endif + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(m_owningThread->m_fHasJMCStepper || (m_flags & c_HasBreakpoint)) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( this, false ); + } +#endif + + const CLR_UINT32 c_flagsToCheck = CLR_RT_StackFrame::c_CallOnPop | CLR_RT_StackFrame::c_Synchronized | CLR_RT_StackFrame::c_SynchronizedGlobally | CLR_RT_StackFrame::c_NativeProfiled; + + if(m_flags & c_flagsToCheck) + { + if(m_flags & CLR_RT_StackFrame::c_CallOnPop) + { + m_flags |= CLR_RT_StackFrame::c_CalledOnPop; + + if(m_nativeMethod) + { + (void)m_nativeMethod( *this ); + } + } + + if(m_flags & CLR_RT_StackFrame::c_Synchronized) + { + m_flags &= ~CLR_RT_StackFrame::c_Synchronized; + + (void)HandleSynchronized( false, false ); + } + + if(m_flags & CLR_RT_StackFrame::c_SynchronizedGlobally) + { + m_flags &= ~CLR_RT_StackFrame::c_SynchronizedGlobally; + + (void)HandleSynchronized( false, true ); + } + + #if defined(ENABLE_NATIVE_PROFILER) + if(m_flags & CLR_RT_StackFrame::c_NativeProfiled) + { + m_owningThread->m_fNativeProfiled = false; + m_flags &= ~CLR_RT_StackFrame::c_NativeProfiled; + Native_Profiler_Stop(); + } + #endif + } + + CLR_RT_StackFrame* caller = Caller(); + + if(caller->Prev() != NULL) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(caller->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( caller, caller->m_IP ); + } +#endif + + // + // Constructors are slightly different, they push the 'this' pointer back into the caller stack. + // + // This is to enable the special case for strings, where the object can be recreated by the constructor... + // + if(caller->m_flags & CLR_RT_StackFrame::c_ExecutingConstructor) + { + CLR_RT_HeapBlock& src = this ->Arg0 ( ); + CLR_RT_HeapBlock& dst = caller->PushValueAndAssign( src ); + + dst.Promote(); + + // + // Undo the special "object -> reference" hack done by CEE_NEWOBJ. + // + if(dst.DataType() == DATATYPE_BYREF) + { + dst.ChangeDataType( DATATYPE_OBJECT ); + } + + caller->m_flags &= ~CLR_RT_StackFrame::c_ExecutingConstructor; + + _ASSERTE((m_flags & CLR_RT_StackFrame::c_AppDomainTransition) == 0); + } + else + { //Note that ExecutingConstructor is checked on 'caller', whereas the other two flags are checked on 'this' + const CLR_UINT32 c_moreFlagsToCheck = CLR_RT_StackFrame::c_PseudoStackFrameForFilter | CLR_RT_StackFrame::c_AppDomainTransition; + + if(m_flags & c_moreFlagsToCheck) + { + if(m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + //Do nothing here. Pushing return values onto stack frames that don't expect them are a bad idea. + } +#if defined(NANOCLR_APPDOMAINS) + else if((m_flags & CLR_RT_StackFrame::c_AppDomainTransition) != 0) + { + (void)PopAppDomainTransition(); + } +#endif + } + else //!c_moreFlagsToCheck + { + // + // Push the return, if any. + // + if(m_call.m_target->retVal != DATATYPE_VOID) + { + if(m_owningThread->m_currentException.Dereference() == NULL) + { + CLR_RT_HeapBlock& src = this ->TopValue ( ); + CLR_RT_HeapBlock& dst = caller->PushValueAndAssign( src ); + + dst.Promote(); + } + } + } + } + } +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + else + { + int idx = m_owningThread->m_scratchPad; + + if(idx >= 0) + { + CLR_RT_HeapBlock_Array* array = g_CLR_RT_ExecutionEngine.m_scratchPadArray; + + if(array && array->m_numOfElements > (CLR_UINT32)idx) + { + CLR_RT_HeapBlock* dst = (CLR_RT_HeapBlock*)array->GetElement( (CLR_UINT32)idx ); + CLR_RT_HeapBlock* exception = m_owningThread->m_currentException.Dereference(); + + dst->SetObjectReference( NULL ); + + if(exception != NULL) + { + dst->SetObjectReference( exception ); + } + else if(m_call.m_target->retVal != DATATYPE_VOID) + { + CLR_RT_SignatureParser sig; sig.Initialize_MethodSignature( this->m_call.m_assm, this->m_call.m_target ); + CLR_RT_SignatureParser::Element res; + CLR_RT_TypeDescriptor desc; + + dst->Assign( this->TopValue() ); + + //Perform boxing, if needed. + + //Box to the return value type + _SIDE_ASSERTE(SUCCEEDED(sig.Advance( res ))); + _SIDE_ASSERTE(SUCCEEDED(desc.InitializeFromType( res.m_cls ))); + + + if(c_CLR_RT_DataTypeLookup[ this->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType + || desc.m_handlerCls.m_target->IsEnum() + ) + { + if(FAILED(dst->PerformBoxing( desc.m_handlerCls ))) + { + dst->SetObjectReference( NULL ); + } + } + } + } + } + } +#endif + + // + // We could be jumping outside of a nested exception handler. + // + + m_owningThread->PopEH( this, NULL ); + + + // + // If this StackFrame owns a SubThread, kill it. + // + { + CLR_RT_SubThread* sth = (CLR_RT_SubThread*)m_owningSubThread->Next(); + + if(sth->Next() && sth->m_owningStackFrame == this) + { + CLR_RT_SubThread::DestroyInstance( sth->m_owningThread, sth, CLR_RT_SubThread::MODE_IncludeSelf ); + } + } + + g_CLR_RT_EventCache.Append_Node( this ); +} + +//--// + +void CLR_RT_StackFrame::SetResult( CLR_INT32 val, CLR_DataType dataType ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val, dataType ); +} + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + +void CLR_RT_StackFrame::SetResult_R4( float val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetFloat( val ); +} + +void CLR_RT_StackFrame::SetResult_R8( double val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetDouble( val ); +} + +#else + +void CLR_RT_StackFrame::SetResult_R4( CLR_INT32 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetFloat( val ); +} + +void CLR_RT_StackFrame::SetResult_R8( CLR_INT64 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetDouble( val ); +} + +#endif + +void CLR_RT_StackFrame::SetResult_I1( CLR_UINT8 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_I2( CLR_INT16 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_I4( CLR_INT32 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_I8( CLR_INT64& val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_U1( CLR_INT8 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_U2( CLR_UINT16 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_U4( CLR_UINT32 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_U8( CLR_UINT64& val ) + +{ + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_Boolean( bool val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetBoolean( val ); +} + +void CLR_RT_StackFrame::SetResult_Object( CLR_RT_HeapBlock* val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetObjectReference( val ); +} + +HRESULT CLR_RT_StackFrame::SetResult_String( const char* val ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& top = PushValue(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( top, val )); + + NANOCLR_NOCLEANUP(); +} + + +void CLR_RT_StackFrame::ConvertResultToBoolean() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = TopValue(); + + top.SetBoolean( top.NumericByRef().s4 == 0 ); +} + +void CLR_RT_StackFrame::NegateResult() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = TopValue(); + + top.NumericByRef().s4 = top.NumericByRef().s4 ? 0 : 1; +} + +//--// + +// input HeapBlock has timeout value **IN TICKS** +// sometimes you have to force a cast to (CLR_INT64) otherwise the set operations will fail because of the var size mismatch +HRESULT CLR_RT_StackFrame::SetupTimeoutFromTicks( CLR_RT_HeapBlock& input, CLR_INT64*& output ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(m_customState == 0) + { + CLR_RT_HeapBlock& ref = PushValueAndClear(); + CLR_INT64 timeExpire; + + // + // Initialize timeout and save it on the stack. + // + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpire, input.NumericByRef().s8 )); + + ref.SetInteger( timeExpire ); + + m_customState = 1; + } + + output = (CLR_INT64*)&m_evalStack[ 0 ].NumericByRef().s8; + + NANOCLR_NOCLEANUP(); +} + +//--// + +void CLR_RT_StackFrame::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + +#ifndef CLR_NO_IL_INLINE + if(m_inlineFrame) + { + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_call.m_assm ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_call.m_target ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_IPStart ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_IP ); + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_assm ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_target ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_nativeMethod ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IPstart ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IP ); + + CLR_RT_GarbageCollector::Heap_Relocate( m_inlineFrame->m_frame.m_args , m_inlineFrame->m_frame.m_call.m_target->numArgs ); + CLR_RT_GarbageCollector::Heap_Relocate( m_inlineFrame->m_frame.m_locals , m_inlineFrame->m_frame.m_call.m_target->numLocals ); + CLR_RT_GarbageCollector::Heap_Relocate( m_inlineFrame->m_frame.m_evalStack, (int)(m_evalStackPos - m_inlineFrame->m_frame.m_evalStack) ); + CLR_RT_GarbageCollector::Heap_Relocate( m_locals, m_call.m_target->numLocals ); + } + else +#endif + { + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_assm ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_target ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_nativeMethod ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IPstart ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IP ); + + CLR_RT_GarbageCollector::Heap_Relocate( m_arguments, m_call.m_target->numArgs ); + CLR_RT_GarbageCollector::Heap_Relocate( m_locals , m_call.m_target->numLocals ); + CLR_RT_GarbageCollector::Heap_Relocate( m_evalStack, TopValuePosition() ); + } +} + +//--// + +HRESULT CLR_RT_StackFrame::NotImplementedStub() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(m_call.m_target->retVal != DATATYPE_VOID) + { + SetResult_I4( 0 ); + } + + NANOCLR_SET_AND_LEAVE(CLR_E_NOTIMPL); + + NANOCLR_NOCLEANUP(); +} + + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp new file mode 100644 index 00000000..e078c67e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +//#include +//#include +//#include "nanoCLR_Interop.h" + +static const CLR_RT_NativeAssemblyData *LookUpAssemblyNativeDataByName +( + const CLR_RT_NativeAssemblyData **pAssembliesNativeData, + const char *lpszAssemblyName +) +{ + // Just sanity check to avoid crash in strcmp if name is NULL. + if ( lpszAssemblyName == NULL ) + { + return NULL; + } + + // Loops in all entries and looks for the CLR_RT_NativeAssemblyData with name same as lpszAssemblyName + for ( int i = 0; pAssembliesNativeData[ i ]; i++ ) + { + if ( pAssembliesNativeData[ i ] != NULL && 0 == strcmp( lpszAssemblyName, pAssembliesNativeData[ i ]->m_szAssemblyName ) ) + { + return pAssembliesNativeData[ i ]; + } + } + return NULL; +} + + +const CLR_RT_NativeAssemblyData *GetAssemblyNativeData( const char *lpszAssemblyName ) +{ + extern const CLR_RT_NativeAssemblyData *g_CLR_InteropAssembliesNativeData[]; + + // This will return NULL if there is no registered interop assembly of that name + return LookUpAssemblyNativeDataByName( + g_CLR_InteropAssembliesNativeData, + lpszAssemblyName + ); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/CLR_RT_UnicodeHelper.cpp b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_UnicodeHelper.cpp new file mode 100644 index 00000000..86ca3a81 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/CLR_RT_UnicodeHelper.cpp @@ -0,0 +1,586 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define UTF8_BAD_LOWPART(ch) (ch < 0x80 || ch > 0xBF) + +#define UTF8_CHECK_LOWPART(ch,src) ch = (CLR_UINT32)*src++; if(UTF8_BAD_LOWPART(ch)) return -1 + +#define UTF8_LOAD_LOWPART(ch,ch2,src) ch = (CLR_UINT32)*src++; ch2 <<= 6; ch2 |= (ch & 0x3F) + +//--// + +int CLR_RT_UnicodeHelper::CountNumberOfCharacters( int max ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT8* pSrc = m_inputUTF8; + int num = 0; + + while(true) + { + CLR_UINT32 ch = (CLR_UINT32)*pSrc++; if(!ch) break; + + if(max-- == 0) break; // This works even if you pass -1 as argument (it will walk through the whole string). + + switch(ch & 0xF0) + { + case 0x00: + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: + num += 1; + break; + + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + return -1; // Illegal characters. + + case 0xC0: + case 0xD0: + UTF8_CHECK_LOWPART(ch,pSrc); + + num += 1; + break; + + case 0xE0: + UTF8_CHECK_LOWPART(ch,pSrc); + UTF8_CHECK_LOWPART(ch,pSrc); + + num += 1; + break; + + case 0xF0: + UTF8_CHECK_LOWPART(ch,pSrc); + UTF8_CHECK_LOWPART(ch,pSrc); + UTF8_CHECK_LOWPART(ch,pSrc); + + num += 2; + break; + } + } + + return num; +} + +int CLR_RT_UnicodeHelper::CountNumberOfBytes( int max ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT16* pSrc = m_inputUTF16; + int num = 0; + + while(true) + { + CLR_UINT16 ch = *pSrc++; if(!ch) break; + + if(max-- == 0) break; // This works even if you pass -1 as argument (it will walk through the whole string). + + if(ch < 0x0080) + { + num += 1; + } + else if(ch < 0x0800) + { + num += 2; + } + else if(ch >= LOW_SURROGATE_START && ch <= LOW_SURROGATE_END) + { + return -1; // Invalid string: Low surrogate should only follow a high surrogate. + } + else if(ch >= HIGH_SURROGATE_START && ch <= HIGH_SURROGATE_END) + { + ch = *pSrc++; + + if(ch >= LOW_SURROGATE_START && ch <= LOW_SURROGATE_END) + { + num += 4; + max--; + } + else + { + return -1; // Invalid string: Low surrogate should follow a high surrogate. + } + } + else + { + num += 3; + } + } + + return num; +} + +//--// + +// dev note: need the pragma below because there are a couple of 'smart' hacks in +// the switch cases to improve the algorithm +#ifdef __GNUC__ +#pragma GCC diagnostic push +// -Wimplicit-fallthrough option was added in GCC 7 +#if (__GNUC__ >= 7) +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +#endif + +bool CLR_RT_UnicodeHelper::ConvertFromUTF8( int iMaxChars, bool fJustMove, int iMaxBytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT8* inputUTF8 = m_inputUTF8; + CLR_UINT16* outputUTF16 = m_outputUTF16; + int outputUTF16_size = m_outputUTF16_size; + CLR_UINT32 ch; + CLR_UINT32 ch2; + bool res; + + if (iMaxBytes == -1) + { + iMaxBytes = iMaxChars * 3; // the max number of bytes it can have based on iMaxChars -- if all characters are of 3 bytes. + } + + while(iMaxChars > 0 && iMaxBytes > 0) + { + ch = (CLR_UINT32)*inputUTF8++; + + switch(ch & 0xF0) + { + case 0x00: if(ch == 0) { inputUTF8--; goto ExitFalse; } + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: + if(fJustMove == false) + { + if(outputUTF16_size < 1) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + + outputUTF16[ 0 ] = ch; + + outputUTF16 += 1; + outputUTF16_size -= 1; + } + + iMaxChars -= 1; + iMaxBytes -= 1; + break; + + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + goto ExitFalse; // Illegal characters. + + case 0xC0: + case 0xD0: + if((ch & 0xFF) < 0xC2) { inputUTF8--; goto ExitFalse; } // illegal - overlong encoding + + if(iMaxBytes >= 2) + { + if(fJustMove) + { + inputUTF8++; + } + else + { + if(outputUTF16_size < 1) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + ch2 = (ch & 0x1F); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + + outputUTF16[ 0 ] = ch2; + + outputUTF16 += 1; + outputUTF16_size -= 1; + } + + iMaxChars -= 1; + iMaxBytes -= 2; + } + else + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + break; + + case 0xE0: + if(iMaxBytes >= 3) + { + if(fJustMove) + { + inputUTF8 += 2; + } + else + { + if(outputUTF16_size < 1) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + ch2 = (ch & 0x0F); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + + outputUTF16[ 0 ] = ch2; + + outputUTF16 += 1; + outputUTF16_size -= 1; + } + + iMaxChars -= 1; + iMaxBytes -= 3; + } + else + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + break; + + case 0xF0: + if((ch & 0xFF) >= 0xF5) { inputUTF8--; goto ExitFalse; } // restricted by RFC 3629 + + if(iMaxBytes >= 4) + { + if(fJustMove) + { + inputUTF8 += 3; + } + else + { + if(outputUTF16_size < 2) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + + ch2 = (ch & 0x07); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + + outputUTF16[ 0 ] = (ch2 >> SURROGATE_HALFSHIFT) + HIGH_SURROGATE_START; + outputUTF16[ 1 ] = (ch2 & SURROGATE_HALFMASK ) + LOW_SURROGATE_START ; + + outputUTF16 += 2; + outputUTF16_size -= 2; + } + + iMaxChars -= 2; + iMaxBytes -= 4; + } + else + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + break; + } + } + + if(fJustMove == false) + { + if(outputUTF16_size < 1) goto ExitFalse; + + outputUTF16[ 0 ] = 0; + } + + res = true; + goto Exit; + + ExitFalse: + res = false; + + Exit: + m_inputUTF8 = inputUTF8; + m_outputUTF16 = outputUTF16; + m_outputUTF16_size = outputUTF16_size; + + return res; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +// move backward in the UTF8 input +bool CLR_RT_UnicodeHelper::MoveBackwardInUTF8( const char* utf8StringStart, int iMaxChars ) +{ + // already at the beginning or iMaxChars < 1? + if (m_inputUTF8 <= (const CLR_UINT8*)utf8StringStart || iMaxChars < 1) + { + return false; + } + + while (true) + { + // move back one byte and test if it's 0xxxxxxx or 11xxxxxx, because that are start bytes + m_inputUTF8--; + char current = m_inputUTF8[0]; + if ((current & 0x10000000) == 0x00000000 || (current & 0x11000000) == 0x11000000) + { + iMaxChars--; + } + + // moved back enough? + if (iMaxChars == 0) + { + return true; + } + + // reached the beginning? + if (m_inputUTF8 == (const CLR_UINT8*)utf8StringStart) + { + return false; + } + } +} + +bool CLR_RT_UnicodeHelper::ConvertToUTF8( int iMaxChars, bool fJustMove ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT16* inputUTF16 = m_inputUTF16; + CLR_UINT8* outputUTF8 = m_outputUTF8; + int outputUTF8_size = m_outputUTF8_size; + CLR_UINT32 ch; + bool res; + + while(iMaxChars > 0) + { + ch = (CLR_UINT32)*inputUTF16++; + + if(ch < 0x0080) + { + if(ch == 0) + { + break; + } + + if(fJustMove == false) + { + if(outputUTF8_size < 1) goto ExitFalse; + + outputUTF8[ 0 ] = ch; + + outputUTF8 += 1; + outputUTF8_size -= 1; + } + + iMaxChars -= 1; + } + else if(ch < 0x0800) + { + if(fJustMove == false) + { + if(outputUTF8_size < 2) goto ExitFalse; + + outputUTF8[ 1 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 0 ] = 0xC0 | (ch & 0x1F); + + outputUTF8 += 2; + outputUTF8_size -= 2; + } + + iMaxChars -= 1; + } + else if(ch >= HIGH_SURROGATE_START && ch <= HIGH_SURROGATE_END) + { + ch = SURROGATE_HALFBASE + ((ch - HIGH_SURROGATE_START) << SURROGATE_HALFSHIFT) + (*inputUTF16++ - LOW_SURROGATE_START); + + if(fJustMove == false) + { + if(outputUTF8_size < 4) goto ExitFalse; + + outputUTF8[ 3 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 2 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 1 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 0 ] = 0xF0 | (ch & 0x07); + + outputUTF8 += 4; + outputUTF8_size -= 4; + } + + iMaxChars -= 2; + } + else + { + if(fJustMove == false) + { + if(outputUTF8_size < 3) goto ExitFalse; + + outputUTF8[ 2 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 1 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 0 ] = 0xE0 | (ch & 0x0F); + + outputUTF8 += 3; + outputUTF8_size -= 3; + } + + iMaxChars -= 1; + } + } + + if(fJustMove == false) + { + if(outputUTF8_size < 1) goto ExitFalse; + + outputUTF8[ 0 ] = 0; + } + + res = true; + goto Exit; + +ExitFalse: + res = false; + +Exit: + m_inputUTF16 = inputUTF16; + m_outputUTF8 = outputUTF8; + m_outputUTF8_size = outputUTF8_size; + + return res; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +void CLR_RT_UnicodeHelper::ConvertToUTF8( const std::wstring& src , + std::string& dst ) +{ + if(src.size()) + { + char* szBuf; + int iSize; + + iSize = ::WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, NULL, 0, NULL, NULL ); + + if(iSize > 0) + { + szBuf = new char[ iSize ]; + + iSize = ::WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, szBuf, iSize, NULL, NULL ); + if(iSize > 0) + { + dst = szBuf; + } + + delete [] szBuf; + } + } + else + { + dst.erase(); + } +} + +void CLR_RT_UnicodeHelper::ConvertFromUTF8( const std::string& src , + std::wstring& dst ) +{ + if(src.size()) + { + wchar_t* szBuf; + int iSize; + + iSize = ::MultiByteToWideChar( CP_UTF8, 0, src.c_str(), -1, NULL, 0 ); + + if(iSize > 0) + { + szBuf = new wchar_t[ iSize ]; + + iSize = ::MultiByteToWideChar( CP_UTF8, 0, src.c_str(), -1, szBuf, iSize ); + if(iSize > 0) + { + dst = szBuf; + } + + delete [] szBuf; + } + } + else + { + dst.erase(); + } +} + + +#endif + +UnicodeString::UnicodeString() +{ + m_wCharArray = NULL; + m_length = 0; +} + +UnicodeString::~UnicodeString() +{ + Release(); +} + +HRESULT UnicodeString::Assign( const char* string ) +{ + NATIVE_PROFILE_CLR_IO(); + NANOCLR_HEADER(); + + int byteLength = 0; + + /// Before we start assigning remove existing stuff. + Release(); + + m_unicodeHelper.SetInputUTF8( string ); + + m_length = m_unicodeHelper.CountNumberOfCharacters(); + + if(m_length < 0) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + /// We have m_length >=0 now. + + byteLength = (m_length + 1) * sizeof (CLR_UINT16); + + m_wCharArray = (CLR_UINT16 *)CLR_RT_Memory::Allocate( byteLength ); CHECK_ALLOCATION(m_wCharArray); + + m_unicodeHelper.m_outputUTF16 = m_wCharArray; + m_unicodeHelper.m_outputUTF16_size = m_length + 1; + + m_unicodeHelper.ConvertFromUTF8( m_length , false ); + + /// Note m_length > 0 already (see above), hence m_length >= 0 or a valid index. + m_wCharArray[ m_length ] = 0; + + NANOCLR_NOCLEANUP(); +} + +void UnicodeString::Release() +{ + if (m_wCharArray != NULL) + { + CLR_RT_Memory::Release( m_wCharArray ); + } + + m_wCharArray = NULL; +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/Cache.cpp b/source/native/nf-interpreter/src/CLR/Core/Cache.cpp new file mode 100644 index 00000000..05524044 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Cache.cpp @@ -0,0 +1,591 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_USE_AVLTREE_FOR_METHODLOOKUP) + +int CLR_RT_EventCache::LookupEntry::Callback_Compare( void* state, CLR_RT_AVLTree::Entry* left, CLR_RT_AVLTree::Entry* right ) +{ + NATIVE_PROFILE_CLR_CORE(); + + LookupEntry* leftDirect = (LookupEntry*)left; + LookupEntry* rightDirect = (LookupEntry*)right; + + return leftDirect->m_payload.Compare( rightDirect->m_payload ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_EventCache::VirtualMethodTable::Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + + m_entries = (Payload*)&g_scratchVirtualMethodPayload[ 0 ]; + + LookupEntry* node; + size_t i; + + m_tree.Initialize(); + + + m_list_freeItems.DblLinkedList_Initialize(); + m_list_inUse .DblLinkedList_Initialize(); + + m_tree.m_owner.m_ftn_compare = LookupEntry ::Callback_Compare; + m_tree.m_owner.m_ftn_newNode = VirtualMethodTable::Callback_NewNode; + m_tree.m_owner.m_ftn_freeNode = VirtualMethodTable::Callback_FreeNode; + m_tree.m_owner.m_ftn_reassignNode = VirtualMethodTable::Callback_Reassign; + m_tree.m_owner.m_state = this; + + + for(i=0, node=m_entries; iGenericNode_Initialize(); + + m_list_freeItems.LinkAtBack( node ); + } +} + +bool CLR_RT_EventCache::VirtualMethodTable::FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + LookupEntry* en; + LookupEntry key; + CLR_RT_MethodDef_Instance instMD; + CLR_RT_TypeDef_Instance instCLS; + + instMD .InitializeFromIndex ( mdVirtual ); + instCLS.InitializeFromMethod( instMD ); + + // + // Shortcut for terminal virtual methods. + // + if(cls.m_data == instCLS.m_data) + { + if((instMD.m_target->flags & CLR_RECORD_METHODDEF::MD_Abstract) == 0) + { + md = mdVirtual; + + return true; + } + } + + key.m_payload.m_mdVirtual = mdVirtual; + key.m_payload.m_cls = cls; + key.m_payload.m_md.Clear(); + + en = (LookupEntry*)m_tree.Find( &key ); + if(en) + { + md = en->m_payload.m_md; + + // + // Move the node to the top of the MRU list. + // + m_list_inUse.LinkAtFront( en ); + + return true; + } + + { + if(g_CLR_RT_TypeSystem.FindVirtualMethodDef( cls, mdVirtual, md ) == false) + { + return false; + } + } + + { + if(m_list_freeItems.IsEmpty()) + { + en = (LookupEntry*)m_list_inUse.LastNode(); + if(en->Prev() == NULL) + { + // + // No node to steal, return. + // + return true; + } + + m_tree.Remove( en ); + + CLR_PROF_Handler::SuspendTime(); + if(!ConsistencyCheck()) + { + DumpTree(); + } + CLR_PROF_Handler::ResumeTime(); + } + + key.m_payload.m_md = md; + m_tree.Insert( &key ); + + CLR_PROF_Handler::SuspendTime(); + if(!ConsistencyCheck()) + { + DumpTree(); + } + CLR_PROF_Handler::ResumeTime(); + } + + return true; +} + +//--// + +CLR_RT_AVLTree::Entry* CLR_RT_EventCache::VirtualMethodTable::Callback_NewNode( void* state, CLR_RT_AVLTree::Entry* payload ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_EventCache::VirtualMethodTable* pThis = (CLR_RT_EventCache::VirtualMethodTable*)state; + LookupEntry* payloadDirect = (LookupEntry*)payload; + LookupEntry* en; + + en = (LookupEntry*)pThis->m_list_freeItems.ExtractFirstNode(); + if(en) + { + en->m_payload = payloadDirect->m_payload; + + pThis->m_list_inUse.LinkAtFront( en ); + } + + return en; +} + +void CLR_RT_EventCache::VirtualMethodTable::Callback_FreeNode( void* state, CLR_RT_AVLTree::Entry* node ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_EventCache::VirtualMethodTable* pThis = (CLR_RT_EventCache::VirtualMethodTable*)state; + LookupEntry* nodeDirect = (LookupEntry*)node; + + pThis->m_list_freeItems.LinkAtBack( nodeDirect ); +} + +void CLR_RT_EventCache::VirtualMethodTable::Callback_Reassign( void* state, CLR_RT_AVLTree::Entry* from, CLR_RT_AVLTree::Entry* to ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_EventCache::VirtualMethodTable* pThis = (CLR_RT_EventCache::VirtualMethodTable*)state; + LookupEntry* fromDirect = (LookupEntry*)from; + LookupEntry* toDirect = (LookupEntry*)to; + + pThis->m_list_inUse.InsertAfterNode( fromDirect, toDirect ); + + toDirect->m_payload = fromDirect->m_payload; +} + +#else + +void CLR_RT_EventCache::VirtualMethodTable::Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 idx; + + m_entries = (Link*) &g_scratchVirtualMethodTableLink [ 0 ]; + m_entriesMRU = (Link*) &g_scratchVirtualMethodTableLinkMRU[ 0 ]; + m_payloads = (Payload*)&g_scratchVirtualMethodPayload [ 0 ]; + + // + // Link all the entries to themselves => no elements in the lists. + // + for(idx = 0; idx < LinkArraySize(); idx++) + { + Link& lnk = m_entries[ idx ]; + + lnk.m_next = idx; + lnk.m_prev = idx; + } + + // + // Link all the entries to the following one => all the elements are in the MRU list. + // + _ASSERTE(LinkMRUArraySize() < 0xFFFF); + for(idx = 0; idx < LinkMRUArraySize(); idx++) + { + Link& lnk = m_entriesMRU[ idx ]; + + lnk.m_next = idx == LinkMRUArraySize() - 1 ? 0 : idx + 1; + lnk.m_prev = idx == 0 ? (CLR_UINT16)LinkMRUArraySize() - 1 : idx - 1; + } +} + +bool CLR_RT_EventCache::VirtualMethodTable::FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + Payload::Key key; + CLR_UINT32 idx; + CLR_UINT32 idxHead; + CLR_UINT32 clsData = cls .m_data; + CLR_UINT32 mdVirtualData = mdVirtual.m_data; + +#if defined(_WIN32) + bool fVerify = false; + + { + CLR_RT_MethodDef_Instance instMD; + CLR_RT_TypeDef_Instance instCLS; + + instMD .InitializeFromIndex ( mdVirtual ); + instCLS.InitializeFromMethod( instMD ); + + // + // Shortcut for terminal virtual methods. + // + if(clsData == instCLS.m_data) + { + if((instMD.m_target->flags & CLR_RECORD_METHODDEF::MD_Abstract) == 0) + { + md = mdVirtual; + + fVerify = true; + } + } + } +#endif + + if(cls.Assembly() == mdVirtual.Assembly()) + { + CLR_RT_Assembly* assm = g_CLR_RT_TypeSystem.m_assemblies [ mdVirtual.Assembly()-1 ]; + CLR_IDX owner = assm->m_pCrossReference_MethodDef[ mdVirtual.Method() ].GetOwner(); + + if(cls.Type() == owner) + { +#if defined(_WIN32) + if(fVerify != true) + { + CLR_Debug::Printf( "INTERNAL ERROR: Shortcut for terminal virtual methods failed: CLS:%08x:%08x => %08x\r\n", cls.m_data, mdVirtual.m_data, md.m_data ); + ::DebugBreak(); + } +#endif + + md = mdVirtual; + + return true; + } + } + +#if defined(_WIN32) + if(fVerify != false) + { + CLR_Debug::Printf( "INTERNAL ERROR: Shortcut for terminal virtual methods failed: CLS:%08x:%08x\r\n", cls.m_data, mdVirtual.m_data ); + ::DebugBreak(); + } +#endif + + + key.m_mdVirtual.m_data = mdVirtualData; + key.m_cls .m_data = clsData; + + idxHead = (SUPPORT_ComputeCRC( &key, sizeof(key), 0 ) % (LinkArraySize() - PayloadArraySize())) + PayloadArraySize(); + + for(idx = m_entries[ idxHead ].m_next; ; idx = m_entries[ idx ].m_next) + { + if(idx != idxHead) + { + Payload& res = m_payloads[ idx ]; + + if(res.m_key.m_mdVirtual.m_data != mdVirtualData) continue; + if(res.m_key.m_cls .m_data != clsData ) continue; + + md = res.m_md; + + break; + } + else + { + if(g_CLR_RT_TypeSystem.FindVirtualMethodDef( cls, mdVirtual, md ) == false) return false; + + idx = GetNewEntry(); + + Payload& res = m_payloads[ idx ]; + + res.m_md = md; + res.m_key = key; + + break; + } + } + + MoveEntryToTop( m_entries , idxHead , idx ); + MoveEntryToTop( m_entriesMRU, LinkMRUArraySize() - 1, idx ); + + return true; +} + +void CLR_RT_EventCache::VirtualMethodTable::MoveEntryToTop( Link* entries, CLR_UINT32 slot, CLR_UINT32 idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + Link& list = entries[ slot ]; + + if(list.m_next != idx) + { + Link& node = entries[ idx ]; + CLR_UINT32 next; + CLR_UINT32 prev; + + // + // Unlink. + // + next = node.m_next; + prev = node.m_prev; + + entries[ next ].m_prev = prev; + entries[ prev ].m_next = next; + + // + // Insert. + // + next = list.m_next; + + node.m_next = next; + node.m_prev = slot; + + list .m_next = idx; + entries[ next ].m_prev = idx; + } +} + +#endif // #if defined(NANOCLR_USE_AVLTREE_FOR_METHODLOOKUP) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_EventCache::EventCache_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_CLEAR(*this); + + m_events = (BoundedList*)&m_scratch[ 0 ]; + + BoundedList* lst = m_events; + size_t num = c_maxFastLists; + + while(num--) + { + lst->m_blocks.DblLinkedList_Initialize(); + + lst++; + } + + m_lookup_VirtualMethod.Initialize(); + +#ifndef CLR_NO_IL_INLINE + m_inlineBufferStart = (CLR_RT_InlineBuffer*)g_scratchInlineBuffer; + + num = InlineBufferCount()-1; + + for(int i=0; i<(int)num; i++) + { + m_inlineBufferStart[i].m_pNext = &m_inlineBufferStart[i+1]; + } + m_inlineBufferStart[num].m_pNext = NULL; +#endif +} + +CLR_UINT32 CLR_RT_EventCache::EventCache_Cleanup() +{ + NATIVE_PROFILE_CLR_CORE(); + BoundedList* lst = m_events; + size_t num = c_maxFastLists; + CLR_UINT32 tot = 0; + + while(num--) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,lst->m_blocks) + { + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK, CLR_RT_HeapBlock::HB_Pinned, ptr->DataSize()) ); + ptr->ClearData(); + + tot += ptr->DataSize(); + } + NANOCLR_FOREACH_NODE_END(); + + lst->m_blocks.DblLinkedList_Initialize(); + + lst++; + } + + return tot; +} + +//--// + +void CLR_RT_EventCache::Append_Node( CLR_RT_HeapBlock* node ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr = (CLR_RT_HeapBlock_Node*)node; + CLR_UINT32 blocks = ptr->DataSize(); + BoundedList& lst = m_events[blocks < c_maxFastLists ? blocks : 0]; + + ptr->ChangeDataType ( DATATYPE_CACHEDBLOCK ); + ptr->ChangeDataFlags( CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event ); + + NANOCLR_CHECK_EARLY_COLLECTION(ptr); + + ptr->Debug_ClearBlock( 0xAB ); + + lst.m_blocks.LinkAtBack( ptr ); + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectDeletion(node); +#endif +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node_Slow( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr; + CLR_RT_HeapBlock_Node* best = NULL; + CLR_UINT32 bestSize = 0; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,m_events[ 0 ].m_blocks) + { + CLR_UINT32 size = ptr->DataSize(); + + if(size == blocks) + { + best = ptr; + bestSize = blocks; + break; + } + + if(size >= blocks) + { + if(( best && (size < bestSize )) || + (!best && (size <= (blocks * 20) / 16)) ) // Accept a maximum overhead of 25%. + { + best = ptr; + bestSize = size; + } + } + } + NANOCLR_FOREACH_NODE_END(); + + ptr = best; + + if(ptr) + { + // + // Did we select a block bigger than requested? Requeue the tail. + // + if(bestSize > blocks) + { + CLR_RT_HeapBlock_Node* next = &ptr[ blocks ]; + + ptr->SetDataId ( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_CACHEDBLOCK, (CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event), blocks) ); + next->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_CACHEDBLOCK, (CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event), (bestSize - blocks)) ); + next->ClearData(); + + Append_Node( next ); + } + + ptr->Unlink(); + + ptr->ChangeDataType ( dataType ); + ptr->ChangeDataFlags( CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event ); + + if(flags & CLR_RT_HeapBlock::HB_InitializeToZero) + { + ptr->InitializeToZero(); + } + else + { + ptr->Debug_ClearBlock( 0xAD ); + } + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( ptr ); +#endif + + return ptr; + } + + return g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForEvents( dataType, flags, blocks ); +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node_Fast( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr = m_events[ blocks ].m_blocks.FirstNode(); + + if(ptr->Next()) + { + ptr->Unlink(); + + ptr->ChangeDataType ( dataType ); + ptr->ChangeDataFlags( CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event ); + + if(flags & CLR_RT_HeapBlock::HB_InitializeToZero) + { + ptr->InitializeToZero(); + } + else + { + ptr->Debug_ClearBlock( 0xAD ); + } + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( ptr ); +#endif + + return ptr; + } + + return g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForEvents( dataType, flags, blocks ); +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node_Bytes( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Extract_Node( dataType, flags, CONVERTFROMSIZETOHEAPBLOCKS(bytes) ); +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ) +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(NANOCLR_FORCE_GC_BEFORE_EVERY_ALLOCATION) + return g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForEvents( dataType, flags, blocks ); +#else + if(blocks > 0 && blocks < c_maxFastLists) return Extract_Node_Fast( dataType, flags, blocks ); + else return Extract_Node_Slow( dataType, flags, blocks ); +#endif +} + +//--// + +bool CLR_RT_EventCache::FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + return m_lookup_VirtualMethod.FindVirtualMethod( cls, mdVirtual, md ); +} + +// -- // + +#ifndef CLR_NO_IL_INLINE +bool CLR_RT_EventCache::GetInlineFrameBuffer(CLR_RT_InlineBuffer** ppBuffer) +{ + if(m_inlineBufferStart != NULL) + { + *ppBuffer = m_inlineBufferStart; + + m_inlineBufferStart = m_inlineBufferStart->m_pNext; + + return true; + } + + *ppBuffer = NULL; + + return false; +} + +bool CLR_RT_EventCache::FreeInlineBuffer(CLR_RT_InlineBuffer* pBuffer) +{ + pBuffer->m_pNext = m_inlineBufferStart; + m_inlineBufferStart = pBuffer; + return true; +} +#endif + +//////////////////////////////////////////////////////////////////////////////// + diff --git a/source/native/nf-interpreter/src/CLR/Core/Checks.cpp b/source/native/nf-interpreter/src/CLR/Core/Checks.cpp new file mode 100644 index 00000000..cc4984b6 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Checks.cpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_Checks::VerifyObject( CLR_RT_HeapBlock& top ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + switch(top.DataType()) + { + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + if(top.Dereference() != NULL) NANOCLR_SET_AND_LEAVE(S_OK); + break; + + case DATATYPE_ARRAY_BYREF: + if(top.DereferenceArray() != NULL) NANOCLR_SET_AND_LEAVE(S_OK); + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_Checks::VerifyArrayReference( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + + if(ref.DataType() != DATATYPE_OBJECT) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + array = ref.DereferenceArray(); + if(array == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + } + + if(array->DataType() != DATATYPE_SZARRAY) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_Checks::VerifyUnknownInstruction( CLR_OPCODE op ) +{ + (void)op; + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_E_UNKNOWN_INSTRUCTION); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_Checks::VerifyUnsupportedInstruction( CLR_OPCODE op ) +{ + (void)op; + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_E_UNSUPPORTED_INSTRUCTION); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj new file mode 100644 index 00000000..0baacbd4 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1} + Win32Proj + Core + 10.0.17763.0 + Core + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(IntDir) + $(SolutionDir)$(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + Use + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj.filters new file mode 100644 index 00000000..106dbc69 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Core-vs2019.vcxproj.filters @@ -0,0 +1,215 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Header Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Core.cpp b/source/native/nf-interpreter/src/CLR/Core/Core.cpp new file mode 100644 index 00000000..6ad28697 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Core.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +CLR_UINT32 g_buildCRC; + +CLR_RT_ExecutionEngine g_CLR_RT_ExecutionEngine; +CLR_RT_WellKnownTypes g_CLR_RT_WellKnownTypes; +CLR_RT_WellKnownMethods g_CLR_RT_WellKnownMethods; +CLR_RT_TypeSystem g_CLR_RT_TypeSystem; +CLR_RT_EventCache g_CLR_RT_EventCache; +CLR_RT_GarbageCollector g_CLR_RT_GarbageCollector; +CLR_HW_Hardware g_CLR_HW_Hardware; + +//const CLR_RADIAN c_CLR_radians[] = +//{ +// { 1000, -0 }, +// { 995, 105 }, +// { 978, 208 }, +// { 951, 309 }, +// { 914, 407 }, +// { 866, 500 }, +// { 809, 588 }, +// { 743, 669 }, +// { 669, 743 }, +// { 588, 809 }, +// { 500, 866 }, +// { 407, 914 }, +// { 309, 951 }, +// { 208, 978 }, +// { 105, 995 }, +// { 0, 1000 }, +// { -105, 995 }, +// { -208, 978 }, +// { -309, 951 }, +// { -407, 914 }, +// { -500, 866 }, +// { -588, 809 }, +// { -669, 743 }, +// { -743, 669 }, +// { -809, 588 }, +// { -866, 500 }, +// { -914, 407 }, +// { -951, 309 }, +// { -978, 208 }, +// { -995, 105 }, +// { -1000, 0 }, +// { -995, -105 }, +// { -978, -208 }, +// { -951, -309 }, +// { -914, -407 }, +// { -866, -500 }, +// { -809, -588 }, +// { -743, -669 }, +// { -669, -743 }, +// { -588, -809 }, +// { -500, -866 }, +// { -407, -914 }, +// { -309, -951 }, +// { -208, -978 }, +// { -105, -995 }, +// { 0, -1000 }, +// { 105, -995 }, +// { 208, -978 }, +// { 309, -951 }, +// { 407, -914 }, +// { 500, -866 }, +// { 588, -809 }, +// { 669, -743 }, +// { 743, -669 }, +// { 809, -588 }, +// { 866, -500 }, +// { 914, -407 }, +// { 951, -309 }, +// { 978, -208 }, +// { 995, -105 }, +//}; + +// UNDONE: FIXME: the Arm 3.0 compiler drags in a bunch of ABI methods (for initialization) if struct arrays are not initialized +CLR_UINT32 g_scratchDebugger [ sizeof(CLR_DBG_Debugger) ]; +CLR_UINT32 g_scratchDebuggerMessaging[ sizeof(CLR_Messaging) ]; +CLR_DBG_Debugger *g_CLR_DBG_Debugger; + +//--// diff --git a/source/native/nf-interpreter/src/CLR/Core/Core.h b/source/native/nf-interpreter/src/CLR/Core/Core.h new file mode 100644 index 00000000..1a5f4e57 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Core.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_CORE_H_ +#define _NANOCLR_CORE_H_ + +#include +#include +//#include +//#include +#include +//#include +//#include +//#include +// +//#include +// +#include +//#include +//#include +#include + +#endif // _NANOCLR_CORE_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Core/Core.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Core.vcxproj new file mode 100644 index 00000000..803701fd --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Core.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1} + Win32Proj + Core + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(Configuration)\ + $(SolutionDir)$(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + Use + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Core.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Core.vcxproj.filters new file mode 100644 index 00000000..106dbc69 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Core.vcxproj.filters @@ -0,0 +1,215 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Header Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Execution.cpp b/source/native/nf-interpreter/src/CLR/Core/Execution.cpp new file mode 100644 index 00000000..7f92b6f7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Execution.cpp @@ -0,0 +1,3573 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static const CLR_INT64 c_MaximumTimeToActive = (TIME_CONVERSION__ONEMINUTE * TIME_CONVERSION__TO_SECONDS); + + +//--// + +CLR_RT_ExecutionEngine::ExecutionConstraintCompensation CLR_RT_ExecutionEngine::s_compensation = { 0, 0, 0 }; + +//--// + +HRESULT CLR_RT_ExecutionEngine::CreateInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CLEAR(g_CLR_RT_ExecutionEngine); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.ExecutionEngine_Initialize()); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::ExecutionEngine_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + m_maximumTimeToActive = c_MaximumTimeToActive; // CLR_INT64 m_maximumTimeToActive + // int m_iDebugger_Conditions; + // + + // CLR_INT64 m_currentNextActivityTime; + m_timerCache = false; // bool m_timerCache; + // CLR_INT64 m_timerCacheNextTimeout; + // + m_heap .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_heap; + // CLR_RT_HeapCluster* m_lastHcUsed; + m_heapState = c_HeapState_Normal; // int m_heapState; + // + m_weakReferences.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_weakReferences; + // + m_timers .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_timers; + m_raisedEvents = 0; // CLR_UINT32 m_raisedEvents; + // + m_threadsReady .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_threadsReady; + m_threadsWaiting.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_threadsWaiting; + m_threadsZombie .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_threadsZombie; + // int m_lastPid; + // + m_finalizersAlive .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_finalizersAlive; + m_finalizersPending.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_finalizersPending; + // CLR_RT_Thread* m_finalizerThread; + // CLR_RT_Thread* m_cctorThread; + // +#if !defined(NANOCLR_APPDOMAINS) + m_globalLock = NULL; // CLR_RT_HeapBlock* m_globalLock; + m_outOfMemoryException = NULL; // CLR_RT_HeapBlock* m_outOfMemoryException; +#endif // + + m_currentUICulture = NULL; // CLR_RT_HeapBlock* m_currentUICulture; + + CLR_RT_HeapBlock_EndPoint::HandlerMethod_Initialize(); + CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_Initialize(); + + m_interruptThread = NULL; // CLR_RT_Thread m_interruptThread; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + m_scratchPadArray = NULL; // CLR_RT_HeapBlock_Array* m_scratchPadArray; +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + +#if defined(NANOCLR_APPDOMAINS) + m_appDomains.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_appDomains; + + m_appDomainCurrent = NULL; // CLR_AppDomainCurrent* m_appDomainCurrent; + m_appDomainIdNext = c_AppDomainId_Invalid + 1; // int m_appDomainIdNext; +#endif + + m_currentThread = NULL; + + m_GlobalExecutionCounter = 0; + +#if !defined(BUILD_RTM) + m_fShuttingDown = false; //bool m_fShuttingDown; +#endif + + //--// + + NANOCLR_CHECK_HRESULT(AllocateHeaps()); + + g_CLR_RT_TypeSystem.TypeSystem_Initialize(); + g_CLR_RT_EventCache.EventCache_Initialize(); + + //--// + + NANOCLR_CHECK_HRESULT(CLR_HW_Hardware::CreateInstance()); + + //--// + + NANOCLR_CHECK_HRESULT(CLR_Messaging::CreateInstance()); + + NANOCLR_CHECK_HRESULT(CLR_DBG_Debugger::CreateInstance()); + +#if defined(NANOCLR_PROFILE_NEW) + NANOCLR_CHECK_HRESULT(CLR_PRF_Profiler::CreateInstance()); +#endif + +#if defined(NANOCLR_APPDOMAINS) + NANOCLR_CHECK_HRESULT(CLR_RT_AppDomain::CreateInstance( "default", m_appDomainCurrent )); +#endif + + m_startTime = HAL_Time_CurrentTime(); + + CLR_RT_HeapBlock_WeakReference::RecoverObjects( m_heap ); + + //--// + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::AllocateHeaps() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_UINT32 c_HeapClusterSize = sizeof(CLR_RT_HeapBlock) * CLR_RT_HeapBlock::HB_MaxSize; + + CLR_UINT8* heapFirstFree = s_CLR_RT_Heap.m_location; + CLR_UINT32 heapFree = s_CLR_RT_Heap.m_size; + CLR_INT32 i = 0; + CLR_UINT32 blockSize = 1; + + if(heapFree <= sizeof(CLR_RT_HeapCluster)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + while(heapFree > sizeof(CLR_RT_HeapCluster)) + { + CLR_RT_HeapCluster* hc = (CLR_RT_HeapCluster*) heapFirstFree; + CLR_UINT32 size = (heapFree < c_HeapClusterSize) ? heapFree : c_HeapClusterSize; + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink + + CLR_Debug::Printf( "Heap Cluster information\r\n"); + CLR_Debug::Printf( "Start: %08x\r\n", (size_t)heapFirstFree); + CLR_Debug::Printf( "Free: %08x\r\n", (size_t)heapFree); + CLR_Debug::Printf( "Block size: %d\r\n", sizeof(CLR_RT_HeapBlock)); + +#endif + /// + /// Speed up heap initialization for devices with very large heaps > 1MB + /// Exponentially increase the size of a default heap block + /// + if(i > 100*1024*1024) + { + blockSize = CLR_RT_HeapBlock::HB_MaxSize; + } + else if( i > 10*1024*1024) + { + blockSize = 10*1024; + } + else if(i > 1024*1024) + { + blockSize = 1*1024; + } + + hc->HeapCluster_Initialize( size, blockSize ); + + m_heap.LinkAtBack( hc ); + + heapFirstFree += size; + heapFree -= size; + i += size; + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::DeleteInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + g_CLR_RT_ExecutionEngine.ExecutionEngine_Cleanup(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_RT_ExecutionEngine::ExecutionEngine_Cleanup() +{ + ///////////////////////////////////////////////////////////////////////////////////////////////// + // developer notes: + // Most of the following calls are just for pure ceremony and gracefully terminating stuff, + // cleaning collections and such. + // In particular the previous existing calls to Abort threads and ReleaseAllThreads is completely irrelevant + // because the execution engine wasn't running anymore. Whatever code that is on those threads + // there to be executed wouldn't never be executed anyways. + ///////////////////////////////////////////////////////////////////////////////////////////////// + + NATIVE_PROFILE_CLR_CORE(); + m_fShuttingDown = true; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + m_scratchPadArray = NULL; + m_breakpointsNum = 0; + + CLR_DBG_Debugger::DeleteInstance(); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(NANOCLR_PROFILE_NEW) + CLR_PRF_Profiler::DeleteInstance(); +#endif + + CLR_Messaging::DeleteInstance(); + + CLR_HW_Hardware::DeleteInstance(); + + m_finalizersAlive .DblLinkedList_PushToCache(); + m_finalizersPending.DblLinkedList_PushToCache(); + m_finalizerThread = NULL; + m_cctorThread = NULL; + m_timerThread = NULL; + + g_CLR_RT_TypeSystem.TypeSystem_Cleanup(); + g_CLR_RT_EventCache.EventCache_Cleanup(); + +#if !defined(NANOCLR_APPDOMAINS) + m_globalLock = NULL; +#endif + + CLR_RT_HeapBlock_EndPoint::HandlerMethod_CleanUp(); + CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_CleanUp(); + + m_interruptThread = NULL; + + m_heap.DblLinkedList_Initialize(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::StartHardware() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(g_CLR_HW_Hardware.Hardware_Initialize()); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_ExecutionEngine::Reboot( bool fHard ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(fHard) + { + ::CPU_Reset(); + } + else + { + CLR_EE_REBOOT_CLR; + CLR_EE_DBG_SET(RebootPending); + } +} + +CLR_INT64 CLR_RT_ExecutionEngine::GetUptime() +{ + return HAL_Time_CurrentTime() - g_CLR_RT_ExecutionEngine.m_startTime; +} + +void CLR_RT_ExecutionEngine::JoinAllThreadsAndExecuteFinalizer() +{ +} + +void CLR_RT_ExecutionEngine::LoadDownloadedAssemblies() +{ + NATIVE_PROFILE_CLR_CORE (); + PerformGarbageCollection(); + PerformHeapCompaction (); + + // + // Load any patch or similar! + // + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,m_weakReferences) + { + if((weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes) != 0 && weak->m_targetSerialized) + { + CLR_RECORD_ASSEMBLY* header; + + header = (CLR_RECORD_ASSEMBLY*)weak->m_targetSerialized->GetFirstElement(); + + if(header->GoodAssembly()) + { + CLR_RT_Assembly* assm = NULL; + + if(SUCCEEDED(CLR_RT_Assembly::CreateInstance( header, assm ))) + { + assm->m_pFile = weak->m_targetSerialized; + + g_CLR_RT_TypeSystem.Link( assm ); + } + } + } + } + NANOCLR_FOREACH_NODE_END(); + + (void)g_CLR_RT_TypeSystem.ResolveAll(); + + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + if(pASSM->m_pFile) + { + // + // For those assemblies that failed to load (missing dependency?), clean up. + // + if((pASSM->m_flags & CLR_RT_Assembly::ResolutionCompleted) == 0) + { + pASSM->m_pFile = NULL; + + pASSM->DestroyInstance(); + } + } + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + g_CLR_RT_TypeSystem.PrepareForExecution(); +} + +//--// + +void CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend() +{ + NATIVE_PROFILE_CLR_CORE(); + s_compensation.Suspend(); +} + +void CLR_RT_ExecutionEngine::ExecutionConstraint_Resume() +{ + NATIVE_PROFILE_CLR_CORE(); + s_compensation.Resume(); +} + +//--// + +CLR_UINT32 CLR_RT_ExecutionEngine::PerformGarbageCollection() +{ + NATIVE_PROFILE_CLR_CORE(); + m_heapState = c_HeapState_UnderGC; + + CLR_UINT32 freeMem = g_CLR_RT_GarbageCollector.ExecuteGarbageCollection(); + + m_heapState = c_HeapState_Normal; + + m_lastHcUsed = NULL; + +#if !defined(BUILD_RTM) || defined(_WIN32) + if(m_fPerformHeapCompaction) CLR_EE_SET( Compaction_Pending ); +#endif + + g_CLR_RT_ExecutionEngine.SpawnFinalizer(); + + return freeMem; +} + +void CLR_RT_ExecutionEngine::PerformHeapCompaction() +{ + NATIVE_PROFILE_CLR_CORE(); + if(CLR_EE_DBG_IS( NoCompaction )) return; + + g_CLR_RT_GarbageCollector.ExecuteCompaction(); + + CLR_EE_CLR( Compaction_Pending ); + + m_lastHcUsed = NULL; +} + +void CLR_RT_ExecutionEngine::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_scratchPadArray ); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if !defined(NANOCLR_APPDOMAINS) + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_globalLock ); + //CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_outOfMemoryException ); +#endif + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_currentUICulture ); + + m_weakReferences.Relocate(); +} + +//--// + +#if defined(NANOCLR_APPDOMAINS) + +void CLR_RT_ExecutionEngine::TryToUnloadAppDomains_Helper_Threads( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + if(th->m_flags & CLR_RT_Thread::TH_F_ContainsDoomedAppDomain) + { + NANOCLR_FOREACH_NODE(CLR_RT_StackFrame, stack, th->m_stackFrames) + { + stack->m_appDomain->m_fCanBeUnloaded = false; + } + NANOCLR_FOREACH_NODE_END(); + } + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::TryToUnloadAppDomains_Helper_Finalizers( CLR_RT_DblLinkedList& finalizers, bool fAlive ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,finalizers) + { + if(!fin->m_appDomain->IsLoaded()) + { + if(fAlive) + { + //When an AppDomain is being unloaded, all live finalizers are run, regardless + //of whether or not they are still reachable. + m_finalizersPending.LinkAtBack( fin ); + } + + fin->m_appDomain->m_fCanBeUnloaded = false; + } + } + NANOCLR_FOREACH_NODE_END(); +} + +bool CLR_RT_ExecutionEngine::TryToUnloadAppDomains() +{ + NATIVE_PROFILE_CLR_CORE(); + bool fAnyAppDomainsUnloaded = false; + + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,m_appDomains) + { + appDomain->m_fCanBeUnloaded = true; + } + NANOCLR_FOREACH_NODE_END(); + + TryToUnloadAppDomains_Helper_Finalizers( m_finalizersAlive , true ); + TryToUnloadAppDomains_Helper_Finalizers( m_finalizersPending, false ); + + TryToUnloadAppDomains_Helper_Threads( m_threadsReady ); + TryToUnloadAppDomains_Helper_Threads( m_threadsWaiting ); + + CLR_EE_CLR( UnloadingAppDomain ); + + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,m_appDomains) + { + if(appDomain->m_state == CLR_RT_AppDomain::AppDomainState_Unloading) + { + if(appDomain->m_fCanBeUnloaded) + { + appDomain->m_state = CLR_RT_AppDomain::AppDomainState_Unloaded; + appDomain->AppDomain_Uninitialize(); + fAnyAppDomainsUnloaded = true; + } + else + { + CLR_EE_SET(UnloadingAppDomain); + } + } + } + NANOCLR_FOREACH_NODE_END(); + + if(fAnyAppDomainsUnloaded) + { + SignalEvents( CLR_RT_ExecutionEngine::c_Event_AppDomain ); +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + Breakpoint_Assemblies_Loaded(); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + return fAnyAppDomainsUnloaded; +} + +#endif + +HRESULT CLR_RT_ExecutionEngine::WaitForDebugger() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + while(CLR_EE_DBG_IS(Stopped) && !CLR_EE_DBG_IS(RebootPending) && !CLR_EE_DBG_IS(ExitPending)) + { + // TODO: Generalize this as a standard HAL API +#if defined(WIN32) + if(HAL_Windows_IsShutdownPending()) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SHUTTING_DOWN); + } +#endif + + DebuggerLoop(); + } + +#if defined(WIN32) + NANOCLR_NOCLEANUP(); +#else + NANOCLR_NOCLEANUP_NOLABEL(); +#endif +} + +#if defined(WIN32) +HRESULT CLR_RT_ExecutionEngine::CreateEntryPointArgs( CLR_RT_HeapBlock& argsBlk, wchar_t* szCommandLineArgs ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + std::list args; + + wchar_t* szArgNext = NULL; + wchar_t* szArg = szCommandLineArgs; + wchar_t* sep = L" "; + wchar_t* context = NULL; + + szArg = wcstok_s( szArg, sep, &context ); + + while(szArg != NULL) + { + std::wstring arg = szArg; + args.insert( args.end(), arg ); + + szArg = wcstok_s( NULL, sep, &context ); + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( argsBlk, (CLR_UINT32)args.size(), g_CLR_RT_WellKnownTypes.m_String )); + + CLR_RT_HeapBlock_Array* array = argsBlk.Array(); + CLR_UINT32 iArg = 0; + + for(std::list::iterator it = args.begin(); it != args.end(); it++, iArg++) + { + std::string arg; + + CLR_RT_HeapBlock* blk = (CLR_RT_HeapBlock*)array->GetElement( iArg ); + CLR_RT_UnicodeHelper::ConvertToUTF8( (*it).c_str(), arg ); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( *blk, arg.c_str() )); + } + + NANOCLR_NOCLEANUP(); +} + +#endif + +HRESULT CLR_RT_ExecutionEngine::Execute( wchar_t* entryPointArgs, int maxContextSwitch ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock ref; + CLR_RT_Thread* thMain = NULL; + + + if(NANOCLR_INDEX_IS_INVALID(g_CLR_RT_TypeSystem.m_entryPoint)) + { +#if !defined(BUILD_RTM) || defined(_WIN32) + CLR_Debug::Printf( "Cannot find any entrypoint!\r\n" ); +#endif + NANOCLR_SET_AND_LEAVE(CLR_E_ENTRYPOINT_NOT_FOUND); + } + + NANOCLR_CHECK_HRESULT(WaitForDebugger()); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET_MASK(StateProgramRunning,StateMask); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( ref, g_CLR_RT_TypeSystem.m_entryPoint, NULL )); + + { + CLR_RT_ProtectFromGC gc( ref ); + + NANOCLR_CHECK_HRESULT(NewThread( thMain, ref.DereferenceDelegate(), ThreadPriority::Normal, -1 )); + } + + { + CLR_RT_StackFrame* stack = thMain->CurrentFrame(); + + if(stack->m_call.m_target->numArgs > 0) + { + //Main entrypoint takes an optional String[] parameter. + //Set the arg to NULL, if that's the case. + + #if defined(WIN32) + if(entryPointArgs != NULL) + { + NANOCLR_CHECK_HRESULT(CreateEntryPointArgs( stack->m_arguments[ 0 ], entryPointArgs )); + } + else + #else + (void)entryPointArgs; + #endif + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( stack->m_arguments[ 0 ], 0, g_CLR_RT_WellKnownTypes.m_String )); + } + } + } + + //To debug static constructors, the thread should be created after the entrypoint thread. + NANOCLR_CHECK_HRESULT(WaitForDebugger()); + + // m_cctorThread is NULL before call and inialized by the SpawnStaticConstructor + SpawnStaticConstructor( m_cctorThread ); + + + while(true) + { + HRESULT hr2 = ScheduleThreads( maxContextSwitch ); NANOCLR_CHECK_HRESULT(hr2); + + if(CLR_EE_DBG_IS( RebootPending ) || CLR_EE_DBG_IS( ExitPending ) || CLR_EE_REBOOT_IS(ClrOnly)) + { + NANOCLR_SET_AND_LEAVE(S_FALSE); + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) + { + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + + NANOCLR_CHECK_HRESULT(WaitForDebugger()); + + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(CLR_EE_IS(Compaction_Pending)) + { + PerformHeapCompaction(); + _ASSERTE(FIMPLIES(CLR_EE_DBG_IS_NOT(NoCompaction), CLR_EE_IS_NOT(Compaction_Pending))); + } + + if(hr2 == CLR_S_NO_READY_THREADS) + { + WaitForActivity(); + } + else if(hr2 == CLR_S_QUANTUM_EXPIRED) + { +#if !defined(BUILD_RTM) || defined(_WIN32) + if(m_fPerformGarbageCollection) + { +#if defined(NANOCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_GC >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: Forcing GC.\r\n" ); + } +#endif + PerformGarbageCollection(); + +#if defined(NANOCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_Memory > c_CLR_RT_Trace_Info) + { + CLR_UINT32 inUse = g_CLR_RT_GarbageCollector.m_totalBytes - g_CLR_RT_GarbageCollector.m_freeBytes; + + CLR_Debug::Printf( " Memory: INUSE: %d\r\n", (int)inUse ); + } +#endif + } +#endif + } + else + { + break; + } + } + + NANOCLR_CLEANUP(); + +#if defined(NANOCLR_PROFILE_NEW) + /* g_CLR_RT_ExecutionEngine.Cleanup() gets called too late to flush things out on the emulator since it + * only gets called when the finalizer dealing with the managed half of the emulator runs. + */ + g_CLR_PRF_Profiler.Stream_Flush(); +#endif + +#if defined(WIN32) +#if defined(NANOCLR_PROFILE_NEW) + if(CLR_EE_PRF_IS( Enabled )) + { + //Clients do not get all the messages they want if a program happens to end and the emulator terminates before + //the pipe can be read; furthermore the emulator must be able to persist until all required data is requested. + CLR_EE_DBG_SET(Stopped); + } +#endif + + //By skipping the whole CLRStartup routine, the Monitor_Program_Exit message never gets sent to clients. + CLR_EE_DBG_EVENT_BROADCAST(CLR_DBG_Commands::c_Monitor_ProgramExit,0,NULL,WP_Flags_c_NonCritical); + WaitForDebugger(); +#endif + + NANOCLR_CLEANUP_END(); +} + +bool CLR_RT_ExecutionEngine::EnsureSystemThread( CLR_RT_Thread*& thread, int priority ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(thread == NULL) + { + return SUCCEEDED(NewThread( thread, NULL, priority, -1, CLR_RT_Thread::TH_F_System )); + } + else + { + return thread->CanThreadBeReused(); + } +} + +void CLR_RT_ExecutionEngine::SpawnTimer() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,m_timers) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_Triggered) + { + if(EnsureSystemThread( m_timerThread, ThreadPriority::Normal )) + { + //only fire one timer at a time + + timer->SpawnTimer( m_timerThread ); + + //put at the back of the queue to allow for fairness of the timers. + m_timers.LinkAtBack( timer ); + } + break; + } + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::StaticConstructorTerminationCallback( void* arg ) +{ + (void)arg; + + NATIVE_PROFILE_CLR_CORE(); + g_CLR_RT_ExecutionEngine.SpawnStaticConstructor( g_CLR_RT_ExecutionEngine.m_cctorThread ); +} + +#if defined(NANOCLR_APPDOMAINS) +bool CLR_RT_ExecutionEngine::SpawnStaticConstructorHelper( CLR_RT_AppDomain* appDomain, CLR_RT_AppDomainAssembly* appDomainAssembly, const CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Index idxNext; + + _ASSERTE(m_cctorThread != NULL); + //_ASSERTE(m_cctorThread->CanThreadBeReused()); + + idxNext.m_data = idx.m_data; + + _ASSERTE(appDomainAssembly != NULL); + + //find next method with static constructor + if(appDomainAssembly->m_assembly->FindNextStaticConstructor( idxNext )) + { + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock refDlg; refDlg.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refDlg ); + + if(SUCCEEDED(CLR_RT_HeapBlock_Delegate::CreateInstance( refDlg, idxNext, NULL ))) + { + dlg = refDlg.DereferenceDelegate(); + dlg->m_appDomain = appDomain; + + if(SUCCEEDED(m_cctorThread->PushThreadProcDelegate( dlg ))) + { + m_cctorThread->m_terminationCallback = CLR_RT_ExecutionEngine::StaticConstructorTerminationCallback; + + return true; + } + } + } + + appDomainAssembly->m_flags |= CLR_RT_AppDomainAssembly::StaticConstructorsExecuted; + return false; +} + +void CLR_RT_ExecutionEngine::SpawnStaticConstructor( CLR_RT_Thread *&pCctorThread ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Delegate* dlg = NULL; + + if(!EnsureSystemThread(pCctorThread, ThreadPriority::System_Highest )) + return; + + dlg = pCctorThread->m_dlg; + + if(dlg != NULL) + { + CLR_RT_AppDomainAssembly* appDomainAssembly; + CLR_RT_MethodDef_Index idx = dlg->DelegateFtn(); + CLR_RT_MethodDef_Instance inst; + + //Find next static constructor for given idx + _ASSERTE(NANOCLR_INDEX_IS_VALID(idx)); + _SIDE_ASSERTE(inst.InitializeFromIndex( idx )); + + appDomainAssembly = dlg->m_appDomain->FindAppDomainAssembly( inst.m_assm ); + + _ASSERTE(appDomainAssembly != NULL); + _ASSERTE(appDomainAssembly->m_assembly == inst.m_assm ); + + //This is ok if idx is no longer valid. SpawnStaticConstructorHelper will call FindNextStaticConstructor + //which will fail + idx.m_data++; + + //This is not the first static constructor run in this appDomain + if(SpawnStaticConstructorHelper( dlg->m_appDomain, appDomainAssembly, idx )) + return; + } + + //first, find the AppDomainAssembly to run. (what about appdomains!!!) + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + NANOCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,appDomain->m_appDomainAssemblies) + { + CLR_RT_Assembly* assembly = appDomainAssembly->m_assembly; + + //Find an AppDomainAssembly that does not have it's static constructor bit set... + if((appDomainAssembly->m_flags & CLR_RT_AppDomainAssembly::StaticConstructorsExecuted) == 0) + { + CLR_RT_MethodDef_Index idx; idx.Set( assembly->m_idx, 0 ); + +#ifdef DEBUG + + //Check that all dependent assemblies have had static constructors run. + CLR_RT_AssemblyRef_CrossReference* ar = assembly->m_pCrossReference_AssemblyRef; + for(int i=0; im_pTablesSize[ TBL_AssemblyRef ]; i++, ar++) + { + CLR_RT_AppDomainAssembly* appDomainAssemblyRef = appDomain->FindAppDomainAssembly(ar->m_target); + + _ASSERTE(appDomainAssemblyRef != NULL); + _ASSERTE(appDomainAssemblyRef->m_flags & CLR_RT_AppDomainAssembly::StaticConstructorsExecuted); + } +#endif + + + if(SpawnStaticConstructorHelper( appDomain, appDomainAssembly, idx )) + return; + } + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); + + + // No more static constructors needed... + // Perform 1 action: + // 1. Destroy constructor thread. + pCctorThread->DestroyInstance(); +} +#else //NANOCLR_APPDOMAINS + +bool CLR_RT_ExecutionEngine::SpawnStaticConstructorHelper( CLR_RT_Assembly* assembly, const CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Index idxNext; + + _ASSERTE(m_cctorThread != NULL); + _ASSERTE(m_cctorThread->CanThreadBeReused()); + + idxNext.m_data = idx.m_data; + + _ASSERTE(assembly != NULL); + + //find next method with static constructor + if(assembly->FindNextStaticConstructor( idxNext )) + { + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock refDlg; refDlg.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refDlg ); + + if(SUCCEEDED(CLR_RT_HeapBlock_Delegate::CreateInstance( refDlg, idxNext, NULL ))) + { + dlg = refDlg.DereferenceDelegate(); + + if(SUCCEEDED(m_cctorThread->PushThreadProcDelegate( dlg ))) + { + m_cctorThread->m_terminationCallback = CLR_RT_ExecutionEngine::StaticConstructorTerminationCallback; + + return true; + } + } + } + + assembly->m_flags |= CLR_RT_Assembly::StaticConstructorsExecuted; + return false; +} + +void CLR_RT_ExecutionEngine::SpawnStaticConstructor( CLR_RT_Thread *&pCctorThread ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Delegate* dlg = NULL; + + if(!EnsureSystemThread(pCctorThread, ThreadPriority::System_Highest)) + return; + + dlg = pCctorThread->m_dlg; + + if(dlg != NULL) + { + CLR_RT_MethodDef_Index idx = dlg->DelegateFtn(); + CLR_RT_MethodDef_Instance inst; + + //Find next static constructor for given idx + _ASSERTE(NANOCLR_INDEX_IS_VALID(idx)); + _SIDE_ASSERTE(inst.InitializeFromIndex( idx )); + + //This is ok if idx is no longer valid. SpawnStaticConstructorHelper will call FindNextStaticConstructor + //which will fail + idx.m_data++; + + if(SpawnStaticConstructorHelper( inst.m_assm, idx )) + return; + } + + //first, find the AppDomainAssembly to run. (what about appdomains!!!) + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + //Find an AppDomainAssembly that does not have it's static constructor bit set... + if((pASSM->m_flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0) + { + CLR_RT_MethodDef_Index idx; idx.Set( pASSM->m_idx, 0 ); + bool fDepedenciesRun = true; + + //Check that all dependent assemblies have had static constructors run. + CLR_RT_AssemblyRef_CrossReference* ar = pASSM->m_pCrossReference_AssemblyRef; + for(int i=0; im_pTablesSize[ TBL_AssemblyRef ]; i++, ar++) + { + if((ar->m_target->m_flags & CLR_RT_Assembly::StaticConstructorsExecuted) == 0) + { + fDepedenciesRun = true; + break; + } + } + + if(fDepedenciesRun && SpawnStaticConstructorHelper( pASSM, idx )) + return; + } + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + //no more static constructors needed... + pCctorThread->DestroyInstance(); +} +#endif //NANOCLR_APPDOMAINS + +void CLR_RT_ExecutionEngine::FinalizerTerminationCallback(void* arg) +{ + (void)arg; + + NATIVE_PROFILE_CLR_CORE(); + g_CLR_RT_ExecutionEngine.SpawnFinalizer(); +} + +void CLR_RT_ExecutionEngine::SpawnFinalizer() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_RT_HeapBlock_Finalizer* fin = (CLR_RT_HeapBlock_Finalizer*)m_finalizersPending.FirstNode(); + if(fin->Next() != NULL) + { + CLR_RT_HeapBlock delegate; delegate.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( delegate ); + +#if defined(NANOCLR_APPDOMAINS) + (void)SetCurrentAppDomain( fin->m_appDomain ); +#endif + + if(EnsureSystemThread(m_finalizerThread, ThreadPriority::BelowNormal)) + { + if(SUCCEEDED(CLR_RT_HeapBlock_Delegate::CreateInstance( delegate, fin->m_md, NULL ))) + { + CLR_RT_HeapBlock_Delegate* dlg = delegate.DereferenceDelegate(); + + dlg->m_object.SetObjectReference( fin->m_object ); + + if(SUCCEEDED(m_finalizerThread->PushThreadProcDelegate( dlg ))) + { + g_CLR_RT_EventCache.Append_Node( fin ); + m_finalizerThread->m_terminationCallback = CLR_RT_ExecutionEngine::FinalizerTerminationCallback; + } + } + } + } +} + +void CLR_RT_ExecutionEngine::AdjustExecutionCounter( CLR_RT_DblLinkedList &threadList, int iUpdateValue ) + +{ // Iterate over threads in increase executioin counter by iUpdateValue + NANOCLR_FOREACH_NODE(CLR_RT_Thread,pThread,threadList) + { + pThread->m_executionCounter += iUpdateValue; + // Update m_executionCounter if thread is too behind of m_GlobalExecutionCounter + pThread->BringExecCounterToDate( m_GlobalExecutionCounter, pThread->GetQuantumDebit() ); + } + NANOCLR_FOREACH_NODE_END() +} + +void CLR_RT_ExecutionEngine::UpdateToLowestExecutionCounter( CLR_RT_Thread *pThread ) const +{ + // Set the m_executionCounter in thread to lowest value among ready threads. + // Thus it will be executed last. + pThread->m_executionCounter = m_GlobalExecutionCounter - 1; +} + +void CLR_RT_ExecutionEngine::RetrieveCurrentMethod( CLR_UINT32& assmIdx, CLR_UINT32& methodIdx ) +{ + assmIdx = 0; + methodIdx = 0; + + if(m_currentThread != NULL) + { + CLR_RT_StackFrame* stack = m_currentThread->CurrentFrame(); + + if(stack) + { + assmIdx = stack->m_call.Assembly(); + methodIdx = stack->m_call.Method (); + } + } +} + +void CLR_RetrieveCurrentMethod( CLR_UINT32 & assmIdx, CLR_UINT32 & methodIdx ) +{ + g_CLR_RT_ExecutionEngine.RetrieveCurrentMethod( assmIdx, methodIdx ); +} + +void CLR_SoftReboot() +{ + CLR_EE_DBG_SET( RebootPending ); +} + +void CLR_DebuggerBreak() +{ + if(g_CLR_RT_ExecutionEngine.m_currentThread != NULL) + { + CLR_RT_HeapBlock *obj = g_CLR_RT_ExecutionEngine.m_currentThread->m_currentException.Dereference(); + + /// + /// Only inject the exception once -- if the dereference is not null then the exception is already set on the current thread + /// + if(obj == NULL) + { + Library_corlib_native_System_Exception::CreateInstance( g_CLR_RT_ExecutionEngine.m_currentThread->m_currentException, g_CLR_RT_WellKnownTypes.m_WatchdogException, CLR_E_WATCHDOG_TIMEOUT, g_CLR_RT_ExecutionEngine.m_currentThread->CurrentFrame() ); + } + } +} + +HRESULT CLR_RT_ExecutionEngine::ScheduleThreads( int maxContextSwitch ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + // We run threads based on the m_executionCounter. + // The thread with highest m_executionCounter is chosen for execution. + // The highest value of m_executionCounter of any thread is stored in m_GlobalExecutionCounter + // We need to check that m_GlobalExecutionCounter does not underflow ( runs below - -2147483647 ) This would be very rare condition, but it may happen. + // We put threshold at - 0x40000000 + if ( m_GlobalExecutionCounter < -EXECUTION_COUNTER_MAXIMUM ) + { // Iterate over threads in all queues and bump the execution counter by MAX_EXECUTION_COUNTER_ADJUSTMENT + + m_GlobalExecutionCounter += EXECUTION_COUNTER_ADJUSTMENT; + + // For each list of threads runs over it and updates execution counter. + // AdjustExecutionCounter gets const & to list of threads. + // List of threads is not modified, but m_executionCounter is bumped up in each thread. + + AdjustExecutionCounter( m_threadsReady, EXECUTION_COUNTER_ADJUSTMENT ); + AdjustExecutionCounter( m_threadsWaiting, EXECUTION_COUNTER_ADJUSTMENT ); + AdjustExecutionCounter( m_threadsZombie, EXECUTION_COUNTER_ADJUSTMENT ); + } + + while(maxContextSwitch-- > 0) + { + +#if defined(WIN32) + if(HAL_Windows_IsShutdownPending()) + { + NANOCLR_SET_AND_LEAVE(CLR_S_NO_THREADS); + } +#endif + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) + { + NANOCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + CLR_RT_Thread* th = NULL; + + // If a static constructor thread exists, we should be running it. + // What about func-eval? + if (m_cctorThread == NULL) + { + // This is normal case execution. Looks for first ready thread. + th = (CLR_RT_Thread*)m_threadsReady.FirstNode(); + } + else //If a static constructor thread exists, we should be running it. + { + // This is special case executed during initialization of static constructors. + if (m_cctorThread->m_status == CLR_RT_Thread::TH_S_Ready && !(m_cctorThread->m_flags & CLR_RT_Thread::TH_F_Suspended)) + { + th = m_cctorThread; + } + else + { + // The m_cctorThread is exists, but not ready - means entered blocking call. + // We do not want to preempt constructor thread, so stay idle. + NANOCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } + } + + + + + // If th->Next() is NULL, then there are no Ready to run threads in the system. + // In this case we spawn finalizer and make finalizer thread as ready one. + if(th->Next() == NULL) + { + g_CLR_RT_ExecutionEngine.SpawnFinalizer(); + + // Now finalizer thread might be in ready state if there are object that need call to finalizer. + // th might point to finilizer thread. + th = (CLR_RT_Thread*)m_threadsReady.FirstNode(); + + //Thread create can cause stopping debugging event +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS(Stopped)) + { + NANOCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + // If there is ready thread - decrease m_executionCounter for this (th) thread. + if( th->Next() != NULL ) + { + // The value to update m_executionCounter for each run. See comment for GetQuantumDebit for possible values + int debitForEachRun = th->GetQuantumDebit(); + + // If thread is way too much behind on its execution, we cutt off extra credit. + // We garantee the thread will not be scheduled more than 4 consequitive times. + th->BringExecCounterToDate( m_GlobalExecutionCounter, debitForEachRun ); + + // Substruct the execution counter by debit value ( for executing thread ) + th->m_executionCounter -= debitForEachRun; + + // Keep the track of lowest execution counter. + if ( th->m_executionCounter < m_GlobalExecutionCounter ) + { + m_GlobalExecutionCounter = th->m_executionCounter; + } + } + else + { + if(m_threadsWaiting.IsEmpty()) + { + NANOCLR_SET_AND_LEAVE(CLR_S_NO_THREADS); + } + + NANOCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } + + Watchdog_Reset(); + + { + // Runs the tread until expiration of its quantum or until thread is blocked. + hr = th->Execute(); + } + + if(FAILED(hr)) + { + switch(hr) + { + case CLR_E_RESCHEDULE: + break; + + case CLR_E_THREAD_WAITING: + th->m_status = CLR_RT_Thread::TH_S_Waiting; + break; + + default: + th->m_status = CLR_RT_Thread::TH_S_Terminated; + break; + } + } + + Watchdog_Reset(); + + PutInProperList( th ); + + (void)ProcessTimer(); + } + + NANOCLR_SET_AND_LEAVE(CLR_S_QUANTUM_EXPIRED); + + NANOCLR_CLEANUP(); + +#if defined(NANOCLR_APPDOMAINS) + + if(CLR_EE_IS( UnloadingAppDomain )) + { + if(TryToUnloadAppDomains()) + { + //If we are successful in unloading an AppDomain, return CLR_S_QUANTUM_EXPIRED + //to cause ScheduleThreads to be called again. This allows the somewhat expensive operation + //of trying to unload an AppDomain once every ScheduleThread call, rather than once every context switch + + hr = CLR_S_QUANTUM_EXPIRED; + } + } + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + NANOCLR_CLEANUP_END(); +} + +CLR_UINT32 CLR_RT_ExecutionEngine::WaitForActivity() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_INT64 timeoutMin = ProcessTimer(); + + if(m_threadsReady.IsEmpty() == false) return 0; // Someone woke up... + + if(timeoutMin > 0LL) + { + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,m_threadsWaiting) + { + if((th->m_waitForEvents & c_Event_IdleCPU) != 0 && th->m_waitForEvents_IdleTimeWorkItem < timeoutMin) + { + th->m_waitForEvents_IdleTimeWorkItem = TIMEOUT_ZERO; + + th->Restart( true ); + + return SYSTEM_EVENT_FLAG_ALL; // Someone woke up... + } + } + NANOCLR_FOREACH_NODE_END(); + + return WaitForActivity( SLEEP_LEVEL__SLEEP, g_CLR_HW_Hardware.m_wakeupEvents, timeoutMin ); + } + + return 0; +} + +CLR_UINT32 CLR_RT_ExecutionEngine::WaitForActivity( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeout_ms ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(powerLevel != PowerLevel__Active) + { + return WaitSystemEvents( powerLevel, events, timeout_ms ); + } + + return 0; +} + +//--// + +void CLR_RT_ExecutionEngine::PutInProperList( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + switch(th->m_status) + { + case CLR_RT_Thread::TH_S_Ready: + if((th->m_flags & CLR_RT_Thread::TH_F_Suspended) == 0) + { + InsertThreadRoundRobin( m_threadsReady, th ); + break; + } + // + // Fall-through... + // + case CLR_RT_Thread::TH_S_Waiting: + m_threadsWaiting.LinkAtBack( th ); + break; + + case CLR_RT_Thread::TH_S_Terminated: + th->Passivate(); + break; + + case CLR_RT_Thread::TH_S_Unstarted: + m_threadsZombie.LinkAtFront( th ); + break; + } +} + +void CLR_RT_ExecutionEngine::AbortAllThreads( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + if((th->m_flags & CLR_RT_Thread::TH_F_Aborted) == 0) + { + th->Abort(); + + NANOCLR_FOREACH_NODE_RESTART(CLR_RT_Thread,th,threads); + } + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::ReleaseAllThreads( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(true) + { + CLR_RT_Thread* th = (CLR_RT_Thread*)threads.ExtractFirstNode(); if(!th) break; + + th->DestroyInstance(); + } +} + +void CLR_RT_ExecutionEngine::InsertThreadRoundRobin( CLR_RT_DblLinkedList& threads, CLR_RT_Thread* thTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th; + + thTarget->Unlink(); + + if(threads.IsEmpty()) + { + th = (CLR_RT_Thread*)threads.Tail(); + } + else + { + int priTarget = thTarget->GetExecutionCounter(); + + NANOCLR_FOREACH_NODE__NODECL(CLR_RT_Thread,th,threads) + { + if(th->GetExecutionCounter() < priTarget) break; + } + NANOCLR_FOREACH_NODE_END(); + } + + thTarget->m_waitForEvents = 0; + thTarget->m_waitForEvents_Timeout = TIMEOUT_INFINITE; + + if(thTarget->m_waitForObject != NULL) + { + g_CLR_RT_EventCache.Append_Node( thTarget->m_waitForObject ); + + thTarget->m_waitForObject = NULL; + } + + threads.InsertBeforeNode( th, thTarget ); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::NewThread( CLR_RT_Thread*& thRes, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_INT32 id, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(CLR_RT_Thread::CreateInstance( id != -1 ? id : ++m_lastPid, pDelegate, priority, thRes, flags )); + + PutInProperList( thRes ); + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(thRes) + { + thRes->DestroyInstance(); + + thRes = NULL; + } + } + + NANOCLR_CLEANUP_END(); +} + +CLR_INT32 CLR_RT_ExecutionEngine::GetNextThreadId() +{ + return ++m_lastPid; +} + +//--// + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocksForArray( CLR_RT_TypeDef_Instance& inst, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DataType dt = (CLR_DataType)inst.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_Array) + length * dtl.m_sizeInBytes); + CLR_UINT32 lengthHB = CONVERTFROMSIZETOHEAPBLOCKS(totLength); + + if(lengthHB > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + CLR_RT_HeapBlock_Array* pArray = (CLR_RT_HeapBlock_Array*)ExtractHeapBlocks( m_heap, DATATYPE_SZARRAY, 0, lengthHB ); + + if(pArray) + { + pArray->ReflectionData() = reflex; + pArray->m_numOfElements = length; + + pArray->m_typeOfElement = dt; + pArray->m_sizeOfElement = dtl.m_sizeInBytes; + pArray->m_fReference = (dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) == 0; + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( pArray ); +#endif + } + + return pArray; +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocksForClassOrValueTypes( CLR_UINT32 dataType, CLR_UINT32 flags, const CLR_RT_TypeDef_Index& cls, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(length > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + _ASSERTE(dataType == DATATYPE_CLASS || dataType == DATATYPE_VALUETYPE); + + flags = flags | CLR_RT_HeapBlock::HB_InitializeToZero; + CLR_RT_HeapBlock* hb = ExtractHeapBlocks( m_heap, dataType, flags, length ); + + if(hb) + { + hb->SetObjectCls(cls); + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( hb ); +#endif + } + + return hb; +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBytesForObjects( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + return ExtractHeapBlocksForObjects( dataType, flags, CONVERTFROMSIZETOHEAPBLOCKS(length) ); +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocksForObjects( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(length > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + _ASSERTE(dataType != DATATYPE_CLASS && dataType != DATATYPE_VALUETYPE && dataType != DATATYPE_SZARRAY); + + flags &= ~CLR_RT_HeapBlock::HB_Alive; + + CLR_RT_HeapBlock* hb = ExtractHeapBlocks( m_heap, dataType, flags, length ); + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + if(hb) + { + g_CLR_PRF_Profiler.TrackObjectCreation( hb ); + } +#endif + + return hb; +} + +//--// + +CLR_RT_HeapBlock_Node* CLR_RT_ExecutionEngine::ExtractHeapBlocksForEvents( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(length > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + flags |= CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event; + + CLR_RT_HeapBlock_Node* hb = (CLR_RT_HeapBlock_Node*)ExtractHeapBlocks( m_heap, dataType, flags, length ); + + if(hb) + { + hb->GenericNode_Initialize(); + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( hb ); +#endif + } + + return hb; +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocks( CLR_RT_DblLinkedList& heap, CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); +#if !defined(BUILD_RTM) + if(m_heapState == c_HeapState_UnderGC && ((flags & CLR_RT_HeapBlock::HB_SpecialGCAllocation) == 0)) + { + CLR_Debug::Printf( "Internal error: call to memory allocation during garbage collection!!!\r\n" ); + + // Getting here during a GC is possible, since the watchdog ISR may now require + // dynamic memory allocation for logging. Returning NULL means the watchdog log will + // be lost, but without major restructuring there is not much we can do. + return NULL; + } +#endif + +#if defined(NANOCLR_FORCE_GC_BEFORE_EVERY_ALLOCATION) + if(m_heapState != c_HeapState_UnderGC) + { + g_CLR_RT_EventCache.EventCache_Cleanup(); + PerformGarbageCollection(); + } +#endif + + for(int phase=0; ; phase++) + { + { + CLR_RT_HeapBlock* hb; + + if(flags & CLR_RT_HeapBlock::HB_Event) + { + NANOCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapCluster,hc,heap) + { + hb = hc->ExtractBlocks( dataType, flags, length ); + if(hb) + { + return hb; + } + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + } + else + { + if(m_lastHcUsed != NULL) + { + hb = m_lastHcUsed->ExtractBlocks( dataType, flags, length ); + if(hb) + { + return hb; + } + } + + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,heap) + { + hb = hc->ExtractBlocks( dataType, flags, length ); + if(hb) + { +#if defined(NANOCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_Memory >= c_CLR_RT_Trace_Info) + { + if(phase != 0) + { + CLR_Debug::Printf( "ExtractHeapBlocks succeeded at phase %d\r\n", phase ); + } + } +#endif + m_lastHcUsed = hc; + return hb; + } + } + NANOCLR_FOREACH_NODE_END(); + } + + m_lastHcUsed = NULL; + } + + if(flags & CLR_RT_HeapBlock::HB_NoGcOnFailedAllocation) + { + return NULL; + } + + switch(phase) + { + case 0: +#if defined(NANOCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_Memory >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: ExtractHeapBlocks: %d bytes needed.\r\n", length * sizeof(CLR_RT_HeapBlock) ); + } +#endif + + PerformGarbageCollection(); + + break; + + default: // Total failure... +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Failed allocation for %d blocks, %d bytes\r\n\r\n", length, length * sizeof(CLR_RT_HeapBlock) ); +#endif + if(g_CLR_RT_GarbageCollector.m_freeBytes >= (length * sizeof(CLR_RT_HeapBlock))) + { + + //A compaction probably would have saved this OOM + //Compaction will occur for Bitmaps, Arrays, etc. if this function returns NULL, so lets not + //through an assert here + + //Throw the OOM, and schedule a compaction at a safe point + CLR_EE_SET( Compaction_Pending ); + } + + return NULL; + } + } +} + + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::AccessStaticField( const CLR_RT_FieldDef_Index& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_FieldDef_Instance inst; + + if(inst.InitializeFromIndex( fd ) && inst.m_target->flags & CLR_RECORD_FIELDDEF::FD_Static) + { +#if defined(NANOCLR_APPDOMAINS) + { + CLR_RT_AppDomainAssembly* appDomainAssembly = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( inst.m_assm ); + + if(appDomainAssembly) + { + return &appDomainAssembly->m_pStaticFields[ inst.CrossReference().m_offset ]; + } + } +#else + return &inst.m_assm->m_pStaticFields[ inst.CrossReference().m_offset ]; +#endif + } + + return NULL; +} + +HRESULT CLR_RT_ExecutionEngine::InitializeReference( CLR_RT_HeapBlock& ref, CLR_RT_SignatureParser& parser ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // If you change this method, change "CLR_RT_ExecutionEngine::InitializeLocals" too. + // + + NANOCLR_HEADER(); + + CLR_RT_SignatureParser::Element res; + CLR_DataType dt; + + NANOCLR_CHECK_HRESULT(parser.Advance( res )); + + dt = res.m_dt; + + if(res.m_levels > 0) // Array + { + dt = DATATYPE_OBJECT; + } + else + { + if(dt == DATATYPE_VALUETYPE) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( res.m_cls ); + + if((inst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum) + { + dt = (CLR_DataType)inst.m_target->dataType; + } + else + { + NANOCLR_SET_AND_LEAVE(NewObject( ref, inst )); + } + } + else + { + if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Reference) + { + dt = DATATYPE_OBJECT; + } + } + } + + ref.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID( dt, CLR_RT_HeapBlock::HB_Alive, 1 ) ); + ref.ClearData(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::InitializeReference( CLR_RT_HeapBlock& ref, const CLR_RECORD_FIELDDEF* target, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_SignatureParser parser; parser.Initialize_FieldDef( assm, target ); + + NANOCLR_SET_AND_LEAVE(InitializeReference( ref, parser )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::InitializeLocals( CLR_RT_HeapBlock* locals, CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // This method is a shortcut for the following code: + // + + NANOCLR_HEADER(); + + CLR_PMETADATA sig = assm->GetSignature( md->locals ); + CLR_UINT32 count = md->numLocals; + bool fZeroed = false; + + while(count) + { + CLR_DataType dt = DATATYPE_VOID; + CLR_RT_TypeDef_Index cls; + CLR_UINT32 levels = 0; + CLR_DataType dtModifier = DATATYPE_VOID; + + while(true) + { + dt = CLR_UncompressElementType( sig ); + + switch(dt) + { + case DATATYPE_TYPE_PINNED : + dtModifier = DATATYPE_TYPE_PINNED; + break; + + // Array declared on stack .locals init [0] int16[] foo, + case DATATYPE_SZARRAY: + // Reference declared on stack - .locals init [1] int16& pinned pShort, + case DATATYPE_BYREF: + levels++; + break; + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + CLR_UINT32 tk = CLR_TkFromStream( sig ); + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk( tk )) + { + case TBL_TypeSpec: + { + CLR_RT_SignatureParser sub; sub.Initialize_TypeSpec( assm, assm->GetTypeSpec( idx ) ); + CLR_RT_SignatureParser::Element res; + + NANOCLR_CHECK_HRESULT(sub.Advance( res )); + + cls = res.m_cls; + levels += res.m_levels; + } + break; + + case TBL_TypeRef: + cls = assm->m_pCrossReference_TypeRef[ idx ].m_target; + break; + + case TBL_TypeDef: + cls.Set( assm->m_idx, idx ); + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + } + goto done; + + default: + { + const CLR_RT_TypeDef_Index* cls2 = c_CLR_RT_DataTypeLookup[ dt ].m_cls; + + if(cls2 == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + cls = *cls2; + } + goto done; + } + } + +done: + if(levels > 0) // Array or reference + { + locals->SetObjectReference( NULL ); + + // If local varialb has DATATYPE_TYPE_PINNED, we mark heap block as + if ( dtModifier == DATATYPE_TYPE_PINNED ) + { + locals->Pin(); + } + } + else + { + if(dt == DATATYPE_VALUETYPE) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( cls ); + + if(inst.m_target->dataType != DATATYPE_VALUETYPE) + { + locals->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID( inst.m_target->dataType, CLR_RT_HeapBlock::HB_Alive, 1 ) ); + locals->ClearData(); + } + else + { + // + // Before we allocate anything, we need to make sure the rest of the local variables are in a consistent state. + // + if(fZeroed == false) + { + fZeroed = true; + + CLR_RT_HeapBlock* ptr = locals; + CLR_RT_HeapBlock* ptrEnd = &locals[ count ]; + + do + { + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_I4,0,1) ); + + } while(++ptr < ptrEnd); + } + + NANOCLR_CHECK_HRESULT(NewObject( *locals, inst )); + } + } + else + { + if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Reference) + { + dt = DATATYPE_OBJECT; + } + + locals->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt,CLR_RT_HeapBlock::HB_Alive,1) ); + locals->ClearData(); + } + } + + locals++; + count--; + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::NewObjectFromIndex( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( cls ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_SET_AND_LEAVE(NewObject( reference, inst )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::NewObject( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + reference.SetObjectReference( NULL ); + + CLR_DataType dt = (CLR_DataType)inst.m_target->dataType; + + // + // You cannot create an array this way. + // + if(inst.m_data == g_CLR_RT_WellKnownTypes.m_Array.m_data) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if((c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Reference) == 0) + { + reference.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt,0,1) ); + } + else + { + switch(dt) + { + case DATATYPE_STRING: + // + // Special case for strings. + // + break; + + case DATATYPE_WEAKCLASS: + { + CLR_RT_HeapBlock_WeakReference* weakref; + + // this used to be a call to CLR_RT_HeapBlock_WeakReference::CreateInstance + weakref = (CLR_RT_HeapBlock_WeakReference*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_WEAKCLASS, CLR_RT_HeapBlock::HB_InitializeToZero, sizeof(*weakref) ); + CHECK_ALLOCATION(weakref); + + reference.SetObjectReference( weakref ); + } + break; + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + int clsFields = inst.m_target->iFields_Num; + int totFields = inst.CrossReference().m_totalFields + CLR_RT_HeapBlock::HB_Object_Fields_Offset; + CLR_RT_HeapBlock* obj = ExtractHeapBlocksForClassOrValueTypes( dt, 0, inst, totFields ); CHECK_ALLOCATION(obj); + + reference.SetObjectReference( obj ); + + { + const CLR_RECORD_FIELDDEF* target = NULL; + CLR_RT_Assembly* assm = NULL; + CLR_RT_TypeDef_Instance instSub = inst; + + + NANOCLR_CHECK_HRESULT(obj->SetObjectCls( inst )); + + // + // Initialize field types, from last to first. + // + // We do the decrement BEFORE the comparison because we want to stop short of the first field, the object descriptor (already initialized). + // + obj += totFields; + while(--totFields > 0) + { + while(clsFields == 0) + { + if(instSub.SwitchToParent() == false) NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + + clsFields = instSub.m_target->iFields_Num; + target = NULL; + } + + if(target == NULL) + { + assm = instSub.m_assm; + target = assm->GetFieldDef( instSub.m_target->iFields_First + clsFields ); + } + + obj--; target--; clsFields--; + + NANOCLR_CHECK_HRESULT(InitializeReference( *obj, target, assm )); + } + } + + if(inst.HasFinalizer()) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Finalizer::CreateInstance( reference.Dereference(), inst )); + } + } + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::NewObject( CLR_RT_HeapBlock& reference, CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance res; + + if(res.ResolveToken( tk, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_CHECK_HRESULT(NewObjectFromIndex( reference, res )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::CloneObject( CLR_RT_HeapBlock& reference, const CLR_RT_HeapBlock& source ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_RT_HeapBlock* obj = &source; + CLR_DataType dt; + + while(true) + { + dt = (CLR_DataType)obj->DataType(); + + if(dt == DATATYPE_BYREF || + dt == DATATYPE_OBJECT ) + { + obj = obj->Dereference(); FAULT_ON_NULL(obj); + } + else + { + break; + } + } + + switch(dt) + { + + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS: + { + // + // Save the pointer to the object to clone, in case 'reference' and 'source' point to the same block. + // + CLR_RT_HeapBlock safeSource; safeSource.SetObjectReference( obj ); + CLR_RT_ProtectFromGC gc( safeSource ); + + NANOCLR_CHECK_HRESULT(NewObjectFromIndex( reference , obj->ObjectCls() )); + NANOCLR_CHECK_HRESULT(CopyValueType ( reference.Dereference(), obj )); + } + break; + + default: + if((c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + // + // Non-reference type, straight copy. + // + reference.Assign( source ); + break; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::CopyValueType( CLR_RT_HeapBlock* destination, const CLR_RT_HeapBlock* source ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(destination != source) + { + const CLR_RT_TypeDef_Index& cls = source->ObjectCls(); + if(cls.m_data == destination->ObjectCls().m_data) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( cls ); + CLR_UINT32 totFields = inst.CrossReference().m_totalFields; + + if(source->IsBoxed()) destination->Box(); + + while(true) + { + if(totFields-- == 0) break; + + // + // We increment the two pointers to skip the header of the objects. + // + source ++; + destination++; + + NANOCLR_CHECK_HRESULT(destination->Reassign( *source )); + } + + NANOCLR_SET_AND_LEAVE(S_OK); + } + + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::NewArrayList( CLR_RT_HeapBlock& ref, int size, CLR_RT_HeapBlock_Array*& array ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const int minCapacity = CLR_RT_ArrayListHelper::c_defaultCapacity; + int count = size; + int capacity = size < minCapacity ? minCapacity : size; + + NANOCLR_CHECK_HRESULT(NewObjectFromIndex( ref, g_CLR_RT_WellKnownTypes.m_ArrayList )); + + NANOCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::PrepareArrayList ( ref, count, capacity )); + NANOCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( ref, array, count, capacity )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::FindFieldDef( CLR_RT_TypeDef_Instance& inst, const char* szText, CLR_RT_FieldDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance local = inst; + + do + { + if(local.m_assm->FindFieldDef( local.m_target, szText, NULL, 0, res )) NANOCLR_SET_AND_LEAVE(S_OK); + } + while(local.SwitchToParent()); + + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::FindFieldDef( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_FieldDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* obj; + CLR_RT_TypeDef_Instance inst; + + if(reference.DataType() != DATATYPE_OBJECT) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + obj = reference.Dereference(); FAULT_ON_NULL(obj); + + if(inst.InitializeFromIndex( obj->ObjectCls() ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_SET_AND_LEAVE(FindFieldDef( inst, szText, res )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::FindField( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_HeapBlock*& field ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_FieldDef_Instance inst; + CLR_RT_FieldDef_Index idx; + CLR_RT_HeapBlock* res; + + field = NULL; + + NANOCLR_CHECK_HRESULT(FindFieldDef( reference, szText, idx )); + + inst.InitializeFromIndex( idx ); + + if(inst.m_target->flags & CLR_RECORD_FIELDDEF::FD_Static) + { + res = CLR_RT_ExecutionEngine::AccessStaticField( idx ); if(res == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + res = reference.Dereference(); FAULT_ON_NULL(res); + + res += inst.CrossReference().m_offset; + } + + field = res; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::SetField( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_HeapBlock& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* field; + + NANOCLR_CHECK_HRESULT(FindField( reference, szText, field )); + + field->Assign( value ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::GetField( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_HeapBlock& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* field; + + NANOCLR_CHECK_HRESULT(FindField( reference, szText, field )); + + value.Assign( *field ); + + NANOCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_HeapBlock_Lock* CLR_RT_ExecutionEngine::FindLockObject( CLR_RT_DblLinkedList& threads, CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + CLR_RT_HeapBlock& res = lock->m_resource; + +#if defined(NANOCLR_APPDOMAINS) + if(lock->m_appDomain != GetCurrentAppDomain()) continue; +#endif + + if(CLR_RT_HeapBlock::ObjectsEqual(res, object, true)) + { + return lock; + } + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); + + return NULL; +} + +CLR_RT_HeapBlock_Lock* CLR_RT_ExecutionEngine::FindLockObject( CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Lock* lock; + + if(object.DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = object.Dereference(); + + if(ptr) + { + switch(ptr->DataType()) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS : + return ptr->ObjectLock(); + + default: + // the remaining data types aren't to be handled + break; + } + } + } + + lock = FindLockObject( m_threadsReady , object ); if(lock) return lock; + lock = FindLockObject( m_threadsWaiting, object ); return lock; +} + +//--// + +void CLR_RT_ExecutionEngine::DeleteLockRequests( CLR_RT_Thread* thTarget, CLR_RT_SubThread* sthTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(( thTarget && thTarget->m_lockRequestsCount) || + (sthTarget && sthTarget->m_lockRequestsCount) ) + { + DeleteLockRequests( thTarget, sthTarget, m_threadsReady ); + DeleteLockRequests( thTarget, sthTarget, m_threadsWaiting ); + } +} + +void CLR_RT_ExecutionEngine::DeleteLockRequests( CLR_RT_Thread* thTarget, CLR_RT_SubThread* sthTarget, CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_LockRequest,req,lock->m_requests) + { + CLR_RT_SubThread* sth = req->m_subthreadWaiting; + + if(sth == sthTarget || sth->m_owningThread == thTarget) + { + g_CLR_RT_EventCache.Append_Node( req ); + + if(sth->ChangeLockRequestCount( -1 )) return; + } + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_RT_ExecutionEngine::ProcessHardware() +{ + NATIVE_PROFILE_CLR_CORE(); + Watchdog_Reset(); + + g_CLR_HW_Hardware.ProcessActivity(); +} + +CLR_INT64 CLR_RT_ExecutionEngine::ProcessTimer() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_INT64 timeoutMin; + + ProcessHardware(); + + timeoutMin = m_maximumTimeToActive; // max sleep. + + //////////////////////////////////////////////// + // WARNING + // + // The check on the 'Stopped' condition, and the 'else' + // condition below cause a race condition when the application is running under debugger + // and there are no ready threads in the app. teh desktop side debugger in facts is prodigal + // of Stopped commands and so is the runtime itself. Since the commands come asynchronously + // though and there is no co-ordination it is possible that + // a) a 'Stopped' condition reset get lost or + // b) waiting threads whose timers are expired are never moved to the ready queue + // + + if(CLR_EE_DBG_IS( Stopped ) && m_threadsWaiting.IsEmpty()) + { + // Don't process events while the debugger is stopped and no thread was waiting. + // if some thread was waiting we might need to transfer it to the ready queue + } + else + { + if(m_timerCache && m_timerCacheNextTimeout > HAL_Time_CurrentTime()) + { + timeoutMin = m_timerCacheNextTimeout - HAL_Time_CurrentTime(); + } + //else + { + CheckTimers( timeoutMin ); + + CheckThreads( timeoutMin, m_threadsReady ); + CheckThreads( timeoutMin, m_threadsWaiting ); + + m_timerCacheNextTimeout = timeoutMin + HAL_Time_CurrentTime(); + m_timerCache = (m_timerCacheNextTimeout > HAL_Time_CurrentTime()); + + } + } + + // if the system timer is not set as one of the wakeup events then just return the max time to active + if(0 == (g_CLR_HW_Hardware.m_wakeupEvents & SYSTEM_EVENT_FLAG_SYSTEM_TIMER)) + { + timeoutMin = m_maximumTimeToActive; + } + + return timeoutMin; +} + +void CLR_RT_ExecutionEngine::ProcessTimeEvent( CLR_UINT32 event ) +{ + NATIVE_PROFILE_CLR_CORE(); + SYSTEMTIME systemTime; + + HAL_Time_ToSystemTime( HAL_Time_CurrentTime(), &systemTime ); + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,m_timers) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_EnabledTimer) + { + CLR_UINT32 val = timer->m_flags & CLR_RT_HeapBlock_Timer::c_AnyChange; + + if(val) + { + timer->AdjustNextFixedExpire( systemTime, true ); + + if(val == event && (timer->m_flags & CLR_RT_HeapBlock_Timer::c_Recurring) == 0) + { + timer->Trigger(); + } + } + } + } + NANOCLR_FOREACH_NODE_END(); + + SpawnTimer(); +} + +void CLR_RT_ExecutionEngine::InvalidateTimerCache() +{ + NATIVE_PROFILE_CLR_CORE(); + g_CLR_RT_ExecutionEngine.m_timerCache = false; +} + +//--//--// + +bool CLR_RT_ExecutionEngine::IsTimeExpired( const CLR_INT64& timeExpire, CLR_INT64& timeoutMin ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(timeExpire <= (CLR_INT64)HAL_Time_CurrentTime()) return true; + + CLR_INT64 diff = timeExpire - HAL_Time_CurrentTime(); + + if(diff < timeoutMin) + { + timeoutMin = diff; + } + + return false; +} + +bool CLR_RT_ExecutionEngine::IsThereEnoughIdleTime( CLR_UINT32 expectedMsec ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(::Events_MaskedRead( g_CLR_HW_Hardware.m_wakeupEvents )) return false; + + CLR_INT64 now = HAL_Time_CurrentTime(); + + if(now + expectedMsec * TIME_CONVERSION__TO_MILLISECONDS >= m_currentNextActivityTime) return false; + + return true; +} + +//--// + +void CLR_RT_ExecutionEngine::CheckTimers( CLR_INT64& timeoutMin ) +{ + NATIVE_PROFILE_CLR_CORE(); + bool fAnyTimersExpired = false; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,m_timers) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_EnabledTimer) + { + CLR_INT64 expire = timer->m_timeExpire; + if(IsTimeExpired( expire, timeoutMin )) + { + + #if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS_NOT( PauseTimers )) + #endif + { + timer->Trigger(); + fAnyTimersExpired = true; + } + } + } + } + NANOCLR_FOREACH_NODE_END(); + + if(fAnyTimersExpired) + { + SpawnTimer(); + } + +} + +void CLR_RT_ExecutionEngine::CheckThreads( CLR_INT64& timeoutMin, CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + CLR_INT64 expire; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(th->m_flags & CLR_RT_Thread::TH_F_Suspended) + { + continue; + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + // + // Check events. + // + expire = th->m_waitForEvents_Timeout; + if(IsTimeExpired( expire, timeoutMin )) + { + th->m_waitForEvents_Timeout = TIMEOUT_INFINITE; + + th->Restart( false ); + } + + // + // Check wait for object. + // + + { + CLR_RT_HeapBlock_WaitForObject* wait = th->m_waitForObject; + + if(wait) + { + if(IsTimeExpired( wait->m_timeExpire, timeoutMin )) + { + th->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_TIMEOUT; + + th->Restart( true ); + } + } + } + + // + // Check lock requests. + // + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_LockRequest,req,lock->m_requests) + { + if(IsTimeExpired( req->m_timeExpire, timeoutMin )) + { + CLR_RT_SubThread* sth = req->m_subthreadWaiting; + + sth->ChangeLockRequestCount( -1 ); + + g_CLR_RT_EventCache.Append_Node( req ); + } + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); + + // + // Check constraints. + // + NANOCLR_FOREACH_NODE_BACKWARD(CLR_RT_SubThread,sth,th->m_subThreads) + { + if(sth->m_timeConstraint != TIMEOUT_INFINITE) + { + if(IsTimeExpired( s_compensation.Adjust( sth->m_timeConstraint ), timeoutMin )) + { + (void)Library_corlib_native_System_Exception::CreateInstance( th->m_currentException, g_CLR_RT_WellKnownTypes.m_ConstraintException, S_OK, th->CurrentFrame() ); + + if((sth->m_status & CLR_RT_SubThread::STATUS_Triggered) == 0) + { + sth->m_status |= CLR_RT_SubThread::STATUS_Triggered; + + // + // This is the first time, give it 500msec to clean before killing it. + // + sth->m_timeConstraint += TIME_CONVERSION__TO_MILLISECONDS * 500; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + } + else + { + CLR_RT_SubThread::DestroyInstance( th, sth, CLR_RT_SubThread::MODE_CheckLocks ); + + // + // So it doesn't fire again... + // + sth->m_timeConstraint = TIMEOUT_INFINITE; + } + + th->Restart( true ); + } + } + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::LockObject( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Lock* lock; + + lock = FindLockObject( reference ); + + if(lock == NULL) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Lock::CreateInstance( lock, sth->m_owningThread, reference )); + } + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Lock::IncrementOwnership( lock, sth, timeExpire, fForce )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::UnlockObject( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Lock* lock; + + lock = FindLockObject( reference ); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Lock::DecrementOwnership( lock, sth )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::Sleep( CLR_RT_Thread* caller, const CLR_INT64& timeExpire ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + caller->m_waitForEvents_Timeout = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + caller->m_status = CLR_RT_Thread::TH_S_Waiting; + + NANOCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::WaitEvents( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_UINT32 events, bool& fSuccess ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(m_raisedEvents & events) + { + m_raisedEvents &= ~events; + + fSuccess = true; + } + else + { + fSuccess = false; + + if((CLR_INT64)HAL_Time_CurrentTime() < timeExpire) + { + caller->m_waitForEvents = events; + caller->m_waitForEvents_Timeout = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + caller->m_status = CLR_RT_Thread::TH_S_Waiting; + + NANOCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + } + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_ExecutionEngine::SignalEvents( CLR_RT_DblLinkedList& threads, CLR_UINT32 events ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_raisedEvents |= events; + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + if((th->m_waitForEvents & events) != 0) + { + _ASSERTE(&threads == &m_threadsWaiting); + _ASSERTE(th->m_status == CLR_RT_Thread::TH_S_Waiting); + + th->Restart( true ); + } + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::SignalEvents( CLR_UINT32 events ) +{ + NATIVE_PROFILE_CLR_CORE(); + //Why does the ready queue need to be checked. + SignalEvents( m_threadsReady , events ); + SignalEvents( m_threadsWaiting, events ); +} + +//--// + +bool CLR_RT_ExecutionEngine::IsInstanceOf( CLR_RT_TypeDescriptor& desc, CLR_RT_TypeDescriptor& descTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Instance& inst = desc .m_handlerCls; + CLR_RT_TypeDef_Instance& instTarget = descTarget.m_handlerCls; + bool fArray = false; + + while(desc .m_reflex.m_levels > 0 && + descTarget.m_reflex.m_levels > 0 ) + { + desc .GetElementType( desc ); + descTarget.GetElementType( descTarget ); + + fArray = true; + } + + if(desc.m_reflex.m_levels < descTarget.m_reflex.m_levels) return false; + + if(desc.m_reflex.m_levels > descTarget.m_reflex.m_levels) + { + if(descTarget.m_reflex.m_levels == 0) + { + // + // Casting from [] to System.Array or System.Object is always allowed. + // + if(inst.m_data == g_CLR_RT_WellKnownTypes.m_Array .m_data || + inst.m_data == g_CLR_RT_WellKnownTypes.m_Object .m_data || + inst.m_data == g_CLR_RT_WellKnownTypes.m_IList .m_data || + inst.m_data == g_CLR_RT_WellKnownTypes.m_ICloneable.m_data ) + { + return true; + } + } + + if(inst.m_target->dataType != instTarget.m_target->dataType) + { + return false; + } + } + + CLR_UINT32 semantic = (inst .m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask); + CLR_UINT32 semanticTarget = (instTarget.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask); + + if(fArray) + { + if(semantic != semanticTarget) + { + return false; + } + } + + do + { + if(inst.m_data == instTarget.m_data) + { + return true; + } + + // + // Scan the list of interfaces. + // + if(semanticTarget == CLR_RECORD_TYPEDEF::TD_Semantics_Interface && inst.m_target->interfaces != CLR_EmptyIndex) + { + CLR_RT_SignatureParser parser; parser.Initialize_Interfaces( inst.m_assm, inst.m_target ); + CLR_RT_SignatureParser::Element res; + + while(parser.Available() > 0) + { + if(FAILED(parser.Advance( res ))) break; + + if(res.m_cls.m_data == instTarget.m_data) + { + return true; + } + } + } + } + while(inst.SwitchToParent()); + + return false; +} + +bool CLR_RT_ExecutionEngine::IsInstanceOf( const CLR_RT_TypeDef_Index& cls, const CLR_RT_TypeDef_Index& clsTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor descTarget; + + if(FAILED(desc .InitializeFromType( cls ))) return false; + if(FAILED(descTarget.InitializeFromType( clsTarget ))) return false; + + return IsInstanceOf( desc, descTarget ); +} + +bool CLR_RT_ExecutionEngine::IsInstanceOf( CLR_RT_HeapBlock& ref, const CLR_RT_TypeDef_Index& clsTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor descTarget; + + if(FAILED(desc .InitializeFromObject( ref ))) return false; + if(FAILED(descTarget.InitializeFromType ( clsTarget ))) return false; + + return IsInstanceOf( desc, descTarget ); +} + +bool CLR_RT_ExecutionEngine::IsInstanceOf( CLR_RT_HeapBlock& obj, CLR_RT_Assembly* assm, CLR_UINT32 token ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor descTarget; + CLR_RT_TypeDef_Instance clsTarget; + CLR_RT_TypeSpec_Instance defTarget; + + if(FAILED(desc.InitializeFromObject( obj ))) return false; + + if(clsTarget.ResolveToken( token, assm )) + { + // + // Shortcut for identity. + // + if(desc.m_handlerCls.m_data == clsTarget.m_data) return true; + + if(FAILED(descTarget.InitializeFromType( clsTarget ))) return false; + } + else if(defTarget.ResolveToken( token, assm )) + { + if(FAILED(descTarget.InitializeFromTypeSpec( defTarget ))) return false; + } + else + { + return false; + } + + return IsInstanceOf( desc, descTarget ); +} + +HRESULT CLR_RT_ExecutionEngine::CastToType( CLR_RT_HeapBlock& ref, CLR_UINT32 tk, CLR_RT_Assembly* assm, bool fUpdate ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(ref.DataType() == DATATYPE_OBJECT && ref.Dereference() == NULL) + { + ; + } + else if(g_CLR_RT_ExecutionEngine.IsInstanceOf( ref, assm, tk ) == true) + { + ; + } + else + { + if(fUpdate == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + } + + ref.SetObjectReference( NULL ); + } + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +HRESULT CLR_RT_ExecutionEngine::InitTimeout( CLR_INT64& timeExpire, const CLR_INT64& timeout ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(timeout < 0) + { + // because we are expecting the timeout value to be in ticks + // need to check for two possible infinite timeouts: + // 1. when coding in native it's supposed to use -1L as a timeout infinite + // 2. in managed code the constant System.Threading.Timeout.Infinite is -1 milliseconds, therefore needs to be converted to ticks + if( (timeout != -1L) && + (timeout != -1L * TIME_CONVERSION__TO_MILLISECONDS)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + timeExpire = TIMEOUT_INFINITE; + } + else + { + timeExpire = timeout + HAL_Time_CurrentTime(); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::InitTimeout( CLR_INT64& timeExpire, CLR_INT32 timeout ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(timeout < 0) + { + if(timeout != -1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + timeExpire = TIMEOUT_INFINITE; + } + else + { + timeExpire = timeout; + timeExpire *= TIME_CONVERSION__TO_MILLISECONDS; + timeExpire += HAL_Time_CurrentTime(); + } + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_ExecutionEngine::DebuggerLoop() +{ + NATIVE_PROFILE_CLR_CORE(); + ProcessHardware(); + + WaitSystemEvents(SLEEP_LEVEL__SLEEP, g_CLR_HW_Hardware.m_wakeupEvents, TIME_CONVERSION__TO_MILLISECONDS * 100 ); +} + + +//--// + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +void CLR_RT_ExecutionEngine::SetDebuggingInfoBreakpoints( bool fSet ) +{ + NATIVE_PROFILE_CLR_CORE(); + for(size_t pos=0; posm_pid; + th->m_timeQuantumExpired = true; + } + + if(m_breakpointsActiveNum == 1) + { + CLR_EE_DBG_EVENT_SEND(CLR_DBG_Commands::c_Debugging_Execution_BreakpointHit, sizeof(CLR_DBG_Commands::Debugging_Execution_BreakpointDef), &m_breakpointsActive[0],WP_Flags_c_NonCritical); + } + } + else + { + _ASSERTE(false); + } + } +} + +void CLR_RT_ExecutionEngine::StopOnBreakpoint( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def, CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ip == NULL) ip = stack->m_IP; + + def.m_depth = stack->m_depth; + def.m_md = stack->m_call; + def.m_IP = (CLR_UINT32)(ip - stack->m_IPstart); + + //Don't fail for special cases regarding messages dealing with exception handling. + _ASSERTE(def.m_IP == 0xffffffff || ip >= stack->m_IPstart); + //we don't actually know the end of the method. + + StopOnBreakpoint( def, stack->m_owningThread ); +} + +bool CLR_RT_ExecutionEngine::DequeueActiveBreakpoint( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_breakpointsActiveNum) + { + def = m_breakpointsActive[ 0 ]; + + if(--m_breakpointsActiveNum == 0) + { + def.m_flags |= CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_LAST_BREAKPOINT; + } + + memmove( &m_breakpointsActive[ 0 ], &m_breakpointsActive[ 1 ], sizeof(m_breakpointsActive[ 0 ]) * m_breakpointsActiveNum ); + + return true; + } + + return false; +} + +//--// + +void CLR_RT_ExecutionEngine::Breakpoint_System_Event( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& hit, CLR_UINT16 event, CLR_RT_Thread* th, CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + for(size_t pos=0; posm_owningThread)); + + th = stack->m_owningThread; + } + + if(th == NULL || (def.m_pid == th->m_pid) || def.m_pid == CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_PID_ANY) + { + if(def.m_flags & event) + { + hit.m_id = def.m_id; + hit.m_flags = event; + + if(stack != NULL) + { + StopOnBreakpoint( hit, stack, ip ); + } + else + { + StopOnBreakpoint( hit, th ); + } + } + } + } +} + +void CLR_RT_ExecutionEngine::Breakpoint_Assemblies_Loaded() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; NANOCLR_CLEAR(hit); + + for(size_t i = 0; i < this->m_breakpointsActiveNum; i++) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def = this->m_breakpointsActive[ i ]; + + if(def.m_flags & CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_ASSEMBLIES_LOADED) + { + //There is already one queued AssembliesLoaded breakpoint. No need to send another one. + return; + } + } + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_ASSEMBLIES_LOADED, m_currentThread, NULL, NULL ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Threads_Prepare( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + th->m_fHasJMCStepper = false; + + for(size_t pos=0; posm_pid) + { + th->m_fHasJMCStepper = true; + break; + } + } + } + + NANOCLR_FOREACH_NODE(CLR_RT_StackFrame,call,th->m_stackFrames) + { + call->m_flags &= ~CLR_RT_StackFrame::c_HasBreakpoint; + + if(call->m_call.DebuggingInfo().HasBreakpoint()) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + else + { + for(size_t pos=0; posm_pid && def.m_depth == call->m_depth) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + break; + } + } + } + } +#ifndef CLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + if(call->m_inlineFrame->m_frame.m_call.DebuggingInfo().HasBreakpoint()) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + else + { + for(size_t pos=0; posm_pid && def.m_depth == (call->m_depth-1)) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + break; + } + } + } + } + } +#endif + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Thread_Terminated( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; NANOCLR_CLEAR(hit); + CLR_UINT16 evt = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_THREAD_TERMINATED; + + hit.m_depth = 0xFFFFFFFF; + + if(th->m_scratchPad >= 0) + { + evt |= CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EVAL_COMPLETE; + } + + Breakpoint_System_Event( hit, evt, th, NULL, NULL ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Thread_Created( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; NANOCLR_CLEAR(hit); + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_THREAD_CREATED, th, NULL, NULL ); +} + +//--// + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Push( CLR_RT_StackFrame* stack, CLR_UINT32 reason ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th = stack->m_owningThread; + int pid = th->m_pid; + CLR_UINT32 depthMax = stack->m_depth - 1; + CLR_UINT16 flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_IN; + CLR_UINT32 depthMin = depthMax; + + if(stack->m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + //If a filter frame is being pushed on (assuming the InterceptMask for filters is set), we want to intercept the frame + //in certain special cases. + _ASSERTE(th->m_nestedExceptionsPos); + CLR_RT_Thread::UnwindStack& us = th->m_nestedExceptions[ th->m_nestedExceptionsPos-1 ]; + _ASSERTE(us.m_stack == stack); + depthMin = us.m_handlerStack->m_depth; + //If we popped off frames from AppDomain transitions that had steppers, we want to break there as well. + depthMax = 0xffffffff; + flags |= CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OVER | CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OUT; + } + + for(size_t pos=0; posm_call.DebuggingInfo().IsJMC(); + } + else + { + fStop = (def.m_depth >= depthMin && def.m_depth <= depthMax); + } + + if(def.m_depth == depthMin && (def.m_flags & CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP) == CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OUT) + { + //In the case a user did a step out in a frame, we don't want to break if a filter gets pushed from that frame. However, if there is a step in or over on that frame, + //we should break. + fStop = false; + } + + if(fStop) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_IN; + hit.m_depthExceptionHandler = reason; + + StopOnBreakpoint( hit, stack, NULL ); + } + } + } + } + + Breakpoint_StackFrame_Hard( stack, stack->m_IP ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Pop( CLR_RT_StackFrame* stack, bool stepEH ) +{ + NATIVE_PROFILE_CLR_CORE(); + int pid = stack->m_owningThread->m_pid; + CLR_UINT32 depth = stack->m_depth; + CLR_RT_StackFrame* caller = stack->Caller(); + + if(caller->Prev() || stepEH) + { + for(size_t pos=0; posm_call.DebuggingInfo().IsJMC(); + } + else + { + fStop = (depth <= def.m_depth); + } + + if(fStop) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OUT; + + if(stepEH) + { + hit.m_depthExceptionHandler = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_EXCEPTION_HANDLER; + } + else + { + hit.m_depthExceptionHandler = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_RETURN; + } + + StopOnBreakpoint( hit, (stepEH)? stack : caller, NULL ); + } + } + } + } + } +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Step( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + int pid = stack->m_owningThread->m_pid; + CLR_UINT32 depth = stack->m_depth; + CLR_UINT32 IPoffset = (CLR_UINT32)(ip - stack->m_IPstart); + + for(size_t pos=0; pos= def.m_IPEnd)) + { + if(def.m_flags & CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_JMC) + { + if(!stack->m_call.DebuggingInfo().IsJMC()) + { + continue; + } + } + + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OVER; + + StopOnBreakpoint( hit, stack, ip ); + } + } + } + + Breakpoint_StackFrame_Hard( stack, ip ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Hard( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(stack->Prev() != NULL && ip != NULL) + { + CLR_UINT32 IPoffset = (CLR_UINT32)(ip - stack->m_IPstart); + + for(size_t pos=0; posm_owningThread->m_pid || def.m_pid == CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_PID_ANY) + { + if(def.m_md.m_data == stack->m_call.m_data && def.m_IP == IPoffset) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_HARD; + + StopOnBreakpoint( hit, stack, ip ); + } + } + } + } + } +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Break( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; NANOCLR_CLEAR(hit); + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_BREAK, NULL, stack, NULL ); +} + +//--// + +void CLR_RT_ExecutionEngine::Breakpoint_Exception( CLR_RT_StackFrame* stack, CLR_UINT32 reason, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; NANOCLR_CLEAR(hit); + hit.m_depthExceptionHandler = reason; + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_THROWN, NULL, stack, ip ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Exception_Uncaught( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; NANOCLR_CLEAR(hit); + + hit.m_depth = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_UNCAUGHT; + hit.m_depthExceptionHandler = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_UNCAUGHT; + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_THROWN, th, NULL, NULL ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Exception_Intercepted( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; NANOCLR_CLEAR(hit); + CLR_UINT16 event = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_CAUGHT + | CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_UNWIND; + + hit.m_depthExceptionHandler = stack->m_depth; + + Breakpoint_System_Event( hit, event, NULL, stack, NULL ); +} + +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_APPDOMAINS) + +CLR_RT_AppDomain* CLR_RT_ExecutionEngine::SetCurrentAppDomain( CLR_RT_AppDomain* appDomain ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_AppDomain* ad = m_appDomainCurrent; + + m_appDomainCurrent = appDomain; + + return ad; +} + +CLR_RT_AppDomain* CLR_RT_ExecutionEngine::GetCurrentAppDomain() +{ + NATIVE_PROFILE_CLR_CORE(); + return m_appDomainCurrent; +} + +void CLR_RT_ExecutionEngine::PrepareThreadsForAppDomainUnload( CLR_RT_AppDomain* appDomain, CLR_RT_DblLinkedList& threads) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread, th, threads) + { + bool fFoundDoomedAppDomain = false; + bool fInjectThreadAbort = false; + + NANOCLR_FOREACH_NODE(CLR_RT_StackFrame, stack, th->m_stackFrames) + { + if(!fFoundDoomedAppDomain) + { + if(stack->m_appDomain == appDomain) + { + //The first stack frame found in a doomed AppDomain + fFoundDoomedAppDomain = true; + fInjectThreadAbort = true; + stack->m_flags |= CLR_RT_StackFrame::c_AppDomainInjectException; + th ->m_flags |= CLR_RT_Thread::TH_F_ContainsDoomedAppDomain; + } + } + else //fFoundDoomedAppDomain + { + if(stack->m_flags & CLR_RT_StackFrame::c_AppDomainInjectException) + { + //This thread is already being unwound due to an unloading AppDomain + stack->m_flags &= ~CLR_RT_StackFrame::c_AppDomainInjectException; + fInjectThreadAbort = false; + } + } + } + NANOCLR_FOREACH_NODE_END(); + + if(fInjectThreadAbort) + { + (void)th->Abort(); + } + } + NANOCLR_FOREACH_NODE_END(); +} + +HRESULT CLR_RT_ExecutionEngine::UnloadAppDomain( CLR_RT_AppDomain* appDomain, CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + //Check to make sure the current thread does not contain any doomed AppDomains + NANOCLR_FOREACH_NODE(CLR_RT_StackFrame, stack, th->m_stackFrames) + { + if(!stack->m_appDomain->IsLoaded() || stack->m_appDomain == appDomain) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + NANOCLR_FOREACH_NODE_END(); + + PrepareThreadsForAppDomainUnload( appDomain, m_threadsReady ); + PrepareThreadsForAppDomainUnload( appDomain, m_threadsWaiting ); + + appDomain->m_state = CLR_RT_AppDomain::AppDomainState_Unloading; + CLR_EE_SET(UnloadingAppDomain); + + NANOCLR_NOCLEANUP(); +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_UINT32 CLR_RT_ExecutionEngine::WaitSystemEvents( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeExpire ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_INT32 timeout; + + CLR_UINT32 res = 0; + + m_currentNextActivityTime = timeExpire + HAL_Time_CurrentTime(); + + timeout = (CLR_INT32)timeExpire / TIME_CONVERSION__TO_MILLISECONDS; + + if(timeout == 0) timeout = 1; + +#if defined(NANOCLR_TRACE_SYSTEMEVENTWAIT) + CLR_INT64 start = HAL_Time_CurrentTime(); +#endif + +#if defined(NANOCLR_STRESS_GC) + if(timeout > 100) + { + CLR_INT64 startGC = HAL_Time_CurrentTime(); + + + g_CLR_RT_ExecutionEngine.PerformHeapCompaction (); + + CLR_INT64 endGC = HAL_Time_CurrentTime(); + + timeout -= (CLR_INT32)((endGC - startGC) / TIME_CONVERSION__TO_MILLISECONDS); + } +#endif + + // UNDONE: FIXME + // ::Watchdog_GetSetEnabled( bool, bool ); + // TODO check if the watchdog needs to be feed here... don't think so + Watchdog_Reset(); + + res = ::Events_WaitForEvents( powerLevel, events, timeout ); + // UNDONE: FIXME + // ::Watchdog_GetSetEnabled( bool, bool ); + // TODO check if the watchdog needs to be feed here... don't think so + Watchdog_Reset(); + + +#if defined(NANOCLR_TRACE_SYSTEMEVENTWAIT) + CLR_INT64 stop = HAL_Time_CurrentTime(); + CLR_INT64 stop2 = HAL_Time_CurrentTime(); + + static CLR_INT64 totalRequested = 0; + static CLR_INT64 totalActual = 0; + static CLR_INT64 samples = 0; + + totalRequested += timeout; + totalActual += (stop - start) - (stop2 - stop); + samples += 1; + + if(samples == 10000) + { + CLR_Debug::Printf( "Wait %lld %lld\r\n", totalRequested / samples, totalActual / samples ); + + totalRequested = 0; + totalActual = 0; + samples = 0; + } +#endif + + m_currentNextActivityTime = 0; + + return res; +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/GarbageCollector.cpp b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector.cpp new file mode 100644 index 00000000..a79979da --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector.cpp @@ -0,0 +1,828 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_ProtectFromGC* CLR_RT_ProtectFromGC::s_first = NULL; + +void CLR_RT_ProtectFromGC::Initialize( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_next = s_first; s_first = this; + + m_data = (void**)&ref; + m_fpn = NULL; + + if(ref.IsForcedAlive()) + { + m_flags = c_HeapBlock; + } + else + { + m_flags = c_HeapBlock | c_ResetKeepAlive; + + ref.MarkForcedAlive(); + } +} + +void CLR_RT_ProtectFromGC::Initialize( void** data, Callback fpn ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_next = s_first; s_first = this; + + m_data = data; + m_fpn = fpn; + m_flags = c_Generic; +} + +void CLR_RT_ProtectFromGC::Cleanup() +{ + NATIVE_PROFILE_CLR_CORE(); + s_first = m_next; + + if(m_flags & c_ResetKeepAlive) + { + CLR_RT_HeapBlock* obj = (CLR_RT_HeapBlock*)m_data; + + obj->UnmarkForcedAlive(); + } +} + +void CLR_RT_ProtectFromGC::Invoke() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_fpn) + { + m_fpn( *m_data ); + } + else if(m_data) + { + g_CLR_RT_GarbageCollector.CheckMultipleBlocks( (CLR_RT_HeapBlock*)m_data, 1 ); + } +} + +void CLR_RT_ProtectFromGC::InvokeAll() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_ProtectFromGC* ptr; + + ptr = s_first; + while(ptr) + { + ptr->Invoke(); + + ptr = ptr->m_next; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_TRACE_EARLYCOLLECTION) + +CLR_RT_AssertEarlyCollection* CLR_RT_AssertEarlyCollection::s_first = NULL; + +CLR_RT_AssertEarlyCollection::CLR_RT_AssertEarlyCollection( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_next = s_first; s_first = this; + + m_ptr = ptr; +} + +CLR_RT_AssertEarlyCollection::~CLR_RT_AssertEarlyCollection() +{ + NATIVE_PROFILE_CLR_CORE(); + s_first = m_next; +} + +void CLR_RT_AssertEarlyCollection::Cancel() +{ + NATIVE_PROFILE_CLR_CORE(); + m_ptr = NULL; +} + +void CLR_RT_AssertEarlyCollection::CheckAll( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_AssertEarlyCollection* node; + + node = s_first; + while(node) + { + if(node->m_ptr == ptr) + { + CLR_Debug::Printf( "INTERNAL ERROR: %08x retired early!!!\r\n", ptr ); + +#if defined(_WIN32) + ::Sleep( 1000 ); + ::DebugBreak(); +#endif + } + + node = node->m_next; + } +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_UINT32 CLR_RT_GarbageCollector::ExecuteGarbageCollection() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordGarbageCollectionBegin(); +#endif + +#if defined(NANOCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_GC >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: Start %s\r\n", HAL_Time_CurrentDateTimeToString() ); + } +#endif + + //////////////////////////////////////////////////////////////////////////////////////////////// + + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + +#if defined(NANOCLR_TRACE_MEMORY_STATS) + + CLR_UINT32 stats_start = HAL_Time_CurrentSysTicks(); + +#endif + + g_CLR_RT_EventCache.EventCache_Cleanup(); + + Mark (); + MarkWeak(); + Sweep (); + + Heap_ComputeAliveVsDeadRatio(); + + CheckMemoryPressure(); + +#if defined(NANOCLR_TRACE_MEMORY_STATS) + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + int milliSec = ((int)::HAL_Time_SysTicksToTime( HAL_Time_CurrentSysTicks() - stats_start ) + TIME_CONVERSION__TICKUNITS - 1) / TIME_CONVERSION__TICKUNITS; + + CLR_Debug::Printf( "GC: %dmsec %d bytes used, %d bytes available\r\n", milliSec, m_totalBytes - m_freeBytes, m_freeBytes ); + } + + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + int countBlocks[ DATATYPE_FIRST_INVALID ]; NANOCLR_CLEAR(countBlocks); + int countArryBlocks[ DATATYPE_FIRST_INVALID ]; NANOCLR_CLEAR(countArryBlocks); + int dt; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + while(ptr < end) + { + dt = ptr->DataType(); + if(dt < DATATYPE_FIRST_INVALID) + { + countBlocks[ dt ] += ptr->DataSize(); + + if(dt == DATATYPE_SZARRAY) + { + CLR_RT_HeapBlock_Array* arr = (CLR_RT_HeapBlock_Array*)ptr; + + if(arr != NULL) + { + dt = arr->m_typeOfElement; + + if(dt < DATATYPE_FIRST_INVALID) + { + countArryBlocks[ dt ] += ptr->DataSize(); + } + else + { + CLR_Debug::Printf("!!!!Unknown array type: %d\r\n", dt); + } + } + + } + } + + ptr += ptr->DataSize(); + } + } + NANOCLR_FOREACH_NODE_END(); + + for(dt = DATATYPE_VOID; dt < DATATYPE_FIRST_INVALID; dt++) + { + if(countBlocks[ dt ]) + { + CLR_Debug::Printf( "Type %02X (%-20s): %6d bytes\r\n", dt, c_CLR_RT_DataTypeLookup[ dt ].m_name, countBlocks[ dt ] * sizeof(CLR_RT_HeapBlock) ); + + if(dt == DATATYPE_SZARRAY) + { + for(int dt2 = DATATYPE_VOID; dt2 < DATATYPE_FIRST_INVALID; dt2++) + { + if(countArryBlocks[ dt2 ]) + { + CLR_Debug::Printf( " Type %02X (%-17s): %6d bytes\r\n", dt2, c_CLR_RT_DataTypeLookup[ dt2 ].m_name, countArryBlocks[ dt2 ] * sizeof(CLR_RT_HeapBlock) ); + } + } + } + } + } + } +#endif + + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + + m_numberOfGarbageCollections++; + + //////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_GC >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: End %s\r\n", HAL_Time_CurrentDateTimeToString() ); + } +#endif + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordGarbageCollectionEnd(); +#endif + + return m_freeBytes; +} + +//--// + +void CLR_RT_GarbageCollector::MarkSlow() +{ + NATIVE_PROFILE_CLR_CORE(); + while(m_fOutOfStackSpaceForGC) + { + m_fOutOfStackSpaceForGC = false; + + //go through managed heap. + //find all objects that are not alive but are pointed to by a live object + //put them on the markstack. + for(CLR_RT_HeapCluster* hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode(); + hc->Next(); + hc = (CLR_RT_HeapCluster*)hc->Next() + ) + { + CLR_RT_HeapBlock* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock* end = hc->m_payloadEnd; + + while(ptr < end) + { + if(ptr->IsAlive() && !ptr->IsEvent()) + { + CheckSingleBlock_Force( ptr ); + } + + ptr += ptr->DataSize(); + } + } + } +} + +void CLR_RT_GarbageCollector::Mark() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + // + // Let's setup the proper workers. + // + m_funcSingleBlock = ComputeReachabilityGraphForSingleBlock; + m_funcMultipleBlocks = ComputeReachabilityGraphForMultipleBlocks; + + m_fOutOfStackSpaceForGC = false; + + //////////////////////////////////////////////////////////////////////////// + // + // Prepare the helper buffers. + // + m_weakDelegates_Reachable.DblLinkedList_Initialize(); + + CLR_RT_DblLinkedList markStackList; + MarkStack markStack; + MarkStackElement markStackBuffer[ c_minimumSpaceForGC ]; + + m_markStackList = &markStackList; + m_markStack = &markStack; + + m_markStack ->Initialize( markStackBuffer, ARRAYSIZE(markStackBuffer) ); + m_markStackList->DblLinkedList_Initialize(); + m_markStackList->LinkAtFront( m_markStack ); + + + //////////////////////////////////////////////////////////////////////////// + // + // Call global markers. + // +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( NULL ); +#endif + + CLR_RT_ProtectFromGC::InvokeAll(); + + g_CLR_HW_Hardware.PrepareForGC(); + + + //////////////////////////////////////////////////////////////////////////// + // + // Do the recursive marking! + // + { + // + // Mark all the events, so we keep the related threads/objects alive. + // + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersPending) + { +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( fin->m_appDomain ); +#endif + CheckSingleBlock( &fin->m_object ); + } + NANOCLR_FOREACH_NODE_END(); + } + + // + // Mark all the static fields. + // + +#if defined(NANOCLR_APPDOMAINS) + AppDomain_Mark(); +#endif + + Assembly_Mark(); + + // + // Walk through all the stack frames, marking the objects as we dig down. + // + Thread_Mark( g_CLR_RT_ExecutionEngine.m_threadsReady ); + Thread_Mark( g_CLR_RT_ExecutionEngine.m_threadsWaiting ); + +#if !defined(NANOCLR_APPDOMAINS) + CheckSingleBlock_Force( g_CLR_RT_ExecutionEngine.m_globalLock ); +#endif + + CheckSingleBlock_Force( g_CLR_RT_ExecutionEngine.m_currentUICulture ); + + +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( NULL ); +#endif //NANOCLR_VALIDATE_APPDOMAIN_ISOLATION + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CheckSingleBlock_Force( g_CLR_RT_ExecutionEngine.m_scratchPadArray ); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(m_fOutOfStackSpaceForGC) + { + MarkSlow(); + _ASSERTE(!m_fOutOfStackSpaceForGC); + } + } + // + // + // + //////////////////////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////////////////////// + // + // Prepare finalization of objects + // + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersAlive) + { + // + // If the object is dead, make it alive one last time and put it in the pending finalizers list. + // + if(fin->m_object->IsAlive() == false) + { +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( fin->m_appDomain ); +#endif + CheckSingleBlock( &fin->m_object ); + + g_CLR_RT_ExecutionEngine.m_finalizersPending.LinkAtBack( fin ); + } + } + NANOCLR_FOREACH_NODE_END(); + } + // + // + // + //////////////////////////////////////////////////////////////////////////// + + if(m_fOutOfStackSpaceForGC) + { + MarkSlow(); + } + + _ASSERTE(m_markStackList == &markStackList); + _ASSERTE(m_markStack == &markStack ); + + while((MarkStack*)m_markStackList->LastValidNode() != m_markStack) + { + MarkStack* markStackT = (MarkStack*)m_markStackList->LastValidNode(); + + markStackT->RemoveFromList(); + + CLR_RT_Memory::Release( markStackT ); + } + + m_markStackList = NULL; + m_markStack = NULL; + +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif +} + +void CLR_RT_GarbageCollector::MarkWeak() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Restored) + { + if(weak->m_targetSerialized) + { + weak->MarkAlive(); + } + } + + if(weak->IsAlive()) + { + if(weak->m_targetDirect) + { + if(weak->m_targetDirect->IsAlive()) + { + // + // If the direct object is alive, keep the serialized version around too!! + // + if(weak->m_targetSerialized && weak->m_targetSerialized->IsAlive() == false) + { + weak->m_targetSerialized->MarkAlive(); + } + } + else + { + weak->m_targetDirect = NULL; + } + } + } + else + { + weak->Unlink(); + } + } + NANOCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_RT_GarbageCollector::Sweep() +{ + NATIVE_PROFILE_CLR_CORE(); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // // + // At this point all the alive objects have been reached, let's start the clean up. // + // // + //////////////////////////////////////////////////////////////////////////////////////////////// + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Delegate_List,weak,m_weakDelegates_Reachable) + { + CLR_UINT32 num = weak->m_length; + CLR_RT_HeapBlock* dlgs = weak->GetDelegates(); + + for(;num--; dlgs++) + { + CLR_RT_HeapBlock_Delegate* dlg = dlgs->DereferenceDelegate(); + if(dlg) + { + CLR_RT_HeapBlock* obj = dlg->m_object.Dereference(); + if(obj && obj->IsAlive() == false) + { + // + // Found a dead delegate, kill it!! + // + dlgs->SetObjectReference( NULL ); + continue; + } + + dlg->MarkAlive(); + } + } + } + NANOCLR_FOREACH_NODE_END(); + + RecoverEventsFromGC(); + + //--// + + // + // All the dead objects are marked as such, it's time to reclaim them. + // + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + hc->RecoverFromGC(); + } + NANOCLR_FOREACH_NODE_END(); + } +} + +//--// + +void CLR_RT_GarbageCollector::CheckMemoryPressure() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_freeBytes > c_memoryThreshold2) + { + m_pressureCounter = 0; + } + else + { + bool fExit = false; + + // + // Drop all the restored objects that haven't been reclaimed by an application. + // + NANOCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Restored) + { + if(weak->m_targetSerialized) + { + fExit = true; + } + } + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + + if(fExit || m_freeBytes > c_memoryThreshold) + { + m_pressureCounter = 0; + } + else + { + m_pressureCounter++; + + if(m_pressureCounter > c_pressureThreshold) + { + NANOCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_targetSerialized && weak->m_targetDirect == NULL) + { +#if !defined(BUILD_RTM) + CLR_RT_ReflectionDef_Index val; + CLR_RT_TypeDef_Instance inst; + char rgBuffer[ 512 ]; + char* szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + CLR_Debug::Printf( "DROPPING OBJECT " ); + + val.InitializeFromHash( weak->m_identity.m_selectorHash ); + + if(inst.InitializeFromReflection( val, NULL )) + { + g_CLR_RT_TypeSystem.BuildTypeName( inst, szBuffer, iBuffer ); rgBuffer[ MAXSTRLEN(rgBuffer) ] = 0; + + CLR_Debug::Printf( "%s:%d ", rgBuffer, weak->m_identity.m_id ); + } + + CLR_Debug::Printf( " [%d bytes] %s\r\n", weak->m_targetSerialized->m_numOfElements, (weak->m_targetDirect ? "DIRECT" : "") ); +#endif + + break; + } + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + } + } + } +} + +//--// + +#if defined(NANOCLR_APPDOMAINS) + +void CLR_RT_GarbageCollector::AppDomain_Mark() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomain ); +#endif + + NANOCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,appDomain->m_appDomainAssemblies) + { + CheckMultipleBlocks( appDomainAssembly->m_pStaticFields, appDomainAssembly->m_assembly->m_iStaticFields ); + } + NANOCLR_FOREACH_NODE_END(); + + CheckSingleBlock_Force( appDomain->m_globalLock ); + CheckSingleBlock_Force( appDomain->m_strName ); + CheckSingleBlock_Force( appDomain->m_outOfMemoryException ); + } + NANOCLR_FOREACH_NODE_END(); +} + +#endif + +void CLR_RT_GarbageCollector::Assembly_Mark() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( NULL ); +#endif + + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + +#if !defined(NANOCLR_APPDOMAINS) + CheckMultipleBlocks( pASSM->m_pStaticFields, pASSM->m_iStaticFields ); +#endif + + CheckSingleBlock( &pASSM->m_pFile ); + } + NANOCLR_FOREACH_ASSEMBLY_END(); +} + +//--// + +void CLR_RT_GarbageCollector::Thread_Mark( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( th->m_dlg->m_appDomain ); +#endif + CheckSingleBlock ( &th->m_dlg ); + +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( th->CurrentAppDomain() ); +#endif + CheckSingleBlock_Force( &th->m_currentException ); + + for(int i=0; im_nestedExceptionsPos; i++) + { + CLR_RT_Thread::UnwindStack& us = th->m_nestedExceptions[ i ]; + +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( us.m_stack->m_appDomain ); +#endif + + CheckSingleBlock_Force( us.m_exception ); + } + + // + // Mark all the objects on the stack frames. + // + NANOCLR_FOREACH_NODE(CLR_RT_StackFrame,stack,th->m_stackFrames) + { +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( stack->m_appDomain ); +#endif +#ifndef CLR_NO_IL_INLINE + if(stack->m_inlineFrame) + { + CheckMultipleBlocks( stack->m_inlineFrame->m_frame.m_args , stack->m_inlineFrame->m_frame.m_call.m_target->numArgs ); + CheckMultipleBlocks( stack->m_inlineFrame->m_frame.m_locals , stack->m_inlineFrame->m_frame.m_call.m_target->numLocals ); + CheckMultipleBlocks( stack->m_inlineFrame->m_frame.m_evalStack, (int)(stack->m_inlineFrame->m_frame.m_evalPos - stack->m_inlineFrame->m_frame.m_evalStack)); + } +#endif + CheckMultipleBlocks( stack->m_arguments, stack->m_call.m_target->numArgs ); + CheckMultipleBlocks( stack->m_locals , stack->m_call.m_target->numLocals ); + CheckMultipleBlocks( stack->m_evalStack, stack->TopValuePosition() ); + } + NANOCLR_FOREACH_NODE_END(); + + // + // Mark locked objects. + // + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( lock->m_appDomain ); +#endif + CheckSingleBlock_Force( &lock->m_resource ); + } + NANOCLR_FOREACH_NODE_END(); + + // + // Mark the objects this thread is waiting for. + // +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( th->CurrentAppDomain() ); +#endif + + { + CLR_RT_HeapBlock_WaitForObject* wait = th->m_waitForObject; + + if(wait) + { + CheckMultipleBlocks( wait->GetWaitForObjects(), wait->m_cObjects ); + } + } +} + +void CLR_RT_GarbageCollector::Thread_Mark( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + Thread_Mark( th ); + } + NANOCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_RT_GarbageCollector::RecoverEventsFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_RT_HeapBlock_EndPoint::HandlerMethod_RecoverFromGC(); + CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_RecoverFromGC(); + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,g_CLR_RT_ExecutionEngine.m_timers) + { + timer->RecoverFromGC(); + } + NANOCLR_FOREACH_NODE_END(); + + //--// + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsReady) + { + th->RecoverFromGC(); + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + th->RecoverFromGC(); + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsZombie) + { + th->RecoverFromGC(); + th->ReleaseWhenDeadEx(); // After the GC has happened, we have to check if any zombie thread can be reclaimed. + } + NANOCLR_FOREACH_NODE_END(); + +#if defined(NANOCLR_APPDOMAINS) + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + appDomain->RecoverFromGC(); + } + NANOCLR_FOREACH_NODE_END(); +#endif +} + +//--// + +CLR_UINT32 CLR_RT_GarbageCollector::Heap_ComputeAliveVsDeadRatio() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 totalBytes = 0; + CLR_UINT32 freeBlocks = 0; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + totalBytes += (CLR_UINT32)((CLR_UINT8*)end - (CLR_UINT8*)ptr); + + NANOCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_Node,ptrFree,hc->m_freeList) + { + freeBlocks += ptrFree->DataSize(); + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + } + NANOCLR_FOREACH_NODE_END(); + + m_totalBytes = totalBytes; + m_freeBytes = freeBlocks * sizeof(CLR_RT_HeapBlock); + + return m_freeBytes; +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Compaction.cpp b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Compaction.cpp new file mode 100644 index 00000000..82596063 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Compaction.cpp @@ -0,0 +1,467 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_UINT32 CLR_RT_GarbageCollector::ExecuteCompaction() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordHeapCompactionBegin(); +#endif + +#if defined(NANOCLR_TRACE_MEMORY_STATS) + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( "GC: performing heap compaction\r\n" ); + } +#endif + + //////////////////////////////////////////////////////////////////////////////////////////////// + + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + + Heap_Compact(); + + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + + m_numberOfCompactions++; + + //////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordHeapCompactionEnd(); +#endif + +#if defined(NANOCLR_TRACE_MEMORY_STATS) + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( "GC: heap compaction completed\r\n" ); + } +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_GarbageCollector::Heap_Compact() +{ + NATIVE_PROFILE_CLR_CORE(); + + ValidatePointers(); + + //--// + + RelocationRegion relocHelper[ c_minimumSpaceForCompact ]; + const size_t relocMax = ARRAYSIZE(relocHelper); + + Heap_Relocate_Prepare( relocHelper, relocMax ); + + RelocationRegion* relocBlocks = relocHelper; + RelocationRegion* relocCurrent = relocBlocks; + + //--// + + TestPointers_PopulateOld(); + + + CLR_RT_HeapCluster* freeRegion_hc = NULL;; + CLR_RT_HeapBlock_Node* freeRegion = NULL; + + CLR_RT_HeapCluster* currentSource_hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode(); + while(currentSource_hc->Next()) + { + CLR_RT_HeapBlock_Node* currentSource = currentSource_hc->m_payloadStart; + CLR_RT_HeapBlock_Node* currentSource_end = currentSource_hc->m_payloadEnd; + + if(!freeRegion) + { + // + // Move to the next first free region. + // + freeRegion_hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode(); + while(true) + { + CLR_RT_HeapCluster* freeRegion_hcNext = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); if(!freeRegion_hcNext) break; + + freeRegion = freeRegion_hc->m_freeList.FirstNode(); if(freeRegion->Next()) break; + + freeRegion = NULL; + freeRegion_hc = freeRegion_hcNext; + } + if(!freeRegion) break; + } + + while(true) + { + // + // We can only move backward. + // + if(currentSource < freeRegion) + { + currentSource_hc = freeRegion_hc; + currentSource = freeRegion; + currentSource_end = freeRegion_hc->m_payloadEnd; + } + + while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable )) + { + currentSource += currentSource->DataSize(); + } + + if(currentSource == currentSource_end) break; + + ////////////////////////////////////////////////////// + // + // At this point, we have at least ONE movable block. + // + ////////////////////////////////////////////////////// + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_4_CompactionPlus + if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, freeRegion, true ) == false) + { + CLR_Debug::Printf( "'freeRegion' is not in a free list!! %08x\r\n", freeRegion ); + + NANOCLR_DEBUG_STOP(); + } + + if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, currentSource, false )) + { + CLR_Debug::Printf( "'currentSource' is in a free list!! %08x\r\n", currentSource ); + + NANOCLR_DEBUG_STOP(); + } +#endif + + if(m_relocCount >= relocMax) + { + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + + Heap_Relocate(); + + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + + relocBlocks = m_relocBlocks; + relocCurrent = relocBlocks; + + TestPointers_PopulateOld(); + } + + { + CLR_UINT32 move = 0; + CLR_UINT32 freeRegion_Size = freeRegion->DataSize(); + bool fSlide; + + relocCurrent->m_destination = (CLR_UINT8*)freeRegion; + relocCurrent->m_start = (CLR_UINT8*)currentSource; + relocCurrent->m_offset = (CLR_UINT32)(relocCurrent->m_destination - relocCurrent->m_start); + + + // + // Are the free block and the last moved block adjacent? + // + if(currentSource == freeRegion + freeRegion_Size) + { + while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ) == false) + { + CLR_UINT32 len = currentSource->DataSize(); + + currentSource += len; + move += len; + } + + fSlide = true; + } + else + { + while(freeRegion_Size && currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ) == false) + { + CLR_UINT32 len = currentSource->DataSize(); + + if(freeRegion_Size < len) + { + break; + } + + freeRegion_Size -= len; + currentSource += len; + move += len; + } + + fSlide = false; + } + + if(move) + { + // + // Skip forward to the next movable block. + // + while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable )) + { + currentSource += currentSource->DataSize(); + } + + CLR_UINT32 moveBytes = move * sizeof(*currentSource); + + relocCurrent->m_end = relocCurrent->m_start + moveBytes; + + //--// + + // + // Remove the old free block, copy the data, recreate the new free block. + // Merge with the following one if they are adjacent now. + // + CLR_RT_HeapBlock_Node* freeRegionNext = freeRegion->Next(); + + freeRegion->Unlink(); + + memmove( relocCurrent->m_destination, relocCurrent->m_start, moveBytes ); + + if(freeRegion_Size) + { + + freeRegion = freeRegion_hc->InsertInOrder( freeRegion + move, freeRegion_Size ); + + } + else + { + freeRegion = freeRegionNext; + + } + + if(fSlide == false) + { + CLR_RT_HeapBlock_Node* dst = currentSource_hc->InsertInOrder( (CLR_RT_HeapBlock_Node*)relocCurrent->m_start, move ); + + if(dst < freeRegion && freeRegion < (dst + dst->DataSize())) + { + freeRegion = dst; + } + + } + + CLR_RT_GarbageCollector::ValidateCluster( currentSource_hc ); + CLR_RT_GarbageCollector::ValidateCluster( freeRegion_hc ); + + relocCurrent++; + m_relocCount++; + } + else + { + freeRegion = freeRegion->Next(); + + } + + if(freeRegion->Next() == NULL) + { + + freeRegion = NULL; + freeRegion_hc = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); + while(true) + { + CLR_RT_HeapCluster* freeRegion_hcNext = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); if(!freeRegion_hcNext) break; + + freeRegion = freeRegion_hc->m_freeList.FirstNode(); if(freeRegion->Next()) break; + + freeRegion = NULL; + freeRegion_hc = freeRegion_hcNext; + } + if(!freeRegion) break; + + } + } + } + + currentSource_hc = (CLR_RT_HeapCluster*)currentSource_hc->Next(); + } + + if(m_relocCount) + { + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + + Heap_Relocate(); + + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate_Prepare( RelocationRegion* blocks, size_t total ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_relocBlocks = blocks; + m_relocTotal = total; + m_relocCount = 0; +} + +void CLR_RT_GarbageCollector::Heap_Relocate_AddBlock( CLR_UINT8* dst, CLR_UINT8* src, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + RelocationRegion* reloc = m_relocBlocks; + size_t count = m_relocCount; + + while(count) + { + if(reloc->m_start > src) + { + // + // Insert region, so they are sorted by start address. + // + memmove( &reloc[ 1 ], &reloc[ 0 ], count * sizeof(*reloc) ); + break; + } + + reloc++; + count--; + } + + reloc->m_start = src; + reloc->m_end = &src[ length ]; + reloc->m_destination = dst; + reloc->m_offset = (CLR_UINT32)(dst - src); + + if(++m_relocCount == m_relocTotal) + { + Heap_Relocate(); + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_relocCount) + { + RelocationRegion* relocBlocks = m_relocBlocks; + + CLR_UINT8* relocMinimum = relocBlocks->m_start; + CLR_UINT8* relocMaximum = relocBlocks->m_end; + + for(size_t i=0; i relocBlocks->m_start) relocMinimum = relocBlocks->m_start; + if(relocMaximum < relocBlocks->m_end ) relocMaximum = relocBlocks->m_end; + } + + m_relocMinimum = relocMinimum; + m_relocMaximum = relocMaximum; + + TestPointers_Remap(); + + Heap_Relocate_Pass( NULL ); + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectRelocation(); +#endif + + ValidatePointers(); + + TestPointers_PopulateNew(); + + m_relocCount = 0; + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate_Pass( RelocateFtn ftn ) +{ + NATIVE_PROFILE_CLR_CORE(); + + #if NANOCLR_VALIDATE_HEAP > NANOCLR_VALIDATE_HEAP_0_None + m_relocWorker = ftn; + #else + (void)ftn; + #endif + + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + + while(ptr < end) + { + CLR_RT_HEAPBLOCK_RELOCATE(ptr); + + ptr += ptr->DataSize(); + } + } + NANOCLR_FOREACH_NODE_END(); + + g_CLR_RT_ExecutionEngine.Relocate(); +} + +//--// + +void CLR_RT_GarbageCollector::Heap_Relocate( CLR_RT_HeapBlock* lst, CLR_UINT32 len ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(len--) + { + CLR_RT_HEAPBLOCK_RELOCATE(lst); + + lst++; + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate( void** ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8* dst = (CLR_UINT8*)*ref; + +#if NANOCLR_VALIDATE_HEAP > NANOCLR_VALIDATE_HEAP_0_None + if(g_CLR_RT_GarbageCollector.m_relocWorker) + { + g_CLR_RT_GarbageCollector.m_relocWorker( ref ); + } + else +#endif + { + if(dst >= g_CLR_RT_GarbageCollector.m_relocMinimum && dst < g_CLR_RT_GarbageCollector.m_relocMaximum) + { + RelocationRegion* relocBlocks = g_CLR_RT_GarbageCollector.m_relocBlocks; + size_t left = 0; + size_t right = g_CLR_RT_GarbageCollector.m_relocCount; + + while(left < right) + { + size_t center = (left + right) / 2; + RelocationRegion& relocCurrent = relocBlocks[ center ]; + + if(dst < relocCurrent.m_start) + { + right = center; + } + else if(dst >= relocCurrent.m_end) + { + left = center+1; + } + else + { + *ref = (void*)(dst + relocCurrent.m_offset); + + return; + } + } + } + } +} + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_3_Compaction + +bool CLR_RT_GarbageCollector::Relocation_JustCheck( void** ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8* dst = (CLR_UINT8*)*ref; + + if(dst) + { + ValidateBlockNotInFreeList( g_CLR_RT_ExecutionEngine.m_heap, (CLR_RT_HeapBlock_Node*)dst ); + } + + return true; +} + +#endif + diff --git a/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp new file mode 100644 index 00000000..5e8ac82b --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp @@ -0,0 +1,300 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//--// + +void CLR_RT_GarbageCollector::MarkStack::Initialize( MarkStackElement* ptr, size_t num ) +{ + NATIVE_PROFILE_CLR_CORE(); + GenericNode_Initialize(); + + m_last = &ptr[ num-1 ]; + m_top = ptr; + + // + // Empty element to act a sentinel. + // + ptr->ptr = NULL; + ptr->num = 0; +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + ptr->appDomain = NULL; +#endif +} + +//--// + +bool CLR_RT_GarbageCollector::ComputeReachabilityGraphForSingleBlock( CLR_RT_HeapBlock** ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = *ptr; if(obj == NULL || obj->IsAlive()) return true; + + return ComputeReachabilityGraphForMultipleBlocks( obj, 1 ); +} + + +bool CLR_RT_GarbageCollector::ComputeReachabilityGraphForMultipleBlocks( CLR_RT_HeapBlock* lst, CLR_UINT32 num ) +{ + NATIVE_PROFILE_CLR_CORE(); + + MarkStack * stackList; + MarkStackElement* stack; + MarkStackElement* stackLast; + +#define COMPUTEREACHABILITY_LOADSTATE() stackLast = g_CLR_RT_GarbageCollector.m_markStack->m_last; stack = g_CLR_RT_GarbageCollector.m_markStack->m_top; stackList = g_CLR_RT_GarbageCollector.m_markStack; +#define COMPUTEREACHABILITY_SAVESTATE() g_CLR_RT_GarbageCollector.m_markStack->m_last = stackLast; g_CLR_RT_GarbageCollector.m_markStack->m_top = stack; g_CLR_RT_GarbageCollector.m_markStack = stackList; + + COMPUTEREACHABILITY_LOADSTATE(); + + { + CLR_RT_HeapBlock* sub = NULL; + + while(true) + { + CLR_RT_HeapBlock* ptr = lst; + + if(num == 0) + { + if(stack->num == 0) + { + MarkStack* stackNext = (MarkStack*)stackList->Prev(); + + //finished with this MarkStack + if(stackNext->Prev() == NULL) + { + //finished marking + break; + } + else + { + COMPUTEREACHABILITY_SAVESTATE(); + g_CLR_RT_GarbageCollector.m_markStack = stackNext; + COMPUTEREACHABILITY_LOADSTATE(); + } + } + + ptr = stack->ptr; + + stack->ptr++; + stack->num--; + + if(stack->num == 0) + { + stack--; + +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( stack->appDomain ); +#endif + } + } + else if(num > 1) + { + if(stack == stackLast) + { + MarkStack* stackNext = (MarkStack*)stackList->Next(); + + if(stackNext->Next() != NULL) + { + COMPUTEREACHABILITY_SAVESTATE(); + g_CLR_RT_GarbageCollector.m_markStack = stackNext; + COMPUTEREACHABILITY_LOADSTATE(); + } + else + { + //try to allocate another stack list... + stackNext = NULL; + + //If there was no space for GC last time, don't bother trying to allocate again + if(!g_CLR_RT_GarbageCollector.m_fOutOfStackSpaceForGC) + { + for(int cElement = g_CLR_RT_GarbageCollector.c_minimumSpaceForGC; cElement >= 1; cElement /= 2) + { + CLR_UINT32 size = sizeof(MarkStack) + sizeof(MarkStackElement) * cElement; + + stackNext = (MarkStack*)CLR_RT_Memory::Allocate( size, CLR_RT_HeapBlock::HB_SpecialGCAllocation ); + + if(stackNext) + { + COMPUTEREACHABILITY_SAVESTATE(); + + stackNext->Initialize( (MarkStackElement*)(&stackNext[ 1 ]), (size_t)cElement ); + + g_CLR_RT_GarbageCollector.m_markStackList->LinkAtBack( stackNext ); + + g_CLR_RT_GarbageCollector.m_markStack = stackNext; + + COMPUTEREACHABILITY_LOADSTATE(); + + break; + } + } + } + + if(stackNext == NULL) + { + //Out of stack support space + //Set the failure flag and continue, ignoring lst, num + //The mark will complete later via MarkSlow + + g_CLR_RT_GarbageCollector.m_fOutOfStackSpaceForGC = true; + + lst = NULL; + num = 0; + continue; + } + } + } + + stack++; + + stack->ptr = lst+1; + stack->num = num-1; + +#if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + stack->appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + } + + + { + + lst = NULL; + num = 0; + + CLR_RT_HeapBlock::Debug_CheckPointer( ptr ); + + ptr->MarkAlive(); + + switch(ptr->DataType()) + { + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + sub = ptr->Dereference(); + break; + + //--// + + #if defined(NANOCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + { + CLR_RT_AppDomain* appDomain = ptr->TransparentProxyAppDomain(); + + if(appDomain) + { + if(!appDomain->IsLoaded()) + { + //If the AppDomain is unloading, we no longer need to keep the reference around + ptr->SetTransparentProxyReference( NULL, NULL ); + } + else + { + #if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( ptr->TransparentProxyAppDomain() ); + #endif + sub = ptr->TransparentProxyDereference(); + } + } + } + break; + #endif + + //--// + + case DATATYPE_ARRAY_BYREF: + sub = (CLR_RT_HeapBlock*)ptr->Array(); + break; + + //--// + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + // + // This is the real object, mark all its fields. + // + lst = ptr + 1; + num = ptr->DataSize() - 1; + break; + + case DATATYPE_SZARRAY: + // + // If the array is full of reference types, mark each of them. + // + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + if(array->m_fReference) + { + lst = (CLR_RT_HeapBlock*)array->GetFirstElement(); + num = array->m_numOfElements; + } + } + break; + + case DATATYPE_REFLECTION: + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + + lst = &dlg->m_object; + num = 1; + } + break; + + case DATATYPE_BINARY_BLOB_HEAD: + { + CLR_RT_HeapBlock_BinaryBlob* blob = (CLR_RT_HeapBlock_BinaryBlob*)ptr; + + _ASSERTE(blob->BinaryBlobMarkingHandler() == NULL); + } + break; + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* dlgList = (CLR_RT_HeapBlock_Delegate_List*)ptr; + + if(dlgList->m_flags & CLR_RT_HeapBlock_Delegate_List::c_Weak) + { + dlgList->ClearData(); + + g_CLR_RT_GarbageCollector.m_weakDelegates_Reachable.LinkAtBack( dlgList ); + } + else + { + lst = dlgList->GetDelegates(); + num = dlgList->m_length; + } + } + break; + + default: + // the remaining data types aren't to be handled + break; + } + + if(sub) + { + if(sub->IsAlive() == false) + { + lst = sub; + num = 1; + } + + sub = NULL; + } + + } + } + } + + COMPUTEREACHABILITY_SAVESTATE(); + + return true; +} + +//--// + diff --git a/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Info.cpp b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Info.cpp new file mode 100644 index 00000000..741567c7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/GarbageCollector_Info.cpp @@ -0,0 +1,322 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_GC_VERBOSE) + +void CLR_RT_GarbageCollector::GC_Stats( int& resNumberObjects, int& resSizeObjects, int& resNumberEvents, int& resSizeEvents ) +{ + NATIVE_PROFILE_CLR_CORE(); + resNumberObjects = 0; + resSizeObjects = 0; + + resNumberEvents = 0; + resSizeEvents = 0; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + while(ptr < end) + { + CLR_UINT16 size = ptr->DataSize(); + + hc->ValidateBlock( ptr ); + + if(ptr->DataType() != DATATYPE_FREEBLOCK) + { + if(ptr->IsEvent()) + { + resNumberEvents += 1; + resSizeEvents += size * sizeof(CLR_RT_HeapBlock); + } + else + { + resNumberObjects += 1; + resSizeObjects += size * sizeof(CLR_RT_HeapBlock); + } + } + + ptr += size; + } + } + NANOCLR_FOREACH_NODE_END(); +} + + +static void DumpTimeout( CLR_RT_Thread* th, CLR_INT64& t ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_Debug::Printf( ": %d", th ? th->m_pid : -1 ); + + if(t < TIMEOUT_INFINITE) + { + t -= HAL_Time_CurrentTime(); + + CLR_Debug::Printf( " %d", (int)t ); + } + else + { + CLR_Debug::Printf( " INFINITE" ); + } +} + +void CLR_RT_GarbageCollector::DumpThreads() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsReady) + { + th->DumpStack(); + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + th->DumpStack(); + } + NANOCLR_FOREACH_NODE_END(); + + CLR_Debug::Printf( "\r\n" ); +} +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_3_Compaction + +void CLR_RT_GarbageCollector::ValidateCluster( CLR_RT_HeapCluster* hc ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + while(ptr < end) + { + hc->ValidateBlock( ptr ); + + ptr += ptr->DataSize(); + } +} + +void CLR_RT_GarbageCollector::ValidateHeap( CLR_RT_DblLinkedList& lst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,lst) + { + ValidateCluster( hc ); + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_GarbageCollector::ValidateBlockNotInFreeList( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,lst) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,hc->m_freeList) + { + CLR_RT_HeapBlock_Node* ptrEnd = ptr + ptr->DataSize(); + + if(ptr <= dst && dst < ptrEnd) + { + CLR_Debug::Printf( "Pointer into free list!! %08x %08x %08x\r\n", dst, ptr, ptrEnd ); + + NANOCLR_DEBUG_STOP(); + } + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); +} + +bool CLR_RT_GarbageCollector::IsBlockInFreeList( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst, bool fExact ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,lst) + { + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,hc->m_freeList) + { + if(fExact) + { + if(ptr == dst) return true; + } + else + { + CLR_RT_HeapBlock_Node* ptrEnd = ptr + ptr->DataSize(); + + if(ptr <= dst && dst < ptrEnd) return true; + } + } + NANOCLR_FOREACH_NODE_END(); + } + NANOCLR_FOREACH_NODE_END(); + + return false; +} + +bool CLR_RT_GarbageCollector::IsBlockInHeap( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,lst) + { + if(hc->m_payloadStart <= dst && dst < hc->m_payloadEnd) return true; + } + NANOCLR_FOREACH_NODE_END(); + + return false; +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_4_CompactionPlus + +CLR_RT_GarbageCollector::Rel_List CLR_RT_GarbageCollector::s_lstRecords; +CLR_RT_GarbageCollector::Rel_Map CLR_RT_GarbageCollector::s_mapOldToRecord; +CLR_RT_GarbageCollector::Rel_Map CLR_RT_GarbageCollector::s_mapNewToRecord; + +//--// + +bool CLR_RT_GarbageCollector::TestPointers_PopulateOld_Worker( void** ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32* dst = (CLR_UINT32*)*ref; + + if(dst) + { + RelocationRecord* ptr = new RelocationRecord(); + + s_lstRecords.push_back( ptr ); + + ptr->oldRef = ref; + ptr->oldPtr = dst; + + ptr->newRef = NULL; + ptr->newPtr = NULL; + + ptr->data = *dst; + + if(s_mapOldToRecord.find( ref ) != s_mapOldToRecord.end()) + { + CLR_Debug::Printf( "Duplicate base OLD: %08x\r\n", ref ); + } + + s_mapOldToRecord[ ref ] = ptr; + + if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, (CLR_RT_HeapBlock_Node*)dst, false )) + { + CLR_Debug::Printf( "Some data points into a free list: %08x\r\n", dst ); + + NANOCLR_DEBUG_STOP(); + } + } + + return false; +} + +void CLR_RT_GarbageCollector::TestPointers_PopulateOld() +{ + NATIVE_PROFILE_CLR_CORE(); + Rel_List_Iter itLst; + + for(itLst = s_lstRecords.begin(); itLst != s_lstRecords.end(); itLst++) + { + RelocationRecord* ptr = *itLst; + + delete ptr; + } + + s_lstRecords .clear(); + s_mapOldToRecord.clear(); + s_mapNewToRecord.clear(); + + //--// + + Heap_Relocate_Pass( TestPointers_PopulateOld_Worker ); +} + +void CLR_RT_GarbageCollector::Relocation_UpdatePointer(void** ref) +{ + NATIVE_PROFILE_CLR_CORE(); + +} + +//--// + +void CLR_RT_GarbageCollector::TestPointers_Remap() +{ + NATIVE_PROFILE_CLR_CORE(); + Rel_Map_Iter it; + + for(it = s_mapOldToRecord.begin(); it != s_mapOldToRecord.end(); it++) + { + RelocationRecord* ptr = it->second; + void** ref = it->first ; CLR_RT_GarbageCollector::Relocation_UpdatePointer( (void**)&ref ); + CLR_UINT32* dst = ptr->oldPtr; CLR_RT_GarbageCollector::Relocation_UpdatePointer( (void**)&dst ); + + if(s_mapNewToRecord.find( ref ) != s_mapNewToRecord.end()) + { + CLR_Debug::Printf( "Duplicate base NEW: %08x\r\n", ref ); + } + + s_mapNewToRecord[ ref ] = ptr; + + ptr->newRef = ref; + ptr->newPtr = dst; + } +} + +//--// + +bool CLR_RT_GarbageCollector::TestPointers_PopulateNew_Worker( void** ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32* dst = (CLR_UINT32*)*ref; + + if(dst) + { + Rel_Map_Iter it = s_mapNewToRecord.find( ref ); + + if(it != s_mapNewToRecord.end()) + { + RelocationRecord* ptr = it->second; + + if(ptr->newPtr != dst) + { + CLR_Debug::Printf( "Bad pointer: %08x %08x\r\n", ptr->newPtr, dst ); + } + else if(ptr->data != *dst) + { + CLR_Debug::Printf( "Bad data: %08x %08x\r\n", ptr->data, *dst ); + } + + if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, (CLR_RT_HeapBlock_Node*)dst, false )) + { + CLR_Debug::Printf( "Some data points into a free list: %08x\r\n", dst ); + + NANOCLR_DEBUG_STOP(); + } + } + else + { + CLR_Debug::Printf( "Bad base: %08x\r\n", ref ); + } + } + + return false; +} + +void CLR_RT_GarbageCollector::TestPointers_PopulateNew() +{ + NATIVE_PROFILE_CLR_CORE(); + Heap_Relocate_Pass( TestPointers_PopulateNew_Worker ); +} + +#endif diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj new file mode 100644 index 00000000..a19015d7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {5D50772E-DAC8-407D-972F-37DEB4450B72} + Win32Proj + Hardware + 10.0.17763.0 + Hardware + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj.filters new file mode 100644 index 00000000..c750e915 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware-vs2019.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.cpp b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.cpp new file mode 100644 index 00000000..1c8c2a56 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.cpp @@ -0,0 +1,175 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_HW_Hardware::CreateInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + NANOCLR_CLEAR(g_CLR_HW_Hardware); + + g_CLR_HW_Hardware.m_fInitialized = false; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_HW_Hardware::Hardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + if(m_fInitialized == false) + { + Time_Initialize(); + + m_interruptData.m_HalQueue.Initialize( (CLR_HW_Hardware::HalInterruptRecord*)&g_scratchInterruptDispatchingStorage, InterruptRecords() ); + + m_interruptData.m_applicationQueue.DblLinkedList_Initialize (); + + m_interruptData.m_queuedInterrupts = 0; + + m_DebuggerEventsMask = 0; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + m_DebuggerEventsMask |= ExtractEventFromTransport( HalSystemConfig.DebuggerPort ); +#endif + + m_wakeupEvents = c_Default_WakeupEvents | m_DebuggerEventsMask; + m_powerLevel = PowerLevel__Active; + + m_fInitialized = true; + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +HRESULT CLR_HW_Hardware::DeleteInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + g_CLR_HW_Hardware.Hardware_Cleanup(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_HW_Hardware::Hardware_Cleanup() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + if(m_fInitialized == true) + { + m_fInitialized = false; + } +} + +//--// + +void CLR_HW_Hardware::PrepareForGC() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +void CLR_HW_Hardware::ProcessActivity() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + for(int i=0; i<10; i++) + { + if(!HAL_CONTINUATION::Dequeue_And_Execute()) break; + } + + // UNDONE: FIXME: + //if(!msg.IsDebuggerInitialized()) + //{ + // msg.InitializeDebugger(); + //} + // UNDONE: FIXME:msg.PurgeCache(); + + // UNDONE: FIXME:dbg.PurgeCache(); + + uint32_t events = ::Events_Get( m_wakeupEvents ); + uint32_t eventsCLR = 0; + + if(events & m_DebuggerEventsMask) + { + //dbg.ProcessCommands(); + +#if defined(PLATFORM_ARM) || defined(PLATFORM_ESP32) + if(CLR_EE_DBG_IS(RebootPending)) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Rebooting...\r\n" ); +#endif + + if(!CLR_EE_REBOOT_IS(ClrOnly)) + { + CLR_RT_ExecutionEngine::Reboot( false ); + } + } +#endif + } + + if(events & SYSTEM_EVENT_FLAG_COM_IN) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_SerialPortIn; + } + + if(events & SYSTEM_EVENT_FLAG_COM_OUT) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_SerialPortOut; + } + + if((events & SYSTEM_EVENT_HW_INTERRUPT) +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + || (!CLR_EE_DBG_IS(Stopped) && !g_CLR_HW_Hardware.m_interruptData.m_applicationQueue.IsEmpty()) +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + ) + { + ProcessInterrupts(); + } + + if(events & SYSTEM_EVENT_FLAG_SOCKET) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_Socket; + } + + if(events & SYSTEM_EVENT_FLAG_SPI_MASTER) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_SpiMaster; + } + + if(events & SYSTEM_EVENT_FLAG_I2C_MASTER) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_I2cMaster; + } + + if(events & SYSTEM_EVENT_FLAG_ONEWIRE_MASTER) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_OneWireMaster; + } + + if(events & SYSTEM_EVENT_FLAG_STORAGE_IO) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_StorageIo; + } + + if(eventsCLR) + { + g_CLR_RT_ExecutionEngine.SignalEvents( eventsCLR ); + } +} + +//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--// + diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj new file mode 100644 index 00000000..36a52f5c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {5D50772E-DAC8-407D-972F-37DEB4450B72} + Win32Proj + Hardware + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj.filters new file mode 100644 index 00000000..c750e915 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.cpp b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.cpp new file mode 100644 index 00000000..3fef9f29 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak HRESULT CLR_HW_Hardware::CreateInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_HEADER(); + NANOCLR_NOCLEANUP_NOLABEL(); +} + +__nfweak HRESULT CLR_HW_Hardware::Hardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_HEADER(); + NANOCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +__nfweak HRESULT CLR_HW_Hardware::DeleteInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_HEADER(); + NANOCLR_NOCLEANUP_NOLABEL(); +} + +__nfweak void CLR_HW_Hardware::Hardware_Cleanup() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +//--// + +__nfweak void CLR_HW_Hardware::PrepareForGC() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +__nfweak void CLR_HW_Hardware::ProcessActivity() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--// + diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj new file mode 100644 index 00000000..193572cb --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B} + Win32Proj + Hardware_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters new file mode 100644 index 00000000..d5de8ea4 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Interpreter.cpp b/source/native/nf-interpreter/src/CLR/Core/Interpreter.cpp new file mode 100644 index 00000000..dd7b41d1 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Interpreter.cpp @@ -0,0 +1,3140 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_TRACE_EXCEPTIONS) && defined(_WIN32) + +struct BackTrackExecution +{ + CLR_RT_Assembly* m_assm; + CLR_RT_MethodDef_Index m_call; + CLR_PMETADATA m_IPstart; + CLR_PMETADATA m_IP; + int m_pid; + int m_depth; +}; + +static BackTrackExecution s_track[ 512 ]; +static int s_trackPos; + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_TRACE_STACK) + +bool g_CLR_RT_fBadStack; + +#define RESETSTACK() { g_CLR_RT_fBadStack = false; } +#define CHECKSTACK(stack,evalPos) { g_CLR_RT_fBadStack = stack->m_evalStackPos <= evalPos ; } +#define UPDATESTACK(stack,evalPos) { g_CLR_RT_fBadStack = false; stack->m_evalStackPos = &evalPos[ + 1]; } + + +#else + +#define RESETSTACK() +#define CHECKSTACK(stack,evalPos) +#define UPDATESTACK(stack,evalPos) { stack->m_evalStackPos = &evalPos[ +1 ]; } + +#endif + +//--// +#define EMPTYSTACK(stack,evalPos) { evalPos = &stack->m_evalStack [ -1 ]; RESETSTACK(); } +#define READCACHE(stack,evalPos,ip,fDirty) { evalPos = &stack->m_evalStackPos[ -1 ]; ip = stack->m_IP; fDirty = true ; RESETSTACK(); } +#define WRITEBACK(stack,evalPos,ip,fDirty) { stack->m_evalStackPos = &evalPos [ +1 ]; stack->m_IP = ip ; fDirty = false; RESETSTACK(); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_HeapBlock::InitObject() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = this; + CLR_DataType dt = obj->DataType(); + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + if(dtl.m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + obj->NumericByRef().u8 = 0; + return false; + } + + if(dt == DATATYPE_VALUETYPE && obj->IsBoxed() == false) + { + CLR_UINT32 num = obj->DataSize(); + + while(--num) + { + (++obj)->InitObject(); + } + + return false; + } + + if(dt == DATATYPE_OBJECT || dt == DATATYPE_BYREF) + { + CLR_RT_HeapBlock* ptr = obj->Dereference(); if(!ptr) return false; + + if(ptr->InitObject() == false) return false; + + obj->SetObjectReference( NULL ); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock::Convert_Internal( CLR_DataType et ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_DataType dt = DataType(); + const CLR_RT_DataTypeLookup& dtlSrc = c_CLR_RT_DataTypeLookup[ dt ]; + const CLR_RT_DataTypeLookup& dtlDst = c_CLR_RT_DataTypeLookup[ et ]; + int scaleIn; + int scaleOut; + + // + // Extend to maximum precision. + // + switch(dt) + { + case DATATYPE_BOOLEAN : + case DATATYPE_I1 : + case DATATYPE_U1 : + + case DATATYPE_CHAR : + case DATATYPE_I2 : + case DATATYPE_U2 : + + case DATATYPE_I4 : + case DATATYPE_U4 : + { + CLR_UINT64 res = (CLR_UINT64)NumericByRef().u4; + + if((dtlSrc.m_flags & CLR_RT_DataTypeLookup::c_Signed) && (dtlDst.m_flags & CLR_RT_DataTypeLookup::c_Signed)) + { + CLR_UINT32 shift = 64 - dtlSrc.m_sizeInBits; + + res <<= shift; + res = (CLR_UINT64)((CLR_INT64 )res >> shift); + } + + NumericByRef().u8 = res; + } + // + // Fall-through!!! + // + case DATATYPE_I8: + case DATATYPE_U8: + scaleIn = 0; + break; + + case DATATYPE_R4: scaleIn = 1; break; + case DATATYPE_R8: scaleIn = 2; break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + //--// + + switch(et) + { + case DATATYPE_R4: scaleOut = 1; break; + case DATATYPE_R8: scaleOut = 2; break; + default : scaleOut = 0; break; + } + + //--// + + if(scaleOut != scaleIn) + { +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + + + double val = 0; + + if((dtlSrc.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleIn = -1; + if((dtlDst.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleOut = -1; + + switch(scaleIn) + { + case -1: val = (double)((CLR_UINT64_TEMP_CAST)NumericByRef().u8); break; + case 0: val = (double)((CLR_INT64_TEMP_CAST) NumericByRef().s8); break; + case 1: val = (double) NumericByRef().r4; break; + case 2: val = NumericByRef().r8; break; + } + + switch(scaleOut) + { + // Direct casting of negative double to CLR_UINT64 is returns zero for RVDS 3.1 compiler. + // Double cast looks as most portable way. + case -1: NumericByRef().u8 = (CLR_UINT64)(CLR_INT64 )val; break; + case 0: NumericByRef().s8 = (CLR_INT64 )val; break; + case 1: NumericByRef().r4 = (float )val; break; + case 2: NumericByRef().r8 = val; break; + } +#else + CLR_INT64 val = 0; + CLR_INT64 orig = 0; + + if((dtlSrc.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleIn = -1; + if((dtlDst.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleOut = -1; + + switch(scaleIn) + { + case -1: orig = ((CLR_INT64)((CLR_UINT64_TEMP_CAST)NumericByRef().u8)); val = orig << CLR_RT_HeapBlock::HB_DoubleShift; break; + case 0: orig = ((CLR_INT64)((CLR_INT64_TEMP_CAST) NumericByRef().s8)); val = orig << CLR_RT_HeapBlock::HB_DoubleShift; break; + case 1: orig = ((CLR_INT64)((CLR_INT32) NumericByRef().r4)); val = orig << (CLR_RT_HeapBlock::HB_DoubleShift - CLR_RT_HeapBlock::HB_FloatShift); break; + case 2: orig = ((CLR_INT64) NumericByRef().r8 ); val = orig; break; + } + + switch(scaleOut) + { + // Direct casting of negative double to CLR_UINT64 is returns zero for RVDS 3.1 compiler. + // Double cast looks as most portable way. + case -1: NumericByRef().u8 = (CLR_UINT64)(CLR_INT64 )(val >> CLR_RT_HeapBlock::HB_DoubleShift); break; + case 0: NumericByRef().s8 = (CLR_INT64 ) (val >> CLR_RT_HeapBlock::HB_DoubleShift); break; + case 1: NumericByRef().r4 = (CLR_INT64 ) (val >> (CLR_RT_HeapBlock::HB_DoubleShift - CLR_RT_HeapBlock::HB_FloatShift)); break; + case 2: NumericByRef().r8 = val; break; + } + + if(scaleIn < 1 && scaleOut > 0) + { + switch(scaleOut) + { + case 1: + { + CLR_INT32 r4 = (CLR_INT32)NumericByRef().r4; + + if((orig != (((CLR_INT64)r4) >> CLR_RT_HeapBlock::HB_FloatShift)) || + (orig > 0 && r4 < 0)) + { + NumericByRef().r4 = orig < 0 ? 0x80000000 : 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + break; + case 2: + { + CLR_INT64 r8 = (CLR_INT64)NumericByRef().r8; + + if((orig != (r8 >> CLR_RT_HeapBlock::HB_DoubleShift)) || + (orig > 0 && r8 < 0)) + { + NumericByRef().r8 = orig < 0 ? ULONGLONGCONSTANT(0x8000000000000000) : ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + break; + } + } + else if(scaleIn == 2 && scaleOut == 1) + { + CLR_INT32 r4 = (CLR_INT64)NumericByRef().r4; + + if((orig != (((CLR_UINT64)r4) << (CLR_RT_HeapBlock::HB_DoubleShift - CLR_RT_HeapBlock::HB_FloatShift))) || + (orig > 0 && r4 < 0)) + { + NumericByRef().r4 = orig < 0 ? 0x80000000 : 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + //NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } +#endif + + } + + //--// + + // + // This takes care of truncations. + // + ChangeDataType( et ); + Promote ( ); + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_Thread::UnwindStack* CLR_RT_Thread::PushEH() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_nestedExceptionsPos < (int)ARRAYSIZE(m_nestedExceptions)) + { + memset(&m_nestedExceptions[ m_nestedExceptionsPos ], 0, sizeof(UnwindStack)); + return &m_nestedExceptions[ m_nestedExceptionsPos++ ]; + } + else + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "WARNING: TOO MANY NESTED EXCEPTIONS!!\r\n" ); +#endif + // clip the oldest exception in the nest + memmove(&m_nestedExceptions[0], &m_nestedExceptions[1], sizeof(m_nestedExceptions) - sizeof(m_nestedExceptions[0])); + return &m_nestedExceptions[ m_nestedExceptionsPos-1 ]; + } +} + +void CLR_RT_Thread::PopEH_Inner( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // We could be jumping outside of a nested exception handler. + // + if(m_nestedExceptionsPos > 0) + { + // + // Different stack, don't pop. + // + if(m_nestedExceptions[ m_nestedExceptionsPos-1 ].m_stack != stack) return; + + // + // No longer check for same stack since nested exceptions will have different + // stacks + // + while(m_nestedExceptionsPos > 0) + { + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos-1 ]; + + // + // The new target is within the previous handler, don't pop. + // + if(ip && (us.m_currentBlockStart <= ip && ip < us.m_currentBlockEnd)) break; + +#ifndef CLR_NO_IL_INLINE + if(stack->m_inlineFrame) break; +#endif + + m_nestedExceptionsPos--; + } + } +} + +bool CLR_RT_Thread::FindEhBlock( CLR_RT_StackFrame* stack, CLR_PMETADATA from, CLR_PMETADATA to, CLR_RT_ExceptionHandler& eh, bool onlyFinallys) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Assembly* assm = stack->m_call.m_assm; + CLR_RT_ExceptionHandler* ptrEhExt = NULL; + const CLR_RECORD_EH* ptrEh = NULL; + CLR_UINT32 numEh = 0; + + //FROM is always non-NULL and indicates the current IP + _ASSERTE(from); + //onlyFinallys is false when we're searching for a handler for an exception, and to should be NULL + _ASSERTE(FIMPLIES(!onlyFinallys, to==NULL)); + //onlyFinallys is true in Phase2, endfinally, leave, etc. to is NULL when we want to leave outside of the current stack frame, + //or non-NULL and pointing to an IL instruction that we are going to when finally's, if any, are processed. + +#if defined(NANOCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if(!onlyFinallys || s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "Unwinding at " ); CLR_RT_DUMP::METHOD( stack->m_call ); CLR_Debug::Printf( " [IP: %04x - %d]\r\n", (size_t)stack->m_IP, (stack->m_IP - stack->m_IPstart) ); + } + } +#endif + + if(stack->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) + { + switch(stack->m_flags & CLR_RT_StackFrame::c_MethodKind_Mask) + { + case CLR_RT_StackFrame::c_MethodKind_Interpreted: + { + CLR_OFFSET ipMethod_Start; + CLR_OFFSET ipMethod_End; + + if(assm->FindMethodBoundaries( stack->m_call.Method(), ipMethod_Start, ipMethod_End )) + { + const CLR_RECORD_EH* ptrEh2; + CLR_UINT32 numEh2; + + CLR_RECORD_EH::ExtractEhFromByteCode( stack->m_IPstart + (ipMethod_End - ipMethod_Start), ptrEh2, numEh2 ); + + ptrEh = ptrEh2; // This allows the compiler to leave ptrEh and numEh in registers... + numEh = numEh2; // This allows the compiler to leave ptrEh and numEh in registers... + } + else + { + return false; + } + + ptrEhExt = NULL; + } + break; + + case CLR_RT_StackFrame::c_MethodKind_Native: + return false; + } + + // + // We're certain there's at least one EH. + // + while(numEh--) + { + if(ptrEh) + { + eh.ConvertFromEH( stack->m_call, stack->m_IPstart, ptrEh++ ); + + ptrEhExt = &eh; + } + +#if defined(NANOCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if(to == NULL || s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "Checking EH: %04X-%04X => %04X\r\n", (size_t)ptrEhExt->m_tryStart, (size_t)ptrEhExt->m_tryEnd, ptrEhExt->m_handlerStart - stack->m_IPstart ); + } + } +#endif + + if(ptrEhExt->IsFilter() && ptrEhExt->m_userFilterStart <= from && from < ptrEhExt->m_handlerStart) + { + //The IP was in the middle of this EH block's filter. + //Therefore, reset the IP to inside the original try block so we can try the next handler in this sequence: + // Try + // ... //2. set IP to here + // Catch When False + // Catch When False //1. from was in this filter + // Catch ... //3. This is the next EH block, and will be found correctly. + // ... + // End Try + from = ptrEhExt->m_tryStart; + } + else if(from >= ptrEhExt->m_tryStart && from < ptrEhExt->m_tryEnd) + { + if(onlyFinallys) + { + // + // Only execute the finally if this is an exception or we leave the block. + // + if(ptrEhExt->IsFinally() && (!to || (to < ptrEhExt->m_tryStart || to >= ptrEhExt->m_tryEnd))) + { +#if defined(NANOCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "Found match for a 'finally'\r\n" ); + } +#endif + + eh = *ptrEhExt; + return true; + } + } + else + { + if(ptrEhExt->IsCatchAll()) + { +#if defined(NANOCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + CLR_Debug::Printf( "Found match for a 'catch all'\r\n" ); + } +#endif + + eh = *ptrEhExt; + return true; // Catch all... + } + else + { + if(ptrEhExt->IsFilter() || CLR_RT_ExecutionEngine::IsInstanceOf( m_currentException, ptrEhExt->m_typeFilter )) + { +#if defined(NANOCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if (ptrEhExt->IsFilter()) + { + CLR_Debug::Printf( "Trying a 'filter'\r\n" ); + } + else + { + CLR_Debug::Printf( "Found match for a 'catch'\r\n" ); + } + } +#endif + + eh = *ptrEhExt; + return true; + } + } + } + } + + ptrEhExt++; + } + } + +#if defined(NANOCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if(to == NULL || s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "No match\r\n" ); + } + } +#endif + + return false; +} + +//--// + +HRESULT CLR_RT_Thread::Execute() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( this->CurrentAppDomain() ); +#endif + + CLR_RT_Thread* currentThreadSav = g_CLR_RT_ExecutionEngine.m_currentThread; + + g_CLR_RT_ExecutionEngine.m_currentThread = this; + + if(m_currentException.Dereference() != NULL) + { + hr = CLR_E_PROCESS_EXCEPTION; + } + else + { + hr = S_OK; + } + + m_timeQuantumExpired = false; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + _ASSERTE(!CLR_EE_DBG_IS( Stopped )); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + ::Events_SetBoolTimer( (bool*)&m_timeQuantumExpired, CLR_RT_Thread::c_TimeQuantum_Milliseconds ); + + while(m_timeQuantumExpired == false && !CLR_EE_DBG_IS( Stopped )) + { + CLR_RT_StackFrame* stack; + + if(SUCCEEDED(hr)) + { + hr = Execute_Inner(); + if(SUCCEEDED(hr)) + { + NANOCLR_LEAVE(); + } + } + + switch(hr) + { + case CLR_E_THREAD_WAITING: + case CLR_E_RESCHEDULE: + NANOCLR_LEAVE(); + + case CLR_E_PROCESS_EXCEPTION: + CLR_RT_DUMP::POST_PROCESS_EXCEPTION( m_currentException ); + break; + + default: // Allocate a new exception. + stack = CurrentFrame(); + if(stack->Prev() != NULL) + { +#if defined(NANOCLR_TRACE_INSTRUCTIONS) && defined(PLATFORM_WINDOWS_EMULATOR) + for(int i = 0; i < ARRAYSIZE(s_track); i++) + { + BackTrackExecution& track = s_track[ (s_trackPos+i) % ARRAYSIZE(s_track) ]; + + CLR_Debug::Printf( " %3d ", track.m_depth ); + + CLR_RT_MethodDef_Instance inst; inst.InitializeFromIndex( track.m_call ); + + //track.m_assm->DumpOpcodeDirect( inst, track.m_IP, track.m_IPstart, track.m_pid ); + } + + CLR_Debug::Printf( "\r\n" ); +#endif + + (void)Library_corlib_native_System_Exception::CreateInstance( m_currentException, hr, stack ); + } + + hr = CLR_E_PROCESS_EXCEPTION; + break; + } + + // + // Process exception. + // + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) break; +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + NANOCLR_CHECK_HRESULT(ProcessException()); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) break; +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(m_currentException.Dereference() != NULL) { break; } + } + + NANOCLR_SET_AND_LEAVE(CLR_S_QUANTUM_EXPIRED); + + NANOCLR_CLEANUP(); + +#if defined(NANOCLR_APPDOMAINS) + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + g_CLR_RT_ExecutionEngine.m_currentThread = currentThreadSav; + + ::Events_SetBoolTimer( NULL, 0 ); + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::Execute_Inner() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + while(m_timeQuantumExpired == false && !CLR_EE_DBG_IS( Stopped )) + { + CLR_RT_StackFrame *stack = CurrentFrame(); + + #if defined(ENABLE_NATIVE_PROFILER) + if(stack->m_owningThread->m_fNativeProfiled == true) + { + Native_Profiler_Start(); + } + #endif + + if(stack->Prev() == NULL) + { + m_status = CLR_RT_Thread::TH_S_Terminated; + + NANOCLR_SET_AND_LEAVE(CLR_S_THREAD_EXITED); // End of Thread. + } + + if(stack->m_flags & CLR_RT_StackFrame::c_ProcessSynchronize) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_InvalidIP) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + // + // Thread cannot run if a lock request is still pending... + // + if(stack->m_flags & (CLR_RT_StackFrame::c_PendingSynchronizeGlobally | CLR_RT_StackFrame::c_PendingSynchronize)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + } + + if(stack->m_flags & CLR_RT_StackFrame::c_NeedToSynchronizeGlobally) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_NeedToSynchronizeGlobally; + + if(FAILED(hr = stack->HandleSynchronized( true, true ))) + { + if(hr == CLR_E_THREAD_WAITING) + { + stack->m_flags |= CLR_RT_StackFrame::c_PendingSynchronizeGlobally; + } + + NANOCLR_LEAVE(); + } + + stack->m_flags |= CLR_RT_StackFrame::c_SynchronizedGlobally; + } + + if(stack->m_flags & CLR_RT_StackFrame::c_NeedToSynchronize) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_NeedToSynchronize; + + if(FAILED(hr = stack->HandleSynchronized( true, false ))) + { + if(hr == CLR_E_THREAD_WAITING) + { + stack->m_flags |= CLR_RT_StackFrame::c_PendingSynchronize; + } + + NANOCLR_LEAVE(); + } + + stack->m_flags |= CLR_RT_StackFrame::c_Synchronized; + } + } + + { +#if defined(NANOCLR_PROFILE_NEW_CALLS) + CLR_PROF_HANDLER_CALLCHAIN( pm2, stack->m_callchain ); +#endif + + CLR_UINT32 methodKind = (stack->m_flags & CLR_RT_StackFrame::c_MethodKind_Mask); + + switch(methodKind) + { + case CLR_RT_StackFrame::c_MethodKind_Native: + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + break; + + case CLR_RT_StackFrame::c_MethodKind_Interpreted: + //_ASSERTE((stack->m_flags & CLR_RT_StackFrame::c_InvalidIP) == 0); + stack->m_flags |= CLR_RT_StackFrame::c_ExecutingIL; + break; + } + + // perform systematic GC and compaction under memory pressure + // (g_CLR_RT_GarbageCollector.m_freeBytes refers to last time GC was run) + if(g_CLR_RT_GarbageCollector.m_freeBytes < g_CLR_RT_GarbageCollector.c_memoryThreshold2) + { + stack->m_flags |= CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; + } + + while(true) + { + { + #if defined(ENABLE_NATIVE_PROFILER) + if(stack->m_flags & CLR_RT_StackFrame::c_NativeProfiled) + { + Native_Profiler_Start(); + } + else if(stack->m_fNativeProfiled == false) + { + stack->m_owningThread->m_fNativeProfiled = false; + Native_Profiler_Stop(); + } + #endif + + hr = stack->m_nativeMethod( *stack ); + } + + // check for exception injected by native code + if(m_currentException.Dereference() != NULL) + { + hr = CLR_E_PROCESS_EXCEPTION; + } + + //The inner loop may push or pop more stack frames + stack = CurrentFrame(); + + if(stack->Prev() == NULL) + { + m_status = CLR_RT_Thread::TH_S_Terminated; + + NANOCLR_SET_AND_LEAVE(CLR_S_THREAD_EXITED); // End of Thread. + } + + if(hr == CLR_E_OUT_OF_MEMORY && (stack->m_flags & CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory)) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; + + g_CLR_RT_ExecutionEngine.PerformHeapCompaction(); + } + else + { + break; + } + } + + switch(methodKind) + { + case CLR_RT_StackFrame::c_MethodKind_Native: + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + break; + } + + if(FAILED(hr)) + { + // + // CLR_E_RESTART_EXECUTION is used to inject calls to methods from native code. + // + if(hr != CLR_E_RESTART_EXECUTION) NANOCLR_LEAVE(); + } + else + { + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingIL; + + if(hr == S_OK) + { + CurrentFrame()->Pop(); + } + } + } + } + + NANOCLR_SET_AND_LEAVE(CLR_S_QUANTUM_EXPIRED); + + NANOCLR_CLEANUP(); + + #if defined(ENABLE_NATIVE_PROFILER) + Native_Profiler_Stop(); + #endif + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::Execute_DelegateInvoke( CLR_RT_StackFrame& stackArg ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* stack = &stackArg; + + const CLR_RECORD_METHODDEF* md; + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock* array; + CLR_RT_HeapBlock* ptr; + CLR_UINT32 num; + + ptr = &stack->m_arguments[ 0 ]; if(ptr->DataType() != DATATYPE_OBJECT) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + dlg = ptr->DereferenceDelegate(); FAULT_ON_NULL(dlg); + + md = stack->m_call.m_target; + + switch(dlg->DataType()) + { + case DATATYPE_DELEGATE_HEAD: + array = ptr; + num = 1; + break; + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* list = ptr->DereferenceDelegateList(); + + array = list->GetDelegates(); + num = list->m_length; + } + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + while(true) + { + if(stack->m_customState >= num) // We have called all the delegates, let's return. + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + + dlg = array[ stack->m_customState++ ].DereferenceDelegate(); + + if(dlg == NULL || dlg->DataType() != DATATYPE_DELEGATE_HEAD) continue; + + break; + } + + //--// + + stack->ResetStack(); + + { + CLR_RT_ProtectFromGC gc( *dlg ); + CLR_RT_MethodDef_Instance inst; inst.InitializeFromIndex( dlg->DelegateFtn() ); + bool fStaticMethod = (inst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) != 0; + + NANOCLR_CHECK_HRESULT(stack->MakeCall(inst, fStaticMethod ? NULL : &dlg->m_object, &stack->m_arguments[ 1 ], md->numArgs - 1 )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::Execute_IL( CLR_RT_StackFrame& stackArg ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* stack = &stackArg; + + CLR_RT_Thread* th = stack->m_owningThread; + CLR_RT_Assembly* assm = stack->m_call.m_assm; + CLR_RT_HeapBlock* evalPos; + CLR_PMETADATA ip; + bool fCondition; + bool fDirty = false; + + READCACHE(stack,evalPos,ip,fDirty); + + while(true) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(th->m_timeQuantumExpired == true) + { + NANOCLR_SET_AND_LEAVE( CLR_S_QUANTUM_EXPIRED ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(NANOCLR_TRACE_EXCEPTIONS) && defined(_WIN32) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + CLR_PROF_HANDLER_SUSPEND_TIME(); + + BackTrackExecution& track = s_track[ s_trackPos++ ]; s_trackPos %= ARRAYSIZE(s_track); + int depth = 0; + + NANOCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,tmp,stack) + { + depth++; + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); + + track.m_assm = assm; + track.m_call = stack->m_call; + track.m_IP = ip; + track.m_IPstart = stack->m_IPstart; + track.m_pid = stack->m_owningThread->m_pid; + track.m_depth = depth; + + CLR_PROF_HANDLER_RESUME_TIME(); + } +#endif + + assm->DumpOpcode( stack, ip ); + + CLR_OPCODE op = CLR_OPCODE(*ip++); + +Execute_RestartDecoding: + +#if defined(NANOCLR_OPCODE_STACKCHANGES) + if(op != CEE_PREFIX1) + { + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK( *stack, &evalPos[ 1 ], c_CLR_RT_OpcodeLookup[ op ].StackChanges() )); + } +#endif + + { + //////////////////////// + // + // +#if defined(PLATFORM_WINDOWS_EMULATOR) + if(s_CLR_RT_fTrace_SimulateSpeed > c_CLR_RT_Trace_None) + { + CLR_PROF_Handler::SuspendTime(); + + HAL_Windows_FastSleep( g_HAL_Configuration_Windows.TicksPerOpcode ); + + CLR_PROF_Handler::ResumeTime(); + } +#endif + // + // + //////////////////////// + + //--// + + + switch(op) + { +#define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) case name: + OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) + { + op = CLR_OPCODE(*ip++ + 256); + goto Execute_RestartDecoding; + } + + OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) + break; + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ 0 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) + OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) + OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ op - CEE_LDARG_0 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ arg ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ arg ] ); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 0 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 1 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 2 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 3 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ arg ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ arg ] ); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_locals[ arg ] ); + break; + } + + OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_locals[ arg ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_arguments[ arg ] ); + break; + } + + OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_arguments[ arg ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) + OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) + OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) + OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) + // Stack: ... ... -> ... + { + stack->m_locals[ op - CEE_STLOC_0 ].AssignPreserveTypeCheckPinned( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + stack->m_locals[ arg ].AssignPreserveTypeCheckPinned( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + stack->m_locals[ arg ].AssignPreserveTypeCheckPinned( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + stack->m_arguments[ arg ].AssignAndPreserveType( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + stack->m_arguments[ arg ].AssignAndPreserveType( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetObjectReference( NULL ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) + OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) + OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) + OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) + OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) + OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) + OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) + OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) + OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) + OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT32)op - (CLR_INT32)CEE_LDC_I4_0 ); + break; + } + + OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_INT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT32)arg ); + break; + } + + OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_INT32(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT32)arg ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_INT64(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT64)arg ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT32(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + evalPos[ 0 ].SetFloatFromBits( arg ); +#else + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].SetFloatIEEE754( arg )); +#endif + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT64(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + evalPos[ 0 ].SetDoubleFromBits( arg ); +#else + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].SetDoubleIEEE754( arg )); +#endif + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( evalPos[ -1 ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) + OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) + { + fCondition = true; + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) + OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + fCondition = (evalPos[ 1 ].IsZero() == true); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) + OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + fCondition = (evalPos[ 1 ].IsZero() == false); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) + OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) == 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) + OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) >= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) + OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) > 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) + OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) <= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) + OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) < 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) + OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) != 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) + OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) >= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) + OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) > 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) + OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) <= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) + OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) < 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + FETCH_ARG_UINT8(arg,ip); + + CLR_UINT32 numCases = arg; + CLR_UINT32 caseSelected = evalPos[ 1 ].NumericByRef().u4; + + if(caseSelected < numCases) + { + CLR_PMETADATA ipsub = ip + (CLR_INT32)caseSelected * sizeof(CLR_INT16); + + FETCH_ARG_INT16(offset,ipsub); + + ip += offset; + } + + ip += (CLR_INT32)numCases * sizeof(CLR_INT16); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) + OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) + OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) + OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) + OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) + OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) + OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) + OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) + OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) + OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) + OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) + // Stack: ... ...

-> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( evalPos[ 0 ] )); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) + OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) + OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) + OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) + OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) + OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) + OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) + OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) + // Stack: ... ...
-> ... + { + int size = 0; + + evalPos -= 2; CHECKSTACK(stack,evalPos); + + switch(op) + { + case CEE_STIND_I : size = 4; break; + case CEE_STIND_I1 : size = 1; break; + case CEE_STIND_I2 : size = 2; break; + case CEE_STIND_I4 : size = 4; break; + case CEE_STIND_I8 : size = 8; break; + case CEE_STIND_R4 : size = 4; break; + case CEE_STIND_R8 : size = 8; break; + case CEE_STIND_REF: size = 0; break; + // the remaining op codes aren't to be handled + default: break; + } + + evalPos[ 2 ].Promote(); + + NANOCLR_CHECK_HRESULT(evalPos[ 2 ].StoreToReference( evalPos[ 1 ], size )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) + OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) + OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericAdd( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) + OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) + OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericSub( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) + OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) + OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericMul( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericDiv( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericDivUn( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericRem( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericRemUn( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].NumericByRef().u8 &= evalPos[ 1 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].NumericByRef().u8 |= evalPos[ 1 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].NumericByRef().u8 ^= evalPos[ 1 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericShl( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericShr( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericShrUn( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].NumericNeg()); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) + // Stack: ... ... -> ... + { + evalPos[ 0 ].NumericByRef().u8 = ~evalPos[ 0 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) + OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) + OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I1, op != CEE_CONV_I1, op == CEE_CONV_OVF_I1_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) + OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) + OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I2, op != CEE_CONV_I2, op == CEE_CONV_OVF_I2_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) + OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) + OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I4, op != CEE_CONV_I4, op == CEE_CONV_OVF_I4_UN )); + break; + } + + OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) + OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) + OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) + // Stack: ... ... -> ... + { + if ( evalPos[ 0 ].DataType() == DATATYPE_BYREF || evalPos[ 0 ].DataType() == DATATYPE_ARRAY_BYREF ) + { + break; + } + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I4, op != CEE_CONV_I, op == CEE_CONV_OVF_I_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) + OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) + OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I8, op != CEE_CONV_I8, op == CEE_CONV_OVF_I8_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_R4, false, false )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) + OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_R8, false, op == CEE_CONV_R_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) + OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) + OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U1, op != CEE_CONV_U1, op == CEE_CONV_OVF_U1_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) + OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) + OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U2, op != CEE_CONV_U2, op == CEE_CONV_OVF_U2_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) + OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) + OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U4, op != CEE_CONV_U4, op == CEE_CONV_OVF_U4_UN )); + break; + } + + OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) + OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) + OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) + // Stack: ... ... -> ... + { + if ( evalPos[ 0 ].DataType() == DATATYPE_BYREF || evalPos[ 0 ].DataType() == DATATYPE_ARRAY_BYREF ) + { + break; + } + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U4, op != CEE_CONV_U, op == CEE_CONV_OVF_U_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) + OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) + OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) + // Stack: ... ... -> ... + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U8, op != CEE_CONV_U8, op == CEE_CONV_OVF_U8_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) + OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) + + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + CLR_RT_MethodDef_Instance calleeInst; if(calleeInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_TypeDef_Index cls; + CLR_RT_HeapBlock* pThis; +#if defined(NANOCLR_APPDOMAINS) + bool fAppDomainTransition = false; +#endif + + pThis = &evalPos[1-calleeInst.m_target->numArgs]; // Point to the first arg, 'this' if an instance method + + if(calleeInst.m_target->flags & CLR_RECORD_METHODDEF::MD_DelegateInvoke) + { + CLR_RT_HeapBlock_Delegate* dlg = pThis->DereferenceDelegate(); FAULT_ON_NULL(dlg); + + if(dlg->DataType() == DATATYPE_DELEGATE_HEAD) + { + calleeInst.InitializeFromIndex( dlg->DelegateFtn() ); + + if((calleeInst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + pThis->Assign( dlg->m_object ); + +#if defined(NANOCLR_APPDOMAINS) + fAppDomainTransition = pThis[ 0 ].IsTransparentProxy(); +#endif + } + else + { + memmove( &pThis[ 0 ], &pThis[ 1 ], calleeInst.m_target->numArgs * sizeof(CLR_RT_HeapBlock) ); + + evalPos--; + } + } + else + { + // + // The lookup for multicast delegates is done at a later stage... + // + } + } + else //Non delegate + { + CLR_RT_MethodDef_Index calleeReal; + + if((calleeInst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + //Instance method, pThis[ 0 ] is valid + + if(op == CEE_CALL && pThis[ 0 ].Dereference() == NULL) + { + //CALL on a null instance is allowed, and should not throw a NullReferenceException on the call + //although a NullReferenceException is likely to be thrown soon thereafter if the call tries to access + //any member variables. + } + else + { + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( pThis[ 0 ], cls )); + + //This test is for performance reasons. c# emits a callvirt on all instance methods to make sure that + //a NullReferenceException is thrown if 'this' is NULL. However, if the instance method isn't virtual + //we don't need to do the more expensive virtual method lookup. + if(op == CEE_CALLVIRT && (calleeInst.m_target->flags & (CLR_RECORD_METHODDEF::MD_Abstract | CLR_RECORD_METHODDEF::MD_Virtual))) + { + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, calleeInst, calleeReal ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + calleeInst.InitializeFromIndex( calleeReal ); + } + +#if defined(NANOCLR_APPDOMAINS) + fAppDomainTransition = pThis[ 0 ].IsTransparentProxy(); +#endif + } + } + } + +#if defined(NANOCLR_APPDOMAINS) + if(fAppDomainTransition) + { + WRITEBACK(stack,evalPos,ip,fDirty); + + _ASSERTE(FIMPLIES(pThis->DataType() == DATATYPE_OBJECT, pThis->Dereference() != NULL)); + NANOCLR_CHECK_HRESULT(CLR_RT_StackFrame::PushAppDomainTransition( th, calleeInst, &pThis[ 0 ], &pThis[ 1 ])); + } + else +#endif //NANOCLR_APPDOMAINS + { +#ifndef CLR_NO_IL_INLINE + if(stack->PushInline(ip, assm, evalPos, calleeInst, pThis)) + { + fDirty = true; + break; + } +#endif + + WRITEBACK(stack,evalPos,ip,fDirty); + NANOCLR_CHECK_HRESULT(CLR_RT_StackFrame::Push( th, calleeInst, -1 )); + } + + goto Execute_Restart; + } + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) + { +#ifndef CLR_NO_IL_INLINE + if(stack->m_inlineFrame) + { + stack->m_evalStackPos = evalPos; + + stack->PopInline(); + + ip = stack->m_IP; + assm = stack->m_call.m_assm; + evalPos = stack->m_evalStackPos-1; + fDirty = true; + + break; + } +#endif + + WRITEBACK(stack,evalPos,ip,fDirty); + + // + // Same kind of handler, no need to pop back out, just restart execution in place. + // + if(stack->m_flags & CLR_RT_StackFrame::c_CallerIsCompatibleForRet) + { + CLR_RT_StackFrame* stackNext = stack->Caller(); + + stack->Pop(); + + stack = stackNext; + goto Execute_Reload; + } + else + { + stack->Pop(); + + NANOCLR_SET_AND_LEAVE(CLR_S_RESTART_EXECUTION); + } + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) + OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) + // Stack: ... ... -> ... + { + ip += 2; // Skip argument, not used... + + evalPos -= 2; CHECKSTACK(stack,evalPos); + + // + // Reassign will make sure these are objects of the same type. + // + NANOCLR_CHECK_HRESULT(evalPos[ 1 ].Reassign( evalPos[ 2 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_RT_TypeDef_Instance type; + CLR_RT_TypeDef_Index cls; + + if(type.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( evalPos[ 0 ], cls )); + + // Check this is an object of the requested type. + if(type.m_data != cls.m_data) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + UPDATESTACK(stack,evalPos); + + { + // + // Save the pointer to the object to load/copy and protect it from GC. + // + CLR_RT_HeapBlock safeSource; safeSource.Assign( evalPos[ 0 ] ); + CLR_RT_ProtectFromGC gc( safeSource ); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( safeSource )); + + } + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) + { + FETCH_ARG_COMPRESSED_STRINGTOKEN(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + UPDATESTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( evalPos[ 0 ], arg, assm )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + CLR_RT_MethodDef_Instance calleeInst; if(calleeInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_TypeDef_Instance cls; + CLR_RT_HeapBlock* top; + CLR_INT32 changes; + + cls.InitializeFromMethod( calleeInst ); // This is the class to create! + + evalPos++; + + WRITEBACK(stack,evalPos,ip,fDirty); + + if(cls.m_target->IsDelegate()) + { + // + // Special case for delegates. LDFTN or LDVIRTFTN have already created the delegate object, just check that... + // + changes = -calleeInst.m_target->numArgs; + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK( *stack, stack->m_evalStackPos, changes )); // Check to see if we have enough parameters. + stack->m_evalStackPos += changes; + + top = stack->m_evalStackPos++; // Push back the result. + + if(top[ 1 ].DataType() != DATATYPE_OBJECT) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_HeapBlock_Delegate* dlg = top[ 1 ].DereferenceDelegate(); + + if(dlg == NULL) + { + NANOCLR_CHECK_HRESULT(CLR_E_NULL_REFERENCE); + } + + dlg->m_cls = cls; + + CLR_RT_MethodDef_Instance dlgInst; + + if(dlgInst.InitializeFromIndex( dlg->DelegateFtn() ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if((dlgInst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + dlg->m_object.Assign( top[ 0 ] ); + } + + top->SetObjectReference( dlg ); + } + else + { + changes = calleeInst.m_target->numArgs; + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK( *stack, stack->m_evalStackPos, -changes )); // Check to see if we have enough parameters. + top = stack->m_evalStackPos; + + // + // We have to insert the 'this' pointer as argument 0, that means moving all the arguments up one slot... + // + top--; + while(--changes > 0) + { + top[ 0 ].Assign( top[ -1 ] ); top--; + } + top->SetObjectReference( NULL ); + + // Stack: ... ... -> ... + // ^ + // Top points here. + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObject( top[ 0 ], cls )); + + // + // This is to flag the fact that we need to copy back the 'this' pointer into our stack. + // + // See CLR_RT_StackFrame::Pop() + // + stack->m_flags |= CLR_RT_StackFrame::c_ExecutingConstructor; + + // + // Ok, creating a ValueType then calls its constructor. + // But the constructor will try to load the 'this' pointer and since it's a value type, it will be cloned. + // For the length of the constructor, change the type from an object pointer to a reference. + // + // See CLR_RT_StackFrame::Pop() + // + if((cls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_ValueType) + { + if(top[ 0 ].DataType() == DATATYPE_OBJECT) + { + top[ 0 ].ChangeDataType( DATATYPE_BYREF ); + } + else + { + // + // This is to support the optimization on DateTime and TimeSpan: + // + // These are passed as built-ins. But we need to pass them as a reference, + // so push everything down and undo the "ExecutingConstructor" trick. + // + top = stack->m_evalStackPos++; + + changes = calleeInst.m_target->numArgs; + while(--changes > 0) + { + top[ 0 ].Assign( top[ -1 ] ); top--; + } + top[ 0 ].SetReference( top[ -1 ] ); + + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingConstructor; + } + } + + if(FAILED(hr = CLR_RT_StackFrame::Push( th, calleeInst, -1 ))) + { + if(hr == CLR_E_NOT_SUPPORTED) + { + // no matter what, we are no longer executing a ctor + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingConstructor; + } + + NANOCLR_LEAVE(); + } + + goto Execute_Restart; + } + + READCACHE(stack,evalPos,ip,fDirty); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) + OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + NANOCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CastToType( evalPos[ 0 ], arg, assm, (op == CEE_ISINST) )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) + { + th->m_currentException.Assign( evalPos[ 0 ] ); + + EMPTYSTACK(stack, evalPos); + + Library_corlib_native_System_Exception::SetStackTrace( th->m_currentException, stack ); + + NANOCLR_CHECK_HRESULT(CLR_E_PROCESS_EXCEPTION); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) + // Stack: ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance fieldInst; if(fieldInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_HeapBlock* obj = &evalPos[ 0 ]; + CLR_DataType dt = obj->DataType(); + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + + switch(dt) + { + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + evalPos[ 0 ].Assign( obj[ fieldInst.CrossReference().m_offset ] ); + goto Execute_LoadAndPromote; + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + evalPos[ 0 ].SetInteger( (CLR_INT64)obj->NumericByRefConst().s8 ); + break; +#if defined(NANOCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + { + CLR_RT_HeapBlock val; + + NANOCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + + UPDATESTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->MarshalObject( obj->TransparentProxyDereference()[ fieldInst.CrossReference().m_offset ], val, obj->TransparentProxyAppDomain() )); + + evalPos[ 0 ].Assign( val ); + } + goto Execute_LoadAndPromote; +#endif + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + break; + + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) + // Stack: ... ->
... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance fieldInst; if(fieldInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_HeapBlock* obj = &evalPos[ 0 ]; + CLR_DataType dt = obj->DataType(); + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + +#if defined(NANOCLR_APPDOMAINS) + _ASSERTE(dt != DATATYPE_TRANSPARENT_PROXY); +#endif + if(dt == DATATYPE_CLASS || dt == DATATYPE_VALUETYPE) + { + evalPos[ 0 ].SetReference( obj[ fieldInst.CrossReference().m_offset ] ); + } + else if(dt == DATATYPE_DATETIME || dt == DATATYPE_TIMESPAN) // Special case. + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); // NOT SUPPORTED. + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + evalPos -= 2; CHECKSTACK(stack,evalPos); + + CLR_RT_FieldDef_Instance fieldInst; if(fieldInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_HeapBlock* obj = &evalPos[ 1 ]; + CLR_DataType dt = obj->DataType(); + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + + switch(dt) + { + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + obj[ fieldInst.CrossReference().m_offset ].AssignAndPreserveType( evalPos[ 2 ] ); + break; + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + obj->NumericByRef().s8 = evalPos[ 2 ].NumericByRefConst().s8; + break; + +#if defined(NANOCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + { + CLR_RT_HeapBlock val; + + UPDATESTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + NANOCLR_CHECK_HRESULT(obj->TransparentProxyAppDomain()->MarshalObject( evalPos[ 2 ], val )); + + obj->TransparentProxyDereference()[ fieldInst.CrossReference().m_offset ].AssignAndPreserveType( val ); + } + break; +#endif + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + break; + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) + // Stack: ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + CLR_RT_HeapBlock* ptr = CLR_RT_ExecutionEngine::AccessStaticField( field ); if(ptr == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( *ptr ); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) + // Stack: ... ->
... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + CLR_RT_HeapBlock* ptr = CLR_RT_ExecutionEngine::AccessStaticField( field ); if(ptr == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( *ptr ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + CLR_RT_HeapBlock* ptr = CLR_RT_ExecutionEngine::AccessStaticField( field ); if(ptr == NULL) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos--; CHECKSTACK(stack,evalPos); + + ptr->AssignAndPreserveType( evalPos[ 1 ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) + OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_RT_TypeDef_Instance typeInst; if(typeInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + + if(op == CEE_BOX) + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].PerformBoxing( typeInst )); + } + else + { + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].PerformUnboxing( typeInst )); + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) + { + //Stack: ... -> ..., value or obj + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + //When applied to the boxed form of a value type, the unbox.any instruction + //extracts the value contained within obj (of type O). (It is equivalent to unbox followed by ldobj.) + //When applied to a reference type, the unbox.any instruction has the same effect as castclass typeTok. + + CLR_RT_TypeDef_Instance typeInst; if(typeInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + + if(((typeInst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_ValueType) || + ((typeInst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum )) + { + //"unbox" + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].PerformUnboxing( typeInst )); + + //"ldobj" + { + CLR_RT_HeapBlock safeSource; safeSource.Assign( evalPos[ 0 ] ); + CLR_RT_ProtectFromGC gc( safeSource ); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( safeSource )); + + goto Execute_LoadAndPromote; + } + } + else + { + //"castclass" + NANOCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CastToType( evalPos[ 0 ], arg, assm, false )); + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) + { + + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_UINT32 size = evalPos[ 0 ].NumericByRef().u4; + + UPDATESTACK(stack,evalPos); + + stack->m_flags &= ~CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; // we do not need this in this case + + for(int pass=0; pass<2; pass++) + { + hr = CLR_RT_HeapBlock_Array::CreateInstance( evalPos[ 0 ], size, assm, arg ); if(SUCCEEDED(hr)) break; + + // if we have an out of memory exception, perform a compaction and try again. + if (hr == CLR_E_OUT_OF_MEMORY && pass == 0) + { + WRITEBACK(stack, evalPos, ip, fDirty); + g_CLR_RT_ExecutionEngine.PerformHeapCompaction(); + READCACHE(stack, evalPos, ip, fDirty); + } + else + { + NANOCLR_SET_AND_LEAVE(hr); + } + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) + // Stack: ... -> ... + { + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyArrayReference( evalPos[ 0 ] )); + + CLR_RT_HeapBlock_Array* array = evalPos[ 0 ].DereferenceArray(); + + evalPos[ 0 ].SetInteger( array->m_numOfElements ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) + // Stack: ... ->
... + { + ip += 2; // Skip argument, not used... + + evalPos--; CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].InitializeArrayReference( evalPos[ 0 ], evalPos[ 1 ].NumericByRef().s4 )); + + evalPos[ 0 ].FixArrayReferenceForValueTypes(); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) + OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) + OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) + OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) + OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) + OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) + OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) + OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) + OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) + OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) + OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) + // Stack: ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + // + // To load an element from an array, we first initialize a temporary reference to the element and then dereference it. + // + CLR_RT_HeapBlock ref; NANOCLR_CHECK_HRESULT(ref.InitializeArrayReference( evalPos[ 0 ], evalPos[ 1 ].NumericByRef().s4 )); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( ref )); + + goto Execute_LoadAndPromote; + } + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) + // Stack: ... -> + { + // treat this like ldelema + ldobj + // read the type token argument from the instruction and advance the instruction pointer accordingly + // LDELEMA doesn't need the type token, but the ldobj portion does + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + // + // move stack pointer back so that evalpos[0] is the array + evalPos--; + CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].InitializeArrayReference( evalPos[ 0 ], evalPos[ 1 ].NumericByRef().s4 )); + + evalPos[ 0 ].FixArrayReferenceForValueTypes(); + // + // + CLR_RT_TypeDef_Instance type; + CLR_RT_TypeDef_Index cls; + + if( !type.ResolveToken( arg, assm ) ) + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( evalPos[ 0 ], cls )); + + // Check this is an object of the requested type. + if( type.m_data != cls.m_data ) + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + { + // Save the pointer to the object to load/copy and protect it from GC. + CLR_RT_HeapBlock safeSource; + safeSource.Assign( evalPos[ 0 ] ); + CLR_RT_ProtectFromGC gc( safeSource ); + + NANOCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( safeSource )); + } + + goto Execute_LoadAndPromote; + // + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) + OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) + OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) + OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) + OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) + OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) + OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) + OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) + // Stack: ... ... -> ... + { + evalPos -= 3; CHECKSTACK(stack,evalPos); + + // + // To load an element from an array, we first initialize a temporary reference to the element and then dereference it. + // + CLR_RT_HeapBlock ref; NANOCLR_CHECK_HRESULT(ref.InitializeArrayReference( evalPos[ 1 ], evalPos[ 2 ].NumericByRef().s4 )); + int size = 0; + + switch(op) + { + case CEE_STELEM_I : size = 4; break; + case CEE_STELEM_I1 : size = 1; break; + case CEE_STELEM_I2 : size = 2; break; + case CEE_STELEM_I4 : size = 4; break; + case CEE_STELEM_I8 : size = 8; break; + case CEE_STELEM_R4 : size = 4; break; + case CEE_STELEM_R8 : size = 8; break; + case CEE_STELEM_REF: size = 0; break; + // the remaining op cpdes aren't to be handled + default: break; + } + + evalPos[ 3 ].Promote(); + + NANOCLR_CHECK_HRESULT(evalPos[ 3 ].StoreToReference( ref, size )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) + // Stack: ... ... -> ... + { + // Treat STELEM like ldelema + stobj + ip += 2; // Skip type argument, not used... + + evalPos -= 3; // "pop" args from evaluation stack + CHECKSTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(evalPos[ 1 ].InitializeArrayReference( evalPos[ 1 ], evalPos[ 2 ].NumericByRef().s4 )); + evalPos[ 1 ].FixArrayReferenceForValueTypes(); + + // Reassign will make sure these are objects of the same type. + NANOCLR_CHECK_HRESULT(evalPos[ 1 ].Reassign( evalPos[ 3 ] )); + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) + { + FETCH_ARG_UINT32(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetObjectReference( NULL ); + + switch(CLR_TypeFromTk( arg )) + { + case TBL_TypeSpec: + { + CLR_RT_TypeSpec_Instance sig; if(sig.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( sig ); + } + break; + + case TBL_TypeRef: + case TBL_TypeDef: + { + CLR_RT_TypeDef_Instance cls; if(cls.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( cls ); + } + break; + + case TBL_FieldRef: + case TBL_FieldDef: + { + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( field ); + } + break; + + case TBL_MethodRef: + case TBL_MethodDef: + { + CLR_RT_MethodDef_Instance method; if(method.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( method ); + } + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + break; + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) + { + EMPTYSTACK(stack, evalPos); + WRITEBACK(stack,evalPos,ip,fDirty); + + NANOCLR_CHECK_HRESULT(th->ProcessException_EndFinally()); + + _ASSERTE(th->m_currentException.Dereference() == NULL); + stack = th->CurrentFrame(); + goto Execute_Reload; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) + OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) + { + CLR_INT32 arg; + + EMPTYSTACK(stack, evalPos); + + if(op == CEE_LEAVE) + { + NANOCLR_READ_UNALIGNED_INT16( arg, ip ); + } + else + { + NANOCLR_READ_UNALIGNED_INT8( arg, ip ); + } + + { + CLR_PMETADATA ipLeave = ip + arg; + CLR_RT_ExceptionHandler eh; + + th->PopEH( stack, ipLeave ); + + if(th->FindEhBlock( stack, ip-1, ipLeave, eh, true )) + { + UnwindStack* us = th->PushEH(); + _ASSERTE(us); + + us->m_stack = stack; + us->m_exception = NULL; + us->m_ip = ipLeave; + us->m_currentBlockStart = eh.m_handlerStart; + us->m_currentBlockEnd = eh.m_handlerEnd; + us->m_flags = UnwindStack::p_4_NormalCleanup; + + ip = eh.m_handlerStart; + break; + } + + ip = ipLeave; + + if(th->m_flags & CLR_RT_Thread::TH_F_Aborted) + { + _ASSERTE(th->m_currentException.Dereference() == NULL); + + (void)Library_corlib_native_System_Exception::CreateInstance( th->m_currentException, g_CLR_RT_WellKnownTypes.m_ThreadAbortException, S_OK, stack ); + + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 0 ], evalPos[ 1 ] ) == 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 0 ], evalPos[ 1 ] ) > 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 0 ], evalPos[ 1 ] ) > 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 0 ], evalPos[ 1 ] ) < 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 0 ], evalPos[ 1 ] ) < 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + CLR_RT_MethodDef_Instance method; if(method.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( evalPos[ 0 ], method, stack )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + CLR_RT_MethodDef_Instance callee; if(callee.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_TypeDef_Index cls; + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( evalPos[ 0 ], cls )); + + CLR_RT_MethodDef_Index calleeReal; + + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, callee, calleeReal ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + UPDATESTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( evalPos[ 0 ], calleeReal, stack )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) + { + ip += 2; // Skip argument, not used... + + evalPos->InitObject(); evalPos--; CHECKSTACK(stack,evalPos); + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) + { + if(th->m_nestedExceptionsPos == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_STACK_UNDERFLOW); + } + else + { + UnwindStack& us = th->m_nestedExceptions[ --th->m_nestedExceptionsPos ]; + + if(us.m_exception) + { + th->m_currentException.SetObjectReference( us.m_exception ); + + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_STACK_UNDERFLOW); + } + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_RT_TypeDef_Instance clsInst; if(clsInst.ResolveToken( arg, assm ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_INT32 len; + + if(clsInst.m_target->dataType) + { + len = sizeof(CLR_RT_HeapBlock); + } + else + { + len = (CLR_RT_HeapBlock::HB_Object_Fields_Offset + clsInst.CrossReference().m_totalFields) * sizeof(CLR_RT_HeapBlock); + } + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( len ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + //nop + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) + { + + CHECKSTACK(stack,evalPos); + WRITEBACK(stack,evalPos,ip,fDirty); + + NANOCLR_CHECK_HRESULT(th->ProcessException_EndFilter()); + + stack = th->CurrentFrame(); + goto Execute_Reload; + } + + //----------------------------------------------------------------------------------------------------------// + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // These opcodes do nothing... + // + OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) + OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) + OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) + OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) + break; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Unsupported opcodes... + // + OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) + OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) + OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) + OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) + OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) + OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) + OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) + OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) + OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) + OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) + OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) + + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyUnsupportedInstruction( op )); + break; + + ////////////////////////////////////////////////////////////////////////////////////////// + + default: + NANOCLR_CHECK_HRESULT(CLR_Checks::VerifyUnknownInstruction( op )); + break; +#undef OPDEF + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, ip ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + continue; + + //--// + + Execute_LoadAndPromote: + + { + CLR_RT_HeapBlock& res = evalPos[ 0 ]; + + switch(res.DataType()) + { + case DATATYPE_VOID : break; + + case DATATYPE_BOOLEAN : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u1; break; + case DATATYPE_I1 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().s4 = (CLR_INT32 )res.NumericByRef().s1; break; + case DATATYPE_U1 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u1; break; + + case DATATYPE_CHAR : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u2; break; + case DATATYPE_I2 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().s4 = (CLR_INT32 )res.NumericByRef().s2; break; + case DATATYPE_U2 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u2; break; + + case DATATYPE_I4 : break; + case DATATYPE_U4 : break; + case DATATYPE_R4 : break; + + case DATATYPE_I8 : break; + case DATATYPE_U8 : break; + case DATATYPE_R8 : break; + case DATATYPE_DATETIME: break; + case DATATYPE_TIMESPAN: break; + case DATATYPE_STRING : break; + + case DATATYPE_OBJECT : + if(evalPos[ 0 ].IsAValueType()) + { + UPDATESTACK(stack,evalPos); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( evalPos[ 0 ], evalPos[ 0 ] )); + } + break; + + // the remaining data types aren't to be handled + default: break; + } + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, ip ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + continue; + + //--// + + Execute_BR: + { + CLR_INT32 offset; + + if(c_CLR_RT_OpcodeLookup[ op ].m_opParam == CLR_OpcodeParam_ShortBrTarget) + { + NANOCLR_READ_UNALIGNED_INT8( offset, ip ); + } + else + { + NANOCLR_READ_UNALIGNED_INT16( offset, ip ); + } + + if(fCondition) ip += offset; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, ip ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(th->m_timeQuantumExpired) + { + NANOCLR_SET_AND_LEAVE( CLR_S_QUANTUM_EXPIRED ); + } + + continue; + } + + //--// + + Execute_Restart: + { + CLR_RT_StackFrame* stackNext = th->CurrentFrame(); + + #if defined(ENABLE_NATIVE_PROFILER) + if(stackNext->m_flags & CLR_RT_StackFrame::c_NativeProfiled) + { + stackNext->m_owningThread->m_fNativeProfiled = true; + Native_Profiler_Start(); + } + else if(stackNext->m_fNativeProfiled == false) + { + stackNext->m_owningThread->m_fNativeProfiled = false; + Native_Profiler_Stop(); + } + #endif + + if((stackNext->m_flags & CLR_RT_StackFrame::c_CallerIsCompatibleForCall) == 0) + { + NANOCLR_SET_AND_LEAVE( CLR_S_RESTART_EXECUTION ); + } + + // + // Same kind of handler, no need to pop back out, just restart execution in place. + // + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingIL; + + stack = stackNext; + goto Execute_Reload; + } + + Execute_Reload: + { + stack->m_flags |= CLR_RT_StackFrame::c_ExecutingIL; + + assm = stack->m_call.m_assm; + + READCACHE(stack,evalPos,ip,fDirty); + continue; + } + } + } + + + NANOCLR_CLEANUP(); + + if(fDirty) + { + WRITEBACK(stack,evalPos,ip,fDirty); + } + + NANOCLR_CLEANUP_END(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj new file mode 100644 index 00000000..e250c980 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {D32EE397-7E49-452D-AC95-AFCB3C962E3D} + Win32Proj + InterruptHandler + 10.0.17763.0 + InterruptHandler + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj.filters new file mode 100644 index 00000000..56780121 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler-vs2019.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.cpp b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.cpp new file mode 100644 index 00000000..feec3bef --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.cpp @@ -0,0 +1,147 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + //this method is called by Hardware_Initialize + //If you want to initialize your own interrupt handling related objects, put them here + +HRESULT CLR_HW_Hardware::ManagedHardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + m_interruptData.m_HalQueue.Initialize( (CLR_HW_Hardware::HalInterruptRecord*)&g_scratchInterruptDispatchingStorage, InterruptRecords() ); + + m_interruptData.m_applicationQueue.DblLinkedList_Initialize (); + + m_interruptData.m_queuedInterrupts = 0; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_HW_Hardware::SpawnDispatcher() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + CLR_RT_ApplicationInterrupt* interrupt; + CLR_RT_HeapBlock_NativeEventDispatcher* ioPort; + CLR_RT_HeapBlock_NativeEventDispatcher ::InterruptPortInterrupt *interruptData; + + // if reboot is in progress, just bail out + if(CLR_EE_DBG_IS( RebootPending )) + { + return S_OK; + } + + interrupt = (CLR_RT_ApplicationInterrupt*)m_interruptData.m_applicationQueue.FirstValidNode(); + + if((interrupt == NULL) || !g_CLR_RT_ExecutionEngine.EnsureSystemThread( g_CLR_RT_ExecutionEngine.m_interruptThread, ThreadPriority::System_Highest )) + { + return S_OK; + } + + interrupt->Unlink(); + + interruptData = &interrupt->m_interruptPortInterrupt; + ioPort = interruptData->context; + + CLR_RT_ProtectFromGC gc1 ( *ioPort ); + + NANOCLR_SET_AND_LEAVE(ioPort->StartDispatch( interrupt, g_CLR_RT_ExecutionEngine.m_interruptThread )); + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + ioPort->ThreadTerminationCallback( interrupt ); + } + + --m_interruptData.m_queuedInterrupts; + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_HW_Hardware::TransferAllInterruptsToApplicationQueue() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + while(true) + { + HalInterruptRecord* rec; + + { + GLOBAL_LOCK(); + + rec = m_interruptData.m_HalQueue.Peek(); + + GLOBAL_UNLOCK(); + } + + if(rec == NULL) break; + + CLR_RT_ApplicationInterrupt* queueRec = (CLR_RT_ApplicationInterrupt*)CLR_RT_Memory::Allocate_And_Erase( sizeof(CLR_RT_ApplicationInterrupt), CLR_RT_HeapBlock::HB_CompactOnFailure ); CHECK_ALLOCATION(queueRec); + + queueRec->m_interruptPortInterrupt.data1 = rec->m_data1; + queueRec->m_interruptPortInterrupt.data2 = rec->m_data2; + queueRec->m_interruptPortInterrupt.data3 = rec->m_data3; + queueRec->m_interruptPortInterrupt.time = rec->m_time; + queueRec->m_interruptPortInterrupt.context = (CLR_RT_HeapBlock_NativeEventDispatcher*)rec->m_context; + + m_interruptData.m_applicationQueue.LinkAtBack( queueRec ); ++m_interruptData.m_queuedInterrupts; + + { + GLOBAL_LOCK(); + + m_interruptData.m_HalQueue.Pop(); + + GLOBAL_UNLOCK(); + } + } + + if(m_interruptData.m_queuedInterrupts == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NO_INTERRUPT); + } + + NANOCLR_CLEANUP(); + + if(CLR_E_OUT_OF_MEMORY == hr) + { + // if there is no memory left discard all interrupts to avoid getting into a death spiral of OOM exceptions + { + GLOBAL_LOCK(); + + while(!m_interruptData.m_HalQueue.IsEmpty()) + { + m_interruptData.m_HalQueue.Pop(); + } + + GLOBAL_UNLOCK(); + } + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_HW_Hardware::ProcessInterrupts() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(TransferAllInterruptsToApplicationQueue()); + + SpawnDispatcher(); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj new file mode 100644 index 00000000..4d2c5fc3 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {D32EE397-7E49-452D-AC95-AFCB3C962E3D} + Win32Proj + InterruptHandler + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters new file mode 100644 index 00000000..56780121 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp new file mode 100644 index 00000000..83e44e2e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp @@ -0,0 +1,33 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak HRESULT CLR_HW_Hardware::ManagedHardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_SYSTEM_STUB_RETURN(); +} + +__nfweak HRESULT CLR_HW_Hardware::SpawnDispatcher() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_SYSTEM_STUB_RETURN(); + +} + +__nfweak HRESULT CLR_HW_Hardware::TransferAllInterruptsToApplicationQueue() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_SYSTEM_STUB_RETURN(); +} + +__nfweak HRESULT CLR_HW_Hardware::ProcessInterrupts() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_SYSTEM_STUB_RETURN(); +} diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj new file mode 100644 index 00000000..5216874f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {5772D362-7277-49CF-9B49-42335A3154BD} + Win32Proj + InterruptHandler_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters new file mode 100644 index 00000000..9dc77bab --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.cpp b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.cpp new file mode 100644 index 00000000..198de873 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.cpp @@ -0,0 +1,289 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_DblLinkedList CLR_RT_HeapBlock_NativeEventDispatcher::eventList; + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_Initialize() +{ + NATIVE_PROFILE_CLR_IOPORT(); + + CLR_RT_HeapBlock_NativeEventDispatcher::eventList.DblLinkedList_Initialize(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_NativeEventDispatcher, event, CLR_RT_HeapBlock_NativeEventDispatcher::eventList) + { + event->RecoverFromGC(); + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_CleanUp() +{ + NATIVE_PROFILE_CLR_IOPORT(); + + CLR_RT_HeapBlock_NativeEventDispatcher* event; + + while(NULL != (event = (CLR_RT_HeapBlock_NativeEventDispatcher*)CLR_RT_HeapBlock_NativeEventDispatcher::eventList.FirstValidNode())) + { + if(event->driverMethods != NULL) + { + event->driverMethods->cleanupProcessor(event); + } + + event->DetachAll(); + event->ReleaseWhenDeadEx(); + } +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::CreateInstance( CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& eventRef ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher* event = NULL; + + event = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_NativeEventDispatcher,DATATYPE_IO_PORT); CHECK_ALLOCATION(event); + + { + + CLR_RT_ProtectFromGC gc( *event ); + + event->Initialize(); + + eventList.LinkAtBack( event ); + + NANOCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( event, owner, eventRef )); + + } + + // Set pointer to driver custom data to NULL. It initialized later by users of CLR_RT_HeapBlock_NativeEventDispatcher + event->pDrvCustomData = NULL; + // Set pointers to drivers methods to NULL. + event->driverMethods = NULL; + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(event) + { + event->ReleaseWhenDead(); + } + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_NativeEventDispatcher*& event ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + + NANOCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* src = CLR_RT_ObjectToEvent_Source::ExtractInstance( ref ); FAULT_ON_NULL(src); + + event = (CLR_RT_HeapBlock_NativeEventDispatcher*)src->m_eventPtr; + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); + + CheckAll(); + + ReleaseWhenDeadEx(); +} + +bool CLR_RT_HeapBlock_NativeEventDispatcher::ReleaseWhenDeadEx() +{ + NATIVE_PROFILE_CLR_IOPORT(); + + if(!IsReadyForRelease()) return false; + + //remove any queued interrupts for this event + NANOCLR_FOREACH_NODE(CLR_RT_ApplicationInterrupt,interrupt,g_CLR_HW_Hardware.m_interruptData.m_applicationQueue) + { + if(this == interrupt->m_interruptPortInterrupt.context) + { + interrupt->Unlink(); + + --g_CLR_HW_Hardware.m_interruptData.m_queuedInterrupts; + + ThreadTerminationCallback( interrupt ); + } + } + NANOCLR_FOREACH_NODE_END(); + + return ReleaseWhenDead(); +} + +/************************************************************************************************************ +** Iterates over HAL queue and remove records that point to this instance of CLR_RT_HeapBlock_NativeEventDispatcher. +** This operation should be done from Dispose as part of destroying the CLR_RT_HeapBlock_NativeEventDispatcher +** +*************************************************************************************************************/ + +void CLR_RT_HeapBlock_NativeEventDispatcher::RemoveFromHALQueue() +{ + // Since we are going to analyze and update the queue we need to disable interrupts. + // Interrupt service routines add records to this queue. + GLOBAL_LOCK(); + CLR_UINT32 elemCount = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.NumberOfElements(); + GLOBAL_UNLOCK(); + + // For all elements in the queue + for ( CLR_UINT32 curElem = 0; curElem < elemCount; curElem++ ) + { + // Retrieve the element ( actually remove it from the queue ) + GLOBAL_LOCK(); + CLR_HW_Hardware::HalInterruptRecord* testRec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Pop(); + GLOBAL_UNLOCK(); + + // Check if context of this record points to the instance of CLR_RT_HeapBlock_NativeEventDispatcher + // If the "context" is the same as "this", then we skip the "Push" and record is removed. + if ( testRec->m_context != this ) + { + // If it is different from this instance of CLR_RT_HeapBlock_NativeEventDispatcher, thin push it back + GLOBAL_LOCK(); + CLR_HW_Hardware::HalInterruptRecord* newRec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Push(); + GLOBAL_UNLOCK(); + + newRec->AssignFrom( *testRec ); + } + } +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::SaveToHALQueue( uint32_t data1, uint32_t data2 ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + + CLR_HW_Hardware::HalInterruptRecord* rec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Push(); + + if(rec == NULL) + { + // remove the oldest interrupt to make room for the newest + g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Pop(); + + rec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Push(); + } + + if(rec) + { + rec->m_data1 = data1; + rec->m_data2 = data2; + rec->m_context = this; + rec->m_time = HAL_Time_CurrentTime(); + } + + ::Events_Set( SYSTEM_EVENT_HW_INTERRUPT ); +} + +void SaveNativeEventToHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, uint32_t data1, uint32_t data2 ) +{ + pContext->SaveToHALQueue( data1, data2 ); +} + +void CleanupNativeEventsFromHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +{ + pContext->RemoveFromHALQueue(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::StartDispatch( CLR_RT_ApplicationInterrupt* appInterrupt, CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + + NANOCLR_HEADER(); + + CLR_RT_StackFrame* stackTop; + CLR_RT_HeapBlock* args; + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock* event; + const CLR_UINT64 c_UTCMask = 0x8000000000000000ULL; + + InterruptPortInterrupt& interrupt = appInterrupt->m_interruptPortInterrupt; + + NANOCLR_CHECK_HRESULT(RecoverManagedObject( event )); + dlg = event[ Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::FIELD__threadSpawn ].DereferenceDelegate(); FAULT_ON_NULL(dlg); + + NANOCLR_CHECK_HRESULT(th->PushThreadProcDelegate( dlg )); + + stackTop = th->CurrentFrame(); + + args = stackTop->m_arguments; + + if((stackTop->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + ++args; + } + + // + // set values for delegate arguments + // + args[0].SetInteger ( interrupt.data1 ); + args[1].SetInteger ( interrupt.data2 ); + args[2].SetInteger ( (CLR_UINT64)interrupt.time | c_UTCMask ); + args[2].ChangeDataType( DATATYPE_DATETIME ); + + th->m_terminationCallback = CLR_RT_HeapBlock_NativeEventDispatcher::ThreadTerminationCallback; + th->m_terminationParameter = appInterrupt; + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::ThreadTerminationCallback( void* arg ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + + CLR_RT_ApplicationInterrupt* appInterrupt = (CLR_RT_ApplicationInterrupt*)arg; + CLR_RT_HeapBlock_NativeEventDispatcher::InterruptPortInterrupt& interrupt = appInterrupt->m_interruptPortInterrupt; + + FreeManagedEvent((interrupt.data1 >> 8) & 0xff, //category + (interrupt.data1 ) & 0xff, //subCategory + interrupt.data1 >> 16 , //data1 + interrupt.data2 ); + + interrupt.data1 = 0; + interrupt.data2 = 0; + + CLR_RT_Memory::Release( appInterrupt ); + + g_CLR_HW_Hardware.SpawnDispatcher(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::RecoverManagedObject( CLR_RT_HeapBlock*& event ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + + NANOCLR_HEADER(); + + // recover the managed object + NANOCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,this->m_references) + { + if(ref->m_objectPtr) + { + event = ref->m_objectPtr; + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + NANOCLR_FOREACH_NODE_END(); + + event = NULL; + + NANOCLR_SET_AND_LEAVE(CLR_E_PIN_DEAD); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj new file mode 100644 index 00000000..0874202a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2} + Win32Proj + NativeEventDispatcher + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include;..\..\..\nanoFramework.Runtime.Events + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include;..\..\..\nanoFramework.Runtime.Events + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj.filters new file mode 100644 index 00000000..2c106a47 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.cpp b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.cpp new file mode 100644 index 00000000..1f739010 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.cpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_Initialize() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_CleanUp() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak void SaveNativeEventToHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, uint32_t data1, uint32_t data2 ) +{ + (void)pContext; + (void)data1; + (void)data2; + + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak void CleanupNativeEventsFromHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +{ + (void)pContext; + + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::CreateInstance( CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& portRef ) +{ + (void)owner; + (void)portRef; + + NATIVE_PROFILE_CLR_IOPORT(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_NativeEventDispatcher*& port ) +{ + (void)ref; + (void)port; + + NATIVE_PROFILE_CLR_IOPORT(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak void CLR_RT_HeapBlock_NativeEventDispatcher::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak bool CLR_RT_HeapBlock_NativeEventDispatcher::ReleaseWhenDeadEx() +{ + NATIVE_PROFILE_CLR_IOPORT(); + return true; +} + +__nfweak void CLR_RT_HeapBlock_NativeEventDispatcher::RemoveFromHALQueue() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak void CLR_RT_HeapBlock_NativeEventDispatcher::SaveToHALQueue( uint32_t data1, uint32_t data2 ) +{ + (void)data1; + (void)data2; + + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::StartDispatch( CLR_RT_ApplicationInterrupt* appInterrupt, CLR_RT_Thread* th ) +{ + (void)appInterrupt; + (void)th; + + NATIVE_PROFILE_CLR_IOPORT(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak void CLR_RT_HeapBlock_NativeEventDispatcher::ThreadTerminationCallback( void* arg ) +{ + (void)arg; + + NATIVE_PROFILE_CLR_IOPORT(); +} + +__nfweak HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::RecoverManagedObject( CLR_RT_HeapBlock*& port ) +{ + (void)port; + + NATIVE_PROFILE_CLR_IOPORT(); + NANOCLR_FEATURE_STUB_RETURN(); +} diff --git a/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj new file mode 100644 index 00000000..657d659a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {5406EB0C-2243-47E1-9F21-F2D7CA277092} + Win32Proj + NativeEventDispatcher_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj.filters new file mode 100644 index 00000000..de337611 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/NativeEventDispatcher/NativeEventDispatcher_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp b/source/native/nf-interpreter/src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp new file mode 100644 index 00000000..a529b6f8 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp @@ -0,0 +1,130 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +CLR_RT_DblLinkedList CLR_RT_HeapBlock_EndPoint::m_endPoints; + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_Initialize() +{ + CLR_RT_HeapBlock_EndPoint::m_endPoints.DblLinkedList_Initialize(); +} + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_RecoverFromGC() +{ + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_EndPoint,endPoint,CLR_RT_HeapBlock_EndPoint::m_endPoints) + { + endPoint->RecoverFromGC(); + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_CleanUp() +{ +} + +CLR_RT_HeapBlock_EndPoint* CLR_RT_HeapBlock_EndPoint::FindEndPoint( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_EndPoint,endPoint,CLR_RT_HeapBlock_EndPoint::m_endPoints) + { + if((endPoint->m_addr.m_type == port.m_type) && (endPoint->m_addr.m_id == port.m_id)) return endPoint; //eliminate the need for another func. call; member variables are public + } + NANOCLR_FOREACH_NODE_END(); + + return NULL; +} + +bool CLR_RT_HeapBlock_EndPoint::Port::Compare( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + return m_type == port.m_type && m_id == port.m_id; +} + +//--// + +HRESULT CLR_RT_HeapBlock_EndPoint::CreateInstance( const CLR_RT_HeapBlock_EndPoint::Port& port, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& epRef ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_EndPoint* endPoint = NULL; + + // + // Create a request and stop the calling thread. + // + endPoint = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_EndPoint,DATATYPE_ENDPOINT_HEAD); CHECK_ALLOCATION(endPoint); + + { + CLR_RT_ProtectFromGC gc( *endPoint ); + + endPoint->Initialize(); + + endPoint->m_seq = 0; + endPoint->m_addr = port; + + endPoint->m_messages.DblLinkedList_Initialize(); + + CLR_RT_HeapBlock_EndPoint::m_endPoints.LinkAtBack( endPoint ); + + NANOCLR_SET_AND_LEAVE(CLR_RT_ObjectToEvent_Source::CreateInstance( endPoint, owner, epRef )); + } + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(endPoint) endPoint->ReleaseWhenDeadEx(); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_HeapBlock_EndPoint::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_EndPoint*& endPoint ) +{ + NANOCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* src = CLR_RT_ObjectToEvent_Source::ExtractInstance( ref ); FAULT_ON_NULL(src); + + endPoint = (CLR_RT_HeapBlock_EndPoint*)src->m_eventPtr; + + NANOCLR_NOCLEANUP(); +} + +bool CLR_RT_HeapBlock_EndPoint::ReleaseWhenDeadEx() +{ + if(!IsReadyForRelease()) return false; + + m_messages.DblLinkedList_Release(); + + return ReleaseWhenDead(); +} + +//--// + +void CLR_RT_HeapBlock_EndPoint::RecoverFromGC() +{ + CheckAll(); + + ReleaseWhenDeadEx(); +} + +//--// + +CLR_RT_HeapBlock_EndPoint::Message* CLR_RT_HeapBlock_EndPoint::FindMessage( CLR_UINT32 cmd, const CLR_UINT32* seq ) +{ + NANOCLR_FOREACH_NODE(Message,msg,m_messages) + { + if(msg->m_cmd == cmd) + { + if(!seq ) return msg; + if(msg->m_addr.m_seq == *seq) return msg; + } + } + NANOCLR_FOREACH_NODE_END(); + + return NULL; +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj new file mode 100644 index 00000000..595bc5e5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {ED4C887A-EC09-465B-B5D9-075450ADC52D} + Win32Proj + RPC + 10.0.17763.0 + RPC + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj.filters new file mode 100644 index 00000000..b7ad3836 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC-vs2019.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj new file mode 100644 index 00000000..16f7a84e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {ED4C887A-EC09-465B-B5D9-075450ADC52D} + Win32Proj + RPC + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj.filters new file mode 100644 index 00000000..b7ad3836 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.cpp b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.cpp new file mode 100644 index 00000000..e0632f9b --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +__nfweak void CLR_RT_HeapBlock_EndPoint::HandlerMethod_Initialize() +{ +} + +__nfweak void CLR_RT_HeapBlock_EndPoint::HandlerMethod_RecoverFromGC() +{ +} + +__nfweak void CLR_RT_HeapBlock_EndPoint::HandlerMethod_CleanUp() +{ +} + +__nfweak CLR_RT_HeapBlock_EndPoint* CLR_RT_HeapBlock_EndPoint::FindEndPoint( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + (void)port; + + return NULL; +} + +__nfweak bool CLR_RT_HeapBlock_EndPoint::Port::Compare( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + (void)port; + + return false; +} + +//--// + +__nfweak HRESULT CLR_RT_HeapBlock_EndPoint::CreateInstance( const CLR_RT_HeapBlock_EndPoint::Port& port, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& epRef ) +{ + (void)port; + (void)owner; + (void)epRef; + + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_HeapBlock_EndPoint::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_EndPoint*& endPoint ) +{ + (void)ref; + (void)endPoint; + + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak bool CLR_RT_HeapBlock_EndPoint::ReleaseWhenDeadEx() +{ + return true; +} + +//--// + +__nfweak void CLR_RT_HeapBlock_EndPoint::RecoverFromGC() +{ +} + +//--// + +__nfweak CLR_RT_HeapBlock_EndPoint::Message* CLR_RT_HeapBlock_EndPoint::FindMessage( CLR_UINT32 cmd, const CLR_UINT32* seq ) +{ + (void)cmd; + (void)seq; + + return NULL; +} diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj new file mode 100644 index 00000000..6fd7ea13 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {D0B2ADFE-3347-4D73-9364-9C36935D12F8} + Win32Proj + RPC_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj.filters new file mode 100644 index 00000000..a1ac8e56 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/RPC/RPC_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Random.cpp b/source/native/nf-interpreter/src/CLR/Core/Random.cpp new file mode 100644 index 00000000..bb1dd1ec --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Random.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +__nfweak void CLR_RT_Random::Initialize() +{ + CLR_INT64 st = HAL_Time_CurrentTime(); + + srand((unsigned int)st); +} + +__nfweak void CLR_RT_Random::Initialize( int seed ) +{ + srand(seed); +} + +__nfweak uint32_t CLR_RT_Random::Next() +{ + return rand(); +} + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + +__nfweak double CLR_RT_Random::NextDouble() +{ + // Next() will return value between 0 - 0x7FFFFFFF (inclusive) + return ((double)rand()) / ((double)0x7FFFFFFF); +} +#else + +__nfweak CLR_INT64 CLR_RT_Random::NextDouble() +{ + // Next() will return value between 0 - 0x7FFFFFFF (inclusive) + + return ((CLR_INT64 )rand() ) / ((CLR_INT64)0x7FFFFFFF >> CLR_RT_HeapBlock::HB_DoubleShift); +} + +#endif + +__nfweak void CLR_RT_Random::NextBytes( unsigned char* buffer, unsigned int count ) +{ + unsigned int i; + + for(i = 0; i < count; i++) + { + buffer[i] = (unsigned char)rand(); + } +} diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter.cpp b/source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter.cpp new file mode 100644 index 00000000..4e52dbed --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter.cpp @@ -0,0 +1,2016 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//this method simply informs if Serialization is enabled +//the stub version of this method returns False +bool CLR_RT_BinaryFormatter::SerializationEnabled() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return true; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixDereference( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (v && v->DataType() == DATATYPE_OBJECT) ? v->Dereference() : v; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixNull( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + if(v && v->DataType() == DATATYPE_OBJECT && v->Dereference() == NULL) return NULL; + + return v; +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::TypeHandler_Initialize( CLR_RT_BinaryFormatter* bf, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* expected ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + NANOCLR_CLEAR(*this); + + m_bf = bf; + + if(hints) + { + m_hints = *hints; + } + + if(expected) + { + m_typeExpected = &m_typeExpected_tmp; + + *m_typeExpected = *expected; + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::SetValue( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + m_value = NULL; + m_type = NULL; + + v = TypeHandler::FixNull( v ); + if(v) + { + m_value = &m_value_tmp; + m_type = &m_type_tmp; + + m_value->Assign( *v ); + + NANOCLR_CHECK_HRESULT(m_type->InitializeFromObject( *v )); + +#if defined(NANOCLR_APPDOMAINS) + if(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) + { + //MarshalByRefObjects are special for the AppDomain marshaler, and need to get marshaled regardless of whether or not they + //are serializable + + if((m_type->m_handlerCls.CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject) || + m_value->IsTransparentProxy()) + { + m_fIsMarshalByRefObject = true; + } + } + +#endif + + if((m_type->m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Serializable) == 0) + { +#if defined(NANOCLR_APPDOMAINS) + + if(m_fIsMarshalByRefObject) NANOCLR_SET_AND_LEAVE(S_OK); + + //For marshaling, we want to throw an exception if we can't correctly marshal an object across AD boundaries + //In fact, this should probably be turned on for all serialization, but I don't know what other implications that + //would have + + if(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) + { + NANOCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + } +#endif + m_value = NULL; + m_type = NULL; + } + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +int CLR_RT_BinaryFormatter::TypeHandler::SignatureRequirements() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + int res = c_Signature_Header | c_Signature_Type | c_Signature_Length; + CLR_RT_TypeDescriptor* td; + CLR_RT_TypeDescriptor sub; + + if(m_hints.m_arraySize != 0) + { + res &= ~c_Signature_Length; + } + + m_typeForced = NULL; + + if(m_typeExpected != NULL) + { + switch(m_typeExpected->m_flags) + { + case CLR_RT_DataTypeLookup::c_Primitive: + case CLR_RT_DataTypeLookup::c_Enum : + case CLR_RT_DataTypeLookup::c_ValueType: + res = 0; + break; + + default: + if(m_hints.m_flags & SF_FixedType) + { + res &= ~c_Signature_Type; + break; + } + + if(m_typeExpected->m_flags & CLR_RT_DataTypeLookup::c_Array) + { + sub.InitializeFromType( m_typeExpected->m_reflex.m_data.m_type ); + + td = ⊂ + } + else + { + td = m_typeExpected; + } + + if(td->m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Sealed) + { + res &= ~c_Signature_Type; + break; + } + } + } + + if((res & c_Signature_Type) == 0) + { + m_typeForced = &m_typeForced_tmp; + *m_typeForced = *m_typeExpected; + + if(m_hints.m_flags & SF_PointerNeverNull) + { + res &= ~c_Signature_Header; + } + } + + return res; +} + +bool CLR_RT_BinaryFormatter::TypeHandler::CompareTypes( CLR_RT_TypeDescriptor* left, CLR_RT_TypeDescriptor* right ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + if(!left && !right) return true; + if(!left || !right) return false; + + return memcmp( left, right, sizeof(*left) ) == 0; +} + +CLR_DataType CLR_RT_BinaryFormatter::TypeHandler::GetDataType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (CLR_DataType)type->m_handlerCls.m_target->dataType; +} + +CLR_UINT32 CLR_RT_BinaryFormatter::TypeHandler::GetSizeOfType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return c_CLR_RT_DataTypeLookup[ type->GetDataType() ].m_sizeInBits; +} + +bool CLR_RT_BinaryFormatter::TypeHandler::GetSignOfType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (c_CLR_RT_DataTypeLookup[ type->GetDataType() ].m_flags & CLR_RT_DataTypeLookup::c_Signed) != 0; +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_UINT32 idx; + int mask = SignatureRequirements(); + + if((mask & c_Signature_Type) == 0) + { + if(m_type && CompareTypes( m_type, m_typeForced ) == false) + { + while(true) + { + if(m_typeForced->m_flags == CLR_RT_DataTypeLookup::c_Enum) + { + break; + } + + if(m_typeForced->m_handlerCls.IsATypeHandler() && + m_type ->m_handlerCls.IsATypeHandler() ) + { + break; + } + + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + } + + if(m_value == NULL) + { + if(mask == 0) + { + // + // Special case for null strings (strings don't emit an hash): send a string of length -1. + // + if(m_typeExpected->GetDataType() == DATATYPE_STRING) + { + + NANOCLR_CHECK_HRESULT(m_bf->WriteCompressedUnsigned( 0xFFFFFFFF )); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Null, TE_L1 )); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + + //--// + +#if defined(NANOCLR_APPDOMAINS) + if(m_fIsMarshalByRefObject) + { + CLR_RT_HeapBlock* valPtr = m_value->Dereference(); + + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other, TE_L1 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Other, TE_L2 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L3_MBRO , TE_L3 )); + + { + /* + The bit stream contains pointers to the MBRO and its AppDomain. Only the header is used, and no + duplicate detection is necessary -- all proxies pointing at the same object are equal. + which will get marshaled into either a proxy or MBRO, depending on the destination AppDomain. + Live pointers are stored, but this is ok since it is for marshaling only. The objects cannot + can collected during a GC due to the live object that is being marshaled. + */ + + _ASSERTE(CLR_EE_DBG_IS(NoCompaction)); + + CLR_RT_HeapBlock* ptr; + CLR_RT_AppDomain* appDomain; + + if(valPtr->DataType() == DATATYPE_TRANSPARENT_PROXY) + { + ptr = valPtr->TransparentProxyDereference(); + appDomain = valPtr->TransparentProxyAppDomain (); + } + else + { + ptr = valPtr; + appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + } + + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)ptr, 32)); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)appDomain, 32)); + } + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } +#endif + + idx = m_bf->SearchDuplicate( m_value ); + if(idx != (CLR_UINT32)-1) + { + // + // No duplicates allowed for fixed-type objects. + // + if((mask & c_Signature_Header) == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + NANOCLR_CHECK_HRESULT(m_bf->WriteBits ( TE_L1_Duplicate, TE_L1 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteCompressedUnsigned( idx )); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + + //--// + + NANOCLR_CHECK_HRESULT(EmitSignature_Inner( mask, m_type, m_value )); + + res = c_Action_ObjectData; NANOCLR_SET_AND_LEAVE(S_OK); + + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature_Inner( int mask, CLR_RT_TypeDescriptor* type, CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + // Unbox reflection types + if(value && value->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* pObj = value->Dereference(); + + if(pObj && pObj->DataType() == DATATYPE_REFLECTION) + { + value = pObj; + } + } + + if(value && value->DataType() == DATATYPE_REFLECTION) + { + switch(value->ReflectionDataConst().m_kind) + { + case REFLECTION_TYPE: + case REFLECTION_TYPE_DELAYED: + if((mask & c_Signature_Header) != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other, TE_L1 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Other, TE_L2 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L3_Type , TE_L3 )); + } + break; + +#if defined(NANOCLR_APPDOMAINS) + case REFLECTION_ASSEMBLY: + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + case REFLECTION_FIELD: + if((m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) == 0) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + if((mask & c_Signature_Header) != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other , TE_L1 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Other , TE_L2 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L3_Reflection, TE_L3 )); + } + break; +#endif + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else if(value && (type->m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList))) + { + CLR_RT_HeapBlock_Array* array; + int sizeReal = -1; + + if(type->m_flags & CLR_RT_DataTypeLookup::c_Array) + { + + if((mask & c_Signature_Header) != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other, TE_L1 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Array, TE_L2 )); + } + + if((mask & c_Signature_Type) != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)type->m_reflex.m_levels, TE_ArrayDepth )); + + CLR_RT_TypeDescriptor typeSub; typeSub.InitializeFromType( type->m_reflex.m_data.m_type ); + + NANOCLR_CHECK_HRESULT(EmitSignature_Inner( c_Signature_Header | c_Signature_Type, &typeSub, NULL )); + } + + + sizeReal = value->DereferenceArray()->m_numOfElements; + } + else + { + int capacity; + + if((mask & c_Signature_Header) != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other , TE_L1 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_ArrayList, TE_L2 )); + } + + NANOCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( *value, array, sizeReal, capacity )); + } + + if((mask & c_Signature_Length) != 0) + { + int bitsMax = m_hints.m_bitPacked; + + if(bitsMax != 0) + { + if(sizeReal >= (1 << bitsMax)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + NANOCLR_SET_AND_LEAVE(m_bf->WriteBits( (CLR_UINT32)sizeReal, bitsMax )); + } + else + { + NANOCLR_SET_AND_LEAVE(m_bf->WriteCompressedUnsigned( (CLR_UINT32)sizeReal )); + } + } + else + { + int sizeExpected = m_hints.m_arraySize; + + if(sizeExpected > 0 && sizeExpected != sizeReal) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + } + else if(type->m_flags == CLR_RT_DataTypeLookup::c_Primitive || + type->m_flags == CLR_RT_DataTypeLookup::c_Enum ) + { + if((mask & c_Signature_Header) != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other , TE_L1 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Primitive, TE_L2 )); + } + + if((mask & c_Signature_Type) != 0) + { + NANOCLR_SET_AND_LEAVE(m_bf->WriteBits( CLR_RT_TypeSystem::MapDataTypeToElementType( type->GetDataType() ), TE_ElementType )); + } + } + else + { + if((mask & c_Signature_Header) != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Reference, TE_L1 )); + } + + if((mask & c_Signature_Type) != 0) + { + NANOCLR_SET_AND_LEAVE(m_bf->WriteType( type->m_handlerCls.CrossReference().m_hash )); + } + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadSignature( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + int mask = SignatureRequirements(); + + m_value = NULL; + m_type = NULL; + + if(m_typeForced) + { + m_type = &m_type_tmp; + + *m_type = *m_typeForced; + } + + if((mask & c_Signature_Header) != 0) + { + CLR_UINT32 levelOne; + CLR_UINT32 levelTwo; + CLR_UINT32 levelThree; + + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( levelOne, TE_L1 )); + + if(levelOne == TE_L1_Null) + { + if(m_hints.m_flags & SF_PointerNeverNull) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(levelOne == TE_L1_Duplicate) + { + CLR_RT_HeapBlock* dup; + CLR_UINT32 idx; + + NANOCLR_CHECK_HRESULT(m_bf->ReadCompressedUnsigned( idx )); + + dup = m_bf->GetDuplicate( idx ); + if(dup == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + m_value = &m_value_tmp; + m_value->SetObjectReference( dup ); + + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromObject( *m_value )); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(levelOne == TE_L1_Reference) + { + if((mask & c_Signature_Type) != 0) + { + CLR_RT_ReflectionDef_Index idx; + + NANOCLR_CHECK_HRESULT(m_bf->ReadType( idx )); + + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromReflection( idx )); + } + } + else + { + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( levelTwo, TE_L2 )); + if(levelTwo == TE_L2_Primitive) + { + if((mask & c_Signature_Type) != 0) + { + CLR_UINT32 et; + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( et, TE_ElementType )); + + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromDataType( CLR_RT_TypeSystem::MapElementTypeToDataType( et ) )); + } + } + else if(levelTwo == TE_L2_Array) + { + if((mask & c_Signature_Type) != 0) + { + CLR_UINT32 depth; + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( depth, TE_ArrayDepth )); + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( levelOne, TE_L1 )); + + if(levelOne == TE_L1_Reference) + { + CLR_RT_ReflectionDef_Index idx; + + NANOCLR_CHECK_HRESULT(m_bf->ReadType( idx )); + + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromReflection( idx )); + } + else if(levelOne == TE_L1_Other) + { + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( levelTwo, TE_L2 )); + + if(levelTwo == TE_L2_Primitive) + { + CLR_UINT32 et; + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( et, TE_ElementType )); + + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromDataType( CLR_RT_TypeSystem::MapElementTypeToDataType( et ) )); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_BADSTREAM); + } + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_BADSTREAM); + } + + m_type->m_reflex.m_levels = depth; + m_type->ConvertToArray(); + } + } + else if(levelTwo == TE_L2_ArrayList) + { + if((mask & c_Signature_Type) != 0) + { + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromType( g_CLR_RT_WellKnownTypes.m_ArrayList )); + } + } + else if(levelTwo == TE_L2_Other) + { + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( levelThree, TE_L3 )); + if(levelThree == TE_L3_Type) + { + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromType( g_CLR_RT_WellKnownTypes.m_Type )); + } +#if defined(NANOCLR_APPDOMAINS) + else if (levelThree == TE_L3_Reflection) + { + CLR_RT_ReflectionDef_Index value; + CLR_UINT64 data; + + _ASSERTE(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal); + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( data, 64 )); + + value.SetRawData( data ); + + m_value = &m_value_tmp; + NANOCLR_CHECK_HRESULT(m_value->SetReflection( value )); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + else if (levelThree == TE_L3_MBRO) + { + CLR_UINT32 uintPtr; + CLR_UINT32 uintAppDomain; + CLR_RT_HeapBlock* ptr; + CLR_RT_AppDomain* appDomain; + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( uintPtr , 32 )); + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( uintAppDomain, 32 )); + + _ASSERTE(CLR_EE_DBG_IS( NoCompaction )); + + ptr = (CLR_RT_HeapBlock*)(size_t)uintPtr; + appDomain = (CLR_RT_AppDomain*)(size_t)uintAppDomain; + + m_type = &m_type_tmp; + NANOCLR_CHECK_HRESULT(m_type->InitializeFromObject( *ptr )); + + m_value = &m_value_tmp; + if(appDomain != g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()) + { + //The MarshalByRefObject lives in a separate AppDomain. + //We need to allocate a TRANSPARENT_PROXY object on the stack + + CLR_RT_HeapBlock* proxy = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForObjects( DATATYPE_TRANSPARENT_PROXY, 0, 1 ); CHECK_ALLOCATION(proxy); + + proxy->SetTransparentProxyReference( appDomain, ptr ); + + ptr = proxy; + } + + //Set the value reference to either the MBRO, or the proxy + m_value->SetObjectReference( ptr ); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } +#endif + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_BADSTREAM); + } + } + } + } + + if(m_type->m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList)) + { + CLR_UINT32 len; + + if(mask & c_Signature_Length) + { + int bitsMax = m_hints.m_bitPacked; + + if(bitsMax != 0) + { + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( len, bitsMax )); + } + else + { + NANOCLR_CHECK_HRESULT(m_bf->ReadCompressedUnsigned( len )); + } + } + else + { + CLR_RT_TypeDescriptor sub; + + if(m_type->m_reflex.m_levels != 1) + { + // + // Only simple arrays can have variable size. + // + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + sub.InitializeFromType( m_type->m_reflex.m_data.m_type ); + + len = m_hints.m_arraySize; + + if(len == (CLR_UINT32)-1) + { + len = m_bf->BitsAvailable(); + + switch(TypeHandler::GetSizeOfType( &sub )) + { + case 1: break; + case 8: len /= 8; break; + case 16: len /= 16; break; + case 32: len /= 32; break; + case 64: len /= 64; break; + default: + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + + if(m_type->m_flags & CLR_RT_DataTypeLookup::c_ArrayList) + { + CLR_RT_HeapBlock_Array* array; + + m_value = &m_value_tmp; + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewArrayList( *m_value, len, array )); + } + else + { + m_value = &m_value_tmp; + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( *m_value, len, m_type->m_reflex )); + } + } + else + { + m_value = &m_value_tmp; + + if(m_type->m_handlerCls.IsATypeHandler()) + { + CLR_RT_ReflectionDef_Index idx; + + NANOCLR_CHECK_HRESULT(m_bf->ReadType( idx )); + + NANOCLR_CHECK_HRESULT(m_value->SetReflection( idx )); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObject( *m_value, m_type->m_handlerCls )); + } + + res = c_Action_ObjectData; NANOCLR_SET_AND_LEAVE(S_OK); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitValue( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* value = m_value->FixBoxingReference(); + CLR_UINT64 val; + CLR_UINT32 bits; + bool fSigned; + + // unbox reflection types + if(value->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* obj = value->Dereference(); + + if(obj && obj->DataType() == DATATYPE_REFLECTION) + { + value = obj; + } + } + + if(value->DataType() == DATATYPE_REFLECTION) + { + switch(value->ReflectionDataConst().m_kind) + { + case REFLECTION_TYPE: + case REFLECTION_TYPE_DELAYED: + NANOCLR_CHECK_HRESULT(m_bf->WriteType( value->ReflectionDataConst() )); + break; +#if defined(NANOCLR_APPDOMAINS) + case REFLECTION_ASSEMBLY: + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + case REFLECTION_FIELD: + { + CLR_UINT64 data; + + _ASSERTE(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal); + + data = value->ReflectionDataConst().GetRawData(); + + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( data, 64 )); + } + break; +#endif + } + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_DateTime.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_DateTime::GetValuePtr( *value ); FAULT_ON_NULL(pVal); + + val = *(CLR_UINT64*)pVal; + bits = 64; + fSigned = false; + } + else if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_TimeSpan.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( *value ); FAULT_ON_NULL(pVal); + + val = *(CLR_UINT64*)pVal; + bits = 64; + fSigned = true; + } + else if(m_type->m_flags == CLR_RT_DataTypeLookup::c_Primitive || + m_type->m_flags == CLR_RT_DataTypeLookup::c_Enum ) + { + bits = TypeHandler::GetSizeOfType( m_type ); + if(bits == CLR_RT_DataTypeLookup::c_VariableSize) + { + const char* szText = value->RecoverString(); + CLR_UINT32 len = szText ? (CLR_UINT32)hal_strlen_s( szText ) : 0xFFFFFFFF; + + NANOCLR_CHECK_HRESULT(m_bf->WriteCompressedUnsigned( len )); + + if(len != (CLR_UINT32)-1) + { + NANOCLR_CHECK_HRESULT(m_bf->WriteArray( (CLR_UINT8*)szText, len )); + } + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + else if(bits == CLR_RT_DataTypeLookup::c_NA) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_HeapBlock* v = FixDereference( value ); FAULT_ON_NULL(v); + + val = v->NumericByRefConst().u8; + + fSigned = TypeHandler::GetSignOfType( m_type ); + } + +#if defined(NANOCLR_APPDOMAINS) + else if(m_fIsMarshalByRefObject) + { + CLR_RT_HeapBlock* valPtr = value->Dereference(); + CLR_RT_AppDomain* appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + + if(valPtr->DataType() == DATATYPE_TRANSPARENT_PROXY) + { + appDomain = valPtr->TransparentProxyAppDomain(); + valPtr = valPtr->TransparentProxyDereference(); + } + + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)valPtr , 32 )); + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)appDomain, 32 )); + + NANOCLR_SET_AND_LEAVE(S_OK); + } +#endif + + else + { + NANOCLR_SET_AND_LEAVE(TrackObject( res )); + } + + { + CLR_UINT32 shift = 64 - bits; + + if(shift) + { + val <<= shift; + + if(fSigned) val = (CLR_UINT64)((CLR_INT64 )val >> shift); + else val = (CLR_UINT64)((CLR_UINT64)val >> shift); + } + } + + if(m_hints.m_bitPacked) bits = m_hints.m_bitPacked; + + val -= m_hints.m_rangeBias; + + if(fSigned) + { + CLR_INT64 valS = (CLR_INT64)val; + + if(m_hints.m_scale != 0) valS /= (CLR_INT64)m_hints.m_scale; + + if(bits != 64) + { + CLR_INT64 maxVal = (LONGLONGCONSTANT(1) << (bits-1)) - 1; + + if(valS < (-maxVal-1) || valS > maxVal) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + + val = (CLR_UINT64)valS; + } + else + { + CLR_UINT64 valU = (CLR_UINT64)val; + + if(m_hints.m_scale != 0) valU /= (CLR_UINT64)m_hints.m_scale; + + if(bits != 64) + { + CLR_UINT64 maxVal = (ULONGLONGCONSTANT(1) << bits) - 1; + + if(valU > maxVal) + { + NANOCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + + val = (CLR_UINT64)valU; + } + + NANOCLR_CHECK_HRESULT(m_bf->WriteBits( val, bits )); + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadValue( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_UINT64* dst; + CLR_UINT64 val; + CLR_UINT32 bits; + bool fSigned; + + if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_DateTime.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_DateTime::GetValuePtr( *m_value ); FAULT_ON_NULL(pVal); + + dst = (CLR_UINT64*)pVal; + bits = 64; + fSigned = false; + } + else if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_TimeSpan.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( *m_value ); FAULT_ON_NULL(pVal); + + dst = (CLR_UINT64*)pVal; + bits = 64; + fSigned = true; + } + else if(m_type->m_flags == CLR_RT_DataTypeLookup::c_Primitive || + m_type->m_flags == CLR_RT_DataTypeLookup::c_Enum ) + { + bits = TypeHandler::GetSizeOfType( m_type ); + + if(bits == CLR_RT_DataTypeLookup::c_VariableSize) + { + CLR_UINT32 len; + + NANOCLR_CHECK_HRESULT(m_bf->ReadCompressedUnsigned( len )); + + if(len == 0xFFFFFFFF) + { + m_value->SetObjectReference( NULL ); + } + else + { + CLR_RT_HeapBlock_String* str = CLR_RT_HeapBlock_String::CreateInstance( *m_value, len ); CHECK_ALLOCATION(str); + char* dst = (char*)str->StringText(); + + NANOCLR_CHECK_HRESULT(m_bf->ReadArray( (CLR_UINT8*)dst, len )); + dst[ len ] = 0; + } + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + } + else if(bits == CLR_RT_DataTypeLookup::c_NA) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + m_value->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(m_type->GetDataType(),0,1) ); + m_value->ClearData( ); + + dst = (CLR_UINT64*)&m_value->NumericByRef().u8; + + fSigned = TypeHandler::GetSignOfType( m_type ); + } + } + else + { + NANOCLR_SET_AND_LEAVE(TrackObject( res )); + } + + if(m_hints.m_bitPacked) bits = m_hints.m_bitPacked; + + NANOCLR_CHECK_HRESULT(m_bf->ReadBits( val, bits )); + + if(bits != 64) + { + int revBits = 64 - bits; + + val <<= revBits; + + if(fSigned) val = (CLR_UINT64)((CLR_INT64)val >> revBits); + else val = ( val >> revBits); + } + + if(m_hints.m_scale != 0) + { + val *= m_hints.m_scale; + } + + *dst = val + m_hints.m_rangeBias; + + res = c_Action_None; NANOCLR_SET_AND_LEAVE(S_OK); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::TrackObject( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + if(m_type->m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList)) + { + res = c_Action_ObjectElements; + } + else + { + res = c_Action_ObjectFields; + + if(m_typeExpected && m_typeExpected->m_flags == CLR_RT_DataTypeLookup::c_ValueType) + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + + NANOCLR_SET_AND_LEAVE(m_bf->TrackDuplicate( m_value )); + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_HeapBlock* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor* pDesc; + SerializationHintsAttribute hintsTmp; + + if(type && CLR_RT_ReflectionDef_Index::Convert( *type, inst, NULL )) + { + NANOCLR_CHECK_HRESULT(desc.InitializeFromType( inst )); + + pDesc = &desc; + + if(hints == NULL) + { + hints = &hintsTmp; + + NANOCLR_CLEAR(*hints); + + hints->m_flags = (SerializationFlags)(SF_PointerNeverNull | SF_FixedType); + } + } + else + { + pDesc = NULL; + } + + NANOCLR_SET_AND_LEAVE(CreateInstance( parent, hints, pDesc )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + State* ptr = EVENTCACHE_EXTRACT_NODE_INITTOZERO(g_CLR_RT_EventCache,State,DATATYPE_SERIALIZER_STATE); + + CHECK_ALLOCATION(ptr); + + parent->m_states.LinkAtBack( ptr ); + + ptr->m_parent = parent; + ptr->m_value_NeedProcessing = true; + ptr->m_value.TypeHandler_Initialize( parent, hints, type ); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_BinaryFormatter::State::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + g_CLR_RT_EventCache.Append_Node( this ); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_TypeDef_Instance& cls ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + NANOCLR_CLEAR(hints); + + if(cls.m_target->flags & CLR_RECORD_TYPEDEF::TD_HasAttributes) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( g_CLR_RT_WellKnownTypes.m_SerializationHintsAttribute ); + CLR_RT_AttributeEnumerator en; en.Initialize( cls ); + + if(en.MatchNext( &inst, NULL )) + { + CLR_RT_AttributeParser parser; + + NANOCLR_CHECK_HRESULT(parser.Initialize( en )); + + while(true) + { + CLR_RT_AttributeParser::Value* val; + + NANOCLR_CHECK_HRESULT(parser.Next( val )); + + if(val == NULL) break; + } + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_FieldDef_Instance& fld ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + NANOCLR_CLEAR(hints); + + if(fld.m_target->flags & CLR_RECORD_FIELDDEF::FD_HasAttributes) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( g_CLR_RT_WellKnownTypes.m_SerializationHintsAttribute ); + CLR_RT_AttributeEnumerator en; en.Initialize( fld ); + + if(en.MatchNext( &inst, NULL )) + { + CLR_RT_AttributeParser parser; + + NANOCLR_CHECK_HRESULT(parser.Initialize( en )); + + while(true) + { + CLR_RT_AttributeParser::Value* val; + + NANOCLR_CHECK_HRESULT(parser.Next( val )); + + if(val == NULL) + { + break; + } + else + { + if (!strcmp( val->m_name, "Flags" )) hints.m_flags = (SerializationFlags)val->m_value.NumericByRef().u4; + else if(!strcmp( val->m_name, "ArraySize" )) hints.m_arraySize = val->m_value.NumericByRef().s4; + else if(!strcmp( val->m_name, "BitPacked" )) hints.m_bitPacked = val->m_value.NumericByRef().s4; + else if(!strcmp( val->m_name, "RangeBias" )) hints.m_rangeBias = val->m_value.NumericByRef().s8; + else if(!strcmp( val->m_name, "Scale" )) hints.m_scale = val->m_value.NumericByRef().u8; + } + } + } + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AssignAndFixBoxing( CLR_RT_HeapBlock& dst ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* src = m_value.m_value; + CLR_DataType dt = dst.DataType(); + CLR_DataType dt2 = (dt == DATATYPE_ARRAY_BYREF) ? (CLR_DataType)dst.DereferenceArray()->m_typeOfElement : dt; + + if(c_CLR_RT_DataTypeLookup[ dt2 ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + if(src && (c_CLR_RT_DataTypeLookup[ src->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) == 0) + { + src = TypeHandler::FixNull( src ); + } + + if(src == NULL || (c_CLR_RT_DataTypeLookup[ src->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else + { + if(src) + { + bool fBox = false; + + if(c_CLR_RT_DataTypeLookup[ src->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + fBox = true; + } + else if(src->IsAValueType()) + { + if(dt == DATATYPE_ARRAY_BYREF) + { + fBox = (dt2 != DATATYPE_VALUETYPE); + } + else + { + fBox = !dst.IsAValueType(); + } + } + // + // Box reflection types + // + else if(src->DataType() == DATATYPE_REFLECTION) + { + const CLR_RT_ReflectionDef_Index* reflex; + const CLR_RT_TypeDef_Index* cls; + CLR_RT_HeapBlock *pDst = &dst; + + reflex = &(src->ReflectionDataConst()); + + switch(reflex->m_kind) + { + case REFLECTION_ASSEMBLY : cls = &g_CLR_RT_WellKnownTypes.m_Assembly ; break; + case REFLECTION_TYPE : cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_TYPE_DELAYED: cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_CONSTRUCTOR : cls = &g_CLR_RT_WellKnownTypes.m_ConstructorInfo; break; + case REFLECTION_METHOD : cls = &g_CLR_RT_WellKnownTypes.m_MethodInfo ; break; + case REFLECTION_FIELD : cls = &g_CLR_RT_WellKnownTypes.m_FieldInfo ; break; + } + + // + // Dereference array element and create boxed reflection type + // + if(dt == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock_Array* array = dst.DereferenceArray(); FAULT_ON_NULL(array); + + pDst = (CLR_RT_HeapBlock*)array->GetElement( dst.ArrayIndex() ); + } + + // + // Create boxed object reference for reflection type + // + g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*pDst, *cls); + + + // + // Set reflection type + // + pDst->Dereference()->SetReflection(*reflex); + + NANOCLR_SET_AND_LEAVE(S_OK); + } + + if(fBox) + { + NANOCLR_CHECK_HRESULT(m_value.m_value->PerformBoxing( m_value.m_type->m_handlerCls )); + } + } + else + { + src = &m_value.m_value_tmp; src->SetObjectReference( NULL ); + } + } + + if(dt == DATATYPE_ARRAY_BYREF) + { + NANOCLR_CHECK_HRESULT(src->StoreToReference( dst, 0 )); + } + else + { + dst.Assign( *src ); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::GetValue() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + State* prev = (State*)Prev(); + if(prev->Prev() == NULL) + { + NANOCLR_SET_AND_LEAVE(m_value.SetValue( &m_parent->m_value )); + } + + if(prev->m_fields_NeedProcessing) + { + NANOCLR_SET_AND_LEAVE(m_value.SetValue( prev->m_fields_Pointer )); + } + + if(prev->m_array_NeedProcessing) + { + CLR_RT_HeapBlock ref; ref.InitializeArrayReferenceDirect( *prev->m_array, prev->m_array_CurrentPos-1 ); + CLR_RT_HeapBlock val; + + NANOCLR_CHECK_HRESULT(val.LoadFromReference( ref )); + + NANOCLR_SET_AND_LEAVE(m_value.SetValue( &val )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::SetValueAndDestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + if(m_parent->m_fDeserialize) + { + State* prev = (State*)Prev(); + + if(prev->Prev() == NULL) + { + NANOCLR_CHECK_HRESULT(AssignAndFixBoxing( m_parent->m_value )); + } + else + { + if(prev->m_fields_NeedProcessing) + { + NANOCLR_CHECK_HRESULT(AssignAndFixBoxing( *prev->m_fields_Pointer )); + } + + if(prev->m_array_NeedProcessing) + { + CLR_RT_HeapBlock ref; ref.InitializeArrayReferenceDirect( *prev->m_array, prev->m_array_CurrentPos-1 ); + + NANOCLR_CHECK_HRESULT(AssignAndFixBoxing( ref )); + } + } + } + + DestroyInstance(); + + NANOCLR_NOCLEANUP(); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::State::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + if(m_value_NeedProcessing) + { + int res; + + m_value_NeedProcessing = false; + + if(m_parent->m_fDeserialize) + { + NANOCLR_CHECK_HRESULT(m_value.ReadSignature( res )); + +#if defined(NANOCLR_APPDOMAINS) + //Make sure that the type being deserialized is loaded in the current appDomain + { + if(m_parent->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) + { + CLR_RT_TypeDef_Index idx; idx.Clear(); + CLR_RT_HeapBlock* value = m_value.m_value; + + if(value && value->DataType() == DATATYPE_REFLECTION) + { + switch(value->ReflectionDataConst().m_kind) + { + case REFLECTION_TYPE: + idx.m_data = value->ReflectionDataConst().m_data.m_type.m_data; + break; + case REFLECTION_TYPE_DELAYED: + //should this be allowed for appdomain+marshaling??? + break; + case REFLECTION_ASSEMBLY: + { + CLR_RT_Assembly_Instance inst; + + if(!inst.InitializeFromIndex( value->ReflectionDataConst().m_data.m_assm )) + { + _ASSERTE(false); + } + + if(!g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( inst.m_assm )) + { + NANOCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + } + } + break; + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + { + CLR_RT_MethodDef_Instance inst; + + if(!inst.InitializeFromIndex( value->ReflectionDataConst().m_data.m_method )) + { + _ASSERTE(false); + } + + idx.Set( inst.Assembly(), inst.CrossReference().GetOwner() ); + } + break; + case REFLECTION_FIELD: + { + CLR_RT_FieldDef_Instance inst; + CLR_RT_TypeDescriptor desc; + + if(!inst.InitializeFromIndex( value->ReflectionDataConst().m_data.m_field )) + { + _ASSERTE(false); + } + + NANOCLR_CHECK_HRESULT(desc.InitializeFromFieldDefinition( inst )); + + idx = desc.m_handlerCls; + } + break; + } + } + else if(m_value.m_type) + { + idx = m_value.m_type->m_handlerCls; + } + + if(idx.m_data != 0) + { + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->VerifyTypeIsLoaded( idx )); + } + } + } +#endif + + } + else + { + NANOCLR_CHECK_HRESULT(GetValue()); + + NANOCLR_CHECK_HRESULT(m_value.EmitSignature( res )); + } + + if(res != TypeHandler::c_Action_None) + { + if(m_parent->m_fDeserialize) + { + NANOCLR_CHECK_HRESULT(m_value.ReadValue( res )); + + } + else + { + NANOCLR_CHECK_HRESULT(m_value.EmitValue( res )); + } + + switch(res) + { + case TypeHandler::c_Action_None: + break; + + case TypeHandler::c_Action_ObjectFields: + { + m_fields_NeedProcessing = true; + m_fields_CurrentClass = m_value.m_type->m_handlerCls; + m_fields_CurrentField = 0; + m_fields_Pointer = NULL; + break; + } + + case TypeHandler::c_Action_ObjectElements: + { + m_array_NeedProcessing = true; + m_array_CurrentPos = 0; + + if(m_value.m_type->m_flags & CLR_RT_DataTypeLookup::c_ArrayList) + { + int capacity; + + NANOCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( *m_value.m_value, m_array, m_array_LastPos, capacity )); + + m_array_ExpectedType = NULL; + } + else + { + m_array = m_value.m_value->DereferenceArray(); + m_array_LastPos = m_array->m_numOfElements; + + m_array_ExpectedType = &m_array_ExpectedType_Tmp; + m_value.m_type->GetElementType( *m_array_ExpectedType ); + } + + break; + } + } + } + } + + if(m_fields_NeedProcessing) + { + NANOCLR_SET_AND_LEAVE(AdvanceToTheNextField()); + } + + if(m_array_NeedProcessing) + { + NANOCLR_SET_AND_LEAVE(AdvanceToTheNextElement()); + } + + NANOCLR_SET_AND_LEAVE(SetValueAndDestroyInstance()); + + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextField() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + while(NANOCLR_INDEX_IS_VALID(m_fields_CurrentClass)) + { + if(m_fields_CurrentField < m_fields_CurrentClass.m_target->iFields_Num) + { + int offset = m_fields_CurrentClass.m_target->iFields_First + m_fields_CurrentField++; + CLR_RT_FieldDef_Index idx ; idx.Set( m_fields_CurrentClass.Assembly(), offset ); + CLR_RT_FieldDef_Instance inst; inst.InitializeFromIndex( idx ); + + m_fields_Pointer = m_value.m_value->Dereference() + inst.CrossReference().m_offset; + + if((inst.m_target->flags & CLR_RECORD_FIELDDEF::FD_NotSerialized) == 0) + { + SerializationHintsAttribute hints; + CLR_RT_TypeDescriptor desc; + + if(m_value.m_type->m_flags & CLR_RT_DataTypeLookup::c_Enum) + { + hints = m_value.m_hints; + } + else + { + NANOCLR_CHECK_HRESULT(FindHints( hints, inst )); + } + + NANOCLR_CHECK_HRESULT(desc.InitializeFromFieldDefinition( inst )); + + NANOCLR_SET_AND_LEAVE(State::CreateInstance( m_parent, &hints, &desc )); + } + } + else + { + m_fields_CurrentClass.SwitchToParent(); + m_fields_CurrentField = 0; + } + } + + NANOCLR_SET_AND_LEAVE(SetValueAndDestroyInstance()); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextElement() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + if(m_array_ExpectedType && (c_CLR_RT_DataTypeLookup[ m_array->m_typeOfElement ].m_flags & CLR_RT_DataTypeLookup::c_Numeric)) + { + CLR_UINT8* ptr = m_array->GetFirstElement(); + CLR_UINT32 bits = TypeHandler::GetSizeOfType( m_array_ExpectedType ); + int count = m_array_LastPos; + bool fDeserialize = m_parent->m_fDeserialize; + CLR_UINT32 size; + CLR_UINT64 val; + + size = bits / 8; if(size == 0) size = 1; + + while(count > 0) + { + if(fDeserialize) + { + NANOCLR_CHECK_HRESULT(m_parent->ReadBits( val, bits )); + + memcpy( ptr, &val, size ); + } + else + { + val = 0; memcpy( &val, ptr, size ); + + NANOCLR_CHECK_HRESULT(m_parent->WriteBits( val, bits )); + } + + ptr += size; + + count--; + } + } + else if(m_array_CurrentPos < m_array_LastPos) + { + m_array_CurrentPos++; + + SerializationHintsAttribute* hints; + + if(m_value.m_hints.m_flags & (SF_FixedType | SF_PointerNeverNull)) + { + hints = &m_value.m_hints; + } + else + { + hints = NULL; + } + + NANOCLR_SET_AND_LEAVE(State::CreateInstance( m_parent, hints, m_array_ExpectedType )); + } + + NANOCLR_SET_AND_LEAVE(SetValueAndDestroyInstance()); + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::CreateInstance( CLR_UINT8* buf, int len, CLR_RT_BinaryFormatter*& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_RT_BinaryFormatter* ptr = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_BinaryFormatter,DATATYPE_SERIALIZER_HEAD); + + res = ptr; CHECK_ALLOCATION(ptr); + + ptr->m_stream = NULL; // CLR_RT_HeapBlock_MemoryStream* m_stream; + ptr->m_idx = 0; // CLR_UINT32 m_idx; + ptr->m_lastTypeRead = 0; // CLR_UINT32 m_lastTypeRead; + ptr->m_duplicates.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_duplicates; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::DuplicateTracker + ptr->m_states .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_states; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::State + // + ptr->m_fDeserialize = (buf != NULL); // bool m_fDeserialize; + ptr->m_value.SetObjectReference( NULL ); // CLR_RT_HeapBlock m_value; + ptr->m_value_desc.TypeDescriptor_Initialize(); // CLR_RT_TypeDescriptor m_value_desc; + + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_MemoryStream::CreateInstance( ptr->m_stream, buf, len )); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_BinaryFormatter::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + m_states .DblLinkedList_PushToCache(); + m_duplicates.DblLinkedList_PushToCache(); + + CLR_RT_HeapBlock_MemoryStream::DeleteInstance( m_stream ); + + g_CLR_RT_EventCache.Append_Node( this ); +} + +HRESULT CLR_RT_BinaryFormatter::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + while(true) + { + State* top = (State*)m_states.LastNode(); if(top->Prev() == NULL) break; + + NANOCLR_CHECK_HRESULT(top->Advance()); + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +void CLR_RT_BinaryFormatter::PrepareForGC( void* data ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + if(data != NULL) + { + CLR_RT_BinaryFormatter* bf = (CLR_RT_BinaryFormatter*)data; + + g_CLR_RT_GarbageCollector.CheckSingleBlock_Force( &bf->m_value ); + + NANOCLR_FOREACH_NODE(CLR_RT_BinaryFormatter::State,state,bf->m_states) + { + g_CLR_RT_GarbageCollector.CheckSingleBlock_Force( state->m_value.m_value ); + } + NANOCLR_FOREACH_NODE_END(); + } +} + +HRESULT CLR_RT_BinaryFormatter::Serialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_RT_BinaryFormatter* bf = NULL; + CLR_RT_ProtectFromGC pgc( (void**)&bf, CLR_RT_BinaryFormatter::PrepareForGC ); + + refData.SetObjectReference( NULL ); + + NANOCLR_CHECK_HRESULT(CLR_RT_BinaryFormatter::CreateInstance( NULL, 0, bf )); + + NANOCLR_CHECK_HRESULT(State::CreateInstance( bf, NULL, cls )); + + bf->m_flags = flags; + bf->m_value.Assign( object ); + + NANOCLR_CHECK_HRESULT(bf->Advance()); + + NANOCLR_CHECK_HRESULT(bf->m_stream->ToArray( refData )); + + NANOCLR_CLEANUP(); + + if(bf) + { + bf->DestroyInstance(); + + bf = NULL; + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = object.DereferenceArray(); + + refData.SetObjectReference( NULL ); + + if(array != NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_RT_BinaryFormatter::Deserialize( refData, array->GetFirstElement(), array->m_numOfElements, cls, unknownType, flags )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_UINT8* data, CLR_UINT32 size, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_RT_BinaryFormatter* bf = NULL; + CLR_RT_ProtectFromGC pgc( (void**)&bf, CLR_RT_BinaryFormatter::PrepareForGC ); + + refData.SetObjectReference( NULL ); + + NANOCLR_CHECK_HRESULT(CLR_RT_BinaryFormatter::CreateInstance( data, size, bf )); + + NANOCLR_CHECK_HRESULT(State::CreateInstance( bf, NULL, cls )); + + bf->m_flags = flags; + + NANOCLR_CHECK_HRESULT(bf->Advance()); + + refData.Assign( bf->m_value ); + + + NANOCLR_CLEANUP(); + + if(bf) + { + if(unknownType) + { + *unknownType = (hr == CLR_E_WRONG_TYPE) ? bf->m_lastTypeRead : 0; + } + + bf->DestroyInstance(); + + bf = NULL; + } + + NANOCLR_CLEANUP_END(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TrackDuplicate( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + DuplicateTracker* ptr = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,DuplicateTracker,DATATYPE_SERIALIZER_DUPLICATE); + + CHECK_ALLOCATION(ptr); + + m_duplicates.LinkAtBack( ptr ); + + ptr->m_ptr = TypeHandler::FixDereference( object ); + ptr->m_idx = m_idx++; + + NANOCLR_NOCLEANUP(); +} + +CLR_UINT32 CLR_RT_BinaryFormatter::SearchDuplicate( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + object = TypeHandler::FixDereference( object ); + + NANOCLR_FOREACH_NODE(DuplicateTracker,ptr,m_duplicates) + { + if(ptr->m_ptr == object) + { + return ptr->m_idx; + } + } + NANOCLR_FOREACH_NODE_END(); + + return (CLR_UINT32)-1; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::GetDuplicate( CLR_UINT32 idx ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FOREACH_NODE(DuplicateTracker,ptr,m_duplicates) + { + if(ptr->m_idx == idx) + { + return ptr->m_ptr; + } + } + NANOCLR_FOREACH_NODE_END(); + + return NULL; +} + +//--//--// + +int CLR_RT_BinaryFormatter::BitsAvailable( ) { return m_stream->BitsAvailable( ); } + +HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT32& res, int bits ) { return m_stream->ReadBits ( res, bits ); } +HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT32 val, int bits ) { return m_stream->WriteBits ( val, bits ); } + +HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT64& res, int bits ) { return m_stream->ReadBits ( res, bits ); } +HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT64 val, int bits ) { return m_stream->WriteBits ( val, bits ); } + +HRESULT CLR_RT_BinaryFormatter::ReadArray ( CLR_UINT8* buf, int bytes ) { return m_stream->ReadArray ( buf, bytes ); } +HRESULT CLR_RT_BinaryFormatter::WriteArray ( const CLR_UINT8* buf, int bytes ) { return m_stream->WriteArray ( buf, bytes ); } + +HRESULT CLR_RT_BinaryFormatter::ReadCompressedUnsigned( CLR_UINT32& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + CLR_UINT32 extra; + + NANOCLR_CHECK_HRESULT(m_stream->ReadBits( val, 8 )); + + if(val == 0xFF) + { + val = 0xFFFFFFFF; + } + else + { + int bits = 0; + + switch(val & 0xC0) + { + case 0x00: bits = 0; break; + case 0x40: bits = 0; break; + case 0x80: bits = 8; break; + case 0xC0: bits = 24; break; + } + + if(bits) + { + hr = m_stream->ReadBits( extra, bits ); + + val = ((val & ~0xC0) << bits) | extra; + } + } + + + NANOCLR_CLEANUP(); + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteCompressedUnsigned( CLR_UINT32 val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + int bits; + + if(val == 0xFFFFFFFF) + { + bits = 8; + } + else if(val < 0x80) + { + bits = 8; + } + else if(val < 0x3F00) + { + val |= 0x8000; + bits = 16; + } + else if(val < 0x3F000000) + { + val |= 0xC0000000; + bits = 32; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + NANOCLR_CHECK_HRESULT(m_stream->WriteBits( val, bits )); + + + NANOCLR_CLEANUP(); + + NANOCLR_CLEANUP_END(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::ReadType( CLR_RT_ReflectionDef_Index& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(m_stream->ReadBits( m_lastTypeRead, 32 )); + + val.InitializeFromHash( m_lastTypeRead ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteType( const CLR_RT_ReflectionDef_Index& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(WriteType( val.GetTypeHash() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteType( CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_HEADER(); + + if(hash == 0xFFFFFFFF || hash == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_SET_AND_LEAVE(m_stream->WriteBits( hash, 32 )); + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter_stub.cpp b/source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter_stub.cpp new file mode 100644 index 00000000..ead85bd4 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/BinaryFormatter_stub.cpp @@ -0,0 +1,389 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +__nfweak bool CLR_RT_BinaryFormatter::SerializationEnabled() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return false; +} + +__nfweak CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixDereference( CLR_RT_HeapBlock* v ) +{ + (void)v; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return NULL; +} + +__nfweak CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixNull( CLR_RT_HeapBlock* v ) +{ + (void)v; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return NULL; +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::TypeHandler_Initialize( CLR_RT_BinaryFormatter* bf, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* expected ) +{ + (void)bf; + (void)hints; + (void)expected; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::SetValue( CLR_RT_HeapBlock* v ) +{ + (void)v; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak int CLR_RT_BinaryFormatter::TypeHandler::SignatureRequirements() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return 0; +} + +__nfweak bool CLR_RT_BinaryFormatter::TypeHandler::CompareTypes( CLR_RT_TypeDescriptor* left, CLR_RT_TypeDescriptor* right ) +{ + (void)left; + (void)right; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return true; +} + +__nfweak CLR_DataType CLR_RT_BinaryFormatter::TypeHandler::GetDataType( CLR_RT_TypeDescriptor* type ) +{ + (void)type; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (CLR_DataType)0; +} + +__nfweak CLR_UINT32 CLR_RT_BinaryFormatter::TypeHandler::GetSizeOfType( CLR_RT_TypeDescriptor* type ) +{ + (void)type; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return 0; +} + +__nfweak bool CLR_RT_BinaryFormatter::TypeHandler::GetSignOfType( CLR_RT_TypeDescriptor* type ) +{ + (void)type; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return true; +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature( int& res ) +{ + (void)res; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature_Inner( int mask, CLR_RT_TypeDescriptor* type, CLR_RT_HeapBlock* value ) +{ + (void)mask; + (void)type; + (void)value; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadSignature( int& res ) +{ + (void)res; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitValue( int& res ) +{ + (void)res; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadValue( int& res ) +{ + (void)res; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::TypeHandler::TrackObject( int& res ) +{ + (void)res; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_HeapBlock* type ) +{ + (void)parent; + (void)hints; + (void)type; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* type ) +{ + (void)parent; + (void)hints; + (void)type; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak void CLR_RT_BinaryFormatter::State::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_TypeDef_Instance& cls ) +{ + (void)hints; + (void)cls; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_FieldDef_Instance& fld ) +{ + (void)hints; + (void)fld; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::AssignAndFixBoxing( CLR_RT_HeapBlock& dst ) +{ + (void)dst; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::GetValue() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::SetValueAndDestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextField() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextElement() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak HRESULT CLR_RT_BinaryFormatter::CreateInstance( CLR_UINT8* buf, int len, CLR_RT_BinaryFormatter*& res ) +{ + (void)buf; + (void)len; + (void)res; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak void CLR_RT_BinaryFormatter::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak void CLR_RT_BinaryFormatter::PrepareForGC( void* data ) +{ + (void)data; + + NATIVE_PROFILE_CLR_SERIALIZATION(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::Serialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32 flags ) +{ + (void)refData; + (void)object; + (void)cls; + (void)flags; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + (void)refData; + (void)object; + (void)cls; + (void)unknownType; + (void)flags; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_UINT8* data, CLR_UINT32 size, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + (void)refData; + (void)data; + (void)size; + (void)cls; + (void)unknownType; + (void)flags; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::TrackDuplicate( CLR_RT_HeapBlock* object ) +{ + (void)object; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak CLR_UINT32 CLR_RT_BinaryFormatter::SearchDuplicate( CLR_RT_HeapBlock* object ) +{ + (void)object; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (CLR_UINT32)-1; +} + +__nfweak CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::GetDuplicate( CLR_UINT32 idx ) +{ + (void)idx; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + return NULL; +} + +//--//--// + +__nfweak int CLR_RT_BinaryFormatter::BitsAvailable( ) { return 0; } + +__nfweak HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT32& res, int bits ) { (void)res; (void)bits; NANOCLR_FEATURE_STUB_RETURN(); } +__nfweak HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT32 val, int bits ) { (void)val; (void)bits; NANOCLR_FEATURE_STUB_RETURN(); } + +__nfweak HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT64& res, int bits ) { (void)res; (void)bits; NANOCLR_FEATURE_STUB_RETURN(); } +__nfweak HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT64 val, int bits ) { (void)val; (void)bits; NANOCLR_FEATURE_STUB_RETURN(); } + +__nfweak HRESULT CLR_RT_BinaryFormatter::ReadArray ( CLR_UINT8* buf, int bytes ) { (void)buf; (void)bytes; NANOCLR_FEATURE_STUB_RETURN(); } +__nfweak HRESULT CLR_RT_BinaryFormatter::WriteArray ( const CLR_UINT8* buf, int bytes ) { (void)buf; (void)bytes; NANOCLR_FEATURE_STUB_RETURN(); } + +__nfweak HRESULT CLR_RT_BinaryFormatter::ReadCompressedUnsigned( CLR_UINT32& val ) +{ + (void)val; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::WriteCompressedUnsigned( CLR_UINT32 val ) +{ + (void)val; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_RT_BinaryFormatter::ReadType( CLR_RT_ReflectionDef_Index& val ) +{ + (void)val; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::WriteType( const CLR_RT_ReflectionDef_Index& val ) +{ + (void)val; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} + +__nfweak HRESULT CLR_RT_BinaryFormatter::WriteType( CLR_UINT32 hash ) +{ + (void)hash; + + NATIVE_PROFILE_CLR_SERIALIZATION(); + NANOCLR_FEATURE_STUB_RETURN(); +} diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj new file mode 100644 index 00000000..6c89da12 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {16BF6131-A3B8-4B97-B867-E45669FB48BD} + Win32Proj + Serialization + 10.0.17763.0 + Serialization + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\CorLib;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\CorLib;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj.filters new file mode 100644 index 00000000..2e4ce595 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization-vs2019.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj new file mode 100644 index 00000000..44d5953f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {16BF6131-A3B8-4B97-B867-E45669FB48BD} + Win32Proj + Serialization + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\CorLib;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\CorLib;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj.filters new file mode 100644 index 00000000..2e4ce595 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj new file mode 100644 index 00000000..03df5555 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {C337041D-344D-49FE-AD99-B137E7FD0188} + Win32Proj + Serialization_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\..\targets\os\win32\Include;..\..\Include;..\..\..\HAL\Include;..\..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters new file mode 100644 index 00000000..4e5d8b8e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Core/Streams.cpp b/source/native/nf-interpreter/src/CLR/Core/Streams.cpp new file mode 100644 index 00000000..3b38e3b0 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Streams.cpp @@ -0,0 +1,297 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_MemoryStream::CreateInstance( CLR_RT_HeapBlock_MemoryStream*& stream, CLR_UINT8* buf, int len ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + stream = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_MemoryStream,DATATYPE_MEMORY_STREAM_HEAD); CHECK_ALLOCATION(stream); + + NANOCLR_SET_AND_LEAVE(stream->Initialize( buf, len )); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_MemoryStream::DeleteInstance( CLR_RT_HeapBlock_MemoryStream*& stream ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(stream) + { + stream->Release(); + + g_CLR_RT_EventCache.Append_Node( stream ); + + stream = NULL; + } +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::Initialize( CLR_UINT8* buf, CLR_UINT32 len ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + m_buffers.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_buffers; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_MemoryStream::Buffer + + CHECK_ALLOCATION(NewBuffer()); + + if(buf) + { + m_current->m_data = buf; + m_current->m_length = len; + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_MemoryStream::Release() +{ + NATIVE_PROFILE_CLR_CORE(); + m_buffers.DblLinkedList_PushToCache(); +} + +//--// + +void CLR_RT_HeapBlock_MemoryStream::Rewind() +{ + NATIVE_PROFILE_CLR_CORE(); + m_current = (Buffer*)m_buffers.FirstNode(); + m_pos = -1; + m_avail = 0; +} + +void CLR_RT_HeapBlock_MemoryStream::Reset() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(Buffer,node,m_buffers) + { + node->m_length = 0; + } + NANOCLR_FOREACH_NODE_END(); + Rewind(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::ToArray( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT32 tot; + CLR_RT_HeapBlock_Array* array; + CLR_UINT8* buf; + + tot = 0; + NANOCLR_FOREACH_NODE(Buffer,node,m_buffers) + { + tot += node->m_length; + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, tot, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + array = ref.DereferenceArray(); + buf = array->GetFirstElement(); + + NANOCLR_FOREACH_NODE(Buffer,node,m_buffers) + { + memcpy( buf, node->m_payload, node->m_length ); buf += node->m_length; + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_HeapBlock_MemoryStream::Buffer* CLR_RT_HeapBlock_MemoryStream::NewBuffer() +{ + NATIVE_PROFILE_CLR_CORE(); + Buffer* ptr = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,Buffer,DATATYPE_MEMORY_STREAM_DATA); + + if(ptr) + { + m_current = ptr; + m_pos = -1; + m_avail = 0; + + ptr->m_data = ptr->m_payload; + ptr->m_length = 0; + + m_buffers.LinkAtBack( ptr ); + } + + return ptr; +} + +//--// + +int CLR_RT_HeapBlock_MemoryStream::BitsAvailable() +{ + NATIVE_PROFILE_CLR_CORE(); + int val = m_avail - 8 * m_pos - 8; + + NANOCLR_FOREACH_NODE__DIRECT(Buffer,ptr,m_current) + { + val += 8 * ptr->m_length; + } + NANOCLR_FOREACH_NODE_END(); + + return val; +} + +int CLR_RT_HeapBlock_MemoryStream::BitsWritten() +{ + NATIVE_PROFILE_CLR_CORE(); + int val = m_pos * 8 - m_avail + 8; + + NANOCLR_FOREACH_NODE_BACKWARD__DIRECT(Buffer,ptr,m_current->Prev()) + { + val += 8 * ptr->m_length; + } + NANOCLR_FOREACH_NODE_END(); + + return val; +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::ReadBits( CLR_UINT64& res, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT32* ptr = (CLR_UINT32*)&res; + + if(bits > 32) { NANOCLR_CHECK_HRESULT(ReadBits( ptr[ 1 ], bits - 32 )); bits = 32; } + else { ptr[ 1 ] = 0; } + + NANOCLR_SET_AND_LEAVE(ReadBits( ptr[ 0 ], bits )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::ReadBits( CLR_UINT32& res, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT32 val = 0; + CLR_UINT32 pos = bits; + + while(bits > 0) + { + while(m_avail == 0) + { + m_pos++; + m_avail = 8; + + while(m_pos >= m_current->m_length) + { + m_current = (Buffer*)m_current->Next(); + + if(m_current->Next() == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + m_pos = 0; + } + } + + CLR_UINT32 insert = (bits < m_avail) ? bits : m_avail; + CLR_UINT32 mask = (1 << insert) - 1; + + pos -= insert; val |= (((CLR_UINT32)m_current->m_data[ m_pos ] >> (m_avail - insert)) & mask) << pos; + bits -= insert; + m_avail -= insert; + } + + res = val; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::WriteBits( CLR_UINT64 res, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(bits > 32) { NANOCLR_CHECK_HRESULT(WriteBits( (CLR_UINT32)(res >> 32), bits - 32 )); bits = 32; } + + NANOCLR_SET_AND_LEAVE(WriteBits( (CLR_UINT32)res, bits )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::WriteBits( CLR_UINT32 val, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT32 pos = bits; + + while(bits > 0) + { + while(m_avail == 0) + { + m_pos++; + + if(m_pos < (int)sizeof(m_current->m_payload)) + { + m_current->m_length++; + m_current->m_payload[ m_pos ] = 0; + m_avail = 8; + break; + } + + CHECK_ALLOCATION(NewBuffer()); + } + + CLR_UINT32 insert = (bits < m_avail) ? bits : m_avail; + CLR_UINT32 mask = (1 << insert) - 1; + + pos -= insert; m_current->m_payload[ m_pos ] |= (CLR_UINT8)(((val >> pos) & mask) << (m_avail - insert)); + bits -= insert; + m_avail -= insert; + + } + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_HeapBlock_MemoryStream::ReadArray( CLR_UINT8* buf, CLR_UINT32 bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_UINT32 data; + + while(bytes-- > 0) + { + NANOCLR_CHECK_HRESULT(ReadBits( data, 8 )); + + *buf++ = (CLR_UINT8)data; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::WriteArray( const CLR_UINT8* buf, CLR_UINT32 bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + while(bytes-- > 0) + { + NANOCLR_CHECK_HRESULT(WriteBits( (CLR_UINT32)*buf++, 8 )); + } + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/StringTable.cpp b/source/native/nf-interpreter/src/CLR/Core/StringTable.cpp new file mode 100644 index 00000000..dddd76a4 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/StringTable.cpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" + +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "StringTableData.cpp" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_Assembly::InitString() +{ + NATIVE_PROFILE_CLR_CORE(); +} + +const char* CLR_RT_Assembly::GetString( CLR_STRING i ) +{ + NATIVE_PROFILE_CLR_CORE(); + static const CLR_STRING iMax = 0xFFFF - c_CLR_StringTable_Size; + + if(i >= iMax) + { + return &c_CLR_StringTable_Data[ c_CLR_StringTable_Lookup[ (CLR_STRING)0xFFFF - i ] ]; + } + + return &(((const char*)GetTable( TBL_Strings ))[ i ]); +} + +#if defined(_WIN32) + +void CLR_RT_Assembly::InitString( std::map& map ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_STRING* array = c_CLR_StringTable_Lookup; + size_t len = c_CLR_StringTable_Size; + CLR_STRING idx = 0xFFFF; + + map.clear(); + + while(len-- > 0) + { + map[ &c_CLR_StringTable_Data[ *array++ ] ] = idx--; + } +} + +#endif + diff --git a/source/native/nf-interpreter/src/CLR/Core/StringTableData.cpp b/source/native/nf-interpreter/src/CLR/Core/StringTableData.cpp new file mode 100644 index 00000000..93610e8a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/StringTableData.cpp @@ -0,0 +1,1741 @@ +// +// The StringTable was generated from the following +// specified in Microsoft.SPOT.Support.Settings: +// +// Microsoft.SPOT.Native.strings +// mscorlib.strings +// +#if defined(__GNUC__) +#include +#include +#endif + +const size_t c_CLR_StringTable_Size = 860; + +const CLR_STRING c_CLR_StringTable_Lookup[] = +{ + /* 0000 */ 0, + /* 0001 */ 7, + /* 0002 */ 13, + /* 0003 */ 19, + /* 0004 */ 23, + /* 0005 */ 56, + /* 0006 */ 61, + /* 0007 */ 65, + /* 0008 */ 73, + /* 0009 */ 82, + /* 000A */ 98, + /* 000B */ 109, + /* 000C */ 120, + /* 000D */ 129, + /* 000E */ 150, + /* 000F */ 160, + /* 0010 */ 187, + /* 0011 */ 194, + /* 0012 */ 207, + /* 0013 */ 218, + /* 0014 */ 238, + /* 0015 */ 259, + /* 0016 */ 277, + /* 0017 */ 299, + /* 0018 */ 327, + /* 0019 */ 337, + /* 001A */ 343, + /* 001B */ 353, + /* 001C */ 363, + /* 001D */ 368, + /* 001E */ 377, + /* 001F */ 390, + /* 0020 */ 409, + /* 0021 */ 422, + /* 0022 */ 440, + /* 0023 */ 452, + /* 0024 */ 472, + /* 0025 */ 479, + /* 0026 */ 493, + /* 0027 */ 498, + /* 0028 */ 504, + /* 0029 */ 514, + /* 002A */ 525, + /* 002B */ 544, + /* 002C */ 559, + /* 002D */ 569, + /* 002E */ 579, + /* 002F */ 591, + /* 0030 */ 596, + /* 0031 */ 609, + /* 0032 */ 616, + /* 0033 */ 629, + /* 0034 */ 642, + /* 0035 */ 652, + /* 0036 */ 660, + /* 0037 */ 666, + /* 0038 */ 671, + /* 0039 */ 680, + /* 003A */ 688, + /* 003B */ 695, + /* 003C */ 700, + /* 003D */ 706, + /* 003E */ 712, + /* 003F */ 718, + /* 0040 */ 724, + /* 0041 */ 732, + /* 0042 */ 746, + /* 0043 */ 754, + /* 0044 */ 770, + /* 0045 */ 780, + /* 0046 */ 791, + /* 0047 */ 798, + /* 0048 */ 818, + /* 0049 */ 834, + /* 004A */ 848, + /* 004B */ 861, + /* 004C */ 870, + /* 004D */ 878, + /* 004E */ 883, + /* 004F */ 890, + /* 0050 */ 907, + /* 0051 */ 911, + /* 0052 */ 916, + /* 0053 */ 929, + /* 0054 */ 944, + /* 0055 */ 968, + /* 0056 */ 980, + /* 0057 */ 993, + /* 0058 */ 1015, + /* 0059 */ 1024, + /* 005A */ 1039, + /* 005B */ 1058, + /* 005C */ 1071, + /* 005D */ 1075, + /* 005E */ 1085, + /* 005F */ 1098, + /* 0060 */ 1111, + /* 0061 */ 1124, + /* 0062 */ 1137, + /* 0063 */ 1149, + /* 0064 */ 1155, + /* 0065 */ 1175, + /* 0066 */ 1184, + /* 0067 */ 1199, + /* 0068 */ 1207, + /* 0069 */ 1217, + /* 006A */ 1226, + /* 006B */ 1234, + /* 006C */ 1246, + /* 006D */ 1262, + /* 006E */ 1270, + /* 006F */ 1277, + /* 0070 */ 1295, + /* 0071 */ 1304, + /* 0072 */ 1325, + /* 0073 */ 1331, + /* 0074 */ 1348, + /* 0075 */ 1357, + /* 0076 */ 1367, + /* 0077 */ 1376, + /* 0078 */ 1384, + /* 0079 */ 1399, + /* 007A */ 1425, + /* 007B */ 1446, + /* 007C */ 1452, + /* 007D */ 1458, + /* 007E */ 1470, + /* 007F */ 1475, + /* 0080 */ 1490, + /* 0081 */ 1497, + /* 0082 */ 1507, + /* 0083 */ 1521, + /* 0084 */ 1531, + /* 0085 */ 1544, + /* 0086 */ 1554, + /* 0087 */ 1563, + /* 0088 */ 1583, + /* 0089 */ 1588, + /* 008A */ 1592, + /* 008B */ 1607, + /* 008C */ 1621, + /* 008D */ 1643, + /* 008E */ 1662, + /* 008F */ 1684, + /* 0090 */ 1706, + /* 0091 */ 1718, + /* 0092 */ 1727, + /* 0093 */ 1744, + /* 0094 */ 1754, + /* 0095 */ 1763, + /* 0096 */ 1780, + /* 0097 */ 1789, + /* 0098 */ 1807, + /* 0099 */ 1820, + /* 009A */ 1826, + /* 009B */ 1832, + /* 009C */ 1838, + /* 009D */ 1847, + /* 009E */ 1854, + /* 009F */ 1871, + /* 00A0 */ 1884, + /* 00A1 */ 1897, + /* 00A2 */ 1917, + /* 00A3 */ 1934, + /* 00A4 */ 1944, + /* 00A5 */ 1947, + /* 00A6 */ 1960, + /* 00A7 */ 1968, + /* 00A8 */ 1982, + /* 00A9 */ 1994, + /* 00AA */ 2014, + /* 00AB */ 2030, + /* 00AC */ 2046, + /* 00AD */ 2068, + /* 00AE */ 2091, + /* 00AF */ 2100, + /* 00B0 */ 2109, + /* 00B1 */ 2124, + /* 00B2 */ 2136, + /* 00B3 */ 2155, + /* 00B4 */ 2166, + /* 00B5 */ 2193, + /* 00B6 */ 2221, + /* 00B7 */ 2231, + /* 00B8 */ 2247, + /* 00B9 */ 2264, + /* 00BA */ 2279, + /* 00BB */ 2293, + /* 00BC */ 2314, + /* 00BD */ 2332, + /* 00BE */ 2341, + /* 00BF */ 2351, + /* 00C0 */ 2361, + /* 00C1 */ 2373, + /* 00C2 */ 2387, + /* 00C3 */ 2402, + /* 00C4 */ 2427, + /* 00C5 */ 2438, + /* 00C6 */ 2448, + /* 00C7 */ 2459, + /* 00C8 */ 2467, + /* 00C9 */ 2477, + /* 00CA */ 2498, + /* 00CB */ 2514, + /* 00CC */ 2532, + /* 00CD */ 2547, + /* 00CE */ 2568, + /* 00CF */ 2580, + /* 00D0 */ 2595, + /* 00D1 */ 2609, + /* 00D2 */ 2630, + /* 00D3 */ 2640, + /* 00D4 */ 2657, + /* 00D5 */ 2675, + /* 00D6 */ 2683, + /* 00D7 */ 2701, + /* 00D8 */ 2717, + /* 00D9 */ 2729, + /* 00DA */ 2745, + /* 00DB */ 2754, + /* 00DC */ 2784, + /* 00DD */ 2797, + /* 00DE */ 2806, + /* 00DF */ 2817, + /* 00E0 */ 2847, + /* 00E1 */ 2852, + /* 00E2 */ 2857, + /* 00E3 */ 2867, + /* 00E4 */ 2887, + /* 00E5 */ 2897, + /* 00E6 */ 2902, + /* 00E7 */ 2915, + /* 00E8 */ 2926, + /* 00E9 */ 2938, + /* 00EA */ 2950, + /* 00EB */ 2960, + /* 00EC */ 2977, + /* 00ED */ 2989, + /* 00EE */ 3001, + /* 00EF */ 3015, + /* 00F0 */ 3027, + /* 00F1 */ 3039, + /* 00F2 */ 3057, + /* 00F3 */ 3072, + /* 00F4 */ 3088, + /* 00F5 */ 3104, + /* 00F6 */ 3117, + /* 00F7 */ 3123, + /* 00F8 */ 3128, + /* 00F9 */ 3140, + /* 00FA */ 3161, + /* 00FB */ 3170, + /* 00FC */ 3180, + /* 00FD */ 3188, + /* 00FE */ 3199, + /* 00FF */ 3224, + /* 0100 */ 3235, + /* 0101 */ 3251, + /* 0102 */ 3276, + /* 0103 */ 3296, + /* 0104 */ 3303, + /* 0105 */ 3325, + /* 0106 */ 3346, + /* 0107 */ 3354, + /* 0108 */ 3360, + /* 0109 */ 3366, + /* 010A */ 3372, + /* 010B */ 3390, + /* 010C */ 3397, + /* 010D */ 3409, + /* 010E */ 3416, + /* 010F */ 3437, + /* 0110 */ 3463, + /* 0111 */ 3470, + /* 0112 */ 3483, + /* 0113 */ 3504, + /* 0114 */ 3515, + /* 0115 */ 3526, + /* 0116 */ 3543, + /* 0117 */ 3554, + /* 0118 */ 3560, + /* 0119 */ 3579, + /* 011A */ 3598, + /* 011B */ 3611, + /* 011C */ 3630, + /* 011D */ 3643, + /* 011E */ 3648, + /* 011F */ 3652, + /* 0120 */ 3666, + /* 0121 */ 3678, + /* 0122 */ 3693, + /* 0123 */ 3698, + /* 0124 */ 3711, + /* 0125 */ 3715, + /* 0126 */ 3721, + /* 0127 */ 3730, + /* 0128 */ 3747, + /* 0129 */ 3766, + /* 012A */ 3771, + /* 012B */ 3775, + /* 012C */ 3784, + /* 012D */ 3795, + /* 012E */ 3807, + /* 012F */ 3823, + /* 0130 */ 3831, + /* 0131 */ 3844, + /* 0132 */ 3855, + /* 0133 */ 3865, + /* 0134 */ 3883, + /* 0135 */ 3894, + /* 0136 */ 3904, + /* 0137 */ 3922, + /* 0138 */ 3937, + /* 0139 */ 3961, + /* 013A */ 3986, + /* 013B */ 4007, + /* 013C */ 4020, + /* 013D */ 4024, + /* 013E */ 4033, + /* 013F */ 4040, + /* 0140 */ 4048, + /* 0141 */ 4054, + /* 0142 */ 4063, + /* 0143 */ 4081, + /* 0144 */ 4098, + /* 0145 */ 4105, + /* 0146 */ 4113, + /* 0147 */ 4118, + /* 0148 */ 4128, + /* 0149 */ 4139, + /* 014A */ 4163, + /* 014B */ 4185, + /* 014C */ 4208, + /* 014D */ 4215, + /* 014E */ 4232, + /* 014F */ 4239, + /* 0150 */ 4263, + /* 0151 */ 4271, + /* 0152 */ 4292, + /* 0153 */ 4298, + /* 0154 */ 4316, + /* 0155 */ 4333, + /* 0156 */ 4347, + /* 0157 */ 4364, + /* 0158 */ 4383, + /* 0159 */ 4397, + /* 015A */ 4402, + /* 015B */ 4408, + /* 015C */ 4412, + /* 015D */ 4429, + /* 015E */ 4448, + /* 015F */ 4452, + /* 0160 */ 4458, + /* 0161 */ 4472, + /* 0162 */ 4485, + /* 0163 */ 4507, + /* 0164 */ 4520, + /* 0165 */ 4525, + /* 0166 */ 4549, + /* 0167 */ 4555, + /* 0168 */ 4561, + /* 0169 */ 4569, + /* 016A */ 4576, + /* 016B */ 4586, + /* 016C */ 4608, + /* 016D */ 4613, + /* 016E */ 4622, + /* 016F */ 4630, + /* 0170 */ 4646, + /* 0171 */ 4662, + /* 0172 */ 4673, + /* 0173 */ 4680, + /* 0174 */ 4697, + /* 0175 */ 4714, + /* 0176 */ 4721, + /* 0177 */ 4730, + /* 0178 */ 4738, + /* 0179 */ 4756, + /* 017A */ 4780, + /* 017B */ 4802, + /* 017C */ 4822, + /* 017D */ 4828, + /* 017E */ 4837, + /* 017F */ 4843, + /* 0180 */ 4859, + /* 0181 */ 4875, + /* 0182 */ 4885, + /* 0183 */ 4899, + /* 0184 */ 4917, + /* 0185 */ 4932, + /* 0186 */ 4955, + /* 0187 */ 4962, + /* 0188 */ 4970, + /* 0189 */ 4976, + /* 018A */ 4996, + /* 018B */ 5018, + /* 018C */ 5041, + /* 018D */ 5060, + /* 018E */ 5077, + /* 018F */ 5092, + /* 0190 */ 5112, + /* 0191 */ 5130, + /* 0192 */ 5142, + /* 0193 */ 5160, + /* 0194 */ 5166, + /* 0195 */ 5184, + /* 0196 */ 5190, + /* 0197 */ 5197, + /* 0198 */ 5202, + /* 0199 */ 5213, + /* 019A */ 5225, + /* 019B */ 5240, + /* 019C */ 5259, + /* 019D */ 5287, + /* 019E */ 5297, + /* 019F */ 5301, + /* 01A0 */ 5313, + /* 01A1 */ 5333, + /* 01A2 */ 5343, + /* 01A3 */ 5356, + /* 01A4 */ 5365, + /* 01A5 */ 5370, + /* 01A6 */ 5381, + /* 01A7 */ 5385, + /* 01A8 */ 5392, + /* 01A9 */ 5397, + /* 01AA */ 5403, + /* 01AB */ 5410, + /* 01AC */ 5419, + /* 01AD */ 5431, + /* 01AE */ 5437, + /* 01AF */ 5442, + /* 01B0 */ 5448, + /* 01B1 */ 5461, + /* 01B2 */ 5474, + /* 01B3 */ 5487, + /* 01B4 */ 5493, + /* 01B5 */ 5504, + /* 01B6 */ 5517, + /* 01B7 */ 5524, + /* 01B8 */ 5531, + /* 01B9 */ 5545, + /* 01BA */ 5561, + /* 01BB */ 5569, + /* 01BC */ 5579, + /* 01BD */ 5588, + /* 01BE */ 5605, + /* 01BF */ 5613, + /* 01C0 */ 5620, + /* 01C1 */ 5639, + /* 01C2 */ 5680, + /* 01C3 */ 5709, + /* 01C4 */ 5740, + /* 01C5 */ 5774, + /* 01C6 */ 5807, + /* 01C7 */ 5839, + /* 01C8 */ 5871, + /* 01C9 */ 5905, + /* 01CA */ 5939, + /* 01CB */ 5973, + /* 01CC */ 5995, + /* 01CD */ 6014, + /* 01CE */ 6035, + /* 01CF */ 6066, + /* 01D0 */ 6076, + /* 01D1 */ 6094, + /* 01D2 */ 6111, + /* 01D3 */ 6143, + /* 01D4 */ 6167, + /* 01D5 */ 6193, + /* 01D6 */ 6239, + /* 01D7 */ 6251, + /* 01D8 */ 6268, + /* 01D9 */ 6284, + /* 01DA */ 6293, + /* 01DB */ 6304, + /* 01DC */ 6315, + /* 01DD */ 6319, + /* 01DE */ 6324, + /* 01DF */ 6331, + /* 01E0 */ 6356, + /* 01E1 */ 6363, + /* 01E2 */ 6384, + /* 01E3 */ 6399, + /* 01E4 */ 6411, + /* 01E5 */ 6423, + /* 01E6 */ 6428, + /* 01E7 */ 6439, + /* 01E8 */ 6448, + /* 01E9 */ 6458, + /* 01EA */ 6467, + /* 01EB */ 6478, + /* 01EC */ 6498, + /* 01ED */ 6504, + /* 01EE */ 6518, + /* 01EF */ 6528, + /* 01F0 */ 6536, + /* 01F1 */ 6551, + /* 01F2 */ 6561, + /* 01F3 */ 6568, + /* 01F4 */ 6580, + /* 01F5 */ 6587, + /* 01F6 */ 6599, + /* 01F7 */ 6608, + /* 01F8 */ 6616, + /* 01F9 */ 6624, + /* 01FA */ 6632, + /* 01FB */ 6644, + /* 01FC */ 6652, + /* 01FD */ 6660, + /* 01FE */ 6669, + /* 01FF */ 6678, + /* 0200 */ 6687, + /* 0201 */ 6696, + /* 0202 */ 6705, + /* 0203 */ 6721, + /* 0204 */ 6729, + /* 0205 */ 6740, + /* 0206 */ 6753, + /* 0207 */ 6775, + /* 0208 */ 6800, + /* 0209 */ 6811, + /* 020A */ 6827, + /* 020B */ 6841, + /* 020C */ 6862, + /* 020D */ 6886, + /* 020E */ 6894, + /* 020F */ 6900, + /* 0210 */ 6905, + /* 0211 */ 6913, + /* 0212 */ 6923, + /* 0213 */ 6934, + /* 0214 */ 6943, + /* 0215 */ 6952, + /* 0216 */ 6965, + /* 0217 */ 6970, + /* 0218 */ 6979, + /* 0219 */ 6987, + /* 021A */ 7003, + /* 021B */ 7011, + /* 021C */ 7027, + /* 021D */ 7036, + /* 021E */ 7053, + /* 021F */ 7060, + /* 0220 */ 7067, + /* 0221 */ 7074, + /* 0222 */ 7086, + /* 0223 */ 7099, + /* 0224 */ 7120, + /* 0225 */ 7127, + /* 0226 */ 7135, + /* 0227 */ 7150, + /* 0228 */ 7156, + /* 0229 */ 7172, + /* 022A */ 7182, + /* 022B */ 7190, + /* 022C */ 7195, + /* 022D */ 7203, + /* 022E */ 7211, + /* 022F */ 7236, + /* 0230 */ 7247, + /* 0231 */ 7260, + /* 0232 */ 7268, + /* 0233 */ 7281, + /* 0234 */ 7295, + /* 0235 */ 7301, + /* 0236 */ 7311, + /* 0237 */ 7313, + /* 0238 */ 7329, + /* 0239 */ 7331, + /* 023A */ 7336, + /* 023B */ 7341, + /* 023C */ 7348, + /* 023D */ 7355, + /* 023E */ 7362, + /* 023F */ 7372, + /* 0240 */ 7379, + /* 0241 */ 7392, + /* 0242 */ 7402, + /* 0243 */ 7411, + /* 0244 */ 7418, + /* 0245 */ 7428, + /* 0246 */ 7450, + /* 0247 */ 7465, + /* 0248 */ 7479, + /* 0249 */ 7485, + /* 024A */ 7492, + /* 024B */ 7499, + /* 024C */ 7511, + /* 024D */ 7526, + /* 024E */ 7535, + /* 024F */ 7552, + /* 0250 */ 7560, + /* 0251 */ 7566, + /* 0252 */ 7578, + /* 0253 */ 7584, + /* 0254 */ 7604, + /* 0255 */ 7626, + /* 0256 */ 7639, + /* 0257 */ 7653, + /* 0258 */ 7666, + /* 0259 */ 7675, + /* 025A */ 7695, + /* 025B */ 7718, + /* 025C */ 7742, + /* 025D */ 7759, + /* 025E */ 7783, + /* 025F */ 7809, + /* 0260 */ 7819, + /* 0261 */ 7832, + /* 0262 */ 7858, + /* 0263 */ 7871, + /* 0264 */ 7881, + /* 0265 */ 7893, + /* 0266 */ 7905, + /* 0267 */ 7920, + /* 0268 */ 7933, + /* 0269 */ 7946, + /* 026A */ 7956, + /* 026B */ 7966, + /* 026C */ 7978, + /* 026D */ 7996, + /* 026E */ 8012, + /* 026F */ 8030, + /* 0270 */ 8050, + /* 0271 */ 8071, + /* 0272 */ 8100, + /* 0273 */ 8109, + /* 0274 */ 8127, + /* 0275 */ 8146, + /* 0276 */ 8154, + /* 0277 */ 8167, + /* 0278 */ 8181, + /* 0279 */ 8195, + /* 027A */ 8212, + /* 027B */ 8221, + /* 027C */ 8239, + /* 027D */ 8249, + /* 027E */ 8257, + /* 027F */ 8271, + /* 0280 */ 8285, + /* 0281 */ 8295, + /* 0282 */ 8320, + /* 0283 */ 8338, + /* 0284 */ 8355, + /* 0285 */ 8379, + /* 0286 */ 8392, + /* 0287 */ 8419, + /* 0288 */ 8447, + /* 0289 */ 8464, + /* 028A */ 8473, + /* 028B */ 8483, + /* 028C */ 8490, + /* 028D */ 8509, + /* 028E */ 8524, + /* 028F */ 8536, + /* 0290 */ 8548, + /* 0291 */ 8563, + /* 0292 */ 8579, + /* 0293 */ 8591, + /* 0294 */ 8602, + /* 0295 */ 8614, + /* 0296 */ 8630, + /* 0297 */ 8646, + /* 0298 */ 8665, + /* 0299 */ 8681, + /* 029A */ 8694, + /* 029B */ 8709, + /* 029C */ 8728, + /* 029D */ 8741, + /* 029E */ 8760, + /* 029F */ 8772, + /* 02A0 */ 8788, + /* 02A1 */ 8802, + /* 02A2 */ 8813, + /* 02A3 */ 8822, + /* 02A4 */ 8831, + /* 02A5 */ 8840, + /* 02A6 */ 8859, + /* 02A7 */ 8870, + /* 02A8 */ 8890, + /* 02A9 */ 8910, + /* 02AA */ 8920, + /* 02AB */ 8940, + /* 02AC */ 8956, + /* 02AD */ 8974, + /* 02AE */ 8989, + /* 02AF */ 9001, + /* 02B0 */ 9012, + /* 02B1 */ 9028, + /* 02B2 */ 9045, + /* 02B3 */ 9055, + /* 02B4 */ 9066, + /* 02B5 */ 9078, + /* 02B6 */ 9088, + /* 02B7 */ 9098, + /* 02B8 */ 9118, + /* 02B9 */ 9133, + /* 02BA */ 9142, + /* 02BB */ 9159, + /* 02BC */ 9167, + /* 02BD */ 9194, + /* 02BE */ 9211, + /* 02BF */ 9236, + /* 02C0 */ 9257, + /* 02C1 */ 9265, + /* 02C2 */ 9279, + /* 02C3 */ 9302, + /* 02C4 */ 9319, + /* 02C5 */ 9333, + /* 02C6 */ 9344, + /* 02C7 */ 9356, + /* 02C8 */ 9371, + /* 02C9 */ 9384, + /* 02CA */ 9401, + /* 02CB */ 9414, + /* 02CC */ 9431, + /* 02CD */ 9448, + /* 02CE */ 9467, + /* 02CF */ 9483, + /* 02D0 */ 9503, + /* 02D1 */ 9518, + /* 02D2 */ 9531, + /* 02D3 */ 9539, + /* 02D4 */ 9550, + /* 02D5 */ 9562, + /* 02D6 */ 9575, + /* 02D7 */ 9596, + /* 02D8 */ 9617, + /* 02D9 */ 9645, + /* 02DA */ 9660, + /* 02DB */ 9677, + /* 02DC */ 9687, + /* 02DD */ 9699, + /* 02DE */ 9712, + /* 02DF */ 9723, + /* 02E0 */ 9739, + /* 02E1 */ 9749, + /* 02E2 */ 9763, + /* 02E3 */ 9781, + /* 02E4 */ 9791, + /* 02E5 */ 9800, + /* 02E6 */ 9837, + /* 02E7 */ 9860, + /* 02E8 */ 9871, + /* 02E9 */ 9882, + /* 02EA */ 9894, + /* 02EB */ 9911, + /* 02EC */ 9920, + /* 02ED */ 9941, + /* 02EE */ 9944, + /* 02EF */ 9950, + /* 02F0 */ 9954, + /* 02F1 */ 9970, + /* 02F2 */ 9986, + /* 02F3 */ 9998, + /* 02F4 */ 10011, + /* 02F5 */ 10025, + /* 02F6 */ 10039, + /* 02F7 */ 10055, + /* 02F8 */ 10066, + /* 02F9 */ 10076, + /* 02FA */ 10081, + /* 02FB */ 10095, + /* 02FC */ 10106, + /* 02FD */ 10115, + /* 02FE */ 10127, + /* 02FF */ 10138, + /* 0300 */ 10153, + /* 0301 */ 10164, + /* 0302 */ 10175, + /* 0303 */ 10189, + /* 0304 */ 10203, + /* 0305 */ 10217, + /* 0306 */ 10224, + /* 0307 */ 10232, + /* 0308 */ 10248, + /* 0309 */ 10254, + /* 030A */ 10271, + /* 030B */ 10279, + /* 030C */ 10294, + /* 030D */ 10303, + /* 030E */ 10310, + /* 030F */ 10315, + /* 0310 */ 10332, + /* 0311 */ 10341, + /* 0312 */ 10351, + /* 0313 */ 10358, + /* 0314 */ 10370, + /* 0315 */ 10379, + /* 0316 */ 10390, + /* 0317 */ 10400, + /* 0318 */ 10407, + /* 0319 */ 10414, + /* 031A */ 10431, + /* 031B */ 10436, + /* 031C */ 10449, + /* 031D */ 10460, + /* 031E */ 10466, + /* 031F */ 10482, + /* 0320 */ 10489, + /* 0321 */ 10498, + /* 0322 */ 10511, + /* 0323 */ 10519, + /* 0324 */ 10527, + /* 0325 */ 10537, + /* 0326 */ 10545, + /* 0327 */ 10559, + /* 0328 */ 10567, + /* 0329 */ 10574, + /* 032A */ 10582, + /* 032B */ 10590, + /* 032C */ 10606, + /* 032D */ 10617, + /* 032E */ 10626, + /* 032F */ 10639, + /* 0330 */ 10644, + /* 0331 */ 10652, + /* 0332 */ 10675, + /* 0333 */ 10696, + /* 0334 */ 10713, + /* 0335 */ 10725, + /* 0336 */ 10737, + /* 0337 */ 10752, + /* 0338 */ 10774, + /* 0339 */ 10788, + /* 033A */ 10800, + /* 033B */ 10819, + /* 033C */ 10834, + /* 033D */ 10851, + /* 033E */ 10864, + /* 033F */ 10877, + /* 0340 */ 10890, + /* 0341 */ 10903, + /* 0342 */ 10914, + /* 0343 */ 10920, + /* 0344 */ 10938, + /* 0345 */ 10959, + /* 0346 */ 10987, + /* 0347 */ 11015, + /* 0348 */ 11028, + /* 0349 */ 11057, + /* 034A */ 11082, + /* 034B */ 11099, + /* 034C */ 11108, + /* 034D */ 11119, + /* 034E */ 11137, + /* 034F */ 11150, + /* 0350 */ 11163, + /* 0351 */ 11179, + /* 0352 */ 11190, + /* 0353 */ 11213, + /* 0354 */ 11230, + /* 0355 */ 11247, + /* 0356 */ 11264, + /* 0357 */ 11269, + /* 0358 */ 11283, + /* 0359 */ 11297, + /* 035A */ 11303, + /* 035B */ 11311, +}; + +const char c_CLR_StringTable_Data[] = + /* 0000 */ ".cctor\0" + /* 0001 */ ".ctor\0" + /* 0002 */ "Abort\0" + /* 0003 */ "Abs\0" + /* 0004 */ "AccessedThroughPropertyAttribute\0" + /* 0005 */ "Acos\0" + /* 0006 */ "Add\0" + /* 0007 */ "AddDays\0" + /* 0008 */ "AddHours\0" + /* 0009 */ "AddMilliseconds\0" + /* 000A */ "AddMinutes\0" + /* 000B */ "AddSeconds\0" + /* 000C */ "AddTicks\0" + /* 000D */ "AnyPendingFinalizers\0" + /* 000E */ "AppDomain\0" + /* 000F */ "AppDomainUnloadedException\0" + /* 0010 */ "Append\0" + /* 0011 */ "AppendHelper\0" + /* 0012 */ "AppendLine\0" + /* 0013 */ "AppendTrailingZeros\0" + /* 0014 */ "ApplicationException\0" + /* 0015 */ "ArgumentException\0" + /* 0016 */ "ArgumentNullException\0" + /* 0017 */ "ArgumentOutOfRangeException\0" + /* 0018 */ "Arguments\0" + /* 0019 */ "Array\0" + /* 001A */ "ArrayList\0" + /* 001B */ "ArraySize\0" + /* 001C */ "Asin\0" + /* 001D */ "Assembly\0" + /* 001E */ "AssemblyInfo\0" + /* 001F */ "AssemblyMemoryInfo\0" + /* 0020 */ "AssemblyName\0" + /* 0021 */ "AssemblyNameFlags\0" + /* 0022 */ "AssemblyRef\0" + /* 0023 */ "AssemblyRefElements\0" + /* 0024 */ "Assert\0" + /* 0025 */ "AsyncCallback\0" + /* 0026 */ "Atan\0" + /* 0027 */ "Atan2\0" + /* 0028 */ "Attribute\0" + /* 0029 */ "Attributes\0" + /* 002A */ "AttributesElements\0" + /* 002B */ "AutoResetEvent\0" + /* 002C */ "Backlight\0" + /* 002D */ "BaseEvent\0" + /* 002E */ "BeginInvoke\0" + /* 002F */ "Bias\0" + /* 0030 */ "BinarySearch\0" + /* 0031 */ "Binder\0" + /* 0032 */ "BindingFlags\0" + /* 0033 */ "BitConverter\0" + /* 0034 */ "BitPacked\0" + /* 0035 */ "Boolean\0" + /* 0036 */ "Break\0" + /* 0037 */ "Byte\0" + /* 0038 */ "ByteCode\0" + /* 0039 */ "Ceiling\0" + /* 003A */ "Change\0" + /* 003B */ "Char\0" + /* 003C */ "Check\0" + /* 003D */ "Clear\0" + /* 003E */ "Clone\0" + /* 003F */ "Close\0" + /* 0040 */ "Combine\0" + /* 0041 */ "CombineArrays\0" + /* 0042 */ "Compare\0" + /* 0043 */ "CompareExchange\0" + /* 0044 */ "CompareTo\0" + /* 0045 */ "ComputeCRC\0" + /* 0046 */ "Concat\0" + /* 0047 */ "ConstraintException\0" + /* 0048 */ "ConstructorInfo\0" + /* 0049 */ "ContactHeight\0" + /* 004A */ "ContactWidth\0" + /* 004B */ "Contains\0" + /* 004C */ "Convert\0" + /* 004D */ "Copy\0" + /* 004E */ "CopyTo\0" + /* 004F */ "CopyToCollection\0" + /* 0050 */ "Cos\0" + /* 0051 */ "Cosh\0" + /* 0052 */ "CreateDomain\0" + /* 0053 */ "CreateInstance\0" + /* 0054 */ "CreateInstanceAndUnwrap\0" + /* 0055 */ "CultureInfo\0" + /* 0056 */ "CultureTypes\0" + /* 0057 */ "CurrentSystemTimeZone\0" + /* 0058 */ "DateTime\0" + /* 0059 */ "DateTimeFormat\0" + /* 005A */ "DateTimeFormatInfo\0" + /* 005B */ "DateTimeKind\0" + /* 005C */ "Day\0" + /* 005D */ "DayOfWeek\0" + /* 005E */ "DaylightBias\0" + /* 005F */ "DaylightDate\0" + /* 0060 */ "DaylightName\0" + /* 0061 */ "DaylightTime\0" + /* 0062 */ "DaysInMonth\0" + /* 0063 */ "Debug\0" + /* 0064 */ "DebuggableAttribute\0" + /* 0065 */ "Debugger\0" + /* 0066 */ "DebuggingModes\0" + /* 0067 */ "Decoder\0" + /* 0068 */ "Decrement\0" + /* 0069 */ "Delegate\0" + /* 006A */ "Dequeue\0" + /* 006B */ "Deserialize\0" + /* 006C */ "DictionaryEntry\0" + /* 006D */ "Dispose\0" + /* 006E */ "Double\0" + /* 006F */ "DoubleToInt64Bits\0" + /* 0070 */ "Duration\0" + /* 0071 */ "EditorBrowsableState\0" + /* 0072 */ "Empty\0" + /* 0073 */ "EnableGCMessages\0" + /* 0074 */ "Encoding\0" + /* 0075 */ "EndInvoke\0" + /* 0076 */ "EndPoint\0" + /* 0077 */ "Enqueue\0" + /* 0078 */ "EnsureCapacity\0" + /* 0079 */ "EnsureStringArrayResource\0" + /* 007A */ "EnsureStringResource\0" + /* 007B */ "Enter\0" + /* 007C */ "Entry\0" + /* 007D */ "EntryForKey\0" + /* 007E */ "Enum\0" + /* 007F */ "EnumeratorType\0" + /* 0080 */ "Equals\0" + /* 0081 */ "EventArgs\0" + /* 0082 */ "EventCategory\0" + /* 0083 */ "EventData\0" + /* 0084 */ "EventMessage\0" + /* 0085 */ "Exception\0" + /* 0086 */ "Exchange\0" + /* 0087 */ "ExecutionConstraint\0" + /* 0088 */ "Exit\0" + /* 0089 */ "Exp\0" + /* 008A */ "ExpandByABlock\0" + /* 008B */ "ExtendedTimer\0" + /* 008C */ "ExtendedWeakReference\0" + /* 008D */ "ExtensionAttribute\0" + /* 008E */ "ExtractRangeFromArray\0" + /* 008F */ "ExtractValueFromArray\0" + /* 0090 */ "FalseString\0" + /* 0091 */ "FieldDef\0" + /* 0092 */ "FieldDefElements\0" + /* 0093 */ "FieldInfo\0" + /* 0094 */ "FieldRef\0" + /* 0095 */ "FieldRefElements\0" + /* 0096 */ "Finalize\0" + /* 0097 */ "FindChunkForIndex\0" + /* 0098 */ "FindResource\0" + /* 0099 */ "Flags\0" + /* 009A */ "Floor\0" + /* 009B */ "Flush\0" + /* 009C */ "FlushAll\0" + /* 009D */ "Format\0" + /* 009E */ "FormatCustomized\0" + /* 009F */ "FormatDigits\0" + /* 00A0 */ "FormatNative\0" + /* 00A1 */ "FromBase64CharArray\0" + /* 00A2 */ "FromBase64String\0" + /* 00A3 */ "FromTicks\0" + /* 00A4 */ "GC\0" + /* 00A5 */ "GenericEvent\0" + /* 00A6 */ "Gesture\0" + /* 00A7 */ "GetAssemblies\0" + /* 00A8 */ "GetAssembly\0" + /* 00A9 */ "GetAssemblyFromHash\0" + /* 00AA */ "GetAssemblyHash\0" + /* 00AB */ "GetAssemblyInfo\0" + /* 00AC */ "GetAssemblyMemoryInfo\0" + /* 00AD */ "GetBase64EncodedLength\0" + /* 00AE */ "GetBytes\0" + /* 00AF */ "GetChars\0" + /* 00B0 */ "GetConstructor\0" + /* 00B1 */ "GetCultures\0" + /* 00B2 */ "GetDaylightChanges\0" + /* 00B3 */ "GetDecoder\0" + /* 00B4 */ "GetDelimitedStringResource\0" + /* 00B5 */ "GetDelimitedStringResources\0" + /* 00B6 */ "GetDomain\0" + /* 00B7 */ "GetDoubleNumber\0" + /* 00B8 */ "GetEffectiveDate\0" + /* 00B9 */ "GetElementType\0" + /* 00BA */ "GetEnumerator\0" + /* 00BB */ "GetExecutingAssembly\0" + /* 00BC */ "GetExpirationDate\0" + /* 00BD */ "GetField\0" + /* 00BE */ "GetFields\0" + /* 00BF */ "GetFormat\0" + /* 00C0 */ "GetHashCode\0" + /* 00C1 */ "GetInterfaces\0" + /* 00C2 */ "GetMachineTime\0" + /* 00C3 */ "GetManifestResourceNames\0" + /* 00C4 */ "GetMessage\0" + /* 00C5 */ "GetMethod\0" + /* 00C6 */ "GetMethods\0" + /* 00C7 */ "GetName\0" + /* 00C8 */ "GetObject\0" + /* 00C9 */ "GetObjectChunkFromId\0" + /* 00CA */ "GetObjectFromId\0" + /* 00CB */ "GetObjectInternal\0" + /* 00CC */ "GetObjectValue\0" + /* 00CD */ "GetParentCultureName\0" + /* 00CE */ "GetPosition\0" + /* 00CF */ "GetRawCertData\0" + /* 00D0 */ "GetRealFormat\0" + /* 00D1 */ "GetSatelliteAssembly\0" + /* 00D2 */ "GetString\0" + /* 00D3 */ "GetSystemVersion\0" + /* 00D4 */ "GetTimeZoneOffset\0" + /* 00D5 */ "GetType\0" + /* 00D6 */ "GetTypeFromHandle\0" + /* 00D7 */ "GetTypeFromHash\0" + /* 00D8 */ "GetTypeHash\0" + /* 00D9 */ "GetTypeInternal\0" + /* 00DA */ "GetTypes\0" + /* 00DB */ "GetTypesImplementingInterface\0" + /* 00DC */ "GetUtcOffset\0" + /* 00DD */ "GetValue\0" + /* 00DE */ "GetVersion\0" + /* 00DF */ "GloballySynchronizedAttribute\0" + /* 00E0 */ "Guid\0" + /* 00E1 */ "Hash\0" + /* 00E2 */ "Hashtable\0" + /* 00E3 */ "HashtableEnumerator\0" + /* 00E4 */ "HexToChar\0" + /* 00E5 */ "Hour\0" + /* 00E6 */ "IAsyncResult\0" + /* 00E7 */ "ICloneable\0" + /* 00E8 */ "ICollection\0" + /* 00E9 */ "IComparable\0" + /* 00EA */ "IComparer\0" + /* 00EB */ "ICustomFormatter\0" + /* 00EC */ "IDictionary\0" + /* 00ED */ "IDisposable\0" + /* 00EE */ "IEEERemainder\0" + /* 00EF */ "IEnumerable\0" + /* 00F0 */ "IEnumerator\0" + /* 00F1 */ "IEqualityComparer\0" + /* 00F2 */ "IEventListener\0" + /* 00F3 */ "IEventProcessor\0" + /* 00F4 */ "IFormatProvider\0" + /* 00F5 */ "IFormattable\0" + /* 00F6 */ "IList\0" + /* 00F7 */ "ILog\0" + /* 00F8 */ "IOException\0" + /* 00F9 */ "IOExceptionErrorCode\0" + /* 00FA */ "IReflect\0" + /* 00FB */ "Increment\0" + /* 00FC */ "IndexOf\0" + /* 00FD */ "IndexOfAny\0" + /* 00FE */ "IndexOutOfRangeException\0" + /* 00FF */ "Initialize\0" + /* 0100 */ "InitializeArray\0" + /* 0101 */ "InitializeForEventSource\0" + /* 0102 */ "InitializeHashTable\0" + /* 0103 */ "Insert\0" + /* 0104 */ "InsertGroupSeperators\0" + /* 0105 */ "InsertValueIntoArray\0" + /* 0106 */ "Install\0" + /* 0107 */ "Int16\0" + /* 0108 */ "Int32\0" + /* 0109 */ "Int64\0" + /* 010A */ "Int64BitsToDouble\0" + /* 010B */ "IntPtr\0" + /* 010C */ "Interlocked\0" + /* 010D */ "Intern\0" + /* 010E */ "InvalidCastException\0" + /* 010F */ "InvalidOperationException\0" + /* 0110 */ "Invoke\0" + /* 0111 */ "InvokeMember\0" + /* 0112 */ "IsDaylightSavingTime\0" + /* 0113 */ "IsEmulator\0" + /* 0114 */ "IsInfinity\0" + /* 0115 */ "IsInstanceOfType\0" + /* 0116 */ "IsInterned\0" + /* 0117 */ "IsNaN\0" + /* 0118 */ "IsNegativeInfinity\0" + /* 0119 */ "IsPositiveInfinity\0" + /* 011A */ "IsSubclassOf\0" + /* 011B */ "IsTransparentProxy\0" + /* 011C */ "IsTypeLoaded\0" + /* 011D */ "Join\0" + /* 011E */ "Key\0" + /* 011F */ "KeyCollection\0" + /* 0120 */ "LastIndexOf\0" + /* 0121 */ "LastIndexOfAny\0" + /* 0122 */ "Load\0" + /* 0123 */ "LoadInternal\0" + /* 0124 */ "Log\0" + /* 0125 */ "Log10\0" + /* 0126 */ "MakeRoom\0" + /* 0127 */ "ManualResetEvent\0" + /* 0128 */ "MarshalByRefObject\0" + /* 0129 */ "Math\0" + /* 012A */ "Max\0" + /* 012B */ "MaxValue\0" + /* 012C */ "MemberInfo\0" + /* 012D */ "MemberTypes\0" + /* 012E */ "MemberwiseClone\0" + /* 012F */ "Message\0" + /* 0130 */ "MetadataSize\0" + /* 0131 */ "MethodBase\0" + /* 0132 */ "MethodDef\0" + /* 0133 */ "MethodDefElements\0" + /* 0134 */ "MethodInfo\0" + /* 0135 */ "MethodRef\0" + /* 0136 */ "MethodRefElements\0" + /* 0137 */ "Microsoft.SPOT\0" + /* 0138 */ "Microsoft.SPOT.Hardware\0" + /* 0139 */ "Microsoft.SPOT.Messaging\0" + /* 013A */ "Microsoft.SPOT.Touch\0" + /* 013B */ "Milliseconds\0" + /* 013C */ "Min\0" + /* 013D */ "MinValue\0" + /* 013E */ "Minute\0" + /* 013F */ "Monitor\0" + /* 0140 */ "Month\0" + /* 0141 */ "MoveNext\0" + /* 0142 */ "MulticastDelegate\0" + /* 0143 */ "Native_Resources\0" + /* 0144 */ "Negate\0" + /* 0145 */ "NewGuid\0" + /* 0146 */ "Next\0" + /* 0147 */ "NextBytes\0" + /* 0148 */ "NextDouble\0" + /* 0149 */ "NotImplementedException\0" + /* 014A */ "NotSupportedException\0" + /* 014B */ "NullReferenceException\0" + /* 014C */ "Number\0" + /* 014D */ "NumberFormatInfo\0" + /* 014E */ "Object\0" + /* 014F */ "ObjectDisposedException\0" + /* 0150 */ "OnEvent\0" + /* 0151 */ "OutOfMemoryException\0" + /* 0152 */ "Parse\0" + /* 0153 */ "ParseAssemblyName\0" + /* 0154 */ "ParseCertificate\0" + /* 0155 */ "ParseNextChar\0" + /* 0156 */ "ParseQuoteString\0" + /* 0157 */ "ParseRepeatPattern\0" + /* 0158 */ "ParseTypeName\0" + /* 0159 */ "Peek\0" + /* 015A */ "Piezo\0" + /* 015B */ "Pop\0" + /* 015C */ "PostProcessFloat\0" + /* 015D */ "PostProcessInteger\0" + /* 015E */ "Pow\0" + /* 015F */ "Print\0" + /* 0160 */ "PriorityLevel\0" + /* 0161 */ "ProcessEvent\0" + /* 0162 */ "ProcessorArchitecture\0" + /* 0163 */ "PropertyInfo\0" + /* 0164 */ "Push\0" + /* 0165 */ "PushBackIntoRecoverList\0" + /* 0166 */ "Queue\0" + /* 0167 */ "Raise\0" + /* 0168 */ "RamSize\0" + /* 0169 */ "Random\0" + /* 016A */ "RangeBias\0" + /* 016B */ "ReRegisterForFinalize\0" + /* 016C */ "Read\0" + /* 016D */ "ReadByte\0" + /* 016E */ "Recover\0" + /* 016F */ "RecoverOrCreate\0" + /* 0170 */ "ReferenceEquals\0" + /* 0171 */ "Reflection\0" + /* 0172 */ "Rehash\0" + /* 0173 */ "RemotedException\0" + /* 0174 */ "RemotingServices\0" + /* 0175 */ "Remove\0" + /* 0176 */ "RemoveAt\0" + /* 0177 */ "Replace\0" + /* 0178 */ "ReplaceAllInChunk\0" + /* 0179 */ "ReplaceDecimalSeperator\0" + /* 017A */ "ReplaceInPlaceAtChunk\0" + /* 017B */ "ReplaceNegativeSign\0" + /* 017C */ "Reply\0" + /* 017D */ "ReplyRaw\0" + /* 017E */ "Reset\0" + /* 017F */ "ResourceManager\0" + /* 0180 */ "ResourceUtility\0" + /* 0181 */ "Resources\0" + /* 0182 */ "ResourcesData\0" + /* 0183 */ "ResourcesElements\0" + /* 0184 */ "ResourcesFiles\0" + /* 0185 */ "ResourcesFilesElements\0" + /* 0186 */ "Resume\0" + /* 0187 */ "RomSize\0" + /* 0188 */ "Round\0" + /* 0189 */ "RunClassConstructor\0" + /* 018A */ "RuntimeArgumentHandle\0" + /* 018B */ "RuntimeConstructorInfo\0" + /* 018C */ "RuntimeFieldHandle\0" + /* 018D */ "RuntimeFieldInfo\0" + /* 018E */ "RuntimeHelpers\0" + /* 018F */ "RuntimeMethodHandle\0" + /* 0190 */ "RuntimeMethodInfo\0" + /* 0191 */ "RuntimeType\0" + /* 0192 */ "RuntimeTypeHandle\0" + /* 0193 */ "SByte\0" + /* 0194 */ "SZArrayEnumerator\0" + /* 0195 */ "Scale\0" + /* 0196 */ "Second\0" + /* 0197 */ "Seek\0" + /* 0198 */ "SeekOrigin\0" + /* 0199 */ "SendMessage\0" + /* 019A */ "SendMessageRaw\0" + /* 019B */ "SerializationFlags\0" + /* 019C */ "SerializationHintsAttribute\0" + /* 019D */ "Serialize\0" + /* 019E */ "Set\0" + /* 019F */ "SetCapacity\0" + /* 01A0 */ "SetCurrentUICulture\0" + /* 01A1 */ "SetLength\0" + /* 01A2 */ "SetLocalTime\0" + /* 01A3 */ "SetValue\0" + /* 01A4 */ "Sign\0" + /* 01A5 */ "Signatures\0" + /* 01A6 */ "Sin\0" + /* 01A7 */ "Single\0" + /* 01A8 */ "Sinh\0" + /* 01A9 */ "Sleep\0" + /* 01AA */ "Source\0" + /* 01AB */ "SourceID\0" + /* 01AC */ "SpecifyKind\0" + /* 01AD */ "Split\0" + /* 01AE */ "Sqrt\0" + /* 01AF */ "Stack\0" + /* 01B0 */ "StandardBias\0" + /* 01B1 */ "StandardDate\0" + /* 01B2 */ "StandardName\0" + /* 01B3 */ "Start\0" + /* 01B4 */ "StartsWith\0" + /* 01B5 */ "StaticFields\0" + /* 01B6 */ "Stream\0" + /* 01B7 */ "String\0" + /* 01B8 */ "StringBuilder\0" + /* 01B9 */ "StringResources\0" + /* 01BA */ "Strings\0" + /* 01BB */ "Substring\0" + /* 01BC */ "Subtract\0" + /* 01BD */ "SuppressFinalize\0" + /* 01BE */ "Suspend\0" + /* 01BF */ "System\0" + /* 01C0 */ "System.Collections\0" + /* 01C1 */ "System.Collections.ICollection.get_Count\0" + /* 01C2 */ "System.Collections.IList.Add\0" + /* 01C3 */ "System.Collections.IList.Clear\0" + /* 01C4 */ "System.Collections.IList.Contains\0" + /* 01C5 */ "System.Collections.IList.IndexOf\0" + /* 01C6 */ "System.Collections.IList.Insert\0" + /* 01C7 */ "System.Collections.IList.Remove\0" + /* 01C8 */ "System.Collections.IList.RemoveAt\0" + /* 01C9 */ "System.Collections.IList.get_Item\0" + /* 01CA */ "System.Collections.IList.set_Item\0" + /* 01CB */ "System.ComponentModel\0" + /* 01CC */ "System.Diagnostics\0" + /* 01CD */ "System.Globalization\0" + /* 01CE */ "System.Globalization.Resources\0" + /* 01CF */ "System.IO\0" + /* 01D0 */ "System.Reflection\0" + /* 01D1 */ "System.Resources\0" + /* 01D2 */ "System.Runtime.CompilerServices\0" + /* 01D3 */ "System.Runtime.Remoting\0" + /* 01D4 */ "System.Runtime.Versioning\0" + /* 01D5 */ "System.Security.Cryptography.X509Certificates\0" + /* 01D6 */ "System.Text\0" + /* 01D7 */ "System.Threading\0" + /* 01D8 */ "SystemException\0" + /* 01D9 */ "SystemID\0" + /* 01DA */ "SystemInfo\0" + /* 01DB */ "SystemTime\0" + /* 01DC */ "Tan\0" + /* 01DD */ "Tanh\0" + /* 01DE */ "Target\0" + /* 01DF */ "TargetFrameworkAttribute\0" + /* 01E0 */ "Thread\0" + /* 01E1 */ "ThreadAbortException\0" + /* 01E2 */ "ThreadPriority\0" + /* 01E3 */ "ThreadStart\0" + /* 01E4 */ "ThreadState\0" + /* 01E5 */ "Time\0" + /* 01E6 */ "TimeEvents\0" + /* 01E7 */ "TimeSpan\0" + /* 01E8 */ "TimeStamp\0" + /* 01E9 */ "TimeZone\0" + /* 01EA */ "TimeZoneId\0" + /* 01EB */ "TimeZoneInformation\0" + /* 01EC */ "Timer\0" + /* 01ED */ "TimerCallback\0" + /* 01EE */ "Timestamp\0" + /* 01EF */ "ToArray\0" + /* 01F0 */ "ToBase64String\0" + /* 01F1 */ "ToBoolean\0" + /* 01F2 */ "ToByte\0" + /* 01F3 */ "ToByteArray\0" + /* 01F4 */ "ToChar\0" + /* 01F5 */ "ToCharArray\0" + /* 01F6 */ "ToDouble\0" + /* 01F7 */ "ToInt16\0" + /* 01F8 */ "ToInt32\0" + /* 01F9 */ "ToInt64\0" + /* 01FA */ "ToLocalTime\0" + /* 01FB */ "ToLower\0" + /* 01FC */ "ToSByte\0" + /* 01FD */ "ToSingle\0" + /* 01FE */ "ToString\0" + /* 01FF */ "ToUInt16\0" + /* 0200 */ "ToUInt32\0" + /* 0201 */ "ToUInt64\0" + /* 0202 */ "ToUniversalTime\0" + /* 0203 */ "ToUpper\0" + /* 0204 */ "TouchEvent\0" + /* 0205 */ "TouchGesture\0" + /* 0206 */ "TouchGestureEventArgs\0" + /* 0207 */ "TouchGestureEventHandler\0" + /* 0208 */ "TouchInput\0" + /* 0209 */ "TouchInputFlags\0" + /* 020A */ "TouchMessages\0" + /* 020B */ "TouchScreenEventArgs\0" + /* 020C */ "TouchScreenEventHandler\0" + /* 020D */ "Touches\0" + /* 020E */ "Trace\0" + /* 020F */ "Trim\0" + /* 0210 */ "TrimEnd\0" + /* 0211 */ "TrimStart\0" + /* 0212 */ "TrueString\0" + /* 0213 */ "Truncate\0" + /* 0214 */ "TryParse\0" + /* 0215 */ "TrySZIndexOf\0" + /* 0216 */ "Type\0" + /* 0217 */ "TypeCode\0" + /* 0218 */ "TypeDef\0" + /* 0219 */ "TypeDefElements\0" + /* 021A */ "TypeRef\0" + /* 021B */ "TypeRefElements\0" + /* 021C */ "TypeSpec\0" + /* 021D */ "TypeSpecElements\0" + /* 021E */ "UInt16\0" + /* 021F */ "UInt32\0" + /* 0220 */ "UInt64\0" + /* 0221 */ "UTF8Decoder\0" + /* 0222 */ "UTF8Encoding\0" + /* 0223 */ "UnknownTypeException\0" + /* 0224 */ "Unload\0" + /* 0225 */ "Utility\0" + /* 0226 */ "ValidateFormat\0" + /* 0227 */ "Value\0" + /* 0228 */ "ValueCollection\0" + /* 0229 */ "ValueType\0" + /* 022A */ "Version\0" + /* 022B */ "Void\0" + /* 022C */ "WaitAll\0" + /* 022D */ "WaitAny\0" + /* 022E */ "WaitForPendingFinalizers\0" + /* 022F */ "WaitHandle\0" + /* 0230 */ "WaitMultiple\0" + /* 0231 */ "WaitOne\0" + /* 0232 */ "WeakDelegate\0" + /* 0233 */ "WeakReference\0" + /* 0234 */ "Write\0" + /* 0235 */ "WriteByte\0" + /* 0236 */ "X\0" + /* 0237 */ "X509Certificate\0" + /* 0238 */ "Y\0" + /* 0239 */ "Year\0" + /* 023A */ "Zero\0" + /* 023B */ "_Build\0" + /* 023C */ "_Major\0" + /* 023D */ "_Minor\0" + /* 023E */ "_Revision\0" + /* 023F */ "_array\0" + /* 0240 */ "_arrayLength\0" + /* 0241 */ "_assembly\0" + /* 0242 */ "_buckets\0" + /* 0243 */ "_count\0" + /* 0244 */ "_endIndex\0" + /* 0245 */ "_frameworkDisplayName\0" + /* 0246 */ "_frameworkName\0" + /* 0247 */ "_growthFactor\0" + /* 0248 */ "_head\0" + /* 0249 */ "_index\0" + /* 024A */ "_items\0" + /* 024B */ "_loadFactor\0" + /* 024C */ "_maxLoadFactor\0" + /* 024D */ "_message\0" + /* 024E */ "_numberOfBuckets\0" + /* 024F */ "_random\0" + /* 0250 */ "_size\0" + /* 0251 */ "_startIndex\0" + /* 0252 */ "_tail\0" + /* 0253 */ "abbreviatedDayNames\0" + /* 0254 */ "abbreviatedMonthNames\0" + /* 0255 */ "amDesignator\0" + /* 0256 */ "dateSeparator\0" + /* 0257 */ "dateTimeInfo\0" + /* 0258 */ "dayNames\0" + /* 0259 */ "fullDateTimePattern\0" + /* 025A */ "generalLongTimePattern\0" + /* 025B */ "generalShortTimePattern\0" + /* 025C */ "get_AMDesignator\0" + /* 025D */ "get_AbbreviatedDayNames\0" + /* 025E */ "get_AbbreviatedMonthNames\0" + /* 025F */ "get_Angle\0" + /* 0260 */ "get_Assembly\0" + /* 0261 */ "get_AssemblyQualifiedName\0" + /* 0262 */ "get_BaseType\0" + /* 0263 */ "get_Build\0" + /* 0264 */ "get_CanRead\0" + /* 0265 */ "get_CanSeek\0" + /* 0266 */ "get_CanTimeout\0" + /* 0267 */ "get_CanWrite\0" + /* 0268 */ "get_Capacity\0" + /* 0269 */ "get_Chars\0" + /* 026A */ "get_Count\0" + /* 026B */ "get_Current\0" + /* 026C */ "get_CurrentDomain\0" + /* 026D */ "get_CurrentInfo\0" + /* 026E */ "get_CurrentThread\0" + /* 026F */ "get_CurrentTimeZone\0" + /* 0270 */ "get_CurrentUICulture\0" + /* 0271 */ "get_CurrentUICultureInternal\0" + /* 0272 */ "get_Date\0" + /* 0273 */ "get_DateSeparator\0" + /* 0274 */ "get_DateTimeFormat\0" + /* 0275 */ "get_Day\0" + /* 0276 */ "get_DayNames\0" + /* 0277 */ "get_DayOfWeek\0" + /* 0278 */ "get_DayOfYear\0" + /* 0279 */ "get_DaylightName\0" + /* 027A */ "get_Days\0" + /* 027B */ "get_DeclaringType\0" + /* 027C */ "get_Delta\0" + /* 027D */ "get_End\0" + /* 027E */ "get_ErrorCode\0" + /* 027F */ "get_FieldType\0" + /* 0280 */ "get_Flags\0" + /* 0281 */ "get_FrameworkDisplayName\0" + /* 0282 */ "get_FrameworkName\0" + /* 0283 */ "get_FriendlyName\0" + /* 0284 */ "get_FullDateTimePattern\0" + /* 0285 */ "get_FullName\0" + /* 0286 */ "get_GeneralLongTimePattern\0" + /* 0287 */ "get_GeneralShortTimePattern\0" + /* 0288 */ "get_GrowthFactor\0" + /* 0289 */ "get_Hour\0" + /* 028A */ "get_Hours\0" + /* 028B */ "get_Id\0" + /* 028C */ "get_InnerException\0" + /* 028D */ "get_IsAbstract\0" + /* 028E */ "get_IsAlive\0" + /* 028F */ "get_IsArray\0" + /* 0290 */ "get_IsAttached\0" + /* 0291 */ "get_IsBigEndian\0" + /* 0292 */ "get_IsClass\0" + /* 0293 */ "get_IsEnum\0" + /* 0294 */ "get_IsFinal\0" + /* 0295 */ "get_IsFixedSize\0" + /* 0296 */ "get_IsInterface\0" + /* 0297 */ "get_IsLittleEndian\0" + /* 0298 */ "get_IsNotPublic\0" + /* 0299 */ "get_IsPublic\0" + /* 029A */ "get_IsReadOnly\0" + /* 029B */ "get_IsSerializable\0" + /* 029C */ "get_IsStatic\0" + /* 029D */ "get_IsSynchronized\0" + /* 029E */ "get_IsValid\0" + /* 029F */ "get_IsValueType\0" + /* 02A0 */ "get_IsVirtual\0" + /* 02A1 */ "get_Issuer\0" + /* 02A2 */ "get_Item\0" + /* 02A3 */ "get_Keys\0" + /* 02A4 */ "get_Kind\0" + /* 02A5 */ "get_LastExpiration\0" + /* 02A6 */ "get_Length\0" + /* 02A7 */ "get_LongDatePattern\0" + /* 02A8 */ "get_LongTimePattern\0" + /* 02A9 */ "get_Major\0" + /* 02AA */ "get_ManagedThreadId\0" + /* 02AB */ "get_MaxCapacity\0" + /* 02AC */ "get_MaxLoadFactor\0" + /* 02AD */ "get_MemberType\0" + /* 02AE */ "get_Message\0" + /* 02AF */ "get_Method\0" + /* 02B0 */ "get_Millisecond\0" + /* 02B1 */ "get_Milliseconds\0" + /* 02B2 */ "get_Minor\0" + /* 02B3 */ "get_Minute\0" + /* 02B4 */ "get_Minutes\0" + /* 02B5 */ "get_Model\0" + /* 02B6 */ "get_Month\0" + /* 02B7 */ "get_MonthDayPattern\0" + /* 02B8 */ "get_MonthNames\0" + /* 02B9 */ "get_Name\0" + /* 02BA */ "get_NegativeSign\0" + /* 02BB */ "get_Now\0" + /* 02BC */ "get_NumberDecimalSeparator\0" + /* 02BD */ "get_NumberFormat\0" + /* 02BE */ "get_NumberGroupSeparator\0" + /* 02BF */ "get_NumberGroupSizes\0" + /* 02C0 */ "get_OEM\0" + /* 02C1 */ "get_OEMString\0" + /* 02C2 */ "get_OffsetToStringData\0" + /* 02C3 */ "get_PMDesignator\0" + /* 02C4 */ "get_ParamName\0" + /* 02C5 */ "get_Parent\0" + /* 02C6 */ "get_Payload\0" + /* 02C7 */ "get_PayloadRaw\0" + /* 02C8 */ "get_Position\0" + /* 02C9 */ "get_PositiveSign\0" + /* 02CA */ "get_Priority\0" + /* 02CB */ "get_PropertyName\0" + /* 02CC */ "get_PropertyType\0" + /* 02CD */ "get_RFC1123Pattern\0" + /* 02CE */ "get_ReadTimeout\0" + /* 02CF */ "get_ResourceManager\0" + /* 02D0 */ "get_ReturnType\0" + /* 02D1 */ "get_Revision\0" + /* 02D2 */ "get_SKU\0" + /* 02D3 */ "get_Second\0" + /* 02D4 */ "get_Seconds\0" + /* 02D5 */ "get_Selector\0" + /* 02D6 */ "get_ShortDatePattern\0" + /* 02D7 */ "get_ShortTimePattern\0" + /* 02D8 */ "get_SortableDateTimePattern\0" + /* 02D9 */ "get_StackTrace\0" + /* 02DA */ "get_StandardName\0" + /* 02DB */ "get_Start\0" + /* 02DC */ "get_Subject\0" + /* 02DD */ "get_SyncRoot\0" + /* 02DE */ "get_Target\0" + /* 02DF */ "get_ThreadState\0" + /* 02E0 */ "get_Ticks\0" + /* 02E1 */ "get_TimeOfDay\0" + /* 02E2 */ "get_TimeSeparator\0" + /* 02E3 */ "get_Today\0" + /* 02E4 */ "get_UTF8\0" + /* 02E5 */ "get_UniversalSortableDateTimePattern\0" + /* 02E6 */ "get_UseRFC4648Encoding\0" + /* 02E7 */ "get_UtcNow\0" + /* 02E8 */ "get_Values\0" + /* 02E9 */ "get_Version\0" + /* 02EA */ "get_WriteTimeout\0" + /* 02EB */ "get_Year\0" + /* 02EC */ "get_YearMonthPattern\0" + /* 02ED */ "ht\0" + /* 02EE */ "index\0" + /* 02EF */ "key\0" + /* 02F0 */ "longDatePattern\0" + /* 02F1 */ "longTimePattern\0" + /* 02F2 */ "m_AppDomain\0" + /* 02F3 */ "m_ChunkChars\0" + /* 02F4 */ "m_ChunkLength\0" + /* 02F5 */ "m_ChunkOffset\0" + /* 02F6 */ "m_ChunkPrevious\0" + /* 02F7 */ "m_Delegate\0" + /* 02F8 */ "m_HResult\0" + /* 02F9 */ "m_Id\0" + /* 02FA */ "m_MaxCapacity\0" + /* 02FB */ "m_Priority\0" + /* 02FC */ "m_Thread\0" + /* 02FD */ "m_appDomain\0" + /* 02FE */ "m_assembly\0" + /* 02FF */ "m_baseAssembly\0" + /* 0300 */ "m_baseName\0" + /* 0301 */ "m_callback\0" + /* 0302 */ "m_certificate\0" + /* 0303 */ "m_cultureInfo\0" + /* 0304 */ "m_cultureName\0" + /* 0305 */ "m_data\0" + /* 0306 */ "m_delta\0" + /* 0307 */ "m_effectiveDate\0" + /* 0308 */ "m_end\0" + /* 0309 */ "m_expirationDate\0" + /* 030A */ "m_flags\0" + /* 030B */ "m_friendlyName\0" + /* 030C */ "m_handle\0" + /* 030D */ "m_hash\0" + /* 030E */ "m_id\0" + /* 030F */ "m_innerException\0" + /* 0310 */ "m_issuer\0" + /* 0311 */ "m_message\0" + /* 0312 */ "m_name\0" + /* 0313 */ "m_paramName\0" + /* 0314 */ "m_parent\0" + /* 0315 */ "m_password\0" + /* 0316 */ "m_payload\0" + /* 0317 */ "m_rand\0" + /* 0318 */ "m_refs\0" + /* 0319 */ "m_resourceFileId\0" + /* 031A */ "m_rm\0" + /* 031B */ "m_rmFallback\0" + /* 031C */ "m_selector\0" + /* 031D */ "m_seq\0" + /* 031E */ "m_sessionHandle\0" + /* 031F */ "m_size\0" + /* 0320 */ "m_source\0" + /* 0321 */ "m_stackTrace\0" + /* 0322 */ "m_start\0" + /* 0323 */ "m_state\0" + /* 0324 */ "m_subject\0" + /* 0325 */ "m_ticks\0" + /* 0326 */ "m_ticksOffset\0" + /* 0327 */ "m_timer\0" + /* 0328 */ "m_type\0" + /* 0329 */ "m_value\0" + /* 032A */ "manager\0" + /* 032B */ "monthDayPattern\0" + /* 032C */ "monthNames\0" + /* 032D */ "mscorlib\0" + /* 032E */ "negativeSign\0" + /* 032F */ "next\0" + /* 0330 */ "numInfo\0" + /* 0331 */ "numberDecimalSeparator\0" + /* 0332 */ "numberGroupSeparator\0" + /* 0333 */ "numberGroupSizes\0" + /* 0334 */ "op_Addition\0" + /* 0335 */ "op_Equality\0" + /* 0336 */ "op_GreaterThan\0" + /* 0337 */ "op_GreaterThanOrEqual\0" + /* 0338 */ "op_Inequality\0" + /* 0339 */ "op_LessThan\0" + /* 033A */ "op_LessThanOrEqual\0" + /* 033B */ "op_Subtraction\0" + /* 033C */ "op_UnaryNegation\0" + /* 033D */ "op_UnaryPlus\0" + /* 033E */ "pmDesignator\0" + /* 033F */ "positiveSign\0" + /* 0340 */ "propertyName\0" + /* 0341 */ "returnType\0" + /* 0342 */ "s_ewr\0" + /* 0343 */ "s_rgbBase64Decode\0" + /* 0344 */ "s_rgchBase64Encoding\0" + /* 0345 */ "s_rgchBase64EncodingDefault\0" + /* 0346 */ "s_rgchBase64EncodingRFC4648\0" + /* 0347 */ "set_Capacity\0" + /* 0348 */ "set_CurrentUICultureInternal\0" + /* 0349 */ "set_FrameworkDisplayName\0" + /* 034A */ "set_GrowthFactor\0" + /* 034B */ "set_Item\0" + /* 034C */ "set_Length\0" + /* 034D */ "set_MaxLoadFactor\0" + /* 034E */ "set_Position\0" + /* 034F */ "set_Priority\0" + /* 0350 */ "set_ReadTimeout\0" + /* 0351 */ "set_Target\0" + /* 0352 */ "set_UseRFC4648Encoding\0" + /* 0353 */ "set_WriteTimeout\0" + /* 0354 */ "shortDatePattern\0" + /* 0355 */ "shortTimePattern\0" + /* 0356 */ "temp\0" + /* 0357 */ "ticksAtOrigin\0" + /* 0358 */ "timeSeparator\0" + /* 0359 */ "value\0" + /* 035A */ "value__\0" + /* 035B */ "yearMonthPattern\0" +; + diff --git a/source/native/nf-interpreter/src/CLR/Core/Thread.cpp b/source/native/nf-interpreter/src/CLR/Core/Thread.cpp new file mode 100644 index 00000000..4fe5d90f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Thread.cpp @@ -0,0 +1,1275 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_SubThread::CreateInstance( CLR_RT_Thread* th, CLR_RT_StackFrame* stack, int priority, CLR_RT_SubThread*& sthRef ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_SubThread* sth = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_SubThread,DATATYPE_SUBTHREAD); CHECK_ALLOCATION(sth); + + sth->m_owningThread = th; // CLR_RT_Thread* m_owningThread; + sth->m_owningStackFrame = stack; // CLR_RT_StackFrame* m_owningStackFrame; + sth->m_lockRequestsCount = 0; // CLR_UINT32 m_lockRequestsCount; + // + sth->m_priority = priority; // int m_priority; + + sth->m_timeConstraint = TIMEOUT_INFINITE; // CLR_INT64 m_timeConstraint; + sth->m_status = 0; // CLR_UINT32 m_status; + + th->m_subThreads.LinkAtBack( sth ); + + NANOCLR_CLEANUP(); + + sthRef = sth; + + NANOCLR_CLEANUP_END(); +} + +void CLR_RT_SubThread::DestroyInstance( CLR_RT_Thread* th, CLR_RT_SubThread* sthBase, int flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // You cannot destroy a subthread without destroying all the children subthreads. + // + while(true) + { + CLR_RT_SubThread* sth = th->CurrentSubThread(); if(sth->Prev() == NULL) break; + + // + // Release all the frames for this subthread. + // + while(true) + { + CLR_RT_StackFrame* stack = th->CurrentFrame(); if(stack->Prev() == NULL) break; + + if(stack == sth->m_owningStackFrame) break; + + stack->Pop(); + } + + // + // Release all the locks for this subthread. + // + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + lock->DestroyOwner( sth ); + } + NANOCLR_FOREACH_NODE_END(); + + // + // Release all the lock requests. + // + g_CLR_RT_ExecutionEngine.DeleteLockRequests( NULL, sth ); + + if(sth == sthBase && (flags & CLR_RT_SubThread::MODE_IncludeSelf) == 0) break; + + g_CLR_RT_EventCache.Append_Node( sth ); + + if(sth == sthBase) break; + } +} + +bool CLR_RT_SubThread::ChangeLockRequestCount( int diff ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th = m_owningThread; + + this->m_lockRequestsCount += diff; + th ->m_lockRequestsCount += diff; + + if(th->m_lockRequestsCount == 0) + { + th->Restart( false ); + + return true; + } + else + { + th->m_status = CLR_RT_Thread::TH_S_Waiting; + + return false; + } +} + +void CLR_RT_Thread::BringExecCounterToDate( int iGlobalExecutionCounter, int iDebitForEachRun ) +{ + (void)iDebitForEachRun; + + // Normally the condition is false. It becomes true if thread was out of execution for some time. + // The value of (ThreadPriority::System_Highest + 1) is 33. + // 33 for ThreadPriority::Highest gives up to 16 cycles to catch up. + // 33 for ThreadPriority::Lowest we provide only 1 cycle to catch up. + // If thread was sleeping for some time we forefeet the time it was sleeping and not updating execution counter. + if ( m_executionCounter - iGlobalExecutionCounter > (int)((1 << ThreadPriority::System_Highest) + 1) ) + { + m_executionCounter = iGlobalExecutionCounter + (int)((1 << ThreadPriority::System_Highest) + 1); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_Thread::IsFinalizerThread() +{ + NATIVE_PROFILE_CLR_CORE(); + return g_CLR_RT_ExecutionEngine.m_finalizerThread == this; +} + +bool CLR_RT_Thread::CanThreadBeReused() +{ + NATIVE_PROFILE_CLR_CORE(); + return (m_flags & CLR_RT_Thread::TH_F_System) && + (m_status == CLR_RT_Thread::TH_S_Terminated || m_status == CLR_RT_Thread::TH_S_Unstarted ); +} + +HRESULT CLR_RT_Thread::PushThreadProcDelegate( CLR_RT_HeapBlock_Delegate* pDelegate ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance inst; + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( pDelegate->m_appDomain ); +#endif + + if(pDelegate == NULL || pDelegate->DataType() != DATATYPE_DELEGATE_HEAD || inst.InitializeFromIndex( pDelegate->DelegateFtn() ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + +#if defined(NANOCLR_APPDOMAINS) + + if(!pDelegate->m_appDomain->IsLoaded()) + { + if(!IsFinalizerThread()) + { + NANOCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_EXITED); + } + + m_flags |= CLR_RT_Thread::TH_F_ContainsDoomedAppDomain; + } +#endif + + this->m_dlg = pDelegate; + this->m_status = TH_S_Ready; + + NANOCLR_CHECK_HRESULT(CLR_RT_StackFrame::Push( this, inst, inst.m_target->numArgs )); + + if((inst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + CLR_RT_StackFrame* stackTop = this->CurrentFrame(); + + stackTop->m_arguments[ 0 ].Assign( pDelegate->m_object ); + } + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + + NANOCLR_CLEANUP(); + +#if defined(NANOCLR_APPDOMAINS) + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::CreateInstance( int pid, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_SubThread* sth; + + //--// + + th = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_Thread,DATATYPE_THREAD); CHECK_ALLOCATION(th); + + { + CLR_RT_ProtectFromGC gc( (void**)&th, CLR_RT_Thread::ProtectFromGCCallback ); + + th->Initialize(); + + th->m_pid = pid; // int m_pid; + th->m_status = TH_S_Unstarted; // CLR_UINT32 m_status; + th->m_flags = flags; // CLR_UINT32 m_flags; + th->m_executionCounter = 0; // int m_executionCounter; + th->m_timeQuantumExpired = false; // bool m_timeQuantumExpired; + // + th->m_dlg = NULL; // CLR_RT_HeapBlock_Delegate* m_dlg; + th->m_currentException .SetObjectReference( NULL ); // CLR_RT_HeapBlock m_currentException; + // UnwindStack m_nestedExceptions[c_MaxStackUnwindDepth]; + th->m_nestedExceptionsPos = 0; // int m_nestedExceptionsPos; + + // + // //--// + // + th->m_terminationCallback = NULL; // ThreadTerminationCallback m_terminationCallback; + th->m_terminationParameter = NULL; // void* m_terminationParameter; + // + th->m_waitForEvents = 0; // CLR_UINT32 m_waitForEvents; + th->m_waitForEvents_Timeout = TIMEOUT_INFINITE; // CLR_INT64 m_waitForEvents_Timeout; + th->m_waitForEvents_IdleTimeWorkItem = TIMEOUT_ZERO; // CLR_INT64 m_waitForEvents_IdleTimeWorkItem; + // + th->m_locks .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_locks; + th->m_lockRequestsCount = 0; // CLR_UINT32 m_lockRequestsCount; + th->m_waitForObject = NULL; + // + th->m_stackFrames .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_stackFrames; + // + th->m_subThreads .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_subThreads; + // + #if defined(ENABLE_NATIVE_PROFILER) + th->m_fNativeProfiled = false; + #endif + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + th->m_scratchPad = -1; // int m_scratchPad; + th->m_fHasJMCStepper = false; // bool m_fHasJMCStepper + + // For normal threads created in CLR m_realThread points to the thread object. + // If debugger creates managed thread for function evaluation, then m_realThread points to the thread that has focus in debugger + th->m_realThread = th; // CLR_RT_Thread* m_realThread +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //--// + + NANOCLR_CHECK_HRESULT(CLR_RT_SubThread::CreateInstance( th, NULL, priority, sth )); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + // + // This needs to happen before the Push + // + g_CLR_RT_ExecutionEngine.Breakpoint_Thread_Created( th ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::CreateInstance( int pid, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(CreateInstance( pid, priority, th, flags )); + + if(pDelegate) + { + NANOCLR_CHECK_HRESULT(th->PushThreadProcDelegate( pDelegate )); + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_Thread::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + DetachAll(); + + Passivate(); + + //Prevent ReleaseWhenDeadEx from keeping the thread alive + if(m_flags & CLR_RT_Thread::TH_F_System) + { + m_flags &= ~CLR_RT_Thread::TH_F_System; + OnThreadTerminated(); + } + + ReleaseWhenDeadEx(); +} + +bool CLR_RT_Thread::ReleaseWhenDeadEx() +{ + NATIVE_PROFILE_CLR_CORE(); + //maybe separate for shutdown.... + //These threads live forever?!!? + if(m_flags & CLR_RT_Thread::TH_F_System) return false; + + if(!IsReadyForRelease()) return false; + + if(this == g_CLR_RT_ExecutionEngine.m_finalizerThread) g_CLR_RT_ExecutionEngine.m_finalizerThread = NULL; + if(this == g_CLR_RT_ExecutionEngine.m_interruptThread) g_CLR_RT_ExecutionEngine.m_interruptThread = NULL; + if(this == g_CLR_RT_ExecutionEngine.m_timerThread ) g_CLR_RT_ExecutionEngine.m_timerThread = NULL; + if(this == g_CLR_RT_ExecutionEngine.m_cctorThread ) g_CLR_RT_ExecutionEngine.m_cctorThread = NULL; + + return ReleaseWhenDead(); +} + +//--// + +void CLR_RT_Thread::ProtectFromGCCallback( void* state ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th = (CLR_RT_Thread*)state; + + g_CLR_RT_GarbageCollector.Thread_Mark( th ); +} + +//--// + +HRESULT CLR_RT_Thread::Suspend() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if((m_flags & CLR_RT_Thread::TH_F_Suspended) == 0 && m_status != CLR_RT_Thread::TH_S_Terminated) + { + m_flags |= CLR_RT_Thread::TH_F_Suspended; + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_Thread::Resume() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if((m_flags & CLR_RT_Thread::TH_F_Suspended) != 0 && m_status != CLR_RT_Thread::TH_S_Terminated) + { + m_flags &= ~CLR_RT_Thread::TH_F_Suspended; + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_Thread::Terminate() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + m_status = CLR_RT_Thread::TH_S_Terminated; + + //An exception is needed to ensure that StackFrame::Pop does not copy uninitialized data + //to callers evaluation stacks. This would likely be harmless, as the entire thread is about to be killed + //However, this is simply a safeguard to prevent possible problems if it ever happens that + //between the start and end of killing the thread, a GC gets run. + (void)Library_corlib_native_System_Exception::CreateInstance( m_currentException, g_CLR_RT_WellKnownTypes.m_ThreadAbortException, S_OK, CurrentFrame() ); + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_Thread::Abort() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + // + // Only abort a non-terminated thread... + // + if(m_status != CLR_RT_Thread::TH_S_Terminated) + { + (void)Library_corlib_native_System_Exception::CreateInstance( m_currentException, g_CLR_RT_WellKnownTypes.m_ThreadAbortException, S_OK, CurrentFrame() ); + + m_flags |= CLR_RT_Thread::TH_F_Aborted; + + Restart( true ); + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_RT_Thread::Restart( bool fDeleteEvent ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // Wake up and queue. + // + m_status = CLR_RT_Thread::TH_S_Ready; + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + + if(fDeleteEvent) + { + m_waitForEvents = 0; + m_waitForEvents_Timeout = TIMEOUT_INFINITE; + } +} + +void CLR_RT_Thread::OnThreadTerminated() +{ + NATIVE_PROFILE_CLR_CORE(); + SignalAll(); + + // + // Release all the subthreads. + // + CLR_RT_SubThread::DestroyInstance( this, NULL, 0 ); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Thread_Terminated( this ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) +} + +void CLR_RT_Thread::Passivate() +{ + NATIVE_PROFILE_CLR_CORE(); + m_flags &= ~(CLR_RT_Thread::TH_F_Suspended | CLR_RT_Thread::TH_F_ContainsDoomedAppDomain | CLR_RT_Thread::TH_F_Aborted); + + g_CLR_RT_ExecutionEngine.m_threadsZombie.LinkAtFront( this ); + + m_waitForEvents = 0; + m_waitForEvents_Timeout = TIMEOUT_INFINITE; + + //--// + + if(m_waitForObject != NULL) + { + g_CLR_RT_EventCache.Append_Node( m_waitForObject ); + m_waitForObject = NULL; + } + + //--// + + if((m_flags & CLR_RT_Thread::TH_F_System) == 0) + { + m_status = CLR_RT_Thread::TH_S_Terminated; + OnThreadTerminated(); + } + else + { + m_status = CLR_RT_Thread::TH_S_Unstarted; + } + + m_currentException.SetObjectReference( NULL ); // Reset exception flag. + + // + // If the thread is associated with a timer, advance the state of the timer. + // + if(m_terminationCallback) + { + ThreadTerminationCallback terminationCallback = m_terminationCallback; m_terminationCallback = NULL; + + terminationCallback( m_terminationParameter ); + } + + if(m_status == CLR_RT_Thread::TH_S_Terminated || m_status == CLR_RT_Thread::TH_S_Unstarted) + { + //This is used by Static constructor thread. + m_dlg = NULL; + } + + ReleaseWhenDeadEx(); +} + +bool CLR_RT_Thread::CouldBeActivated() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_waitForEvents_Timeout != TIMEOUT_INFINITE) return true; + if(m_waitForEvents ) return true; + + return false; +} + +void CLR_RT_Thread::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + CheckAll(); +} + +void CLR_RT_Thread::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_dlg ); + + m_currentException.Relocate__HeapBlock(); + + for(int i=0; im_call ); CLR_Debug::Printf( " [IP: %04x]\r\n", (stack->m_IP - stack->m_IPstart) ); + } + NANOCLR_FOREACH_NODE_BACKWARD_END(); +} + +#endif + +//--// + +void CLR_RT_Thread::ProcessException_FilterPseudoFrameCopyVars(CLR_RT_StackFrame* to, CLR_RT_StackFrame* from) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8 numArgs = from->m_call.m_target->numArgs; + + if(numArgs) + { + memcpy( to->m_arguments, from->m_arguments, sizeof(CLR_RT_HeapBlock) * numArgs ); + } + + if(from->m_call.m_target->numLocals) + { + memcpy( to->m_locals, from->m_locals, sizeof(CLR_RT_HeapBlock) * from->m_call.m_target->numLocals ); + } +} + +HRESULT CLR_RT_Thread::ProcessException_EndFilter() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* stack = CurrentFrame(); + CLR_INT32 choice = stack->PopValue().NumericByRef().s4; + + + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + ProcessException_FilterPseudoFrameCopyVars(us.m_handlerStack, stack); + + //Clear the stack variable so Pop doesn't remove us from the UnwindStack. + us.m_stack = NULL; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + stack->Pop(); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(choice == 1) + { + //The filter signaled that it will handle this exception. Update the phase state + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + g_CLR_RT_ExecutionEngine.Breakpoint_Exception(us.m_handlerStack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_HANDLER_FOUND, us.m_handlerBlockStart); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + } + else + { + //Store the IP so Phase1/FindEhBlock knows to start looking from the point of the filter we were executing. + us.m_ip = us.m_currentBlockStart; + } + + //Signal that this is a continuation of processing for the handler on top of the unwind stack. + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + //We must stop if we sent out a Catch Handler found message. + if(CLR_EE_DBG_IS( Stopped )) + { //If the debugger stopped because of the messages we sent, then we should break out of Execute_IL, drop down, + //and wait for the debugger to continue. + m_currentException.SetObjectReference(us.m_exception); + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + (void)ProcessException(); + + + // Swap results around. ProcessException must return a success code in Thread::Execute and set m_currentException to continue processing. + // Execute_IL must get a FAILED hr in order to break outside of the execution loop. + if(m_currentException.Dereference() == NULL) + { + //Return S_OK because exception handling is complete or handling is in-flight and needs to execute IL to continue. + NANOCLR_SET_AND_LEAVE(S_OK); + } + else + { + //Return PROCESS_EXCEPTION to break out of the IL loop to rerun ProcessException and/or abort from an unhandled exception + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::ProcessException_EndFinally() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_StackFrame* stack = CurrentFrame(); + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + if(us.m_ip) + { + CLR_PMETADATA ipLeave = us.m_ip; + CLR_RT_ExceptionHandler eh; + + if(FindEhBlock( stack, stack->m_IP-1, ipLeave, eh, true )) + { + us.m_stack = stack; + us.m_exception = NULL; + us.m_ip = ipLeave; + us.m_currentBlockStart = eh.m_handlerStart; + us.m_currentBlockEnd = eh.m_handlerEnd; + //Leave is not valid to leave a finally block, and is the only thing that leaves m_ip set when executing IL. + //Therefore if we're here then we are not interfering with an unhandled exception and flags can be safely set. + us.SetPhase( UnwindStack::p_4_NormalCleanup ); + stack->m_IP = eh.m_handlerStart ; + } + else + { //We're truely done with finally's for now. Pop off the handler + m_nestedExceptionsPos--; + stack->m_IP = ipLeave; + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, stack->m_IP ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + NANOCLR_SET_AND_LEAVE(S_OK); + } + else if(us.m_exception) + { + //This finally block was executed because an exception was thrown inside its protected block. + //Signal that this is a continuation of an already existing EH process. + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + + (void)ProcessException(); + //Similar to EndFilter, we need to swap the return codes around. Thread::Execute needs a success code or the thread will be aborted. + //ExecuteIL needs a failure code or we'll continue to execute IL when we possibly shouldn't. + if (m_currentException.Dereference() == NULL) + { + //Return S_OK because exception handling is complete or handling is in-flight and needs to execute IL to continue. + NANOCLR_SET_AND_LEAVE(S_OK); + } + else + { + //Return PROCESS_EXCEPTION to break out of the IL loop to rerun ProcessException and/or abort from an unhandled exception + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::ProcessException_Phase1() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + // Load the UnwindStack entry to process, as created/loaded by ProcessException + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + CLR_RT_ExceptionHandler eh; + + // If we were executing a filter that returned false, there's not much point checking the stack frames above the point of the filter. + // Try to resume from the frame of the last filter executed. + CLR_RT_StackFrame* stack = us.m_handlerStack; + +#ifndef CLR_NO_IL_INLINE + CLR_RT_InlineFrame tmpInline; + tmpInline.m_IP = NULL; +#endif + + // If this is the first pass through _Phase1 then start at the top. + if(!stack) { stack = CurrentFrame(); } + + //Search for a willing catch handler. + while(stack->Caller() != NULL) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum && us.GetPhase() < UnwindStack::p_1_SearchingForHandler_2_SentUsersChance && stack->m_IP) + { //We have a debugger attached and we need to send some messages before we start searching. + //These messages should only get sent when the search reaches managed code. Stack::Push sets m_IP to NULL for native code, + //so therefore we need IP to be non-NULL + + us.m_handlerStack = stack; + + if(us.GetPhase() < UnwindStack::p_1_SearchingForHandler_1_SentFirstChance) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_FIRST_CHANCE, NULL ); + us.SetPhase(UnwindStack::p_1_SearchingForHandler_1_SentFirstChance); + + //Break out here, because of synchronization issues (false positives) with JMC checking. + if(CLR_EE_DBG_IS( Stopped )) { goto ContinueAndExit; } + } + + //In order to send the User's first chance message, we have to know that we're in JMC + //Do we have thread synchronization issues here? The debugger is sending out 3 Not My Code messages for a function, + //presumably the one on the top of the stack, but when we execute this, we're reading true. + if(stack->m_call.DebuggingInfo().IsJMC()) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_USERS_CHANCE, NULL ); + us.SetPhase( UnwindStack::p_1_SearchingForHandler_2_SentUsersChance ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(stack->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) + { + CLR_PMETADATA ip; + if (us.m_ip) + { + ip = us.m_ip; //Use the IP set by endfilter + us.m_ip = NULL; //Reset to prevent catch block & PopEH issues via 'leave' or 'endfinally' + } + else + { + ip = stack->m_IP; //Normal case: use the IP where the exception was thrown. + } + + if(ip) // No IP? Either out of memory during allocation of stack frame or native method. + { + if(FindEhBlock( stack, ip, NULL, eh, false )) + { //There are two cases here: + //1. We found a catch block... in this case, we want to break out and go to phase 2. + //2. We found a filter... in this case, we want to duplicate the stack and execute the filter. + + //Store the handler block address and stack frame. + //It's needed in Phase2 for when finally's are finished and we execute the catch handler + us.m_handlerBlockStart = eh.m_handlerStart; + us.m_handlerBlockEnd = eh.m_handlerEnd; + us.m_handlerStack = stack; + +#ifndef CLR_NO_IL_INLINE + if(tmpInline.m_IP) + { + us.m_flags |= UnwindStack::c_MagicCatchForInline; + } +#endif + + if (eh.IsFilter()) + { + CLR_RT_StackFrame* newStack = NULL; + + //Store the IP range that we're currently executing so leave/PopEH doesn't accidentally pop the filter off. + us.m_currentBlockStart = eh.m_userFilterStart; + us.m_currentBlockEnd = eh.m_handlerStart; + + //Create a pseudo-frame at the top of the stack so the filter can call other functions. + CLR_UINT8 numArgs = stack->m_call.m_target->numArgs; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + hr = CLR_RT_StackFrame::Push( stack->m_owningThread, stack->m_call, numArgs ); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(FAILED(hr)) + { //We probably ran out of memory. In either case, don't run this handler. + //Set the IP so we'll try the next catch block. + us.m_ip = us.m_currentBlockStart; + continue; + } + + //stack is the original filter stack frame; newStack is the new pseudoframe + newStack = CurrentFrame(); + newStack->m_flags |= CLR_RT_StackFrame::c_PseudoStackFrameForFilter; + us.m_stack = newStack; + + //Copy local variables and arguments so the filter has access to them. + if(numArgs) + { + memcpy( newStack->m_arguments, stack->m_arguments, sizeof(CLR_RT_HeapBlock) * numArgs ); + } + + if (stack->m_call.m_target->numLocals) + { + memcpy( newStack->m_locals, stack->m_locals, sizeof(CLR_RT_HeapBlock) * stack->m_call.m_target->numLocals ); + } + + newStack->PushValueAndAssign( m_currentException ); + + //Set the ip to the handler + newStack->m_IP = eh.m_userFilterStart; + + //We are willing to execute IL again so clear the m_currentException flag. + m_currentException.SetObjectReference( NULL ); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Push( newStack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_INTERCEPT ); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Return a success value to break out of ProcessException and to signal that execution of IL can continue. + NANOCLR_SET_AND_LEAVE(S_OK); + } + else + { //We found a normal Catch or CatchAll block. We are all set to proceed onto the Unwinding phase. + //Note that we found a catch handler so we don't look for it again for this exception. + us.SetPhase( UnwindStack::p_2_RunningFinallys_0 ); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_HANDLER_FOUND, eh.m_handlerStart ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //We want to continue running EH "goo" code so leave m_currentException set and return PROCESS_EXCEPTION + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + } + } + } + + //We didn't find a catch block at this level... + //Check to see if we trickled up to a pseudoStack frame that we created to execute a handler + //Both of these shouldn't be set at once because of the two-pass handling mechanism. + if (stack->m_flags & CLR_RT_StackFrame::c_AppDomainTransition) + { + us.m_handlerStack = NULL; + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + //Send the IP offset -1 for a catch handler in the case of an appdomain transition to mimic the desktop. + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_HANDLER_FOUND, stack->m_IPstart - 1 ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + if (stack->m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + us.m_handlerStack = NULL; + us.SetPhase( UnwindStack::p_2_RunningFinallys_0 ); + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + +#ifndef CLR_NO_IL_INLINE + if(stack->m_inlineFrame != NULL && tmpInline.m_IP == NULL) + { + stack->SaveStack(tmpInline); + stack->RestoreFromInlineStack(); + } + else + { + if(tmpInline.m_IP) + { + stack->RestoreStack(tmpInline); + tmpInline.m_IP = NULL; + } +#else + { +#endif + + stack = stack->Caller(); + } + } + + us.m_handlerStack = NULL; + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception_Uncaught( this ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //We want to continue running EH "goo" code so leave m_currentException set and return PROCESS_EXCEPTION + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) +ContinueAndExit: +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //There are multiple cases where we want to break out of this function, send debug messages, and then resume exactly where we were. + //All of those cases jump to here. + //However, there are cases where we may be stopped but we don't want to set this flag (i.e. pushing on a filter and completing a stepper) + //where we do not want to set this flag, so it cannot be in nanoCLR_Cleanup. + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + NANOCLR_SET_AND_LEAVE(S_OK); + + NANOCLR_CLEANUP(); + +#ifndef CLR_NO_IL_INLINE + if(tmpInline.m_IP) + { + stack->RestoreStack(tmpInline); + } +#endif + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::ProcessException_Phase2() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + /* + * Start running through the stack frames, running all finally handlers and popping them off until + * we hit our target catch handler, if any. + */ + + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + CLR_RT_StackFrame* iterStack = CurrentFrame(); + + CLR_RT_ExceptionHandler eh; + + //Unwind the stack, running finally's as we go + while (iterStack->Caller() != NULL) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if (g_CLR_RT_ExecutionEngine.m_breakpointsNum && iterStack == us.m_handlerStack && (us.m_flags & UnwindStack::c_MagicCatchForInteceptedException) != 0) + { + //We've reached the frame we want to "handle" this exception. However, since the handler doesn't really exist, we want to remove the UnwindStack entry. + m_nestedExceptionsPos--; + iterStack->ResetStack(); + + //We are willing to execute IL again so clear the m_currentException flag. + m_currentException.SetObjectReference( NULL ); + + //CPDE better reset the IP, or there are going to be issues. + iterStack->m_flags |= CLR_RT_StackFrame::c_InvalidIP; + + //Send the message to the debugger. + g_CLR_RT_ExecutionEngine.Breakpoint_Exception_Intercepted( iterStack ); + + //Return a success value to break out of ProcessException and to signal that execution of IL can continue. + NANOCLR_SET_AND_LEAVE(S_OK); + } + else +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(iterStack->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) + { + if(iterStack->m_IP) // No IP? Either out of memory during allocation of iterStack frame or native method. + { + //handlerBlockStart is used to not execute finally's who's protected blocks contain the handler itself. + //NULL is used when we're not in the handler stack frame to make it work in the case of recursive functions with filtered handlers. + if(FindEhBlock( iterStack, iterStack->m_IP, (us.m_handlerStack == iterStack)? us.m_handlerBlockStart : NULL, eh, true )) + { + //We have a finally block to process + + us.m_stack = iterStack; + us.m_ip = NULL; + us.m_currentBlockStart = eh.m_handlerStart; + us.m_currentBlockEnd = eh.m_handlerEnd; + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); + + m_currentException.SetObjectReference( NULL ); // Reset exception flag. + + iterStack->ResetStack(); + iterStack->m_IP = eh.m_handlerStart; + iterStack->m_flags &= ~CLR_RT_StackFrame::c_InvalidIP; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) +#ifndef CLR_NO_IL_INLINE + if(iterStack->m_inlineFrame == NULL) +#endif + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( iterStack, true ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + NANOCLR_SET_AND_LEAVE(S_OK); + } + + if (iterStack == us.m_handlerStack) + { +#ifndef CLR_NO_IL_INLINE + if(iterStack->m_inlineFrame == NULL || 0 == (us.m_flags & UnwindStack::c_MagicCatchForInline)) +#endif + { + //We've popped off all stack frames above the target. + //Now we should run the exception handler. + + //Store the range of the block and the stack frame we're executing for PopEH + us.m_currentBlockStart = us.m_handlerBlockStart; + us.m_currentBlockEnd = us.m_handlerBlockEnd; + us.m_stack = us.m_handlerStack; + us.SetPhase( UnwindStack::p_3_RunningHandler ); + + //Set the IP and push the exception object on the stack. + iterStack->m_IP = us.m_handlerBlockStart; + iterStack->m_flags &= ~CLR_RT_StackFrame::c_InvalidIP; + + iterStack->ResetStack(); + iterStack->PushValue().SetObjectReference( us.m_exception ); + + //We are willing to execute IL again so clear the m_currentException flag. + m_currentException.SetObjectReference( NULL ); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) +#ifndef CLR_NO_IL_INLINE + if(iterStack->m_inlineFrame == NULL) +#endif + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( iterStack, true ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Return a success value to break out of ProcessException and to signal that execution of IL can continue. + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + } + } + + //We didn't find a finally block at this level... + //Check to see if we trickled up to a pseudoiterStack frame that we created to execute a filter handler: + if (iterStack->m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + //An exception was thrown while executing a filter block. + //The CLR should swallow the current exception, perform some filter-cleanup, act as if the filter returned false and + //continue looking for a handler for the old exception + m_nestedExceptionsPos--; + + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + //Since there are no applicable handlers for this IP inside this filter block, and all finally's nested below the + //filter have executed, we should pop off our pseudoframe and try to find another catch block. + + //Copy the arguments and locals back to the original stack frame. + ProcessException_FilterPseudoFrameCopyVars( us.m_handlerStack, iterStack ); + + //Set IP so we can resume looking for the next filter. + us.m_ip = us.m_currentBlockStart; + + us.m_stack = NULL; //Prevent Pop from taking this handler off the stack. + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + iterStack->Pop(); //No finally's for the current ip in this method, pop to the next. + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + m_currentException.SetObjectReference( us.m_exception ); //Drop current exception, use old one. + + //Set the continue flag, and leave with S_OK to loop around and get Phase1 called again via ProcessException + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + + //We are not ready to execute IL yet so do NOT clear m_currentException flag. + //There still remains hope for this thread so return S_OK so ProcessException can get called again via Thread::Execute + NANOCLR_SET_AND_LEAVE(S_OK); + } + +#if defined(NANOCLR_APPDOMAINS) + if(iterStack->m_flags & CLR_RT_StackFrame::c_AppDomainTransition) + { + //If we hit an AppDomain transition and haven't handled the exception, then a special case occurs. + //Exception handling stops at this point and the whole process needs to start over in the caller's AppDomain. + //We need to pop the handler off the unwind stack, pop the current stack frame, and then proceed to Phase1. + m_nestedExceptionsPos--; //Take off the pseudo-handler + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#ifndef CLR_NO_IL_INLINE + if(iterStack->m_inlineFrame) + { + iterStack->PopInline(); + } + else +#endif + { + iterStack->Pop(); //No finally's for the current ip in this method, pop to the next. + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //We are not ready to execute IL yet so do NOT clear m_currentException flag. + //There still remains hope for this thread so return S_OK so ProcessException can get called again via Thread::Execute + NANOCLR_SET_AND_LEAVE(S_OK); + } +#endif + + us.m_stack = NULL; //Don't pop off the handler when we pop this stack frame + + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + +#ifndef CLR_NO_IL_INLINE + if(iterStack->m_inlineFrame) + { + iterStack->PopInline(); + } + else +#endif + { + iterStack->Pop(); //No finally's for the current ip in this method, pop to the next. + } + iterStack = CurrentFrame(); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + //If we reached this point, we've unwound the entire thread and have an unhandled exception. + m_nestedExceptionsPos = 0; //We have an unhandled exception, we might as well clean the unwind stack. + + //At this point, no hope remains. + //m_currentException is still set, but we return PROCESS_EXCEPTION signalling that there is no hope for the thread, + //which causes Thread::Execute to terminate it. +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) +#if !defined(BUILD_RTM) + //special case thread abort exception + if((this->m_flags & CLR_RT_Thread::TH_F_Aborted) == 0) + { + CLR_Debug::Printf(" Uncaught exception \r\n" ); + //Perhaps some stronger notification is needed. Consider CLR 2.0's fail-fast work + //We could kill the application, and perhaps even store relevant data to dump to the user + //when they connect to the PC. Save the state so the debug API for the uncaught exception could be + //retrieved? + } +#endif //!BUILD_RTM +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::ProcessException() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_StackFrame* stack = CurrentFrame(); + UnwindStack* us = NULL; + + // If the exception was thrown in the middle of an IL instruction, + // back up the pointer to point to the executing instruction, not the next one. + // Not an assert because the exception can be thrown by a native method. + if(stack->m_flags & CLR_RT_StackFrame::c_ExecutingIL) + { + stack->m_IP--; + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingIL; + stack->m_flags |= CLR_RT_StackFrame::c_InvalidIP; + } + + // If we are supposed to continue with the old exception handler, then pull the state from it rather than create a new exception. + if (m_nestedExceptionsPos) + { + us = &m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + if (us->m_flags & UnwindStack::c_ContinueExceptionHandler) + { + //Reset the flag so we don't get false positives from new exceptions + us->m_flags &= ~UnwindStack::c_ContinueExceptionHandler; + m_currentException.SetObjectReference( us->m_exception ); + } + else + { + //Signal that we need a new handler pushed on the stack. + us = NULL; + } + } + + if (us == NULL) + { + //Push a new handler on the unwind stack that will last until its handler gets executed or + //something out-of-band forces the stack frame to get popped. + us = PushEH(); + + //decent failure case is currently not implemented + //a. Clearing the unwind stack and throwing a new exception is just asking for undefined behavior if this exception is caught + //and the IP in stack frames somewhere below are in a finally due to an exception that hasn't yet ran a catch block and + //endfinally gets executed. Execution would continue, thinking that nothing was wrong... a guranteed way to create hard-to-find bugs. + + //b. We could treat it as an unhandled exception, which would terminate the thread. It would be annoying, but it wouldn't lead to + //unexpected code execution leading to potentially more exceptions. + + //c. We could forcibly pop stack frames until there is room on the unwind stack and then throw a stack overflow exception. + //It gives a program a chance to recover, especially for 'always-on' type devices that are inconvenient for the user to perform a cold-boot. + //At any restartable point in the program, there could be a try { } catch-all { } block inside a loop, causing the app to immediately restart + //after an error that would normally terminate the thread. + + //A similar setup would be needed for leave, involving goto Execute_Restart to compensate for possible stack frame changes. Perhaps it could be + //implemented directly in PushEh to reduce common code. + + us->m_exception = m_currentException.Dereference(); + us->m_stack = stack; + us->m_flags = UnwindStack::p_1_SearchingForHandler_0; + } + + if (us->GetPhase() <= UnwindStack::p_1_SearchingForHandler_2_SentUsersChance) + { + NANOCLR_EXIT_ON_SUCCESS(ProcessException_Phase1()); // Leave if we're executing a filter. + } + + NANOCLR_SET_AND_LEAVE(ProcessException_Phase2()); //Leave if we're executing a finally or the catch block, or have an unhandled exception + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/TypeSystem.cpp b/source/native/nf-interpreter/src/CLR/Core/TypeSystem.cpp new file mode 100644 index 00000000..59a07629 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/TypeSystem.cpp @@ -0,0 +1,4420 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +#include "Core.h" +#include "corhdr_private.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define ITERATE_THROUGH_RECORDS(assm,i,tblName,tblNameUC) \ + const CLR_RECORD_##tblNameUC* src = (const CLR_RECORD_##tblNameUC*)assm->GetTable( TBL_##tblName );\ + CLR_RT_##tblName##_CrossReference* dst = assm->m_pCrossReference_##tblName;\ + for(i=0; im_pTablesSize[TBL_##tblName]; i++, src++, dst++) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) +#define NANOCLR_TRACE_DEFAULT(win,arm) (win) +#else +#define NANOCLR_TRACE_DEFAULT(win,arm) (arm) +#endif + +#if defined(NANOCLR_TRACE_ERRORS) +int s_CLR_RT_fTrace_Errors = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_Info); +#endif + +#if defined(NANOCLR_TRACE_EXCEPTIONS) +int s_CLR_RT_fTrace_Exceptions = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_Info); +#endif + +#if defined(NANOCLR_TRACE_INSTRUCTIONS) +int s_CLR_RT_fTrace_Instructions = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(NANOCLR_GC_VERBOSE) +int s_CLR_RT_fTrace_Memory = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(NANOCLR_TRACE_MEMORY_STATS) +int s_CLR_RT_fTrace_MemoryStats = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_Info); +#endif + +#if defined(NANOCLR_GC_VERBOSE) +int s_CLR_RT_fTrace_GC = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(WIN32) +int s_CLR_RT_fTrace_SimulateSpeed = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_None); +#endif + +#if !defined(BUILD_RTM) +int s_CLR_RT_fTrace_AssemblyOverhead = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_Info); +#endif + +#if defined(WIN32) +int s_CLR_RT_fTrace_StopOnFAILED = NANOCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(WIN32) +int s_CLR_RT_fTrace_ARM_Execution = 0; + +int s_CLR_RT_fTrace_RedirectLinesPerFile; +std::wstring s_CLR_RT_fTrace_RedirectOutput; +std::wstring s_CLR_RT_fTrace_RedirectCallChain; + +std::wstring s_CLR_RT_fTrace_HeapDump_FilePrefix; +bool s_CLR_RT_fTrace_HeapDump_IncludeCreators = false; + +bool s_CLR_RT_fTimeWarp = false; +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_ReflectionDef_Index::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + m_kind = REFLECTION_INVALID; + m_levels = 0; + m_data.m_raw = 0; +} + +CLR_UINT32 CLR_RT_ReflectionDef_Index::GetTypeHash() const +{ + NATIVE_PROFILE_CLR_CORE(); + switch(m_kind) + { + case REFLECTION_TYPE: + { + CLR_RT_TypeDef_Instance inst; + + if(m_levels != 0) return 0; + + if(!inst.InitializeFromIndex( m_data.m_type )) return 0; + + return inst.CrossReference().m_hash; + } + + case REFLECTION_TYPE_DELAYED: + return m_data.m_raw; + } + + return 0; +} + +void CLR_RT_ReflectionDef_Index::InitializeFromHash( CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_kind = REFLECTION_TYPE_DELAYED; + m_levels = 0; + m_data.m_raw = hash; +} + +CLR_UINT64 CLR_RT_ReflectionDef_Index::GetRawData() const +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT64 data; + _ASSERTE(sizeof(data) == sizeof(*this)); + + memcpy( &data, this, sizeof(data) ); + + return data; +} + +void CLR_RT_ReflectionDef_Index::SetRawData( CLR_UINT64 data ) +{ + NATIVE_PROFILE_CLR_CORE(); + _ASSERTE(sizeof(data) == sizeof(*this)); + + memcpy( this, &data, sizeof(data) ); +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_Assembly_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION) + { + return inst.InitializeFromIndex( ref.ReflectionDataConst().m_data.m_assm ); + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Instance& inst, CLR_UINT32* levels ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION) + { + return inst.InitializeFromReflection( ref.ReflectionDataConst(), levels ); + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_MethodDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION) + { + switch(ref.ReflectionData().m_kind) + { + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + return inst.InitializeFromIndex( ref.ReflectionDataConst().m_data.m_method ); + } + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_FieldDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION && ref.ReflectionData().m_kind == REFLECTION_FIELD) + { + return inst.InitializeFromIndex( ref.ReflectionDataConst().m_data.m_field ); + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_UINT32& hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() != DATATYPE_REFLECTION) return false; + + hash = ref.ReflectionData().GetTypeHash(); + + return hash != 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_SignatureParser::Initialize_TypeSpec( CLR_RT_Assembly* assm, const CLR_RECORD_TYPESPEC* ts ) +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize_TypeSpec( assm, assm->GetSignature( ts->sig ) ); +} + +void CLR_RT_SignatureParser::Initialize_TypeSpec( CLR_RT_Assembly* assm, CLR_PMETADATA ts ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_assm = assm; + m_sig = ts; + + m_type = CLR_RT_SignatureParser::c_TypeSpec; + m_flags = 0; + m_count = 1; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_Interfaces( CLR_RT_Assembly* assm, const CLR_RECORD_TYPEDEF* td ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(td->interfaces != CLR_EmptyIndex) + { + CLR_PMETADATA sig = assm->GetSignature( td->interfaces ); + + m_count = (*sig++); + m_sig = sig; + } + else + { + m_count = 0; + m_sig = NULL; + } + + m_type = CLR_RT_SignatureParser::c_Interfaces; + m_flags = 0; + + m_assm = assm; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_FieldDef( CLR_RT_Assembly* assm, const CLR_RECORD_FIELDDEF* fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize_FieldDef( assm, assm->GetSignature( fd->sig ) ); +} + +void CLR_RT_SignatureParser::Initialize_FieldDef( CLR_RT_Assembly* assm, CLR_PMETADATA fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_type = CLR_RT_SignatureParser::c_Field; + m_flags = (*fd++); + m_count = 1; + + m_assm = assm; + m_sig = fd; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_MethodSignature( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ) +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize_MethodSignature( assm, assm->GetSignature( md->sig ) ); +} + +void CLR_RT_SignatureParser::Initialize_MethodSignature( CLR_RT_Assembly* assm, CLR_PMETADATA md ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_type = CLR_RT_SignatureParser::c_Method; + m_flags = (*md++); + m_count = (*md++) + 1; + + m_assm = assm; + m_sig = md; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_MethodLocals( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // If you change this method, change "CLR_RT_ExecutionEngine::InitializeLocals" too. + // + + m_assm = assm; + m_sig = assm->GetSignature( md->locals ); + + m_type = CLR_RT_SignatureParser::c_Locals; + m_flags = 0; + m_count = md->numLocals; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_Objects( CLR_RT_HeapBlock* lst, int count, bool fTypes ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_lst = lst; + + m_type = CLR_RT_SignatureParser::c_Object; + m_flags = fTypes ? 1 : 0; + m_count = count; +} + +//--// + +HRESULT CLR_RT_SignatureParser::Advance( Element& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // If you change this method, change "CLR_RT_ExecutionEngine::InitializeLocals" too. + // + + NANOCLR_HEADER(); + + _ASSERTE(m_count > 0); + + m_count--; + + res.m_fByRef = false; + res.m_levels = 0; + + switch(m_type) + { + case c_Interfaces: + { + CLR_RT_TypeDef_Instance cls; + + res.m_dt = DATATYPE_CLASS; + + if(cls.ResolveToken( CLR_TkFromStream( m_sig ), m_assm ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + res.m_cls = cls; + } + break; + + case c_Object: + { + CLR_RT_TypeDescriptor desc; + CLR_RT_HeapBlock* ptr = m_lst++; + + if(m_flags) + { + // Reflection types are now boxed, so unbox first + if(ptr->DataType() == DATATYPE_OBJECT) + { + ptr = ptr->Dereference(); + } + if(ptr->DataType() != DATATYPE_REFLECTION) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_CHECK_HRESULT(desc.InitializeFromReflection( ptr->ReflectionDataConst() )); + } + else + { + switch(ptr->DataType()) + { + case DATATYPE_BYREF: + case DATATYPE_ARRAY_BYREF: + res.m_fByRef = true; + break; + + default: + // the remaining data types aren't to be handled + break; + } + + NANOCLR_CHECK_HRESULT(desc.InitializeFromObject( *ptr )); + } + + desc.m_handlerCls.InitializeFromIndex( desc.m_reflex.m_data.m_type ); + + res.m_levels = desc.m_reflex.m_levels; + res.m_dt = (CLR_DataType)desc.m_handlerCls.m_target->dataType; + res.m_cls = desc.m_reflex.m_data.m_type; + + // + // Special case for Object types. + // + if(res.m_cls.m_data == g_CLR_RT_WellKnownTypes.m_Object.m_data) + { + res.m_dt = DATATYPE_OBJECT; + } + } + break; + + default: + while(true) + { + res.m_dt = CLR_UncompressElementType( m_sig ); + + switch(res.m_dt) + { + case DATATYPE_BYREF: + if(res.m_fByRef) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + res.m_fByRef = true; + break; + + case DATATYPE_SZARRAY: + res.m_levels++; + break; + + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + { + CLR_UINT32 tk = CLR_TkFromStream( m_sig ); + + if(CLR_TypeFromTk( tk ) == TBL_TypeSpec) + { + CLR_RT_SignatureParser sub; sub.Initialize_TypeSpec( m_assm, m_assm->GetTypeSpec( CLR_DataFromTk( tk ) ) ); + int extraLevels = res.m_levels; + + NANOCLR_CHECK_HRESULT(sub.Advance( res )); + + res.m_levels += extraLevels; + } + else + { + CLR_RT_TypeDef_Instance cls; + + if(cls.ResolveToken( tk, m_assm ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + res.m_cls = cls; + } + + NANOCLR_SET_AND_LEAVE(S_OK); + } + + case DATATYPE_OBJECT: + res.m_cls = g_CLR_RT_WellKnownTypes.m_Object; + + NANOCLR_SET_AND_LEAVE(S_OK); + + case DATATYPE_VOID: + res.m_cls = g_CLR_RT_WellKnownTypes.m_Void; + + NANOCLR_SET_AND_LEAVE(S_OK); + + default: + { + const CLR_RT_TypeDef_Index* cls = c_CLR_RT_DataTypeLookup[ res.m_dt ].m_cls; + + if(cls) + { + res.m_cls = *cls; + NANOCLR_SET_AND_LEAVE(S_OK); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + } + break; + } + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_Assembly_Instance::InitializeFromIndex( const CLR_RT_Assembly_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + + return true; + } + + m_data = 0; + m_assm = NULL; + + return false; +} + +void CLR_RT_Assembly_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Assembly_Index::Clear(); + + m_assm = NULL; +} + +////////////////////////////// + +bool CLR_RT_TypeSpec_Instance::InitializeFromIndex( const CLR_RT_TypeSpec_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ] ; + m_target = m_assm->GetSignature( m_assm->GetTypeSpec ( TypeSpec() )->sig ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +void CLR_RT_TypeSpec_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeSpec_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_TypeSpec_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm && CLR_TypeFromTk( tk ) == TBL_TypeSpec) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = assm->GetSignature( assm->GetTypeSpec( idx )->sig ); + + return true; + } + + Clear(); + + return false; +} + +////////////////////////////// + +bool CLR_RT_TypeDef_Instance::InitializeFromReflection( const CLR_RT_ReflectionDef_Index& reflex, CLR_UINT32* levels ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Index cls; + const CLR_RT_TypeDef_Index* ptr = NULL; + + if(levels) *levels = reflex.m_levels; + + switch(reflex.m_kind) + { + case REFLECTION_TYPE: + if(reflex.m_levels > 0 && levels == NULL) + { + ptr = &g_CLR_RT_WellKnownTypes.m_Array; + } + else + { + ptr = &reflex.m_data.m_type; + } + break; + + case REFLECTION_TYPE_DELAYED: + if(g_CLR_RT_TypeSystem.FindTypeDef( reflex.m_data.m_raw, cls )) + { + ptr = &cls; + } + break; + } + + return ptr ? InitializeFromIndex( *ptr ) : false; +} + +bool CLR_RT_TypeDef_Instance::InitializeFromIndex( const CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetTypeDef ( Type () ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +bool CLR_RT_TypeDef_Instance::InitializeFromMethod( const CLR_RT_MethodDef_Instance& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(md)) + { + CLR_IDX idxAssm = md.Assembly(); + CLR_IDX idxType = md.CrossReference().GetOwner(); + + Set( idxAssm, idxType ); + + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ idxAssm-1 ]; + m_target = m_assm->GetTypeDef ( idxType ); + + return true; + } + + Clear(); + + return false; +} + +bool CLR_RT_TypeDef_Instance::InitializeFromField( const CLR_RT_FieldDef_Instance& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(fd)) + { + CLR_RT_Assembly* assm = fd.m_assm; + const CLR_RECORD_TYPEDEF* td = (const CLR_RECORD_TYPEDEF*)assm->GetTable( TBL_TypeDef ); + CLR_IDX idxField = fd.Field(); + int i = assm->m_pTablesSize[ TBL_TypeDef ]; + + if(fd.m_target->flags & CLR_RECORD_FIELDDEF::FD_Static) + { + for(;i; i--, td++) + { + if(td->sFields_First <= idxField && idxField < td->sFields_First + td->sFields_Num) + { + break; + } + } + } + else + { + for(;i; i--, td++) + { + if(td->iFields_First <= idxField && idxField < td->iFields_First + td->iFields_Num) + { + break; + } + } + } + + if(i) + { + CLR_IDX idxAssm = fd.Assembly(); + CLR_IDX idxType = assm->m_pTablesSize[ TBL_TypeDef ] - i; + + Set( idxAssm, idxType ); + + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ idxAssm-1 ]; + m_target = m_assm->GetTypeDef ( idxType ); + + return true; + } + } + + Clear(); + + return false; +} + +bool CLR_RT_TypeDef_Instance::IsATypeHandler() +{ + NATIVE_PROFILE_CLR_CORE(); + return (m_data == g_CLR_RT_WellKnownTypes.m_Type.m_data || m_data == g_CLR_RT_WellKnownTypes.m_TypeStatic.m_data); +} + +void CLR_RT_TypeDef_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_TypeDef_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch( CLR_TypeFromTk( tk ) ) + { + case TBL_TypeRef: + m_data = assm->m_pCrossReference_TypeRef[ idx ].m_target.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetTypeDef ( Type () ); + return true; + + case TBL_TypeDef: + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = assm->GetTypeDef( idx ); + return true; + + default: + // the remaining data types aren't to be handled + break; + } + } + + Clear(); + + return false; +} + +//--// + +bool CLR_RT_TypeDef_Instance::SwitchToParent() +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(*this)) + { + CLR_IDX extends = m_target->extends; + + if(extends != CLR_EmptyIndex) + { + CLR_RT_TypeDef_Index tmp; + const CLR_RT_TypeDef_Index* cls; + + if(extends & 0x8000) // TypeRef + { + cls = &m_assm->m_pCrossReference_TypeRef[ extends & 0x7FFF ].m_target; + } + else + { + tmp.Set( Assembly(), extends ); + + cls = &tmp; + } + + return InitializeFromIndex( *cls ); + } + } + + Clear(); + + return false; +} + +bool CLR_RT_TypeDef_Instance::HasFinalizer() const +{ + NATIVE_PROFILE_CLR_CORE(); + return NANOCLR_INDEX_IS_VALID(*this) && (CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_HasFinalizer); +} + +////////////////////////////// + +bool CLR_RT_FieldDef_Instance::InitializeFromIndex( const CLR_RT_FieldDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetFieldDef ( Field () ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +void CLR_RT_FieldDef_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_FieldDef_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_FieldDef_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk( tk )) + { + case TBL_FieldRef: + m_data = assm->m_pCrossReference_FieldRef[ idx ].m_target.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetFieldDef ( Field () ); + return true; + + case TBL_FieldDef: + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = m_assm->GetFieldDef( idx ); + return true; + + default: + // the remaining data types aren't to be handled + break; + } + } + + Clear(); + + return false; +} + +////////////////////////////// + +bool CLR_RT_MethodDef_Instance::InitializeFromIndex( const CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(NANOCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetMethodDef ( Method () ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +void CLR_RT_MethodDef_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_MethodDef_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk( tk )) + { + case TBL_MethodRef: + m_data = assm->m_pCrossReference_MethodRef[ idx ].m_target.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetMethodDef ( Method () ); + return true; + + case TBL_MethodDef: + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = m_assm->GetMethodDef( idx ); + return true; + + default: + // the remaining data types aren't to be handled + break; + } + } + + Clear(); + + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_TypeDescriptor::TypeDescriptor_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + m_flags = 0; // CLR_UINT32 m_flags; + m_handlerCls.Clear(); // CLR_RT_TypeDef_Instance m_handlerCls; + // + m_reflex .Clear(); // CLR_RT_ReflectionDef_Index m_reflex; +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromDataType( CLR_DataType dt ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(dt >= DATATYPE_FIRST_INVALID) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + m_flags = dtl.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask2; + + if(dtl.m_cls) + { + if(m_handlerCls.InitializeFromIndex( *dtl.m_cls ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + m_reflex.m_kind = REFLECTION_TYPE; + m_reflex.m_levels = 0; + m_reflex.m_data.m_type = *dtl.m_cls; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromReflection( const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + CLR_UINT32 levels; + + if(inst.InitializeFromReflection( reflex, &levels ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_CHECK_HRESULT(InitializeFromType( inst )); + + if(levels) + { + m_reflex.m_levels = levels; + + ConvertToArray(); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromTypeSpec( const CLR_RT_TypeSpec_Index& sig ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeSpec_Instance inst; + CLR_RT_SignatureParser parser; + + if(inst.InitializeFromIndex( sig ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + parser.Initialize_TypeSpec( inst.m_assm, inst.m_target ); + + NANOCLR_SET_AND_LEAVE(InitializeFromSignatureParser( parser )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromType( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(m_handlerCls.InitializeFromIndex( cls ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ m_handlerCls.m_target->dataType ]; + + m_flags = dtl.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask; + + m_reflex.m_kind = REFLECTION_TYPE; + m_reflex.m_levels = 0; + m_reflex.m_data.m_type = m_handlerCls; + + if(m_flags == CLR_RT_DataTypeLookup::c_Primitive) + { + if((m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum) + { + m_flags = CLR_RT_DataTypeLookup::c_Enum; + } + } + else + { + switch(m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) + { + case CLR_RECORD_TYPEDEF::TD_Semantics_ValueType: m_flags = CLR_RT_DataTypeLookup::c_ValueType; break; + case CLR_RECORD_TYPEDEF::TD_Semantics_Class : m_flags = CLR_RT_DataTypeLookup::c_Class ; break; + case CLR_RECORD_TYPEDEF::TD_Semantics_Interface: m_flags = CLR_RT_DataTypeLookup::c_Interface; break; + case CLR_RECORD_TYPEDEF::TD_Semantics_Enum : m_flags = CLR_RT_DataTypeLookup::c_Enum ; break; + } + } + + if(m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_Array.m_data) + { + m_flags |= CLR_RT_DataTypeLookup::c_Array; + } + + if(m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_ArrayList.m_data) + { + m_flags |= CLR_RT_DataTypeLookup::c_ArrayList; + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromFieldDefinition( const CLR_RT_FieldDef_Instance& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_SignatureParser parser; parser.Initialize_FieldDef( fd.m_assm, fd.m_target ); + + NANOCLR_SET_AND_LEAVE(InitializeFromSignatureParser( parser )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromSignatureParser( CLR_RT_SignatureParser& parser ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_SignatureParser::Element res; + + if(parser.Available() <= 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + NANOCLR_CHECK_HRESULT(parser.Advance( res )); + + NANOCLR_CHECK_HRESULT(InitializeFromType( res.m_cls )); + + if(res.m_levels) + { + m_reflex.m_levels = res.m_levels; + + ConvertToArray(); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromObject( const CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_RT_HeapBlock* obj = &ref; + CLR_DataType dt; + + + while(true) + { + dt = (CLR_DataType)obj->DataType(); + + if(dt == DATATYPE_BYREF || + dt == DATATYPE_OBJECT ) + { + obj = obj->Dereference(); FAULT_ON_NULL(obj); + } +#if defined(NANOCLR_APPDOMAINS) + else if(dt == DATATYPE_TRANSPARENT_PROXY) + { + NANOCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + obj = obj->TransparentProxyDereference(); + } +#endif + else + { + break; + } + } + + { + const CLR_RT_TypeDef_Index* cls = NULL; + const CLR_RT_ReflectionDef_Index* reflex = NULL; + + switch(dt) + { + case DATATYPE_SZARRAY: + reflex = &obj->ReflectionDataConst(); + cls = &reflex->m_data.m_type; + break; + + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS: + cls = &obj->ObjectCls(); + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)obj; + + cls = NANOCLR_INDEX_IS_VALID(dlg->m_cls) ? &dlg->m_cls : &g_CLR_RT_WellKnownTypes.m_Delegate; + } + break; + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* dlgLst = (CLR_RT_HeapBlock_Delegate_List*)obj; + + cls = NANOCLR_INDEX_IS_VALID(dlgLst->m_cls) ? &dlgLst->m_cls : &g_CLR_RT_WellKnownTypes.m_MulticastDelegate; + } + break; + + //--// + + case DATATYPE_WEAKCLASS: + { + cls = &g_CLR_RT_WellKnownTypes.m_WeakReference; + } + break; + + //--// + + case DATATYPE_REFLECTION: + reflex = &(obj->ReflectionDataConst()); + + switch(reflex->m_kind) + { + case REFLECTION_ASSEMBLY : cls = &g_CLR_RT_WellKnownTypes.m_Assembly ; break; + case REFLECTION_TYPE : cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_TYPE_DELAYED: cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_CONSTRUCTOR : cls = &g_CLR_RT_WellKnownTypes.m_ConstructorInfo; break; + case REFLECTION_METHOD : cls = &g_CLR_RT_WellKnownTypes.m_MethodInfo ; break; + case REFLECTION_FIELD : cls = &g_CLR_RT_WellKnownTypes.m_FieldInfo ; break; + } + + break; + + //--// + + case DATATYPE_ARRAY_BYREF: + { + CLR_RT_HeapBlock_Array* array = obj->Array(); FAULT_ON_NULL(array); + + if(array->m_fReference) + { + obj = (CLR_RT_HeapBlock*)array->GetElement( obj->ArrayIndex() ); + + NANOCLR_SET_AND_LEAVE(InitializeFromObject( *obj )); + } + + reflex = &array->ReflectionDataConst(); + cls = &reflex->m_data.m_type; + } + break; + + //--// + + default: + NANOCLR_SET_AND_LEAVE(InitializeFromDataType( dt )); + } + + if(cls) + { + NANOCLR_CHECK_HRESULT(InitializeFromType( *cls )); + } + + if(reflex) + { + m_reflex = *reflex; + } + + if(dt == DATATYPE_SZARRAY) + { + ConvertToArray(); + } + } + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////// + +void CLR_RT_TypeDescriptor::ConvertToArray() +{ + NATIVE_PROFILE_CLR_CORE(); + m_flags &= CLR_RT_DataTypeLookup::c_SemanticMask; + m_flags |= CLR_RT_DataTypeLookup::c_Array; + + m_handlerCls.InitializeFromIndex( g_CLR_RT_WellKnownTypes.m_Array ); +} + +bool CLR_RT_TypeDescriptor::ShouldEmitHash() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList)) + { + return true; + } + + if(m_flags & (CLR_RT_DataTypeLookup::c_Primitive | CLR_RT_DataTypeLookup::c_ValueType | CLR_RT_DataTypeLookup::c_Enum)) + { + return false; + } + + if(m_handlerCls.CrossReference().m_hash != 0) + { + return true; + } + + return false; +} + +bool CLR_RT_TypeDescriptor::GetElementType( CLR_RT_TypeDescriptor& sub ) +{ + NATIVE_PROFILE_CLR_CORE(); + switch(m_reflex.m_levels) + { + case 0: + return false; + + case 1: + sub.InitializeFromType( m_reflex.m_data.m_type ); + break; + + default: + sub = *this; + sub.m_reflex.m_levels--; + break; + } + + return true; +} + +//////////////////////////////////////// + +HRESULT CLR_RT_TypeDescriptor::ExtractObjectAndDataType( CLR_RT_HeapBlock*& ref, CLR_DataType& dt ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + while(true) + { + dt = (CLR_DataType)ref->DataType(); + + if(dt == DATATYPE_BYREF || + dt == DATATYPE_OBJECT ) + { + ref = ref->Dereference(); FAULT_ON_NULL(ref); + } + else + { + break; + } + } + + NANOCLR_NOCLEANUP(); +} + + +HRESULT CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( const CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* obj = (CLR_RT_HeapBlock*)&ref; + CLR_DataType dt; + + NANOCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + + if(dt == DATATYPE_VALUETYPE || dt == DATATYPE_CLASS) + { + res = obj->ObjectCls(); + } + else + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + if(dtl.m_cls) + { + res = *dtl.m_cls; + } + else + { + res.Clear(); + } + } + + if(NANOCLR_INDEX_IS_INVALID(res)) + { + CLR_RT_TypeDescriptor desc; + + NANOCLR_CHECK_HRESULT(desc.InitializeFromObject( ref )) + + // If desc.InitializeFromObject( ref ) call succeded, then we use m_handlerCls for res + res = desc.m_handlerCls; + + if(NANOCLR_INDEX_IS_INVALID(res)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + NANOCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// +// Keep this string less than 8-character long (including terminator) because it's stuffed into an 8-byte structure. +// +static const char c_MARKER_ASSEMBLY_V1[] = "NFMRK1"; + +bool CLR_RECORD_ASSEMBLY::GoodHeader() const +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RECORD_ASSEMBLY header = *this; header.headerCRC = 0; + + if(SUPPORT_ComputeCRC( &header, sizeof(header), 0 ) != this->headerCRC) return false; + + if(this->stringTableVersion != c_CLR_StringTable_Version) return false; + + return memcmp( marker, c_MARKER_ASSEMBLY_V1, sizeof(c_MARKER_ASSEMBLY_V1) ) == 0; +} + +bool CLR_RECORD_ASSEMBLY::GoodAssembly() const +{ + NATIVE_PROFILE_CLR_CORE(); + if(!GoodHeader()) return false; + return SUPPORT_ComputeCRC( &this[ 1 ], this->TotalSize() - sizeof(*this), 0 ) == this->assemblyCRC; +} + +#if defined(WIN32) + +void CLR_RECORD_ASSEMBLY::ComputeCRC() +{ + NATIVE_PROFILE_CLR_CORE(); + memcpy( marker, c_MARKER_ASSEMBLY_V1, sizeof(marker) ); + + headerCRC = 0; + assemblyCRC = SUPPORT_ComputeCRC( &this[ 1 ], this->TotalSize() - sizeof(*this), 0 ); + headerCRC = SUPPORT_ComputeCRC( this , sizeof(*this), 0 ); +} + +#endif + +CLR_UINT32 CLR_RECORD_ASSEMBLY::ComputeAssemblyHash( const char* name, const CLR_RECORD_VERSION& ver ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 assemblyHASH; + + assemblyHASH = SUPPORT_ComputeCRC( name, (int)hal_strlen_s( name ), 0 ); + assemblyHASH = SUPPORT_ComputeCRC( &ver, sizeof( ver ), assemblyHASH ); + + return assemblyHASH; +} + +//--// + +CLR_PMETADATA CLR_RECORD_EH::ExtractEhFromByteCode( CLR_PMETADATA ipEnd, const CLR_RECORD_EH*& ptrEh, CLR_UINT32& numEh ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 num = *(--ipEnd); ipEnd -= sizeof(CLR_RECORD_EH) * num; + + numEh = num; + ptrEh = (const CLR_RECORD_EH*)ipEnd; + + return ipEnd; +} + +CLR_UINT32 CLR_RECORD_EH::GetToken() const +{ + NATIVE_PROFILE_CLR_CORE(); + if(classToken & 0x8000) + { + return CLR_TkFromType( TBL_TypeRef, classToken & 0x7FFF ); + } + else + { + return CLR_TkFromType( TBL_TypeDef, classToken ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_ExceptionHandler::ConvertFromEH( const CLR_RT_MethodDef_Instance& owner, CLR_PMETADATA ipStart, const CLR_RECORD_EH* ehPtr ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RECORD_EH eh; memcpy( &eh, ehPtr, sizeof(eh) ); + + switch(eh.mode) + { + case CLR_RECORD_EH::EH_Finally: + m_typeFilter.Clear(); + break; + + case CLR_RECORD_EH::EH_Filter: + m_userFilterStart = ipStart + eh.filterStart; + break; + + case CLR_RECORD_EH::EH_CatchAll: + m_typeFilter = g_CLR_RT_WellKnownTypes.m_Object; + break; + + case CLR_RECORD_EH::EH_Catch: + { + CLR_RT_TypeDef_Instance cls; + if(cls.ResolveToken( eh.GetToken(), owner.m_assm ) == false) return false; + m_typeFilter = cls; + } + break; + + default: + return false; + } + + if(owner.m_target->RVA == CLR_EmptyIndex) return false; + + m_ehType = eh.mode; + m_tryStart = ipStart + eh.tryStart; + m_tryEnd = ipStart + eh.tryEnd; + m_handlerStart = ipStart + eh.handlerStart; + m_handlerEnd = ipStart + eh.handlerEnd; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +bool CLR_RT_Assembly::IsSameAssembly( const CLR_RT_Assembly& assm ) const +{ + if( + m_header->headerCRC == assm.m_header->headerCRC && + m_header->assemblyCRC == assm.m_header->assemblyCRC + ) + { + return true; + } + + return false; +} + +void CLR_RT_Assembly::Assembly_Initialize( CLR_RT_Assembly::Offsets& offsets ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8* buffer = (CLR_UINT8*)this; + int i; + + m_szName = GetString( m_header->assemblyName ); + + //--// + buffer += offsets.iBase ; + m_pCrossReference_AssemblyRef = (CLR_RT_AssemblyRef_CrossReference*)buffer; buffer += offsets.iAssemblyRef ; + m_pCrossReference_TypeRef = (CLR_RT_TypeRef_CrossReference *)buffer; buffer += offsets.iTypeRef ; + m_pCrossReference_FieldRef = (CLR_RT_FieldRef_CrossReference *)buffer; buffer += offsets.iFieldRef ; + m_pCrossReference_MethodRef = (CLR_RT_MethodRef_CrossReference *)buffer; buffer += offsets.iMethodRef ; + m_pCrossReference_TypeDef = (CLR_RT_TypeDef_CrossReference *)buffer; buffer += offsets.iTypeDef ; + m_pCrossReference_FieldDef = (CLR_RT_FieldDef_CrossReference *)buffer; buffer += offsets.iFieldDef ; + m_pCrossReference_MethodDef = (CLR_RT_MethodDef_CrossReference *)buffer; buffer += offsets.iMethodDef ; + +#if !defined(NANOCLR_APPDOMAINS) + m_pStaticFields = (CLR_RT_HeapBlock *)buffer; buffer += offsets.iStaticFields ; + + memset( m_pStaticFields, 0, offsets.iStaticFields ); +#endif + + //--// + + { + ITERATE_THROUGH_RECORDS(this,i,TypeDef,TYPEDEF) + { + dst->m_flags = 0; + dst->m_totalFields = 0; + dst->m_hash = 0; + } + } + + { + ITERATE_THROUGH_RECORDS(this,i,FieldDef,FIELDDEF) + { + dst->m_offset = CLR_EmptyIndex; + } + } + + { + ITERATE_THROUGH_RECORDS(this,i,MethodDef,METHODDEF) + { + dst->m_data = CLR_EmptyIndex; + } + } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + { + m_pDebuggingInfo_MethodDef = (CLR_RT_MethodDef_DebuggingInfo*)buffer; buffer += offsets.iDebuggingInfoMethods; + + memset( m_pDebuggingInfo_MethodDef, 0, offsets.iDebuggingInfoMethods ); + } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) +} + +HRESULT CLR_RT_Assembly::CreateInstance( const CLR_RECORD_ASSEMBLY* header, CLR_RT_Assembly*& assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // We have to use this trick, otherwise the C++ compiler will try to all the constructor for Assembly. + // + NANOCLR_HEADER(); + + CLR_UINT8 buf[ sizeof(CLR_RT_Assembly) ]; + CLR_RT_Assembly* skeleton = (CLR_RT_Assembly*)buf; + + NANOCLR_CLEAR(*skeleton); + + if(header->GoodAssembly() == false) NANOCLR_MSG_SET_AND_LEAVE(CLR_E_FAIL, L"Failed in type system: assembly is not good.\n"); + + skeleton->m_header = header; + + + // + // Compute overall size for assembly data structure. + // + { + for(uint32_t i = 0; im_pTablesSize)-1; i++) + { + skeleton->m_pTablesSize[ i ] = header->SizeOfTable ( (CLR_TABLESENUM)i ); + } + + skeleton->m_pTablesSize[ TBL_AssemblyRef ] /= sizeof(CLR_RECORD_ASSEMBLYREF ); + skeleton->m_pTablesSize[ TBL_TypeRef ] /= sizeof(CLR_RECORD_TYPEREF ); + skeleton->m_pTablesSize[ TBL_FieldRef ] /= sizeof(CLR_RECORD_FIELDREF ); + skeleton->m_pTablesSize[ TBL_MethodRef ] /= sizeof(CLR_RECORD_METHODREF ); + skeleton->m_pTablesSize[ TBL_TypeDef ] /= sizeof(CLR_RECORD_TYPEDEF ); + skeleton->m_pTablesSize[ TBL_FieldDef ] /= sizeof(CLR_RECORD_FIELDDEF ); + skeleton->m_pTablesSize[ TBL_MethodDef ] /= sizeof(CLR_RECORD_METHODDEF ); + skeleton->m_pTablesSize[ TBL_Attributes ] /= sizeof(CLR_RECORD_ATTRIBUTE ); + skeleton->m_pTablesSize[ TBL_TypeSpec ] /= sizeof(CLR_RECORD_TYPESPEC ); + skeleton->m_pTablesSize[ TBL_Resources ] /= sizeof(CLR_RECORD_RESOURCE ); + skeleton->m_pTablesSize[ TBL_ResourcesFiles ] /= sizeof(CLR_RECORD_RESOURCE_FILE); + } + + //--// + + // + // Count static fields. + // + { + const CLR_RECORD_TYPEDEF* src = (const CLR_RECORD_TYPEDEF*)skeleton->GetTable( TBL_TypeDef ); + + for(int i=0; im_pTablesSize[ TBL_TypeDef ]; i++, src++) + { + skeleton->m_iStaticFields += src->sFields_Num; + } + } + + //--// + + { + CLR_RT_Assembly::Offsets offsets; + + offsets.iBase = ROUNDTOMULTIPLE(sizeof(CLR_RT_Assembly) , CLR_UINT32); + offsets.iAssemblyRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_AssemblyRef ] * sizeof(CLR_RT_AssemblyRef_CrossReference), CLR_UINT32); + offsets.iTypeRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_TypeRef ] * sizeof(CLR_RT_TypeRef_CrossReference ), CLR_UINT32); + offsets.iFieldRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_FieldRef ] * sizeof(CLR_RT_FieldRef_CrossReference ), CLR_UINT32); + offsets.iMethodRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_MethodRef ] * sizeof(CLR_RT_MethodRef_CrossReference ), CLR_UINT32); + offsets.iTypeDef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_TypeDef ] * sizeof(CLR_RT_TypeDef_CrossReference ), CLR_UINT32); + offsets.iFieldDef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_FieldDef ] * sizeof(CLR_RT_FieldDef_CrossReference ), CLR_UINT32); + offsets.iMethodDef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_CrossReference ), CLR_UINT32); + + if(skeleton->m_header->numOfPatchedMethods > 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_ASSM_PATCHING_NOT_SUPPORTED); + } + +#if !defined(NANOCLR_APPDOMAINS) + offsets.iStaticFields = ROUNDTOMULTIPLE(skeleton->m_iStaticFields * sizeof(CLR_RT_HeapBlock ), CLR_UINT32); +#endif + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + offsets.iDebuggingInfoMethods = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_DebuggingInfo ), CLR_UINT32); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + size_t iTotalRamSize = offsets.iBase + + offsets.iAssemblyRef + + offsets.iTypeRef + + offsets.iFieldRef + + offsets.iMethodRef + + offsets.iTypeDef + + offsets.iFieldDef + + offsets.iMethodDef; + +#if !defined(NANOCLR_APPDOMAINS) + iTotalRamSize += offsets.iStaticFields; +#endif + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + iTotalRamSize += offsets.iDebuggingInfoMethods; +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //--// + + assm = EVENTCACHE_EXTRACT_NODE_AS_BYTES(g_CLR_RT_EventCache,CLR_RT_Assembly,DATATYPE_ASSEMBLY,0,(CLR_UINT32)iTotalRamSize); CHECK_ALLOCATION(assm); + + { + // + // We don't want to blow away the block header... + // + CLR_RT_HeapBlock* src = skeleton; + CLR_RT_HeapBlock* dst = assm; + + memset( &dst[ 1 ], 0, iTotalRamSize-sizeof(CLR_RT_HeapBlock) ); + memcpy( &dst[ 1 ], &src[ 1 ], sizeof(*assm)-sizeof(CLR_RT_HeapBlock) ); + } + + assm->Assembly_Initialize( offsets ); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( " Assembly: %s (%d.%d.%d.%d) ", assm->m_szName, header->version.iMajorVersion, header->version.iMinorVersion, header->version.iBuildNumber, header->version.iRevisionNumber ); + + if(s_CLR_RT_fTrace_AssemblyOverhead >= c_CLR_RT_Trace_Info) + { + size_t iMetaData = header->SizeOfTable( TBL_AssemblyRef ) + + header->SizeOfTable( TBL_TypeRef ) + + header->SizeOfTable( TBL_FieldRef ) + + header->SizeOfTable( TBL_MethodRef ) + + header->SizeOfTable( TBL_TypeDef ) + + header->SizeOfTable( TBL_FieldDef ) + + header->SizeOfTable( TBL_MethodDef ) + + header->SizeOfTable( TBL_Attributes ) + + header->SizeOfTable( TBL_TypeSpec ) + + header->SizeOfTable( TBL_Signatures ); + + CLR_Debug::Printf( " (%d RAM - %d ROM - %d METADATA)\r\n\r\n", iTotalRamSize, header->TotalSize(), iMetaData ); + + CLR_Debug::Printf( " AssemblyRef = %8d bytes (%8d elements)\r\n", offsets.iAssemblyRef , skeleton->m_pTablesSize[ TBL_AssemblyRef ] ); + CLR_Debug::Printf( " TypeRef = %8d bytes (%8d elements)\r\n", offsets.iTypeRef , skeleton->m_pTablesSize[ TBL_TypeRef ] ); + CLR_Debug::Printf( " FieldRef = %8d bytes (%8d elements)\r\n", offsets.iFieldRef , skeleton->m_pTablesSize[ TBL_FieldRef ] ); + CLR_Debug::Printf( " MethodRef = %8d bytes (%8d elements)\r\n", offsets.iMethodRef , skeleton->m_pTablesSize[ TBL_MethodRef ] ); + CLR_Debug::Printf( " TypeDef = %8d bytes (%8d elements)\r\n", offsets.iTypeDef , skeleton->m_pTablesSize[ TBL_TypeDef ] ); + CLR_Debug::Printf( " FieldDef = %8d bytes (%8d elements)\r\n", offsets.iFieldDef , skeleton->m_pTablesSize[ TBL_FieldDef ] ); + CLR_Debug::Printf( " MethodDef = %8d bytes (%8d elements)\r\n", offsets.iMethodDef , skeleton->m_pTablesSize[ TBL_MethodDef ] ); +#if !defined(NANOCLR_APPDOMAINS) + CLR_Debug::Printf( " StaticFields = %8d bytes (%8d elements)\r\n", offsets.iStaticFields , skeleton->m_iStaticFields ); +#endif + CLR_Debug::Printf( "\r\n" ); + + CLR_Debug::Printf( " Attributes = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_Attributes ] * sizeof(CLR_RECORD_ATTRIBUTE), skeleton->m_pTablesSize[ TBL_Attributes ] ); + CLR_Debug::Printf( " TypeSpec = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_TypeSpec ] * sizeof(CLR_RECORD_TYPESPEC ), skeleton->m_pTablesSize[ TBL_TypeSpec ] ); + CLR_Debug::Printf( " Resources = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_Resources ] * sizeof(CLR_RECORD_RESOURCE ), skeleton->m_pTablesSize[ TBL_Resources ] ); + CLR_Debug::Printf( " Resources Files = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_ResourcesFiles ] * sizeof(CLR_RECORD_RESOURCE ), skeleton->m_pTablesSize[ TBL_ResourcesFiles ] ); + CLR_Debug::Printf( " Resources Data = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_ResourcesData ] ); + CLR_Debug::Printf( " Strings = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_Strings ] ); + CLR_Debug::Printf( " Signatures = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_Signatures ] ); + CLR_Debug::Printf( " ByteCode = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_ByteCode ] ); + CLR_Debug::Printf( "\r\n\r\n" ); + } +#endif + } + + NANOCLR_NOCLEANUP(); +} + + +#if defined(WIN32) +HRESULT CLR_RT_Assembly::CreateInstance( const CLR_RECORD_ASSEMBLY* header, CLR_RT_Assembly*& assm, const wchar_t* szName ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + std::string strPath; + + NANOCLR_CHECK_HRESULT(CLR_RT_Assembly::CreateInstance( header, assm )); + + if(szName != NULL) + { + CLR_RT_UnicodeHelper::ConvertToUTF8( szName, strPath ); + + assm->m_strPath = new std::string( strPath ); + } + + NANOCLR_NOCLEANUP(); +} +#endif + +bool CLR_RT_Assembly::Resolve_AssemblyRef( bool fOutput ) +{ + NATIVE_PROFILE_CLR_CORE(); + bool fGot = true; + int i; + + ITERATE_THROUGH_RECORDS(this,i,AssemblyRef,ASSEMBLYREF) + { + const char* szName = GetString( src->name ); + + if(dst->m_target == NULL) + { + bool fExact = true; + + // + // Exact matching if this is a patch and the reference is toward the patched assembly. + // + if(m_header->flags & CLR_RECORD_ASSEMBLY::c_Flags_Patch) + { + if(!strcmp( szName, m_szName )) + { + fExact = true; + } + } + + CLR_RT_Assembly* target = g_CLR_RT_TypeSystem.FindAssembly( szName, &src->version, fExact ); + + if(target == NULL || (target->m_flags & CLR_RT_Assembly::Resolved) == 0) + { +#if !defined(BUILD_RTM) + if(fOutput) + { + CLR_Debug::Printf( "Assembly: %s (%d.%d.%d.%d)", m_szName, m_header->version.iMajorVersion, m_header->version.iMinorVersion, m_header->version.iBuildNumber, m_header->version.iRevisionNumber ); + + CLR_Debug::Printf( " needs assembly '%s' (%d.%d.%d.%d)\r\n", szName, src->version.iMajorVersion, src->version.iMinorVersion, src->version.iBuildNumber, src->version.iRevisionNumber ); + } +#endif + + fGot = false; + } + else + { + dst->m_target = target; + } + } + } + + return fGot; +} + +void CLR_RT_Assembly::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_idx) + { + g_CLR_RT_TypeSystem.m_assemblies[ m_idx-1 ] = NULL; + } + +#if defined(WIN32) + if(this->m_strPath != NULL) + { + delete this->m_strPath; + this->m_strPath = NULL; + } +#endif + + //--// + + g_CLR_RT_EventCache.Append_Node( this ); +} + +//--// +HRESULT CLR_RT_Assembly::Resolve_TypeRef() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int i; + + ITERATE_THROUGH_RECORDS(this,i,TypeRef,TYPEREF) + { + if(src->scope & 0x8000) // Flag for TypeRef + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->scope & 0x7FFF ].m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown scope: %08x\r\n", src->scope ); +#endif + +#if defined(_WIN32) + NANOCLR_CHARMSG_SET_AND_LEAVE(CLR_E_FAIL, "Resolve: unknown scope: %08x\r\n", src->scope); +#else + NANOCLR_MSG1_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve: unknown scope: %08x\r\n", src->scope); +#endif + } + + const char* szName = GetString( src->name ); + if(inst.m_assm->FindTypeDef( szName, inst.Type(), dst->m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown type: %s\r\n", szName ); +#endif + +#if defined(_WIN32) + NANOCLR_CHARMSG_SET_AND_LEAVE(CLR_E_FAIL, "Resolve: unknown type: %s\r\n", szName); +#else + NANOCLR_MSG1_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve: unknown type: %s\r\n", szName); +#endif + } + } + else + { + CLR_RT_Assembly* assm = m_pCrossReference_AssemblyRef[ src->scope ].m_target; + if(assm == NULL) + { + NANOCLR_MSG_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve: assm is null\n"); + } + + const char* szNameSpace = GetString( src->nameSpace ); + const char* szName = GetString( src->name ); + if(assm->FindTypeDef( szName, szNameSpace, dst->m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown type: %s.%s\r\n", szNameSpace, szName ); +#endif + +#if defined(_WIN32) + NANOCLR_CHARMSG_SET_AND_LEAVE(CLR_E_FAIL, "Resolve: unknown type: %s.%s\r\n", szNameSpace, szName); +#else + NANOCLR_MSG1_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve: unknown type: %s\r\n", szName); +#endif + } + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Assembly::Resolve_FieldRef() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int i; + + ITERATE_THROUGH_RECORDS(this,i,FieldRef,FIELDREF) + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->container ].m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve Field: unknown scope: %08x\r\n", src->container ); +#endif + +#if defined(_WIN32) + NANOCLR_CHARMSG_SET_AND_LEAVE(CLR_E_FAIL, "Resolve Field: unknown scope: %08x\r\n", src->container); +#else + NANOCLR_MSG1_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve Field: unknown scope: %08x\r\n", src->container); +#endif + } + + const char* szName = GetString( src->name ); + + if(inst.m_assm->FindFieldDef( inst.m_target, szName, this, src->sig, dst->m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown field: %s\r\n", szName ); +#endif + +#if defined(_WIN32) + NANOCLR_CHARMSG_SET_AND_LEAVE(CLR_E_FAIL, "Resolve: unknown field: %s\r\n", szName); +#else + NANOCLR_MSG1_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve: unknown field: %s\r\n", szName); +#endif + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Assembly::Resolve_MethodRef() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int i; + + ITERATE_THROUGH_RECORDS(this,i,MethodRef,METHODREF) + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->container ].m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve Field: unknown scope: %08x\r\n", src->container ); +#endif + +#if defined(_WIN32) + NANOCLR_CHARMSG_SET_AND_LEAVE(CLR_E_FAIL, "Resolve Field: unknown scope: %08x\r\n", src->container); +#else + NANOCLR_MSG1_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve Field: unknown scope: %08x\r\n", src->container); +#endif + } + + const char* name = GetString( src->name ); + bool fGot = false; + + while(NANOCLR_INDEX_IS_VALID(inst)) + { + if(inst.m_assm->FindMethodDef( inst.m_target, name, this, src->sig, dst->m_target )) + { + fGot = true; + break; + } + + inst.SwitchToParent(); + } + + if(fGot == false) + { + inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->container ].m_target ); + + const CLR_RECORD_TYPEDEF* qTD = inst.m_target; + CLR_RT_Assembly* qASSM = inst.m_assm; + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown method: %s.%s.%s\r\n", qASSM->GetString( qTD->nameSpace ), qASSM->GetString( qTD->name ), name ); +#endif + +#if defined(_WIN32) + NANOCLR_CHARMSG_SET_AND_LEAVE(CLR_E_FAIL, "Resolve: unknown method: %s\r\n", name); +#else + NANOCLR_MSG1_SET_AND_LEAVE(CLR_E_FAIL, L"Resolve: unknown method: %s\r\n", name); +#endif + } + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_Assembly::Resolve_Link() +{ + NATIVE_PROFILE_CLR_CORE(); + int iStaticFields = 0; + int idxType; + + ITERATE_THROUGH_RECORDS(this,idxType,TypeDef,TYPEDEF) + { + int num; + int i; + + // + // Link static fields. + // + { + CLR_RT_FieldDef_CrossReference* fd = &m_pCrossReference_FieldDef[ src->sFields_First ]; + + num = src->sFields_Num; + + for(; num; num--, fd++) + { + fd->m_offset = iStaticFields++; + } + } + + // + // Link instance fields. + // + { + CLR_RT_TypeDef_Index idx ; idx.Set( m_idx, idxType ); + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( idx ); + CLR_IDX tot = 0; + + do + { + if(inst.m_target->flags & CLR_RECORD_TYPEDEF::TD_HasFinalizer) + { + dst->m_flags |= CLR_RT_TypeDef_CrossReference::TD_CR_HasFinalizer; + } + +#if defined(NANOCLR_APPDOMAINS) + if(inst.m_data == g_CLR_RT_WellKnownTypes.m_MarshalByRefObject.m_data) + { + dst->m_flags |= CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject; + } +#endif + + tot += inst.m_target->iFields_Num; + } + while(inst.SwitchToParent()); + + dst->m_totalFields = tot; + + //--// + + CLR_RT_FieldDef_CrossReference* fd = &m_pCrossReference_FieldDef[ src->iFields_First ]; + + num = src->iFields_Num; + i = tot - num + CLR_RT_HeapBlock::HB_Object_Fields_Offset; // Take into account the offset from the beginning of the object. + + for(; num; num--, i++, fd++) + { + fd->m_offset = i; + } + } + + // + // Link methods. + // + { + CLR_RT_MethodDef_CrossReference* md = &m_pCrossReference_MethodDef[ src->methods_First ]; + + int num = src->vMethods_Num + src->iMethods_Num + src->sMethods_Num; + + for(; num; num--, md++) + { + md->m_data = idxType; + } + } + } +} + +//--// + +#if defined(NANOCLR_APPDOMAINS) + +HRESULT CLR_RT_AppDomain::CreateInstance( const char* szName, CLR_RT_AppDomain*& appDomain ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + CLR_RT_HeapBlock name; name.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( name ); + + if(!szName || szName[ 0 ] == '\0') NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + //Check to see that the name does not already exist. + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + if(!strcmp( appDomain->m_strName->StringText(), szName )) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( name, szName )); + + appDomain = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_AppDomain,DATATYPE_APPDOMAIN_HEAD); CHECK_ALLOCATION(appDomain); + + appDomain->AppDomain_Initialize(); + + appDomain->m_strName = name.DereferenceString(); + + g_CLR_RT_ExecutionEngine.m_appDomains.LinkAtBack( appDomain ); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_AppDomain::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + CheckAll(); + + /* + AppDomains can be zombied and stay around forever. It is worth looking into cleaning up dead AppDomains, but this + needs to be done with great care. First, enumerations of AppDomains must not be allowed. Second, the AppDomain must really be dead. + This is much harder to ensure. Everything that is needed to be checked for explicit AD unloading (stack frames, finalizable objects) + must be checked, but also other things that can cause the AppDomain to be alive, like timers, manaaged drivers, transparent proxies, etc.. + */ + + if(m_state == CLR_RT_AppDomain::AppDomainState_Unloaded) + { + //We could actually clean up here. Since the AppDomain is now officially loaded, + //we can remove all object_to_event_dst references, and null out the + //pointers in the managed AppDomain class, provided that calling any method on the + //AppDomain will result in a AppDomainDisposed exception. However, it's probably + //not worth the effort, the majority of the resources have been already cleaned + //up, from AppDomain_Uninitialize + + if(IsReadyForRelease()) + { + DestroyInstance(); + } + } +} + +void CLR_RT_AppDomain::AppDomain_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize(); + + m_appDomainAssemblies.DblLinkedList_Initialize(); + + m_state = CLR_RT_AppDomain::AppDomainState_Loaded; + m_id = g_CLR_RT_ExecutionEngine.m_appDomainIdNext++; + m_globalLock = NULL; + m_strName = NULL; + m_outOfMemoryException = NULL; + m_appDomainAssemblyLastAccess = NULL; +} + +void CLR_RT_AppDomain::AppDomain_Uninitialize() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,m_appDomainAssemblies) + { + appDomainAssembly->DestroyInstance(); + } + NANOCLR_FOREACH_NODE_END(); +} + +void CLR_RT_AppDomain::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + AppDomain_Uninitialize(); + + Unlink(); + + g_CLR_RT_EventCache.Append_Node( this ); +} + +HRESULT CLR_RT_AppDomain::LoadAssembly( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( this ); + CLR_RT_AppDomainAssembly* appDomainAssembly = NULL; + int i; + + FAULT_ON_NULL( assm ); + + //check to make sure the assembly is not already loaded + if(FindAppDomainAssembly( assm ) != NULL) NANOCLR_SET_AND_LEAVE(S_OK); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + g_CLR_RT_ExecutionEngine.Breakpoint_Assemblies_Loaded(); +#endif + + //Next, make sure that all dependent assemblies are loaded. + { + ITERATE_THROUGH_RECORDS(assm,i,AssemblyRef,ASSEMBLYREF) + { + NANOCLR_CHECK_HRESULT(LoadAssembly( dst->m_target )); + } + } + + NANOCLR_CHECK_HRESULT(CLR_RT_AppDomainAssembly::CreateInstance( this, assm, appDomainAssembly )); + + if(m_outOfMemoryException == NULL) + { + //Allocate an out of memory exception. We should never get into a case where an out of memory exception + //cannot be thrown. + CLR_RT_HeapBlock exception; + + _ASSERTE(!strcmp( assm->m_szName, "mscorlib" )); //always the first assembly to be loaded + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( exception, g_CLR_RT_WellKnownTypes.m_OutOfMemoryException )); + + m_outOfMemoryException = exception.Dereference(); + } + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(appDomainAssembly) + { + appDomainAssembly->DestroyInstance(); + } + } + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + NANOCLR_CLEANUP_END(); +} + + +HRESULT CLR_RT_AppDomain::GetManagedObject( CLR_RT_HeapBlock& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( this ); + + res.SetObjectReference( NULL ); + + //Check if a managed object is already present, and use it + NANOCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,m_references) + { + CLR_RT_HeapBlock* obj = ref->m_objectPtr; + + _ASSERTE(FIMPLIES(obj, obj->DataType() == DATATYPE_CLASS || obj->DataType() == DATATYPE_VALUETYPE)); + + if(obj && obj->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_AppDomain.m_data) + { + //managed appDomain is found. Use it. + res.SetObjectReference( ref->m_objectPtr ); + + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + NANOCLR_FOREACH_NODE_END(); + + { + //Create the managed AppDomain in the destination AppDomain + CLR_RT_HeapBlock* pRes; + CLR_RT_ProtectFromGC gc( res ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( res, g_CLR_RT_WellKnownTypes.m_AppDomain )); + + pRes = res.Dereference(); + + NANOCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( this, *pRes, pRes[ Library_corlib_native_System_AppDomain::FIELD___appDomain ] )); + + pRes[ Library_corlib_native_System_AppDomain::FIELD___friendlyName ].SetObjectReference( m_strName ); + } + + NANOCLR_CLEANUP(); + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + NANOCLR_CLEANUP_END(); +} + +CLR_RT_AppDomainAssembly* CLR_RT_AppDomain::FindAppDomainAssembly( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_appDomainAssemblyLastAccess != NULL && m_appDomainAssemblyLastAccess->m_assembly == assm) + { + return m_appDomainAssemblyLastAccess; + } + + NANOCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,m_appDomainAssemblies) + { + if(appDomainAssembly->m_assembly == assm) + { + m_appDomainAssemblyLastAccess = appDomainAssembly; + + return appDomainAssembly; + } + } + NANOCLR_FOREACH_NODE_END(); + + return NULL; +} + +void CLR_RT_AppDomain::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_globalLock ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_strName ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_outOfMemoryException ); +} + +HRESULT CLR_RT_AppDomain::VerifyTypeIsLoaded( const CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + + if(!inst.InitializeFromIndex( idx )) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER ); + if(!FindAppDomainAssembly ( inst.m_assm )) NANOCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_AppDomain::MarshalObject( CLR_RT_HeapBlock& src, CLR_RT_HeapBlock& dst, CLR_RT_AppDomain* appDomainSrc ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + //This function marshals an object from appDomainSrc to 'this' AppDomain + //If appDomainSrc == NULL, this uses the current AppDomain + + CLR_RT_AppDomain* appDomainDst = this; + CLR_RT_HeapBlock* proxySrc = NULL; + CLR_RT_HeapBlock* mbroSrc = NULL; + bool fSimpleAssign = false; + CLR_RT_TypeDef_Index idxVerify = g_CLR_RT_WellKnownTypes.m_Object; + CLR_DataType dtSrc = src.DataType(); + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + + if(!appDomainSrc) + { + appDomainSrc = appDomainSav; + } + + // + //DATATYPE_LAST_PRIMITIVE_TO_MARSHAL note + //We should think about allowing STRINGS to be shared across AD boundaries + //Strings are read-only and it is safe to do this with some small restrictions + //First, as with the Assembly unloading, some strings can actually point within an + //assembly. If we allow assemblies to be unloaded (and why shouldn't we, if they are + //not in any AppDomain, than we need to deal with this case). If we just + //get copy the string on constructor, then we do not need to marshal strings + //across AD boundaries. + // + fSimpleAssign = (appDomainSrc == appDomainDst); + fSimpleAssign = fSimpleAssign || (dtSrc <= DATATYPE_LAST_PRIMITIVE_TO_MARSHAL); + fSimpleAssign = fSimpleAssign || (dtSrc == DATATYPE_OBJECT && src.Dereference() == NULL); + +#if !defined(NANOCLR_NO_ASSEMBLY_STRINGS) + fSimpleAssign = fSimpleAssign || (dtSrc == DATATYPE_STRING && !src.StringAssembly()); +#endif + + if(!fSimpleAssign) + { + if(dtSrc == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = src.Dereference(); + + switch(ptr->DataType()) + { + case DATATYPE_TRANSPARENT_PROXY: + { + proxySrc = ptr; + + NANOCLR_CHECK_HRESULT(proxySrc->TransparentProxyValidate()); + + idxVerify = proxySrc->TransparentProxyDereference()->ObjectCls(); + + if(proxySrc->TransparentProxyAppDomain() != appDomainDst) + { + //marshalling a transparent proxy object to a third AppDomain + //This makes the marshaling a simple assign of the DATATYPE_TRANSPARENT_PROXY heapblock + fSimpleAssign = true; + } + } + break; + case DATATYPE_CLASS: + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( ptr->ObjectCls() )) + { + if((inst.CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject) != 0) + { + idxVerify = inst; + + mbroSrc = ptr; + } + } + } + break; + } + } + } + + NANOCLR_CHECK_HRESULT(appDomainDst->VerifyTypeIsLoaded( idxVerify )); + + if(fSimpleAssign) + { + dst.Assign( src ); + } + else if(proxySrc != NULL) + { + //src is OBJECT->TRANSPARENT_PROXY->CLASS, and we are marshalling into 'this' appDomain + //dst is OBJECT->CLASS + _ASSERTE(proxySrc->TransparentProxyAppDomain() == appDomainDst); + + dst.SetObjectReference( proxySrc->TransparentProxyDereference() ); + } + else if(mbroSrc != NULL) + { + //src is a MarshalByRefObject that we are marshalling outside of its AppDomain + //src is OBJECT->CLASS + //dst is OBJECT->TRANSPARENT_PROXY->CLASS + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainDst ); + CLR_RT_HeapBlock* proxyDst = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForObjects( DATATYPE_TRANSPARENT_PROXY, 0, 1 ); CHECK_ALLOCATION(proxyDst); + + proxyDst->SetTransparentProxyReference( appDomainSrc, mbroSrc ); + dst.SetObjectReference( proxyDst ); + } + else + { + CLR_RT_HeapBlock blk; blk.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( blk ); + bool fNoCompaction = CLR_EE_DBG_IS(NoCompaction); + + //Need to prevent compaction between serialization/deserialization. + //Doesn't seem that currently compaction can actually occur during this time, + //but just to be safe, we should prevent it. + + CLR_EE_DBG_SET(NoCompaction); + NANOCLR_CHECK_HRESULT(CLR_RT_BinaryFormatter::Serialize( blk, src, NULL, CLR_RT_BinaryFormatter::c_Flags_Marshal )); + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainDst ); + hr = CLR_RT_BinaryFormatter::Deserialize( dst, blk, NULL, NULL, CLR_RT_BinaryFormatter::c_Flags_Marshal ); + + CLR_EE_DBG_RESTORE(NoCompaction,fNoCompaction); + } + + NANOCLR_CLEANUP(); + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_AppDomain::MarshalParameters( CLR_RT_HeapBlock* callerArgs, CLR_RT_HeapBlock* calleeArgs, int count, bool fOnReturn, CLR_RT_AppDomain* appDomainSrc ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* src = fOnReturn ? calleeArgs : callerArgs; + CLR_RT_HeapBlock* dst = fOnReturn ? callerArgs : calleeArgs; + + while(count-- > 0) + { + CLR_DataType dtSrc = src->DataType(); + CLR_DataType dtDst = dst->DataType(); + + if(dtSrc == DATATYPE_BYREF || dtSrc == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock srcObj; + CLR_RT_HeapBlock dstObj; + + if(fOnReturn) + { + srcObj.Assign( *src->Dereference() ); + + NANOCLR_CHECK_HRESULT(MarshalObject( srcObj, dstObj, appDomainSrc )); + + //Move the marshaled object back into dst heapblock + if(dtDst == DATATYPE_BYREF) + { + dst->Dereference()->Assign( dstObj ); + } + else + { + dstObj.StoreToReference( *dst, 0 ); + } + } + else //!fOnReturn + { + CLR_RT_HeapBlock* dstPtr = NULL; + + if(dtSrc == DATATYPE_BYREF) + { + srcObj.Assign( *src->Dereference() ); + } + else + { + srcObj.LoadFromReference( *src ); + } + + NANOCLR_CHECK_HRESULT(MarshalObject( srcObj, dstObj, appDomainSrc )); + + //Need to copy DstObj onto the heap. + dstPtr = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForObjects( DATATYPE_OBJECT, 0, 1 ); FAULT_ON_NULL(dstPtr); + + _ASSERTE(c_CLR_RT_DataTypeLookup[ dstObj.DataType() ].m_sizeInBytes != CLR_RT_DataTypeLookup::c_NA); + + dstPtr->Assign( dstObj ); + + //Turn the OBJECT back into a BYREF + dst->SetReference( *dstPtr ); + } + } + else //Not BYREF + { + if(!fOnReturn) + { + NANOCLR_CHECK_HRESULT(MarshalObject( *src, *dst, appDomainSrc )); + } + } + + src++; + dst++; + } + + NANOCLR_NOCLEANUP(); +} + + +HRESULT CLR_RT_AppDomain::GetAssemblies( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int count = 0; + CLR_RT_HeapBlock* pArray = NULL; + + for(int pass=0; pass<2; pass++) + { + NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN( this ) + { + if(pASSM->m_header->flags & CLR_RECORD_ASSEMBLY::c_Flags_Patch) continue; + + if(pass == 0) + { + count++; + } + else + { + CLR_RT_HeapBlock* hbObj; + CLR_RT_Assembly_Index idx; idx.Set( pASSM->m_idx ); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*pArray, g_CLR_RT_WellKnownTypes.m_Assembly)); + hbObj = pArray->Dereference(); + + hbObj->SetReflection( idx ); + + pArray++; + } + } + NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END(); + + if(pass == 0) + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, count, g_CLR_RT_WellKnownTypes.m_Assembly )); + + pArray = (CLR_RT_HeapBlock*)ref.DereferenceArray()->GetFirstElement(); + } + } + + NANOCLR_NOCLEANUP(); +} + +bool CLR_RT_AppDomain::IsLoaded() +{ + NATIVE_PROFILE_CLR_CORE(); + return m_state == CLR_RT_AppDomain::AppDomainState_Loaded; +} + +//--// + +HRESULT CLR_RT_AppDomainAssembly::CreateInstance( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm, CLR_RT_AppDomainAssembly*& appDomainAssembly ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + int size = CONVERTFROMSIZETOHEAPBLOCKS(sizeof(CLR_RT_AppDomainAssembly)) + assm->m_iStaticFields; + + appDomainAssembly = EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(g_CLR_RT_EventCache,CLR_RT_AppDomainAssembly,DATATYPE_APPDOMAIN_ASSEMBLY,CLR_RT_HeapBlock::HB_InitializeToZero,size); CHECK_ALLOCATION(appDomainAssembly); + + NANOCLR_CHECK_HRESULT(appDomainAssembly->AppDomainAssembly_Initialize( appDomain, assm )); + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(appDomainAssembly) + { + appDomainAssembly->DestroyInstance(); + } + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_AppDomainAssembly::AppDomainAssembly_Initialize( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomain ); + + m_appDomain = appDomain; + m_assembly = assm; + m_flags = 0; + m_pStaticFields = (CLR_RT_HeapBlock*)&this[ 1 ]; + + /* + The AppDomainAssembly gets linked before it is actually initialized, for two reasons. First, it needs to be + attached to the AppDomain in case a GC runs during the allocation of fields. Second, this assembly needs to be + loaded in the AppDomain when the static constructors are run. + */ + + appDomain->m_appDomainAssemblies.LinkAtBack( this ); + + NANOCLR_CHECK_HRESULT(assm->Resolve_AllocateStaticFields( m_pStaticFields )); + + if(!CLR_EE_DBG_IS_MASK(StateInitialize,StateMask)) + { + //Only in the non-boot case should we do this. Otherwise, debug events can occur out of order (thread creation of the + //static constructor before thread creation of the main thread. + g_CLR_RT_ExecutionEngine.SpawnStaticConstructor( g_CLR_RT_ExecutionEngine.m_cctorThread ); + } + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + Unlink(); + } + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + NANOCLR_CLEANUP_END(); +} + +void CLR_RT_AppDomainAssembly::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + Unlink(); + + g_CLR_RT_EventCache.Append_Node( this ); +} + +void CLR_RT_AppDomainAssembly::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( m_pStaticFields, m_assembly->m_iStaticFields ); +} + +#endif //NANOCLR_APPDOMAINS + +//--// + + +struct TypeIndexLookup +{ + const char* nameSpace; + const char* name; + CLR_RT_TypeDef_Index* ptr; +}; + +static const TypeIndexLookup c_TypeIndexLookup[] = +{ +#define TIL(ns,nm,fld) { ns, nm, &g_CLR_RT_WellKnownTypes.fld } + TIL( "System" , "Boolean" , m_Boolean ), + TIL( "System" , "Char" , m_Char ), + TIL( "System" , "SByte" , m_Int8 ), + TIL( "System" , "Byte" , m_UInt8 ), + TIL( "System" , "Int16" , m_Int16 ), + TIL( "System" , "UInt16" , m_UInt16 ), + TIL( "System" , "Int32" , m_Int32 ), + TIL( "System" , "UInt32" , m_UInt32 ), + TIL( "System" , "Int64" , m_Int64 ), + TIL( "System" , "UInt64" , m_UInt64 ), + TIL( "System" , "Single" , m_Single ), + TIL( "System" , "Double" , m_Double ), + TIL( "System" , "DateTime" , m_DateTime ), + TIL( "System" , "TimeSpan" , m_TimeSpan ), + TIL( "System" , "String" , m_String ), + + TIL( "System" , "Void" , m_Void ), + TIL( "System" , "Object" , m_Object ), + TIL( "System" , "ValueType" , m_ValueType ), + TIL( "System" , "Enum" , m_Enum ), + + TIL( "System" , "AppDomainUnloadedException" , m_AppDomainUnloadedException ), + TIL( "System" , "ArgumentNullException" , m_ArgumentNullException ), + TIL( "System" , "ArgumentException" , m_ArgumentException ), + TIL( "System" , "ArgumentOutOfRangeException" , m_ArgumentOutOfRangeException ), + TIL( "System" , "Exception" , m_Exception ), + TIL( "System" , "IndexOutOfRangeException" , m_IndexOutOfRangeException ), + TIL( "System" , "InvalidCastException" , m_InvalidCastException ), + TIL( "System" , "InvalidOperationException" , m_InvalidOperationException ), + TIL( "System" , "NotSupportedException" , m_NotSupportedException ), + TIL( "System" , "NotImplementedException" , m_NotImplementedException ), + TIL( "System" , "NullReferenceException" , m_NullReferenceException ), + TIL( "System" , "OutOfMemoryException" , m_OutOfMemoryException ), + TIL( "System" , "ObjectDisposedException" , m_ObjectDisposedException ), + TIL( "System.Threading" , "ThreadAbortException" , m_ThreadAbortException ), + TIL( "nanoFramework.Runtime.Native" , "ConstraintException" , m_ConstraintException ), + + TIL( "System" , "Delegate" , m_Delegate ), + TIL( "System" , "MulticastDelegate" , m_MulticastDelegate ), + + TIL( "System" , "Array" , m_Array ), + TIL( "System.Collections" , "ArrayList" , m_ArrayList ), + TIL( "System" , "ICloneable" , m_ICloneable ), + TIL( "System.Collections" , "IList" , m_IList ), + + TIL( "System.Reflection" , "Assembly" , m_Assembly ), + TIL( "System" , "Type" , m_TypeStatic ), + TIL( "System" , "RuntimeType" , m_Type ), + TIL( "System.Reflection" , "RuntimeConstructorInfo" , m_ConstructorInfo ), + TIL( "System.Reflection" , "RuntimeMethodInfo" , m_MethodInfo ), + TIL( "System.Reflection" , "RuntimeFieldInfo" , m_FieldInfo ), + + TIL( "System" , "WeakReference" , m_WeakReference ), + + TIL( "Microsoft.SPOT" , "SerializationHintsAttribute" , m_SerializationHintsAttribute ), + + TIL( "Microsoft.SPOT.Hardware" , "WatchdogException" , m_WatchdogException ), + + TIL( "System.Net.NetworkInformation" , "NetworkInterface" , m_NetworkInterface ), + TIL( "System.Net.NetworkInformation" , "Wireless80211Configuration" , m_Wireless80211Configuration ), + TIL( "System.Net.NetworkInformation" , "WirelessAPConfiguration" , m_WirelessAPConfiguration ), + TIL( "System.Net.NetworkInformation" , "WirelessAPStation" , m_WirelessAPStation ), + +#if defined(NANOCLR_APPDOMAINS) + TIL( "System" , "AppDomain" , m_AppDomain ), + TIL( "System" , "MarshalByRefObject" , m_MarshalByRefObject ), +#endif + + TIL( "System.Threading" , "Thread" , m_Thread ), + TIL( "System.Resources" , "ResourceManager" , m_ResourceManager ), + + TIL( "System.Net.Sockets" , "SocketException" , m_SocketException ), + + TIL( "Windows.Devices.I2c" , "I2cTransferResult" , m_I2cTransferResult ), + +#undef TIL +}; + + +//--// + + +struct MethodIndexLookup +{ + const char* name; + CLR_RT_TypeDef_Index* type; + CLR_RT_MethodDef_Index* method; +}; + +static const MethodIndexLookup c_MethodIndexLookup[] = +{ + #define MIL(nm,type,method) { nm, &g_CLR_RT_WellKnownTypes.type, &g_CLR_RT_WellKnownMethods.method } + + MIL( "GetObjectFromId" , m_ResourceManager, m_ResourceManager_GetObjectFromId ), + MIL( "GetObjectChunkFromId", m_ResourceManager, m_ResourceManager_GetObjectChunkFromId ), + + #undef MIL +}; + +void CLR_RT_Assembly::Resolve_TypeDef() +{ + NATIVE_PROFILE_CLR_CORE(); + const TypeIndexLookup* tilOuterClass = NULL; + const TypeIndexLookup* til = c_TypeIndexLookup; + + for(size_t i=0; iptr; + + if(NANOCLR_INDEX_IS_INVALID(dst)) + { + if(til->nameSpace == NULL) + { + if(tilOuterClass) + { + FindTypeDef( til->name, tilOuterClass->ptr->Type(), dst ); + } + } + else + { + FindTypeDef( til->name, til->nameSpace, dst ); + } + } + + if(til->nameSpace != NULL) + { + tilOuterClass = til; + } + } +} + +void CLR_RT_Assembly::Resolve_MethodDef() +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_METHODDEF* md = GetMethodDef( 0 ); + + for(int i=0; itype; + CLR_RT_MethodDef_Index& idxMethod = *mil->method; + + if(NANOCLR_INDEX_IS_VALID(idxType) && NANOCLR_INDEX_IS_INVALID(idxMethod)) + { + CLR_RT_TypeDef_Instance instType; + + _SIDE_ASSERTE(instType.InitializeFromIndex( idxType )); + + if(instType.m_assm == this) + { + if(!strcmp( GetString(md->name), mil->name )) + { + idxMethod.m_data = idx.m_data; + } + } + } + } + + if(md->flags & CLR_RECORD_METHODDEF::MD_EntryPoint) + { + g_CLR_RT_TypeSystem.m_entryPoint = idx; + } + } +} + +HRESULT CLR_RT_Assembly::Resolve_AllocateStaticFields( CLR_RT_HeapBlock* pStaticFields ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_RECORD_FIELDDEF* fd = GetFieldDef( 0 ); + + for(int i=0; iflags & CLR_RECORD_FIELDDEF::FD_Static) + { + CLR_RT_FieldDef_CrossReference& res = m_pCrossReference_FieldDef[ i ]; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitializeReference( pStaticFields[ res.m_offset ], fd, this )); + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Assembly::PrepareForExecution() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if((m_flags & CLR_RT_Assembly::PreparingForExecution) != 0) + { + //Circular dependency + _ASSERTE(false); + + NANOCLR_MSG_SET_AND_LEAVE(CLR_E_FAIL, L"Failed to prepare type system for execution\n"); + } + + if((m_flags & CLR_RT_Assembly::PreparedForExecution) == 0) + { + int i; + + m_flags |= CLR_RT_Assembly::PreparingForExecution; + + ITERATE_THROUGH_RECORDS(this,i,AssemblyRef,ASSEMBLYREF) + { + _ASSERTE(dst->m_target != NULL); + + if(dst->m_target != NULL) + { + NANOCLR_CHECK_HRESULT(dst->m_target->PrepareForExecution()); + } + } + + if(m_header->patchEntryOffset != 0xFFFFFFFF) + { + CLR_PMETADATA ptr = GetResourceData( m_header->patchEntryOffset ); + +#if defined(WIN32) + CLR_Debug::Printf( "Simulating jump into patch code...\r\n" ); +#else + ((void (*)())ptr)(); +#endif + } + +#if defined(NANOCLR_APPDOMAINS) + //Temporary solution. All Assemblies get added to the current AppDomain + //Which assemblies get loaded at boot, and when assemblies get added to AppDomain at runtime is + //not yet determined/implemented + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->LoadAssembly( this )); +#endif + } + + NANOCLR_CLEANUP(); + + //Only try once. If this fails, then what? + m_flags |= CLR_RT_Assembly::PreparedForExecution; + m_flags &= ~CLR_RT_Assembly::PreparingForExecution; + + NANOCLR_CLEANUP_END(); +} + +//--// + +CLR_UINT32 CLR_RT_Assembly::ComputeAssemblyHash() +{ + NATIVE_PROFILE_CLR_CORE(); + return m_header->ComputeAssemblyHash( m_szName, m_header->version ); +} + +CLR_UINT32 CLR_RT_Assembly::ComputeAssemblyHash( const CLR_RECORD_ASSEMBLYREF* ar ) +{ + NATIVE_PROFILE_CLR_CORE(); + return m_header->ComputeAssemblyHash( GetString( ar->name ), ar->version ); +} + +//--// + +bool CLR_RT_Assembly::FindTypeDef( const char* name, const char* nameSpace, CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_TYPEDEF* target = GetTypeDef( 0 ); + int tblSize = m_pTablesSize[ TBL_TypeDef ]; + + for(int i=0; ienclosingType == CLR_EmptyIndex) + { + const char* szNameSpace = GetString( target->nameSpace ); + const char* szName = GetString( target->name ); + + if(!strcmp( szName, name ) && !strcmp( szNameSpace, nameSpace )) + { + idx.Set( m_idx, i ); + + return true; + } + } + } + + idx.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindTypeDef( const char* name, CLR_IDX scope, CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_TYPEDEF* target = GetTypeDef( 0 ); + int tblSize = m_pTablesSize[ TBL_TypeDef ]; + + for(int i=0; ienclosingType == scope) + { + const char* szName = GetString( target->name ); + + if(!strcmp( szName, name )) + { + idx.Set( m_idx, i ); + + return true; + } + } + } + + idx.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindTypeDef( CLR_UINT32 hash, CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_CrossReference* p = m_pCrossReference_TypeDef; + CLR_UINT32 tblSize = m_pTablesSize[ TBL_TypeDef ]; + CLR_UINT32 i; + + for(i=0; im_hash == hash) break; + } + + if(i != tblSize) + { + idx.Set( m_idx, i ); + + return true; + } + else + { + idx.Clear(); + + return false; + } +} + +//--// + +static bool local_FindFieldDef( CLR_RT_Assembly* assm, CLR_UINT32 first, CLR_UINT32 num, const char* szText, CLR_RT_Assembly* base, CLR_IDX sig, CLR_RT_FieldDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_FIELDDEF* fd = assm->GetFieldDef( first ); + + for(CLR_UINT32 i=0; iGetString( fd->name ); + + if(!strcmp( fieldName, szText )) + { + if(base) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_FieldDef( assm, fd ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_FieldDef( base, base->GetSignature( sig ) ); + + if(CLR_RT_TypeSystem::MatchSignature( parserLeft, parserRight ) == false) continue; + } + + res.Set( assm->m_idx, first + i ); + + return true; + } + } + + res.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindFieldDef( const CLR_RECORD_TYPEDEF* td, const char* name, CLR_RT_Assembly* base, CLR_IDX sig, CLR_RT_FieldDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(local_FindFieldDef( this, td->iFields_First, td->iFields_Num, name, base, sig, idx )) return true; + if(local_FindFieldDef( this, td->sFields_First, td->sFields_Num, name, base, sig, idx )) return true; + + idx.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindMethodDef( const CLR_RECORD_TYPEDEF* td, const char* name, CLR_RT_Assembly* base, CLR_SIG sig, CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + int i; + int num = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num; + const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First ); + + for(i=0; iname ); + + if(!strcmp( methodName, name )) + { + bool fMatch = true; + + if(CLR_SIG_INVALID != sig) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_MethodSignature( this, md ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_MethodSignature( base, base->GetSignature( sig ) ); + + fMatch = CLR_RT_TypeSystem::MatchSignature( parserLeft, parserRight ); + } + + if(fMatch) + { + idx.Set( m_idx, i + td->methods_First ); + + return true; + } + } + } + + idx.Clear(); + + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_Assembly::FindMethodBoundaries( CLR_IDX i, CLR_OFFSET& start, CLR_OFFSET& end ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_METHODDEF* p = GetMethodDef( i ); + + if(p->RVA == CLR_EmptyIndex) return false; + + start = p->RVA; + + while(true) + { + p++; + i++; + + if(i == m_pTablesSize[ TBL_MethodDef ]) + { + end = m_pTablesSize[ TBL_ByteCode ]; + break; + } + + if(p->RVA != CLR_EmptyIndex) + { + end = p->RVA; + break; + } + } + + return true; +} + +bool CLR_RT_Assembly::FindNextStaticConstructor( CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + _ASSERTE(m_idx == idx.Assembly()); + + for(int i=idx.Method(); iflags & CLR_RECORD_METHODDEF::MD_StaticConstructor) + { + return true; + } + } + + idx.Clear(); + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_Assembly::Resolve_ComputeHashes() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + const CLR_RECORD_TYPEDEF* src = GetTypeDef( 0 ); + CLR_RT_TypeDef_CrossReference* dst = m_pCrossReference_TypeDef; + + for(int i=0; iGetFieldDef( target->iFields_First ); + + for(int j=0; jiFields_Num; j++, fd++) + { + if((fd->flags & CLR_RECORD_FIELDDEF::FD_NotSerialized) == 0) + { + CLR_RT_SignatureParser parser; parser.Initialize_FieldDef( inst.m_assm, fd ); + CLR_RT_SignatureParser::Element res; + + NANOCLR_CHECK_HRESULT(parser.Advance( res )); + + while(res.m_levels-- > 0) + { + hash = ComputeHashForType( DATATYPE_SZARRAY, hash ); + } + + hash = ComputeHashForType( res.m_dt, hash ); + + if( (res.m_dt == DATATYPE_VALUETYPE) || + (res.m_dt == DATATYPE_CLASS)) + { + hash = ComputeHashForName( res.m_cls, hash ); + } + + const char* fieldName = inst.m_assm->GetString( fd->name ); + + hash = SUPPORT_ComputeCRC( fieldName, (CLR_UINT32)hal_strlen_s(fieldName), hash ); + } + } + + inst.SwitchToParent(); + } + + dst->m_hash = hash ? hash : 0xFFFFFFFF; // Don't allow zero as an hash value!! + } + + NANOCLR_NOCLEANUP(); +} + +CLR_UINT32 CLR_RT_Assembly::ComputeHashForName( const CLR_RT_TypeDef_Index& td, CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + char rgBuffer[ 512 ]; + char* szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildTypeName( td, szBuffer, iBuffer ); + + CLR_UINT32 hashPost = SUPPORT_ComputeCRC( rgBuffer, (int)(MAXSTRLEN(rgBuffer) - iBuffer), hash ); + + return hashPost; +} + +CLR_UINT32 CLR_RT_Assembly::ComputeHashForType( CLR_DataType et, CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8 val = (CLR_UINT8)CLR_RT_TypeSystem::MapDataTypeToElementType( et ); + + CLR_UINT32 hashPost = SUPPORT_ComputeCRC( &val, sizeof(val), hash ); + + return hashPost; +} + +//--// + +CLR_RT_HeapBlock* CLR_RT_Assembly::GetStaticField( const int index ) +{ + NATIVE_PROFILE_CLR_CORE(); + +#if defined(NANOCLR_APPDOMAINS) + + CLR_RT_AppDomainAssembly* adAssm = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( this ); + + _ASSERTE(adAssm); + + return &adAssm->m_pStaticFields[ index ]; + +#else + + return &m_pStaticFields[ index ]; + +#endif +} + +//--// + +void CLR_RT_Assembly::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + +#if !defined(NANOCLR_APPDOMAINS) + CLR_RT_GarbageCollector::Heap_Relocate( m_pStaticFields, m_iStaticFields ); +#endif + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_header ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_szName ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_pFile ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_nativeCode ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_TypeSystem::TypeSystem_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_CLEAR(g_CLR_RT_TypeSystem); + NANOCLR_CLEAR(g_CLR_RT_WellKnownTypes); +} + +void CLR_RT_TypeSystem::TypeSystem_Cleanup() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_ASSEMBLY(*this) + { + pASSM->DestroyInstance(); + + *ppASSM = NULL; + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + m_assembliesMax = 0; +} + +//--// + +void CLR_RT_TypeSystem::Link( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_ASSEMBLY_NULL(*this) + { + *ppASSM = assm; + + assm->m_idx = idx; + + PostLinkageProcessing( assm ); + + if(m_assembliesMax < idx) m_assembliesMax = idx; + + return; + } + NANOCLR_FOREACH_ASSEMBLY_NULL_END(); +} + +void CLR_RT_TypeSystem::PostLinkageProcessing( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(!strcmp( assm->m_szName, "mscorlib" )) + { + m_assemblyMscorlib = assm; + } + if(!strcmp( assm->m_szName, "nanoFramework.Runtime.Native" )) + { + m_assemblyNative = assm; + } +} + +CLR_RT_Assembly* CLR_RT_TypeSystem::FindAssembly( const char* szName, const CLR_RECORD_VERSION* ver, bool fExact ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_FOREACH_ASSEMBLY(*this) + { + if(!strcmp(pASSM->m_szName, szName)) + { + // if there is no version information, anything goes + if(NULL == ver) + { + return pASSM; + } + // exact match must take into accoutn all numbers + else if(fExact) + { + if(0 == memcmp( &pASSM->m_header->version, ver, sizeof(*ver) )) + { + return pASSM; + } + } + // if excet match is not required but still we have version we will enforce only the first two number because by convention + // we increse the minor numbers when native assemblies change CRC + else if( + ver->iMajorVersion == pASSM->m_header->version.iMajorVersion && + ver->iMinorVersion == pASSM->m_header->version.iMinorVersion + ) + { + return pASSM; + } + } + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + return NULL; +} + +bool CLR_RT_TypeSystem::FindTypeDef( const char* name, const char* nameSpace, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(assm) + { + NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(*this) + { + if(pASSM->IsSameAssembly( *assm ) && pASSM->FindTypeDef( name, nameSpace, res )) return true; + } + NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END(); + + res.Clear(); + + return false; + } + + return FindTypeDef( name, nameSpace, res); +} + +bool CLR_RT_TypeSystem::FindTypeDef( const char* name, const char* nameSpace, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(*this) + { + if(pASSM->FindTypeDef( name, nameSpace, res )) return true; + } + NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END(); + + res.Clear(); + return false; +} + +bool CLR_RT_TypeSystem::FindTypeDef( CLR_UINT32 hash, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(*this) + { + if(pASSM->FindTypeDef( hash, res )) return true; + } + NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END(); + + res.Clear(); + return false; +} + +bool CLR_RT_TypeSystem::FindTypeDef( const char* szClass, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ) +{ + (void)szClass; + (void)assm; + (void)res; + + NATIVE_PROFILE_CLR_CORE(); + + char rgName [ MAXTYPENAMELEN ]; + char rgNamespace[ MAXTYPENAMELEN ]; + + if(hal_strlen_s(szClass) < ARRAYSIZE(rgNamespace)) + { + const char* szPtr = szClass; + const char* szPtr_LastDot = NULL; + const char* szPtr_FirstSubType = NULL; + char c; + size_t len; + + while(true) + { + c = szPtr[ 0 ]; if(!c) break; + + if(c == '.') + { + szPtr_LastDot = szPtr; + } + else if(c == '+') + { + szPtr_FirstSubType = szPtr; + break; + } + + szPtr++; + } + + if(szPtr_LastDot) + { + len = szPtr_LastDot++ - szClass ; hal_strncpy_s( rgNamespace, ARRAYSIZE(rgNamespace), szClass , len ); + len = szPtr - szPtr_LastDot; hal_strncpy_s( rgName , ARRAYSIZE(rgName ), szPtr_LastDot, len ); + } + else + { + rgNamespace[ 0 ] = 0; + hal_strcpy_s( rgName, ARRAYSIZE(rgName), szClass ); + } + + + if(FindTypeDef( rgName, rgNamespace, assm, res )) + { + // + // Found the containing type, let's look for the nested type. + // + if(szPtr_FirstSubType) + { + CLR_RT_TypeDef_Instance inst; + + do + { + szPtr = ++szPtr_FirstSubType; + + while(true) + { + c = szPtr_FirstSubType[ 0 ]; if(!c) break; + + if(c == '+') break; + + szPtr_FirstSubType++; + } + + len = szPtr_FirstSubType - szPtr; hal_strncpy_s( rgName, ARRAYSIZE(rgName), szPtr, len ); + + inst.InitializeFromIndex( res ); + + if(inst.m_assm->FindTypeDef( rgName, res.Type(), res ) == false) + { + return false; + } + + } while(c == '+'); + } + + return true; + } + } + + res.Clear(); + + return false; +} + +bool CLR_RT_TypeSystem::FindTypeDef( const char* szClass, CLR_RT_Assembly* assm, CLR_RT_ReflectionDef_Index& reflex ) +{ + (void)szClass; + (void)assm; + (void)reflex; + + NATIVE_PROFILE_CLR_CORE(); + + // UNDONE: FIXME + // char rgName [ MAXTYPENAMELEN ]; + // char rgNamespace[ MAXTYPENAMELEN ]; + // CLR_RT_TypeDef_Index res; + + // if(hal_strlen_s(szClass) < ARRAYSIZE(rgNamespace)) + // { + // const char* szPtr = szClass; + // const char* szPtr_LastDot = NULL; + // const char* szPtr_FirstSubType = NULL; + // char c; + // size_t len; + // bool arrayType = false; + + // while(true) + // { + // c = szPtr[ 0 ]; if(!c) break; + + // if(c == '.') + // { + // szPtr_LastDot = szPtr; + // } + // else if(c == '+') + // { + // szPtr_FirstSubType = szPtr; + // break; + // } + // else if(c == '[') + // { + // char ch = szPtr[ 1 ]; + // if (ch == ']') + // { + // arrayType = true; + // break; + // } + // } + + // szPtr++; + // } + + // if(szPtr_LastDot) + // { + // len = szPtr_LastDot++ - szClass ; hal_strncpy_s( rgNamespace, ARRAYSIZE(rgNamespace), szClass , len ); + // len = szPtr - szPtr_LastDot; hal_strncpy_s( rgName , ARRAYSIZE(rgName ), szPtr_LastDot, len ); + // } + // else + // { + // rgNamespace[ 0 ] = 0; + // hal_strcpy_s( rgName, ARRAYSIZE(rgName), szClass ); + // } + + // if(FindTypeDef( rgName, rgNamespace, assm, res )) + // { + // // + // // Found the containing type, let's look for the nested type. + // // + // if(szPtr_FirstSubType) + // { + // CLR_RT_TypeDef_Instance inst; + + // do + // { + // szPtr = ++szPtr_FirstSubType; + + // while(true) + // { + // c = szPtr_FirstSubType[ 0 ]; if(!c) break; + + // if(c == '+') break; + + // szPtr_FirstSubType++; + // } + + // len = szPtr_FirstSubType - szPtr; hal_strncpy_s( rgName, ARRAYSIZE(rgName), szPtr, len ); + + // inst.InitializeFromIndex( res ); + + // if(inst.m_assm->FindTypeDef( rgName, res.Type(), res ) == false) + // { + // return false; + // } + + // } while(c == '+'); + // } + + // reflex.m_kind = REFLECTION_TYPE; + // // make sure this works for multidimensional arrays. + // reflex.m_levels = arrayType ? 1 : 0; + // reflex.m_data.m_type = res; + // return true; + // } + // } + // + //res.Clear(); + + return false; +} + +//--// + +int +#if defined(_MSC_VER) +__cdecl +#endif +CompareResource( const void* p1, const void* p2 ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_RESOURCE* resource1 = (const CLR_RECORD_RESOURCE*)p1; + const CLR_RECORD_RESOURCE* resource2 = (const CLR_RECORD_RESOURCE*)p2; + + return (int)resource1->id - (int)resource2->id; +} + +HRESULT CLR_RT_TypeSystem::LocateResourceFile( CLR_RT_Assembly_Instance assm, const char* name, CLR_INT32& idxResourceFile ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly* pAssm = assm.m_assm; + + for(idxResourceFile = 0; idxResourceFile < pAssm->m_pTablesSize[ TBL_ResourcesFiles ]; idxResourceFile++) + { + const CLR_RECORD_RESOURCE_FILE* resourceFile = pAssm->GetResourceFile( idxResourceFile ); + + if(!strcmp( pAssm->GetString( resourceFile->name ), name )) + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + + idxResourceFile = -1; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::LocateResource( CLR_RT_Assembly_Instance assm, CLR_INT32 idxResourceFile, CLR_INT16 id, const CLR_RECORD_RESOURCE*& res, CLR_UINT32& size ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly* pAssm = assm.m_assm; + const CLR_RECORD_RESOURCE_FILE* resourceFile; + CLR_RECORD_RESOURCE resourceT; + const CLR_RECORD_RESOURCE* resNext; + const CLR_RECORD_RESOURCE* resZero; + + res = NULL; + size = 0; + + if(idxResourceFile < 0 || idxResourceFile >= pAssm->m_pTablesSize[ TBL_ResourcesFiles ]) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + resourceFile = pAssm->GetResourceFile( idxResourceFile ); + + _ASSERTE(resourceFile->numberOfResources > 0); + + resZero = pAssm->GetResource( resourceFile->offset ); + + resourceT.id = id; + + res = (const CLR_RECORD_RESOURCE*)bsearch( &resourceT, resZero, resourceFile->numberOfResources, sizeof(CLR_RECORD_RESOURCE), CompareResource ); + + if(res != NULL) + { + //compute size here... + //assert not the last resource + _ASSERTE(res + 1 <= pAssm->GetResource( pAssm->m_pTablesSize[ TBL_Resources ] - 1)); + resNext = res+1; + + size = resNext->offset - res->offset; + + //deal with alignment. + size -= (resNext->flags & CLR_RECORD_RESOURCE::FLAGS_PaddingMask); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::ResolveAll() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + bool fOutput = false; + + while(true) + { + bool fGot = false; + bool fNeedResolution = false; + + NANOCLR_FOREACH_ASSEMBLY(*this) + { + if((pASSM->m_flags & CLR_RT_Assembly::Resolved) == 0) + { + fNeedResolution = true; + + if(pASSM->Resolve_AssemblyRef( fOutput )) + { + fGot = true; + + pASSM->m_flags |= CLR_RT_Assembly::Resolved; + + NANOCLR_CHECK_HRESULT(pASSM->Resolve_TypeRef ()); + NANOCLR_CHECK_HRESULT(pASSM->Resolve_FieldRef ()); + NANOCLR_CHECK_HRESULT(pASSM->Resolve_MethodRef ()); + /********************/pASSM->Resolve_TypeDef () ; + /********************/pASSM->Resolve_MethodDef () ; + /********************/pASSM->Resolve_Link () ; + NANOCLR_CHECK_HRESULT(pASSM->Resolve_ComputeHashes ()); + +#if !defined(NANOCLR_APPDOMAINS) + NANOCLR_CHECK_HRESULT(pASSM->Resolve_AllocateStaticFields( pASSM->m_pStaticFields )); +#endif + + pASSM->m_flags |= CLR_RT_Assembly::ResolutionCompleted; + } + } + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + if(fOutput == true) + { + NANOCLR_SET_AND_LEAVE(CLR_E_TYPE_UNAVAILABLE); + } + + if(fGot == false) + { + if(fNeedResolution) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Link failure: some assembly references cannot be resolved!!\r\n\r\n" ); +#endif + + fOutput = true; + } + else + { + break; + } + } + } + +#if !defined(BUILD_RTM) + + if(s_CLR_RT_fTrace_AssemblyOverhead >= c_CLR_RT_Trace_Info) + { + { + int pTablesSize[ TBL_Max ]; memset( pTablesSize, 0, sizeof(pTablesSize) ); + CLR_RT_Assembly::Offsets offsets ; memset( &offsets , 0, sizeof(offsets ) ); + + size_t iStaticFields = 0 ; + size_t iTotalRamSize = 0 ; + size_t iTotalRomSize = 0 ; + size_t iMetaData = 0 ; + + NANOCLR_FOREACH_ASSEMBLY(*this) + { + offsets.iBase += ROUNDTOMULTIPLE(sizeof(CLR_RT_Assembly) , CLR_UINT32); + offsets.iAssemblyRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_AssemblyRef ] * sizeof(CLR_RT_AssemblyRef_CrossReference), CLR_UINT32); + offsets.iTypeRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_TypeRef ] * sizeof(CLR_RT_TypeRef_CrossReference ), CLR_UINT32); + offsets.iFieldRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_FieldRef ] * sizeof(CLR_RT_FieldRef_CrossReference ), CLR_UINT32); + offsets.iMethodRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_MethodRef ] * sizeof(CLR_RT_MethodRef_CrossReference ), CLR_UINT32); + offsets.iTypeDef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_TypeDef ] * sizeof(CLR_RT_TypeDef_CrossReference ), CLR_UINT32); + offsets.iFieldDef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_FieldDef ] * sizeof(CLR_RT_FieldDef_CrossReference ), CLR_UINT32); + offsets.iMethodDef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_CrossReference ), CLR_UINT32); + +#if !defined(NANOCLR_APPDOMAINS) + offsets.iStaticFields += ROUNDTOMULTIPLE(pASSM->m_iStaticFields * sizeof(CLR_RT_HeapBlock ), CLR_UINT32); +#endif + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + offsets.iDebuggingInfoMethods += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_DebuggingInfo ), CLR_UINT32); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + iMetaData += pASSM->m_header->SizeOfTable( TBL_AssemblyRef ) + + pASSM->m_header->SizeOfTable( TBL_TypeRef ) + + pASSM->m_header->SizeOfTable( TBL_FieldRef ) + + pASSM->m_header->SizeOfTable( TBL_MethodRef ) + + pASSM->m_header->SizeOfTable( TBL_TypeDef ) + + pASSM->m_header->SizeOfTable( TBL_FieldDef ) + + pASSM->m_header->SizeOfTable( TBL_MethodDef ) + + pASSM->m_header->SizeOfTable( TBL_Attributes ) + + pASSM->m_header->SizeOfTable( TBL_TypeSpec ) + + pASSM->m_header->SizeOfTable( TBL_Signatures ); + + for(int tbl=0; tblm_pTablesSize[ tbl ]; + } + + iTotalRomSize += pASSM->m_header->TotalSize(); + + iStaticFields += pASSM->m_iStaticFields; + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + iTotalRamSize = offsets.iBase + + offsets.iAssemblyRef + + offsets.iTypeRef + + offsets.iFieldRef + + offsets.iMethodRef + + offsets.iTypeDef + + offsets.iFieldDef + + offsets.iMethodDef; + +#if !defined(NANOCLR_APPDOMAINS) + iTotalRamSize += offsets.iStaticFields; +#endif + + CLR_Debug::Printf( "\r\nTotal: (%d RAM - %d ROM - %d METADATA)\r\n\r\n", iTotalRamSize, iTotalRomSize, iMetaData ); + + CLR_Debug::Printf( " AssemblyRef = %8d bytes (%8d elements)\r\n", offsets.iAssemblyRef , pTablesSize[TBL_AssemblyRef] ); + CLR_Debug::Printf( " TypeRef = %8d bytes (%8d elements)\r\n", offsets.iTypeRef , pTablesSize[TBL_TypeRef ] ); + CLR_Debug::Printf( " FieldRef = %8d bytes (%8d elements)\r\n", offsets.iFieldRef , pTablesSize[TBL_FieldRef ] ); + CLR_Debug::Printf( " MethodRef = %8d bytes (%8d elements)\r\n", offsets.iMethodRef , pTablesSize[TBL_MethodRef ] ); + CLR_Debug::Printf( " TypeDef = %8d bytes (%8d elements)\r\n", offsets.iTypeDef , pTablesSize[TBL_TypeDef ] ); + CLR_Debug::Printf( " FieldDef = %8d bytes (%8d elements)\r\n", offsets.iFieldDef , pTablesSize[TBL_FieldDef ] ); + CLR_Debug::Printf( " MethodDef = %8d bytes (%8d elements)\r\n", offsets.iMethodDef , pTablesSize[TBL_MethodDef ] ); + +#if !defined(NANOCLR_APPDOMAINS) + CLR_Debug::Printf( " StaticFields = %8d bytes (%8d elements)\r\n", offsets.iStaticFields , iStaticFields ); +#endif + + CLR_Debug::Printf( "\r\n" ); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_Debug::Printf( " DebuggingInfo = %8d bytes\r\n", offsets.iDebuggingInfoMethods ); + CLR_Debug::Printf( "\r\n" ); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + CLR_Debug::Printf( " Attributes = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_Attributes ] * sizeof(CLR_RECORD_ATTRIBUTE ), pTablesSize[ TBL_Attributes ] ); + CLR_Debug::Printf( " TypeSpec = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_TypeSpec ] * sizeof(CLR_RECORD_TYPESPEC ), pTablesSize[ TBL_TypeSpec ] ); + CLR_Debug::Printf( " Resources Files = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_ResourcesFiles ] * sizeof(CLR_RECORD_RESOURCE_FILE ), pTablesSize[ TBL_ResourcesFiles ] ); + CLR_Debug::Printf( " Resources = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_Resources ] * sizeof(CLR_RECORD_RESOURCE ), pTablesSize[ TBL_Resources ] ); + CLR_Debug::Printf( " Resources Data = %8d bytes\r\n" , pTablesSize[ TBL_ResourcesData ] ); + CLR_Debug::Printf( " Strings = %8d bytes\r\n" , pTablesSize[ TBL_Strings ] ); + CLR_Debug::Printf( " Signatures = %8d bytes\r\n" , pTablesSize[ TBL_Signatures ] ); + CLR_Debug::Printf( " ByteCode = %8d bytes\r\n" , pTablesSize[ TBL_ByteCode ] ); + CLR_Debug::Printf( "\r\n\r\n" ); + } + } + +#endif + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::PrepareForExecutionHelper( const char* szAssembly ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_FOREACH_ASSEMBLY(*this) + { + if(!strcmp( szAssembly, pASSM->m_szName )) + { + NANOCLR_CHECK_HRESULT(pASSM->PrepareForExecution()); + } + } + + NANOCLR_FOREACH_ASSEMBLY_END(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::PrepareForExecution() +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if !defined(NANOCLR_APPDOMAINS) + if(g_CLR_RT_ExecutionEngine.m_outOfMemoryException == NULL) + { + CLR_RT_HeapBlock exception; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( exception, g_CLR_RT_WellKnownTypes.m_OutOfMemoryException )); + + g_CLR_RT_ExecutionEngine.m_outOfMemoryException = exception.Dereference(); + } +#endif + + // Load Runtime.Events to setup EventSink for other assemblies using it + NANOCLR_CHECK_HRESULT(PrepareForExecutionHelper( "nanoFramework.Runtime.Events" )); + + // Load Runtime.Native for other assemblies using it + NANOCLR_CHECK_HRESULT(PrepareForExecutionHelper( "nanoFramework.Runtime.Native" )); + + NANOCLR_FOREACH_ASSEMBLY(*this) + { + NANOCLR_CHECK_HRESULT(pASSM->PrepareForExecution()); + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + NANOCLR_CLEANUP(); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_CLR(BreakpointsDisabled); + + g_CLR_RT_ExecutionEngine.Breakpoint_Assemblies_Loaded(); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + NANOCLR_CLEANUP_END(); +} + +//--// + +bool CLR_RT_TypeSystem::MatchSignature( CLR_RT_SignatureParser& parserLeft, CLR_RT_SignatureParser& parserRight ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(parserLeft.m_type != parserRight.m_type ) return false; + if(parserLeft.m_flags != parserRight.m_flags) return false; + + return MatchSignatureDirect( parserLeft, parserRight, false ); +} + +bool CLR_RT_TypeSystem::MatchSignatureDirect( CLR_RT_SignatureParser& parserLeft, CLR_RT_SignatureParser& parserRight, bool fIsInstanceOfOK ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(true) + { + int iAvailLeft = parserLeft .Available(); + int iAvailRight = parserRight.Available(); + + if(iAvailLeft != iAvailRight) return false; + + if(!iAvailLeft) return true; + + CLR_RT_SignatureParser::Element resLeft; if(FAILED(parserLeft .Advance( resLeft ))) return false; + CLR_RT_SignatureParser::Element resRight; if(FAILED(parserRight.Advance( resRight ))) return false; + + if(!MatchSignatureElement( resLeft, resRight, fIsInstanceOfOK )) return false; + } + + return true; +} + +bool CLR_RT_TypeSystem::MatchSignatureElement( CLR_RT_SignatureParser::Element& resLeft, CLR_RT_SignatureParser::Element& resRight, bool fIsInstanceOfOK ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(fIsInstanceOfOK) + { + CLR_RT_ReflectionDef_Index idxLeft ; CLR_RT_TypeDescriptor descLeft; + CLR_RT_ReflectionDef_Index idxRight; CLR_RT_TypeDescriptor descRight; + + idxLeft.m_kind = REFLECTION_TYPE; + idxLeft.m_levels = resLeft.m_levels; + idxLeft.m_data.m_type = resLeft.m_cls; + + idxRight.m_kind = REFLECTION_TYPE; + idxRight.m_levels = resRight.m_levels; + idxRight.m_data.m_type = resRight.m_cls; + + if(FAILED(descLeft .InitializeFromReflection( idxLeft ))) return false; + if(FAILED(descRight.InitializeFromReflection( idxRight ))) return false; + + if(!CLR_RT_ExecutionEngine::IsInstanceOf( descRight, descLeft )) return false; + } + else + { + if(resLeft.m_fByRef != resRight.m_fByRef ) return false; + if(resLeft.m_levels != resRight.m_levels ) return false; + if(resLeft.m_dt != resRight.m_dt ) return false; + if(resLeft.m_cls.m_data != resRight.m_cls.m_data) return false; + } + + return true; +} + +//--// + +HRESULT CLR_RT_TypeSystem::QueueStringToBuffer( char*& szBuffer, size_t& iBuffer, const char* szText ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(szText) + { + if(CLR_SafeSprintf( szBuffer, iBuffer, "%s", szText ) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + } + else + { + szBuffer[ 0 ] = 0; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::BuildTypeName( const CLR_RT_TypeDef_Index& cls, char*& szBuffer, size_t& iBuffer ) +{ + NATIVE_PROFILE_CLR_CORE(); + return BuildTypeName( cls, szBuffer, iBuffer, CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL, 0 ); +} + +HRESULT CLR_RT_TypeSystem::BuildTypeName ( const CLR_RT_TypeDef_Index& cls, char*& szBuffer, size_t& iBuffer, CLR_UINT32 flags, CLR_UINT32 levels ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + CLR_RT_Assembly* assm; + const CLR_RECORD_TYPEDEF* td; + bool fFullName; + + if(inst.InitializeFromIndex( cls ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + assm = inst.m_assm; + td = inst.m_target; + fFullName = flags & CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL; + + if(fFullName && td->enclosingType != CLR_EmptyIndex) + { + CLR_RT_TypeDef_Index clsSub; clsSub.Set( inst.Assembly(), td->enclosingType ); + + NANOCLR_CHECK_HRESULT(BuildTypeName( clsSub, szBuffer, iBuffer, flags, 0 )); + + NANOCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, (flags & CLR_RT_TypeSystem::TYPENAME_NESTED_SEPARATOR_DOT) ? "." : "+" )); + } + + if(fFullName && td->nameSpace != CLR_EmptyIndex) + { + const char* szNameSpace = assm->GetString( td->nameSpace ); + + if(szNameSpace[ 0 ]) + { + NANOCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, szNameSpace )); + NANOCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, "." )); + } + } + + NANOCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, assm->GetString( td->name ) )); + + while(levels-- > 0) + { + NANOCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, "[]" )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::BuildMethodName( const CLR_RT_MethodDef_Index& md, char*& szBuffer, size_t& iBuffer ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_MethodDef_Instance inst; + CLR_RT_TypeDef_Instance instOwner; + + if(inst .InitializeFromIndex ( md ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + if(instOwner.InitializeFromMethod( inst ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_CHECK_HRESULT(BuildTypeName( instOwner, szBuffer, iBuffer )); + + CLR_SafeSprintf( szBuffer, iBuffer, "::%s", inst.m_assm->GetString( inst.m_target->name ) ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::BuildFieldName( const CLR_RT_FieldDef_Index& fd, char*& szBuffer, size_t& iBuffer ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_FieldDef_Instance inst; + CLR_RT_TypeDef_Instance instOwner; + + if(inst .InitializeFromIndex( fd ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + if(instOwner.InitializeFromField( inst ) == false) NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + NANOCLR_CHECK_HRESULT(BuildTypeName( instOwner, szBuffer, iBuffer )); + + CLR_SafeSprintf( szBuffer, iBuffer, "::%s", inst.m_assm->GetString( inst.m_target->name ) ); + + NANOCLR_NOCLEANUP(); +} + +//--// + +bool CLR_RT_TypeSystem::FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD, CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Instance calleeInst; + + if(calleeInst.InitializeFromIndex( calleeMD )) + { + const char* calleeName = calleeInst.m_assm->GetString( calleeInst.m_target->name ); + + CLR_RT_TypeDef_Instance inst; inst.InitializeFromMethod( calleeInst ); + + if((inst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Interface) + { + // + // It's an interface method, it could be that the class is implementing explicitly the method. + // Prepend the Interface name to the method name and try again. + // + char rgBuffer[ 512 ]; + char* szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + BuildTypeName ( inst, szBuffer, iBuffer, CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL | CLR_RT_TypeSystem::TYPENAME_NESTED_SEPARATOR_DOT, 0 ); + QueueStringToBuffer( szBuffer, iBuffer, "." ); + QueueStringToBuffer( szBuffer, iBuffer, calleeName ); + + if(FindVirtualMethodDef( cls, calleeMD, rgBuffer, idx )) return true; + } + + if(FindVirtualMethodDef( cls, calleeMD, calleeName, idx )) return true; + } + + idx.Clear(); + + return false; +} + +bool CLR_RT_TypeSystem::FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD, const char* calleeName, CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Instance clsInst ; clsInst .InitializeFromIndex( cls ); + CLR_RT_MethodDef_Instance calleeInst; calleeInst.InitializeFromIndex( calleeMD ); + + CLR_RT_Assembly* calleeAssm = calleeInst.m_assm; + const CLR_RECORD_METHODDEF* calleeMDR = calleeInst.m_target; + CLR_UINT8 calleeNumArgs = calleeMDR->numArgs; + + while(NANOCLR_INDEX_IS_VALID(clsInst)) + { + CLR_RT_Assembly* targetAssm = clsInst.m_assm; + const CLR_RECORD_TYPEDEF* targetTDR = clsInst.m_target; + const CLR_RECORD_METHODDEF* targetMDR = targetAssm->GetMethodDef( targetTDR->methods_First ); + int num = targetTDR->vMethods_Num + targetTDR->iMethods_Num; + + for(int i=0; inumArgs == calleeNumArgs && (targetMDR->flags & CLR_RECORD_METHODDEF::MD_Abstract) == 0) + { + const char* targetName = targetAssm->GetString( targetMDR->name ); + + if(!strcmp( targetName, calleeName )) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_MethodSignature( calleeAssm, calleeMDR ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_MethodSignature( targetAssm, targetMDR ); + + if(CLR_RT_TypeSystem::MatchSignature( parserLeft, parserRight )) + { + idx.Set( targetAssm->m_idx, i + targetTDR->methods_First ); + + return true; + } + } + } + } + + clsInst.SwitchToParent(); + } + + idx.Clear(); + + return false; +} + +CLR_DataType CLR_RT_TypeSystem::MapElementTypeToDataType( CLR_UINT32 et ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RT_DataTypeLookup* ptr = c_CLR_RT_DataTypeLookup; + + for(CLR_UINT32 num = 0; numm_convertToElementType == et) return (CLR_DataType)num; + } + + if(et == ELEMENT_TYPE_I) return DATATYPE_I4; + if(et == ELEMENT_TYPE_U) return DATATYPE_U4; + + return DATATYPE_FIRST_INVALID; +} + +CLR_UINT32 CLR_RT_TypeSystem::MapDataTypeToElementType( CLR_DataType dt ) +{ + NATIVE_PROFILE_CLR_CORE(); + return c_CLR_RT_DataTypeLookup[ dt ].m_convertToElementType; +} + +//--// + +void CLR_RT_AttributeEnumerator::Initialize( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_assm = assm; // CLR_RT_Assembly* m_assm; + m_ptr = NULL; // const CLR_RECORD_ATTRIBUTE* m_ptr; + m_num = 0; // int m_num; + // CLR_RECORD_ATTRIBUTE m_data; + m_match.Clear(); // CLR_RT_MethodDef_Index m_match; +} + +void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_data.ownerType = TBL_TypeDef; + m_data.ownerIdx = inst.Type(); + + Initialize( inst.m_assm ); +} + +void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_FieldDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_data.ownerType = TBL_FieldDef; + m_data.ownerIdx = inst.Field(); + + Initialize( inst.m_assm ); +} + +void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_MethodDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_data.ownerType = TBL_MethodDef; + m_data.ownerIdx = inst.Method(); + + Initialize( inst.m_assm ); +} + +bool CLR_RT_AttributeEnumerator::Advance() +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_ATTRIBUTE* ptr = m_ptr; + int num = m_num; + CLR_UINT32 key = m_data.Key(); + bool fRes = false; + + if(ptr == NULL) + { + ptr = m_assm->GetAttribute( 0 ) - 1; + num = m_assm->m_pTablesSize[ TBL_Attributes ]; + } + + while(num) + { + ptr++; + num--; + + if(ptr->Key() == key) + { + CLR_IDX tk = ptr->constructor; + if(tk & 0x8000) + { + m_match = m_assm->m_pCrossReference_MethodRef[ tk & 0x7FFF ].m_target; + } + else + { + m_match.Set( m_assm->m_idx, tk ); + } + + m_blob = m_assm->GetSignature( ptr->data ); + + fRes = true; + break; + } + } + + m_ptr = ptr; + m_num = num; + + return fRes; +} + +void CLR_RT_AttributeEnumerator::GetCurrent( CLR_RT_TypeDef_Instance* instTD ) +{ + CLR_RT_MethodDef_Instance md; + + md.InitializeFromIndex ( m_match ); + instTD->InitializeFromMethod( md ); +} + +bool CLR_RT_AttributeEnumerator::MatchNext( const CLR_RT_TypeDef_Instance* instTD, const CLR_RT_MethodDef_Instance* instMD ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(Advance()) + { + if(instMD) + { + if(m_match.m_data != instMD->m_data) continue; + } + + if(instTD) + { + CLR_RT_MethodDef_Instance md; + CLR_RT_TypeDef_Instance td; + + md.InitializeFromIndex ( m_match ); + td.InitializeFromMethod( md ); + + if(td.m_data != instTD->m_data) continue; + } + + return true; + } + + return false; +} + +//--// + +HRESULT CLR_RT_AttributeParser::Initialize( const CLR_RT_AttributeEnumerator& en ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(m_md.InitializeFromIndex ( en.m_match ) == false || + m_td.InitializeFromMethod( m_md ) == false ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + m_parser.Initialize_MethodSignature( m_md.m_assm, m_md.m_target ); + m_parser.Advance( m_res ); // Skip return value. + + m_assm = en.m_assm; + m_blob = en.m_blob; + + m_currentPos = 0; + m_fixed_Count = m_md.m_target->numArgs - 1; + m_named_Count = -1; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_AttributeParser::Next( Value*& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if(m_currentPos == m_fixed_Count) + { + NANOCLR_READ_UNALIGNED_UINT16(m_named_Count,m_blob); + } + + if(m_currentPos < m_fixed_Count) + { + m_lastValue.m_mode = Value::c_ConstructorArgument; + m_lastValue.m_name = NULL; + + // + // attribute contructor support is currently not implemented + // + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + else if(m_currentPos < m_fixed_Count + m_named_Count) + { + CLR_UINT32 kind; NANOCLR_READ_UNALIGNED_UINT8(kind,m_blob); + + m_lastValue.m_name = GetString(); + + if(kind == SERIALIZATION_TYPE_FIELD) + { + CLR_RT_FieldDef_Index fd; + CLR_RT_FieldDef_Instance inst; + + m_lastValue.m_mode = Value::c_NamedField; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.FindFieldDef( m_td, m_lastValue.m_name, fd )); + + inst.InitializeFromIndex( fd ); + + m_parser.Initialize_FieldDef( inst.m_assm, inst.m_target ); + } + else + { + m_lastValue.m_mode = Value::c_NamedProperty; + + // + //attribute contructor support is currently not implemented + // + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + } + else + { + res = NULL; + NANOCLR_SET_AND_LEAVE(S_OK); + } + + + NANOCLR_CHECK_HRESULT(m_parser.Advance( m_res )); + + res = &m_lastValue; + + // + // Check for Enums. + // + if(m_res.m_dt == DATATYPE_VALUETYPE) + { + CLR_RT_TypeDef_Instance td; td.InitializeFromIndex( m_res.m_cls ); + + if((td.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum) + { + m_res.m_dt = (CLR_DataType)td.m_target->dataType; + } + } + + // + // Skip value info. + // + m_blob += sizeof(CLR_UINT8); + + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ m_res.m_dt ]; + + if(dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) + { + m_lastValue.m_value.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(m_res.m_dt, 0, 1) ); + + CLR_UINT32 size = (dtl.m_sizeInBits + 7) / 8; + +// FIXME GJS - the numeric values, what is their endiannes??? In the MSTV code there is a BIG endian fix but it looks like it will not work, so was it ever used? + memcpy( &m_lastValue.m_value.NumericByRef(), m_blob, size ); m_blob += size; + } + else if(m_res.m_dt == DATATYPE_STRING) + { + CLR_UINT32 tk; NANOCLR_READ_UNALIGNED_UINT16(tk,m_blob); + + CLR_RT_HeapBlock_String::CreateInstance( m_lastValue.m_value, CLR_TkFromType( TBL_Strings, tk ), m_assm ); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + m_lastValue.m_pos = m_currentPos++; + + NANOCLR_NOCLEANUP(); +} + +const char* CLR_RT_AttributeParser::GetString() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 tk; NANOCLR_READ_UNALIGNED_UINT16(tk,m_blob); + + return m_assm->GetString( tk ); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/TypeSystemLookup.cpp b/source/native/nf-interpreter/src/CLR/Core/TypeSystemLookup.cpp new file mode 100644 index 00000000..7be8e054 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/TypeSystemLookup.cpp @@ -0,0 +1,1774 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" +#include "corhdr_private.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define DT_NA CLR_RT_DataTypeLookup::c_NA +#define DT_VS CLR_RT_DataTypeLookup::c_VariableSize + +#define DT_PRIM CLR_RT_DataTypeLookup::c_Primitive +#define DT_ITF CLR_RT_DataTypeLookup::c_Interface +#define DT_CLASS CLR_RT_DataTypeLookup::c_Class +#define DT_VALUE CLR_RT_DataTypeLookup::c_ValueType +#define DT_ENUM CLR_RT_DataTypeLookup::c_Enum + +#define DT_ARRAY CLR_RT_DataTypeLookup::c_Array +#define DT_ARLST CLR_RT_DataTypeLookup::c_ArrayList + +#define DT_REF CLR_RT_DataTypeLookup::c_Reference +#define DT_NUM CLR_RT_DataTypeLookup::c_Numeric +#define DT_INT CLR_RT_DataTypeLookup::c_Integer +#define DT_SGN CLR_RT_DataTypeLookup::c_Signed +#define DT_DIR CLR_RT_DataTypeLookup::c_Direct +#define DT_OPT CLR_RT_DataTypeLookup::c_OptimizedValueType +#define DT_MT CLR_RT_DataTypeLookup::c_ManagedType + +#define DT_U1 sizeof(CLR_UINT8) +#define DT_I1 sizeof(CLR_INT8) +#define DT_U2 sizeof(CLR_UINT16) +#define DT_I2 sizeof(CLR_INT16) +#define DT_U4 sizeof(CLR_UINT32) +#define DT_I4 sizeof(CLR_INT32) +#define DT_U8 sizeof(CLR_UINT64) +#define DT_I8 sizeof(CLR_INT64) +#define DT_BL sizeof(CLR_RT_HeapBlock) + +#define DT_T(x) (CLR_UINT8)DATATYPE_##x +#define DT_CNV(x) (CLR_UINT8)ELEMENT_TYPE_##x +#define DT_CLS(x) &g_CLR_RT_WellKnownTypes.x + +#define DT_NOREL(x) NULL +#define DT_REL(x) (CLR_RT_HeapBlockRelocate)&x + +#if defined(WIN32) || defined(NANOCLR_TRACE_MEMORY_STATS) +#define DT_OPT_NAME(x) , #x +#else +#define DT_OPT_NAME(x) +#endif + +#define DATATYPE_NOT_SUPPORTED { DT_NA, DT_NA, DT_NA, DT_T(FIRST_INVALID), DT_CNV(END), NULL, DT_NOREL(CLR_RT_HeapBlock) DT_OPT_NAME(NOT_SUPPORTED) }, + +const CLR_RT_DataTypeLookup c_CLR_RT_DataTypeLookup[] = +{ +//// m_flags, m_sizeInBits, m_sizeInBytes, m_promoteTo, m_convertToElementType, m_cls, m_relocate, m_name +//// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { DT_NA , DT_NA, DT_NA, DT_T(VOID ), DT_CNV(VOID ), NULL , DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(VOID ) }, // DATATYPE_VOID + // + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 1, DT_U1, DT_T(I4 ), DT_CNV(BOOLEAN ), DT_CLS(m_Boolean ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(BOOLEAN ) }, // DATATYPE_BOOLEAN + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 8, DT_I1, DT_T(I4 ), DT_CNV(I1 ), DT_CLS(m_Int8 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I1 ) }, // DATATYPE_I1 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 8, DT_U1, DT_T(I4 ), DT_CNV(U1 ), DT_CLS(m_UInt8 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U1 ) }, // DATATYPE_U1 + // + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 16, DT_U2, DT_T(I4 ), DT_CNV(CHAR ), DT_CLS(m_Char ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(char ) }, // DATATYPE_CHAR + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 16, DT_I2, DT_T(I4 ), DT_CNV(I2 ), DT_CLS(m_Int16 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I2 ) }, // DATATYPE_I2 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 16, DT_U2, DT_T(I4 ), DT_CNV(U2 ), DT_CLS(m_UInt16 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U2 ) }, // DATATYPE_U2 + // + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 32, DT_I4, DT_T(I4 ), DT_CNV(I4 ), DT_CLS(m_Int32 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I4 ) }, // DATATYPE_I4 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 32, DT_U4, DT_T(I4 ), DT_CNV(U4 ), DT_CLS(m_UInt32 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U4 ) }, // DATATYPE_U4 + { DT_NUM | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 32, DT_I4, DT_T(R4 ), DT_CNV(R4 ), DT_CLS(m_Single ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(R4 ) }, // DATATYPE_R4 + // + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 64, DT_I8, DT_T(I8 ), DT_CNV(I8 ), DT_CLS(m_Int64 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I8 ) }, // DATATYPE_I8 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 64, DT_U8, DT_T(I8 ), DT_CNV(U8 ), DT_CLS(m_UInt64 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U8 ) }, // DATATYPE_U8 + { DT_NUM | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 64, DT_I8, DT_T(R8 ), DT_CNV(R8 ), DT_CLS(m_Double ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(R8 ) }, // DATATYPE_R8 + { DT_INT | DT_SGN | DT_VALUE | DT_DIR | DT_OPT | DT_MT, 64, DT_BL, DT_T(DATETIME ), DT_CNV(END ), DT_CLS(m_DateTime ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(DATETIME ) }, // DATATYPE_DATETIME + { DT_INT | DT_SGN | DT_VALUE | DT_DIR | DT_OPT | DT_MT, 64, DT_BL, DT_T(TIMESPAN ), DT_CNV(END ), DT_CLS(m_TimeSpan ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(TIMESPAN ) }, // DATATYPE_TIMESPAN + { DT_REF | DT_PRIM | DT_DIR | DT_MT, DT_VS, DT_BL, DT_T(STRING ), DT_CNV(STRING ), DT_CLS(m_String ), DT_REL (CLR_RT_HeapBlock ::Relocate_String ) DT_OPT_NAME(STRING ) }, // DATATYPE_STRING + // + { DT_REF | DT_DIR | DT_MT, DT_NA, DT_BL, DT_T(OBJECT ), DT_CNV(OBJECT ), DT_CLS(m_Object ), DT_REL (CLR_RT_HeapBlock ::Relocate_Obj ) DT_OPT_NAME(OBJECT ) }, // DATATYPE_OBJECT + { DT_REF | DT_CLASS | DT_MT, DT_NA, DT_BL, DT_T(CLASS ), DT_CNV(CLASS ), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_Cls ) DT_OPT_NAME(CLASS ) }, // DATATYPE_CLASS + { DT_REF | DT_VALUE | DT_MT, DT_NA, DT_BL, DT_T(VALUETYPE ), DT_CNV(VALUETYPE), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_Cls ) DT_OPT_NAME(VALUETYPE ) }, // DATATYPE_VALUETYPE + { DT_REF | DT_CLASS | DT_ARRAY | DT_MT, DT_NA, DT_BL, DT_T(SZARRAY ), DT_CNV(SZARRAY ), DT_CLS(m_Array ), DT_REL (CLR_RT_HeapBlock_Array ::Relocate ) DT_OPT_NAME(SZARRAY ) }, // DATATYPE_SZARRAY + { DT_REF | DT_MT, DT_NA, DT_NA, DT_T(BYREF ), DT_CNV(BYREF ), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_Ref ) DT_OPT_NAME(BYREF ) }, // DATATYPE_BYREF + // + //////////////////////////////////// + // + { DT_NA , DT_NA, DT_NA, DT_T(FREEBLOCK ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(FREEBLOCK ) }, // DATATYPE_FREEBLOCK + { DT_NA , DT_NA, DT_NA, DT_T(CACHEDBLOCK ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_Node ) DT_OPT_NAME(CACHEDBLOCK ) }, // DATATYPE_CACHEDBLOCK + { DT_REF , DT_NA, DT_NA, DT_T(ASSEMBLY ), DT_CNV(END ), NULL , DT_REL (CLR_RT_Assembly ::Relocate ) DT_OPT_NAME(ASSEMBLY ) }, // DATATYPE_ASSEMBLY + { DT_REF | DT_MT, DT_NA, DT_BL, DT_T(WEAKCLASS ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_WeakReference::Relocate ) DT_OPT_NAME(WEAKCLASS ) }, // DATATYPE_WEAKCLASS + { DT_MT, DT_NA, DT_NA, DT_T(REFLECTION ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(REFLECTION ) }, // DATATYPE_REFLECTION + { DT_MT, DT_NA, DT_NA, DT_T(ARRAY_BYREF ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_ArrayRef) DT_OPT_NAME(ARRAY_BYREF ) }, // DATATYPE_ARRAY_BYREF + { DT_REF | DT_MT, DT_NA, DT_BL, DT_T(DELEGATE_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Delegate ::Relocate ) DT_OPT_NAME(DELEGATE_HEAD ) }, // DATATYPE_DELEGATE_HEAD + { DT_REF | DT_MT, DT_NA, DT_NA, DT_T(DELEGATELIST_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Delegate_List::Relocate ) DT_OPT_NAME(DELEGATELIST_HEAD ) }, // DATATYPE_DELEGATELIST_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(OBJECT_TO_EVENT ), DT_CNV(END ), NULL , DT_REL (CLR_RT_ObjectToEvent_Source ::Relocate ) DT_OPT_NAME(OBJECT_TO_EVENT ) }, // DATATYPE_OBJECT_TO_EVENT + { DT_REF , DT_NA, DT_NA, DT_T(BINARY_BLOB_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_BinaryBlob ::Relocate ) DT_OPT_NAME(BINARY_BLOB_HEAD ) }, // DATATYPE_BINARY_BLOB_HEAD + // + { DT_REF , DT_NA, DT_NA, DT_T(THREAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_Thread ::Relocate ) DT_OPT_NAME(THREAD ) }, // DATATYPE_THREAD + { DT_REF , DT_NA, DT_NA, DT_T(SUBTHREAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_SubThread ::Relocate ) DT_OPT_NAME(SUBTHREAD ) }, // DATATYPE_SUBTHREAD + { DT_REF , DT_NA, DT_NA, DT_T(STACK_FRAME ), DT_CNV(END ), NULL , DT_REL (CLR_RT_StackFrame ::Relocate ) DT_OPT_NAME(STACK_FRAME ) }, // DATATYPE_STACK_FRAME + { DT_REF , DT_NA, DT_NA, DT_T(TIMER_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_Timer ) DT_OPT_NAME(TIMER_HEAD ) }, // DATATYPE_TIMER_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(LOCK_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Lock ::Relocate ) DT_OPT_NAME(LOCK_HEAD ) }, // DATATYPE_LOCK_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(LOCK_OWNER_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Lock ::Relocate_Owner ) DT_OPT_NAME(LOCK_OWNER_HEAD ) }, // DATATYPE_LOCK_OWNER_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(LOCK_REQUEST_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_LockRequest ::Relocate ) DT_OPT_NAME(LOCK_REQUEST_HEAD ) }, // DATATYPE_LOCK_REQUEST_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(WAIT_FOR_OBJECT_HEAD), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_WaitForObject::Relocate ) DT_OPT_NAME(WAIT_FOR_OBJECT_HEAD) }, // DATATYPE_WAIT_FOR_OBJECT_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(FINALIZER_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Finalizer ::Relocate ) DT_OPT_NAME(FINALIZER_HEAD ) }, // DATATYPE_FINALIZER_HEAD + { DT_NA , DT_NA, DT_NA, DT_T(MEMORY_STREAM_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_MemoryStream ) DT_OPT_NAME(MEMORY_STREAM_HEAD ) }, // DATATYPE_MEMORY_STREAM_HEAD + { DT_NA , DT_NA, DT_NA, DT_T(MEMORY_STREAM_DATA ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_MemoryStream ) DT_OPT_NAME(MEMORY_STREAM_DATA ) }, // DATATYPE_MEMORY_STREAM_DATA + // + { DT_NA , DT_NA, DT_NA, DT_T(SERIALIZER_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_BinaryFormatter ) DT_OPT_NAME(SERIALIZER_HEAD ) }, // DATATYPE_SERIALIZER_HEAD + { DT_NA , DT_NA, DT_NA, DT_T(SERIALIZER_DUPLICATE), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_BinaryFormatter ) DT_OPT_NAME(SERIALIZER_DUPLICATE) }, // DATATYPE_SERIALIZER_DUPLICATE + { DT_NA , DT_NA, DT_NA, DT_T(SERIALIZER_STATE ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_BinaryFormatter ) DT_OPT_NAME(SERIALIZER_STATE ) }, // DATATYPE_SERIALIZER_STATE + // + { DT_REF , DT_NA, DT_NA, DT_T(ENDPOINT_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_EndPoint ) DT_OPT_NAME(ENDPOINT_HEAD ) }, // DATATYPE_ENDPOINT_HEAD + // + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED + + { DT_REF , DT_NA, DT_NA, DT_T(IO_PORT ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_NativeEventDispatcher ) DT_OPT_NAME(IO_PORT ) }, // DATATYPE_IO_PORT + + DATATYPE_NOT_SUPPORTED //VTU_PORT + +#if defined(NANOCLR_APPDOMAINS) + { DT_REF , DT_NA, DT_NA, DT_T(APPDOMAIN_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_AppDomain::Relocate ) DT_OPT_NAME(APPDOMAIN_HEAD ) }, // DATATYPE_APPDOMAIN_HEAD + { DT_REF | DT_MT, DT_NA, DT_NA, DT_T(TRANSPARENT_PROXY ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock::Relocate_TransparentProxy ) DT_OPT_NAME(TRANSPARENT_PROXY ) }, // DATATYPE_TRANSPARENT_PROXY + { DT_REF , DT_NA, DT_NA, DT_T(APPDOMAIN_ASSEMBLY ), DT_CNV(END ), NULL , DT_REL (CLR_RT_AppDomainAssembly::Relocate ) DT_OPT_NAME(APPDOMAIN_ASSEMBLY ) }, // DATATYPE_APPDOMAIN_ASSEMBLY +#else + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define InlineBrTarget CLR_OpcodeParam_BrTarget +#define InlineField CLR_OpcodeParam_Field +#define InlineI CLR_OpcodeParam_I +#define InlineI8 CLR_OpcodeParam_I8 +#define InlineMethod CLR_OpcodeParam_Method +#define InlineNone CLR_OpcodeParam_None +#define InlineR CLR_OpcodeParam_R +#define InlineSig CLR_OpcodeParam_Sig +#define InlineString CLR_OpcodeParam_String +#define InlineSwitch CLR_OpcodeParam_Switch +#define InlineTok CLR_OpcodeParam_Tok +#define InlineType CLR_OpcodeParam_Type +#define InlineVar CLR_OpcodeParam_Var +#define ShortInlineBrTarget CLR_OpcodeParam_ShortBrTarget +#define ShortInlineI CLR_OpcodeParam_ShortI +#define ShortInlineR CLR_OpcodeParam_ShortR +#define ShortInlineVar CLR_OpcodeParam_ShortVar + +#define Pop0 0 +#define Pop1 1 +#define PopI 1 +#define PopI8 1 +#define PopR4 1 +#define PopR8 1 +#define PopRef 1 + +#define Push0 0 +#define Push1 1 +#define PushI 1 +#define PushI8 1 +#define PushR4 1 +#define PushR8 1 +#define PushRef 1 + +#define VarPop 0 +#define VarPush 0 + +#if defined(NANOCLR_OPCODE_NAMES) +#define OPDEF_NAME(name) name, +#else +#define OPDEF_NAME(name) +#endif + +#if defined(NANOCLR_OPCODE_STACKCHANGES) +#define OPDEF_STACKCHANGE(pop,push) ((pop) << 4) | (push), +#else +#define OPDEF_STACKCHANGE(pop,push) +#endif + +#if defined(NANOCLR_OPCODE_PARSER) +#define OPDEF_EX(lo,dt,index,flags) , lo, dt, index, flags +#else +#define OPDEF_EX(lo,dt,index,flags) +#endif + +#define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) OPDEF_NAME(string) OPDEF_STACKCHANGE(pop,push) oprType + +//--// + +const CLR_RT_OpcodeLookup c_CLR_RT_OpcodeLookup[] = +{ + { + OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) + + OPDEF_EX(LO_Nop, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) + + OPDEF_EX(LO_LoadArgumentAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) + + OPDEF_EX(LO_StoreArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) + + OPDEF_EX(LO_LoadLocalAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) + + OPDEF_EX(LO_LoadNull, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, -1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 4, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 5, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 6, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 7, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 8, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) + + OPDEF_EX(LO_LoadConstant_I8, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I8) + }, + { + OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) + + OPDEF_EX(LO_LoadConstant_R4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_R4) + }, + { + OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) + + OPDEF_EX(LO_LoadConstant_R8, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_R8) + }, + { + OPDEF(CEE_UNUSED49, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x24, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) + + OPDEF_EX(LO_Dup, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) + + OPDEF_EX(LO_Pop, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) + + OPDEF_EX(LO_Call, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) + + OPDEF_EX(LO_Ret, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS) + }, + { + OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFFALSE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFTRUE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFEQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFNOTEQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFFALSE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFTRUE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFEQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFNOTEQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) + + OPDEF_EX(LO_Switch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFMATCH | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) + + OPDEF_EX(LO_Add, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) + + OPDEF_EX(LO_Sub, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) + + OPDEF_EX(LO_Mul, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) + + OPDEF_EX(LO_Div, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) + + OPDEF_EX(LO_Div, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) + + OPDEF_EX(LO_Rem, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) + + OPDEF_EX(LO_Rem, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) + + OPDEF_EX(LO_And, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) + + OPDEF_EX(LO_Or, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) + + OPDEF_EX(LO_Xor, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) + + OPDEF_EX(LO_Shl, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) + + OPDEF_EX(LO_Shr, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) + + OPDEF_EX(LO_Shr, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) + + OPDEF_EX(LO_Neg, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) + + OPDEF_EX(LO_Not, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) + + OPDEF_EX(LO_CallVirt, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) + + OPDEF_EX(LO_CopyObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) + + OPDEF_EX(LO_LoadObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) + + OPDEF_EX(LO_LoadString, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) + + OPDEF_EX(LO_NewObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) + + OPDEF_EX(LO_CastClass, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) + + OPDEF_EX(LO_IsInst, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_UNUSED58, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x77, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED1, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x78, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) + + OPDEF_EX(LO_Unbox, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) + + OPDEF_EX(LO_Throw, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) + + OPDEF_EX(LO_LoadField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) + + OPDEF_EX(LO_LoadFieldAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) + + OPDEF_EX(LO_StoreField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) + + OPDEF_EX(LO_LoadStaticField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) + + OPDEF_EX(LO_LoadStaticFieldAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) + + OPDEF_EX(LO_StoreStaticField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) + + OPDEF_EX(LO_StoreObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) + + OPDEF_EX(LO_Box, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) + + OPDEF_EX(LO_NewArray, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) + + OPDEF_EX(LO_LoadLength, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) + + OPDEF_EX(LO_LoadElementAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) + OPDEF_EX(LO_LoadElement, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) + + OPDEF_EX(LO_Unbox, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_UNUSED5, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED6, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED7, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA8, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED8, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA9, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED9, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAA, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED10, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED11, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED12, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAD, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED13, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED14, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED15, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB0, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED16, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED17, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_UNUSED50, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED18, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED19, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBD, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED20, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED21, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED22, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC0, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED23, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED24, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC4, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED25, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC5, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED59, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED60, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC8, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED61, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC9, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED62, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCA, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED63, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED64, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED65, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCD, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED66, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED67, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) + + OPDEF_EX(LO_LoadToken, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) + + OPDEF_EX(LO_Add, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW) + }, + { + OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) + + OPDEF_EX(LO_Add, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) + + OPDEF_EX(LO_Mul, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW) + }, + { + OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) + + OPDEF_EX(LO_Mul, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) + + OPDEF_EX(LO_Sub, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW) + }, + { + OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) + + OPDEF_EX(LO_Sub, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) + + OPDEF_EX(LO_EndFinally, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) + + OPDEF_EX(LO_Leave, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) + + OPDEF_EX(LO_Leave, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_UNUSED26, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED27, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED28, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE3, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED29, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE4, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED30, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE5, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED31, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED32, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED33, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE8, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED34, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE9, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED35, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEA, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED36, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED37, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED38, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xED, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED39, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED40, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED41, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF0, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED42, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED43, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED44, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF3, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED45, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF4, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED46, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF5, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED47, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED48, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX7, "prefix7", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF8, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX6, "prefix6", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF9, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX5, "prefix5", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFA, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX4, "prefix4", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFB, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX3, "prefix3", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFC, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX2, "prefix2", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFD, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIXREF, "prefixref", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFF, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFEQUAL) + }, + { + OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER) + }, + { + OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS) + }, + { + OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) + + OPDEF_EX(LO_LoadFunction, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) + + OPDEF_EX(LO_LoadVirtFunction, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_UNUSED56, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x08, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) + + OPDEF_EX(LO_LoadArgumentAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) + + OPDEF_EX(LO_StoreArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) + + OPDEF_EX(LO_LoadLocalAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED57, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x10, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) + + OPDEF_EX(LO_EndFilter, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) + + OPDEF_EX(LO_InitObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) + + OPDEF_EX(LO_Nop, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED69, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x19, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) + + OPDEF_EX(LO_Rethrow, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS) + }, + { + OPDEF(CEE_UNUSED51, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1B, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED53, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1F, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED54, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x20, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED55, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x21, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED70, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x22, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, +}; + +#undef OPDEF_NAME +#undef OPDEF_STACKCHANGE +#undef OPDEF_EX +#undef OPDEF + +//--// + +#undef LoadString // Legacy Windows macro, whatever... + +#if defined(NANOCLR_OPCODE_NAMES) +#define OPDEF_NAME(name) #name, +#else +#define OPDEF_NAME(name) +#endif + +#define OPDEF(name,flags) OPDEF_NAME(name) flags + +#define VAL_NONE 0 +#define VAL_RP CLR_RT_LogicalOpcodeLookup::RESTARTPOINT_NEXT +#define VAL_EX CLR_RT_LogicalOpcodeLookup::EXCEPTION +#define VAL_EX_ZERO CLR_RT_LogicalOpcodeLookup::EXCEPTION_IF_ZERO +#define VAL_EX_OVF CLR_RT_LogicalOpcodeLookup::EXCEPTION_IF_OVERFLOW + +const CLR_RT_LogicalOpcodeLookup c_CLR_RT_LogicalOpcodeLookup[] = +{ + OPDEF(Not , VAL_NONE ), // LO_Not = 0x00, + OPDEF(And , VAL_NONE ), // LO_And = 0x01, + OPDEF(Or , VAL_NONE ), // LO_Or = 0x02, + OPDEF(Xor , VAL_NONE ), // LO_Xor = 0x03, + OPDEF(Shl , VAL_NONE ), // LO_Shl = 0x04, + OPDEF(Shr , VAL_NONE ), // LO_Shr = 0x05, + + OPDEF(Neg , VAL_NONE ), // LO_Neg = 0x06, + OPDEF(Add , VAL_EX_OVF ), // LO_Add = 0x07, + OPDEF(Sub , VAL_EX_OVF ), // LO_Sub = 0x08, + OPDEF(Mul , VAL_EX_OVF ), // LO_Mul = 0x09, + OPDEF(Div , VAL_EX_ZERO ), // LO_Div = 0x0A, + OPDEF(Rem , VAL_EX_ZERO ), // LO_Rem = 0x0B, + + OPDEF(Box , VAL_EX ), // LO_Box = 0x0C, + OPDEF(Unbox , VAL_EX ), // LO_Unbox = 0x0D, + + OPDEF(Branch , VAL_NONE ), // LO_Branch = 0x0E, + OPDEF(Set , VAL_NONE ), // LO_Set = 0x0F, + OPDEF(Switch , VAL_NONE ), // LO_Switch = 0x10, + + OPDEF(LoadFunction , VAL_EX ), // LO_LoadFunction = 0x11, + OPDEF(LoadVirtFunction , VAL_EX ), // LO_LoadVirtFunction = 0x12, + + OPDEF(Call , VAL_EX | VAL_RP), // LO_Call = 0x13, + OPDEF(CallVirt , VAL_EX | VAL_RP), // LO_CallVirt = 0x14, + OPDEF(Ret , VAL_NONE ), // LO_Ret = 0x15, + + OPDEF(NewObject , VAL_EX | VAL_RP), // LO_NewObject = 0x16, + OPDEF(CastClass , VAL_EX ), // LO_CastClass = 0x17, + OPDEF(IsInst , VAL_NONE ), // LO_IsInst = 0x18, + + OPDEF(Dup , VAL_NONE ), // LO_Dup = 0x19, + OPDEF(Pop , VAL_NONE ), // LO_Pop = 0x1A, + + OPDEF(Throw , VAL_EX ), // LO_Throw = 0x1B, + OPDEF(Rethrow , VAL_EX ), // LO_Rethrow = 0x1C, + OPDEF(Leave , VAL_NONE ), // LO_Leave = 0x1D, + OPDEF(EndFinally , VAL_EX ), // LO_EndFinally = 0x1E, + + OPDEF(Convert , VAL_EX_OVF ), // LO_Convert = 0x1F, + + OPDEF(StoreArgument , VAL_NONE ), // LO_StoreArgument = 0x20, + OPDEF(LoadArgument , VAL_NONE ), // LO_LoadArgument = 0x21, + OPDEF(LoadArgumentAddress , VAL_NONE ), // LO_LoadArgumentAddress = 0x22, + + OPDEF(StoreLocal , VAL_NONE ), // LO_StoreLocal = 0x23, + OPDEF(LoadLocal , VAL_NONE ), // LO_LoadLocal = 0x24, + OPDEF(LoadLocalAddress , VAL_NONE ), // LO_LoadLocalAddress = 0x25, + + OPDEF(LoadConstant_I4 , VAL_NONE ), // LO_LoadConstant_I4 = 0x26, + OPDEF(LoadConstant_I8 , VAL_NONE ), // LO_LoadConstant_I8 = 0x27, + OPDEF(LoadConstant_R4 , VAL_NONE ), // LO_LoadConstant_R4 = 0x28, + OPDEF(LoadConstant_R8 , VAL_NONE ), // LO_LoadConstant_R8 = 0x29, + + OPDEF(LoadNull , VAL_NONE ), // LO_LoadNull = 0x2A, + OPDEF(LoadString , VAL_EX ), // LO_LoadString = 0x2B, + OPDEF(LoadToken , VAL_NONE ), // LO_LoadToken = 0x2C, + + OPDEF(NewArray , VAL_EX ), // LO_NewArray = 0x2D, + OPDEF(LoadLength , VAL_EX ), // LO_LoadLength = 0x2E, + + OPDEF(StoreElement , VAL_EX ), // LO_StoreElement = 0x2F, + OPDEF(LoadElement , VAL_EX ), // LO_LoadElement = 0x30, + OPDEF(LoadElementAddress , VAL_EX ), // LO_LoadElementAddress = 0x31, + + OPDEF(StoreField , VAL_EX ), // LO_StoreField = 0x32, + OPDEF(LoadField , VAL_EX ), // LO_LoadField = 0x33, + OPDEF(LoadFieldAddress , VAL_EX ), // LO_LoadFieldAddress = 0x34, + + OPDEF(StoreStaticField , VAL_NONE ), // LO_StoreStaticField = 0x35, + OPDEF(LoadStaticField , VAL_NONE ), // LO_LoadStaticField = 0x36, + OPDEF(LoadStaticFieldAddress, VAL_NONE ), // LO_LoadStaticFieldAddress = 0x37, + + OPDEF(StoreIndirect , VAL_EX ), // LO_StoreIndirect = 0x38, + OPDEF(LoadIndirect , VAL_EX ), // LO_LoadIndirect = 0x39, + + OPDEF(InitObject , VAL_NONE ), // LO_InitObject = 0x3A, + OPDEF(LoadObject , VAL_EX ), // LO_LoadObject = 0x3B, + OPDEF(CopyObject , VAL_EX ), // LO_CopyObject = 0x3C, + OPDEF(StoreObject , VAL_EX ), // LO_StoreObject = 0x3D, + + OPDEF(Nop , VAL_NONE ), // LO_Nop = 0x3E, + + OPDEF(EndFilter , VAL_EX ), // LO_EndFilter = 0x3F, + + OPDEF(Unsupported , VAL_NONE ), // LO_Unsupported = 0x40, +}; + diff --git a/source/native/nf-interpreter/src/CLR/Core/Various.cpp b/source/native/nf-interpreter/src/CLR/Core/Various.cpp new file mode 100644 index 00000000..b810979a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/Various.cpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_GetVersion( unsigned short int* pMajor, unsigned short int* pMinor, unsigned short int* pBuild, unsigned short int* pRevision ) +{ + NATIVE_PROFILE_CLR_CORE(); + if (pMajor) *pMajor = VERSION_MAJOR; + if (pMinor) *pMinor = VERSION_MINOR; + if (pBuild) *pBuild = VERSION_BUILD; + if (pRevision) *pRevision = VERSION_REVISION; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_ArrayListHelper::PrepareArrayList( CLR_RT_HeapBlock& thisRef, int count, int capacity ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = thisRef.Dereference(); FAULT_ON_NULL(pThis); + + if(count > capacity || capacity < 1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( pThis[ FIELD___items ], capacity, g_CLR_RT_WellKnownTypes.m_Object )); + + pThis[ FIELD___size ].NumericByRef().s4 = count; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( CLR_RT_HeapBlock & thisRef, CLR_RT_HeapBlock_Array* & array, int& count, int& capacity ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* pThis; + CLR_RT_HeapBlock* items; + + pThis = thisRef.Dereference(); FAULT_ON_NULL(pThis); + items = &pThis[ FIELD___items ]; + + if(items->DataType() != DATATYPE_OBJECT) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + array = items->DereferenceArray(); FAULT_ON_NULL(array); + + if(array->DataType() != DATATYPE_SZARRAY) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + capacity = array->m_numOfElements; + count = pThis[ FIELD___size ].NumericByRef().s4; + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ByteArrayReader::Init( const unsigned char* src, unsigned int srcSize ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if (src == NULL || srcSize == 0) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + source = src; + sourceSize = srcSize; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ByteArrayReader::Read( void* dst, unsigned int size ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if (size > sourceSize) NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + + memcpy( dst, source, size ); + + source += size; + sourceSize -= size; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ByteArrayReader::Read1Byte( void* dst ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if (1 > sourceSize) NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + + *(unsigned char*)dst = *source; + + source++; + sourceSize--; + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ByteArrayReader::Skip( unsigned int size ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + if (size > sourceSize) NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + + source += size; + sourceSize -= size; + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/CLR/Core/corhdr_private.h b/source/native/nf-interpreter/src/CLR/Core/corhdr_private.h new file mode 100644 index 00000000..b9e98a54 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/corhdr_private.h @@ -0,0 +1,111 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_CORHDR_H_ +#define _NANOCLR_CORHDR_H_ + +///////////////////////////////////////////////////////////////////////////// +// +// !!!! Lifted verbatim from corhdr.h !!!!! +// https://github.com/dotnet/coreclr/blob/master/src/inc/corhdr.h +// + +//***************************************************************************** +// +// Element type for Cor signature +// +//***************************************************************************** + +typedef enum CorElementType +{ + ELEMENT_TYPE_END = 0x0, + ELEMENT_TYPE_VOID = 0x1, + ELEMENT_TYPE_BOOLEAN = 0x2, + ELEMENT_TYPE_CHAR = 0x3, + ELEMENT_TYPE_I1 = 0x4, + ELEMENT_TYPE_U1 = 0x5, + ELEMENT_TYPE_I2 = 0x6, + ELEMENT_TYPE_U2 = 0x7, + ELEMENT_TYPE_I4 = 0x8, + ELEMENT_TYPE_U4 = 0x9, + ELEMENT_TYPE_I8 = 0xa, + ELEMENT_TYPE_U8 = 0xb, + ELEMENT_TYPE_R4 = 0xc, + ELEMENT_TYPE_R8 = 0xd, + ELEMENT_TYPE_STRING = 0xe, + + // every type above PTR will be simple type + ELEMENT_TYPE_PTR = 0xf, // PTR + ELEMENT_TYPE_BYREF = 0x10, // BYREF + + // Please use ELEMENT_TYPE_VALUETYPE. ELEMENT_TYPE_VALUECLASS is deprecated. + ELEMENT_TYPE_VALUETYPE = 0x11, // VALUETYPE + ELEMENT_TYPE_CLASS = 0x12, // CLASS + ELEMENT_TYPE_VAR = 0x13, // a class type variable VAR + ELEMENT_TYPE_ARRAY = 0x14, // MDARRAY ... ... + ELEMENT_TYPE_GENERICINST = 0x15, // instantiated type + ELEMENT_TYPE_TYPEDBYREF = 0x16, // This is a simple type. + + ELEMENT_TYPE_I = 0x18, // native integer size + ELEMENT_TYPE_U = 0x19, // native unsigned integer size + ELEMENT_TYPE_FNPTR = 0x1B, // FNPTR + ELEMENT_TYPE_OBJECT = 0x1C, // Shortcut for System.Object + ELEMENT_TYPE_SZARRAY = 0x1D, // Shortcut for single dimension zero lower bound array + // SZARRAY + ELEMENT_TYPE_MVAR = 0x1e, // a method type variable MVAR + + // This is only for binding + ELEMENT_TYPE_CMOD_REQD = 0x1F, // required C modifier : E_T_CMOD_REQD + ELEMENT_TYPE_CMOD_OPT = 0x20, // optional C modifier : E_T_CMOD_OPT + + // This is for signatures generated internally (which will not be persisted in any way). + ELEMENT_TYPE_INTERNAL = 0x21, // INTERNAL + + // Note that this is the max of base type excluding modifiers + ELEMENT_TYPE_MAX = 0x22, // first invalid element type + + + ELEMENT_TYPE_MODIFIER = 0x40, + ELEMENT_TYPE_SENTINEL = 0x01 | ELEMENT_TYPE_MODIFIER, // sentinel for varargs + ELEMENT_TYPE_PINNED = 0x05 | ELEMENT_TYPE_MODIFIER, + ELEMENT_TYPE_R4_HFA = 0x06 | ELEMENT_TYPE_MODIFIER, // used only internally for R4 HFA types + ELEMENT_TYPE_R8_HFA = 0x07 | ELEMENT_TYPE_MODIFIER, // used only internally for R8 HFA types + +} CorElementType; + +//***************************************************************************** +// +// Serialization types for Custom attribute support +// +//***************************************************************************** + +typedef enum CorSerializationType +{ + SERIALIZATION_TYPE_UNDEFINED = 0, + SERIALIZATION_TYPE_BOOLEAN = ELEMENT_TYPE_BOOLEAN, + SERIALIZATION_TYPE_CHAR = ELEMENT_TYPE_CHAR, + SERIALIZATION_TYPE_I1 = ELEMENT_TYPE_I1, + SERIALIZATION_TYPE_U1 = ELEMENT_TYPE_U1, + SERIALIZATION_TYPE_I2 = ELEMENT_TYPE_I2, + SERIALIZATION_TYPE_U2 = ELEMENT_TYPE_U2, + SERIALIZATION_TYPE_I4 = ELEMENT_TYPE_I4, + SERIALIZATION_TYPE_U4 = ELEMENT_TYPE_U4, + SERIALIZATION_TYPE_I8 = ELEMENT_TYPE_I8, + SERIALIZATION_TYPE_U8 = ELEMENT_TYPE_U8, + SERIALIZATION_TYPE_R4 = ELEMENT_TYPE_R4, + SERIALIZATION_TYPE_R8 = ELEMENT_TYPE_R8, + SERIALIZATION_TYPE_STRING = ELEMENT_TYPE_STRING, + SERIALIZATION_TYPE_SZARRAY = ELEMENT_TYPE_SZARRAY, // Shortcut for single dimension zero lower bound array + SERIALIZATION_TYPE_TYPE = 0x50, + SERIALIZATION_TYPE_TAGGED_OBJECT= 0x51, + SERIALIZATION_TYPE_FIELD = 0x53, + SERIALIZATION_TYPE_PROPERTY = 0x54, + SERIALIZATION_TYPE_ENUM = 0x55 +} CorSerializationType; + +///////////////////////////////////////////////////////////////////////////// + +#endif // _NANOCLR_CORHDR_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Core/nanoSupport_CRC32.c b/source/native/nf-interpreter/src/CLR/Core/nanoSupport_CRC32.c new file mode 100644 index 00000000..b4e11c10 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Core/nanoSupport_CRC32.c @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include + +///////////////////////////////////////////////////////////////////////////// +// +// CRC 32 table for use under ZModem protocol, IEEE 802 +// G(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 +// +static const unsigned int c_CRCTable[256] = +{ + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, + 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, + 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, + 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, + 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, + 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, + 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, + 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, + 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, + 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, + 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, + 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, + 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, + 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, + 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, + 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, + 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, + 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, + 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, + 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, + 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// This is declared with GCC weak attribute so it can be replaced with an implementation at target level // +// Currently this is happening with the STM32 targets as all chips feature a CRC hardware unit // +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +__nfweak unsigned int SUPPORT_ComputeCRC(const void* rgBlock, int nLength, unsigned int crc) +{ + const unsigned char* ptr = (const unsigned char*)rgBlock; + + while(nLength-- > 0) + { + crc = c_CRCTable[((crc >> 24) ^ (*ptr++)) & 0xFF] ^ (crc << 8); + } + + return crc; +}; diff --git a/source/native/nf-interpreter/src/CLR/Debugger/CMakeLists.txt b/source/native/nf-interpreter/src/CLR/Debugger/CMakeLists.txt new file mode 100644 index 00000000..ab90ee1a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append Wire Protocol files to source +# list(APPEND DEBUGGER_WIRE_PROTOCOL_SOURCES_LIST "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_Commands.c") +# list(APPEND DEBUGGER_WIRE_PROTOCOL_SOURCES_LIST "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_App_Interface.c") +# make Wire Protocol files list global +# set(DEBUGGER_WIRE_PROTOCOL_SOURCES ${DEBUGGER_WIRE_PROTOCOL_SOURCES_LIST} CACHE INTERNAL "CLR debugger Wire Protocol source files list") + + +# append Wire Protocol include directory +list(APPEND DEBUGGER_WIRE_PROTOCOL_INCLUDE_DIRS_LIST "${CMAKE_CURRENT_SOURCE_DIR}") +# make include dirs global +set(DEBUGGER_WIRE_PROTOCOL_INCLUDE_DIRS ${DEBUGGER_WIRE_PROTOCOL_INCLUDE_DIRS_LIST} CACHE INTERNAL "CLR debugger Wire Protocol include dirs list") diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger.cpp b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.cpp new file mode 100644 index 00000000..cf320930 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.cpp @@ -0,0 +1,3417 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include +#include +#include +#include +#include +#include "Debugger.h" +#include + +#define __min(a,b) (((a) < (b)) ? (a) : (b)) + +#if 0 +#define TRACE0( msg, ...) debug_printf( msg ) +#define TRACE( msg, ...) debug_printf( msg, __VA_ARGS__ ) +char const* const AccessMemoryModeNames[] = { +"AccessMemory_Check", +"AccessMemory_Read", +"AccessMemory_Write", +"AccessMemory_Erase" +}; +#else +#define TRACE0(msg,...) +#define TRACE(msg,...) +#endif + +//--// + +BlockStorageDevice* CLR_DBG_Debugger::m_deploymentStorageDevice = NULL; + +//--// + +void CLR_DBG_Debugger::Debugger_WaitForCommands() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Waiting for debug commands...\r\n" ); +#endif + + while( !CLR_EE_DBG_IS(RebootPending) && !CLR_EE_DBG_IS(ExitPending) ) + { + g_CLR_RT_ExecutionEngine.DebuggerLoop(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_DBG_Debugger::CreateInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + g_CLR_DBG_Debugger = (CLR_DBG_Debugger*)&g_scratchDebugger[0]; + + + + CLR_RT_Memory::ZeroFill( g_CLR_DBG_Debugger, sizeof(CLR_DBG_Debugger) ); + + g_CLR_DBG_Debugger->m_messaging = (CLR_Messaging*)&g_scratchDebuggerMessaging[0]; + + NANOCLR_CHECK_HRESULT(g_CLR_DBG_Debugger->Debugger_Initialize(HalSystemConfig.DebuggerPort)); + + BlockStorageStream stream; + memset(&stream, 0, sizeof(BlockStorageStream)); + + if (BlockStorageStream_Initialize(&stream, BlockUsage_DEPLOYMENT )) + { + m_deploymentStorageDevice = stream.Device; + } + else + { + m_deploymentStorageDevice = NULL; + } + + // UNDONE: FIXME: MFUpdate_Initialize(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_DBG_Debugger::Debugger_Initialize( COM_HANDLE port ) +{ + (void)port; + + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + m_messaging->Initialize( c_Debugger_Lookup_Request, c_Debugger_Lookup_Request_count, c_Debugger_Lookup_Reply, c_Debugger_Lookup_Reply_count ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +HRESULT CLR_DBG_Debugger::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + g_CLR_DBG_Debugger->Debugger_Cleanup(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_DBG_Debugger::Debugger_Cleanup() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + m_messaging->Cleanup(); +} + +//--// + +// void CLR_DBG_Debugger::ProcessCommands() +// { +// NATIVE_PROFILE_CLR_DEBUGGER(); +// m_messaging->m_controller.AdvanceState(); +// } + +void CLR_DBG_Debugger::BroadcastEvent( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + WP_PrepareAndSendProtocolMessage( cmd, payloadSize, payload, flags ); +} + +//--// + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(NANOCLR_APPDOMAINS) + +CLR_RT_AppDomain* CLR_DBG_Debugger::GetAppDomainFromID( CLR_UINT32 id ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain, appDomain, g_CLR_RT_ExecutionEngine.m_appDomains) + { + if(appDomain->m_id == id) return appDomain; + } + NANOCLR_FOREACH_NODE_END(); + + return NULL; +} +#endif //NANOCLR_APPDOMAINS + +CLR_RT_Thread* CLR_DBG_Debugger::GetThreadFromPid( CLR_INT32 pid ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsReady) + { + if(th->m_pid == pid) return th; + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + if(th->m_pid == pid) return th; + } + NANOCLR_FOREACH_NODE_END(); + + return NULL; +} + +HRESULT CLR_DBG_Debugger::CreateListOfThreads( CLR_DBG_Commands::Debugging_Thread_List::Reply*& cmdReply, int& totLen ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + CLR_UINT32* pidDst; + int num; + + num = g_CLR_RT_ExecutionEngine.m_threadsReady .NumOfNodes() + + g_CLR_RT_ExecutionEngine.m_threadsWaiting.NumOfNodes(); + + totLen = sizeof(*cmdReply) + (num-1) * sizeof(CLR_UINT32); + + cmdReply = (CLR_DBG_Commands::Debugging_Thread_List::Reply*)CLR_RT_Memory::Allocate_And_Erase( totLen, true ); CHECK_ALLOCATION(cmdReply); + + cmdReply->m_num = num; + + pidDst = cmdReply->m_pids; + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,thSrc,g_CLR_RT_ExecutionEngine.m_threadsReady) + { + *pidDst++ = thSrc->m_pid; + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_FOREACH_NODE(CLR_RT_Thread,thSrc,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + *pidDst++ = thSrc->m_pid; + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_DBG_Debugger::CreateListOfCalls( CLR_INT32 pid, CLR_DBG_Commands::Debugging_Thread_Stack::Reply*& cmdReply, int& totLen ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + CLR_RT_Thread* th = GetThreadFromPid( pid ); FAULT_ON_NULL(th); + + for(int pass=0; pass<2; pass++) + { + int num = 0; + + NANOCLR_FOREACH_NODE(CLR_RT_StackFrame,call,th->m_stackFrames) + { + if(pass == 1) + { + int tmp = num; + +#ifndef CLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + CLR_DBG_Commands::Debugging_Thread_Stack::Reply::Call& dst = cmdReply->m_data[ tmp++ ]; + + dst.m_md = call->m_inlineFrame->m_frame.m_call; + dst.m_IP = (CLR_UINT32)(call->m_inlineFrame->m_frame.m_IP - call->m_inlineFrame->m_frame.m_IPStart); +#if defined(NANOCLR_APPDOMAINS) + dst.m_appDomainID = call->m_appDomain->m_id; + dst.m_flags = call->m_flags; +#endif + } +#endif + CLR_DBG_Commands::Debugging_Thread_Stack::Reply::Call& dst = cmdReply->m_data[ tmp ]; + + dst.m_md = call->m_call; + dst.m_IP = (CLR_UINT32)(call->m_IP - call->m_IPstart); + + if(dst.m_IP && call != th->CurrentFrame()) + { + //With the exception of when the IP is 0, for a breakpoint on Push, + //The call->m_IP is the next instruction to execute, not the currently executing one. + //For non-leaf frames, this will return the IP within the call. + dst.m_IP--; + } + +#if defined(NANOCLR_APPDOMAINS) + dst.m_appDomainID = call->m_appDomain->m_id; + dst.m_flags = call->m_flags; +#endif + } + +#ifndef CLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + num++; + } +#endif + + num++; + } + NANOCLR_FOREACH_NODE_END(); + + if(pass == 0) + { + totLen = sizeof(*cmdReply) + (num-1) * sizeof(CLR_DBG_Commands::Debugging_Thread_Stack::Reply::Call); + + cmdReply = (CLR_DBG_Commands::Debugging_Thread_Stack::Reply*)CLR_RT_Memory::Allocate_And_Erase( totLen, CLR_RT_HeapBlock::HB_CompactOnFailure ); CHECK_ALLOCATION(cmdReply); + + cmdReply->m_num = num; + cmdReply->m_status = th->m_status; + cmdReply->m_flags = th->m_flags; + } + } + + NANOCLR_NOCLEANUP(); +} + +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_DBG_Debugger::Monitor_Ping( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool fStopOnBoot = true; + + // + // There's someone on the other side!! + // + CLR_EE_DBG_SET( Enabled ); + + if((msg->m_header.m_flags & WP_Flags_c_Reply ) == 0) + { + Monitor_Ping_Reply cmdReply; + Monitor_Ping_Command *cmd = (Monitor_Ping_Command*)msg->m_payload; + + // default is to stop the debugger (backwards compatibility) + fStopOnBoot = (cmd != NULL) && (cmd->m_dbg_flags & Monitor_Ping_c_Ping_DbgFlag_Stop); + + cmdReply.m_source = Monitor_Ping_c_Ping_Source_NanoCLR; + + cmdReply.m_dbg_flags = CLR_EE_DBG_IS(StateProgramExited) != 0 ? Monitor_Ping_c_Ping_DbgFlag_AppExit : 0; + + #if defined(WP_IMPLEMENTS_CRC32) + cmdReply.m_dbg_flags |= Monitor_Ping_c_Ping_WPFlag_SupportsCRC32; + #endif + + // Wire Protocol packet size + #if (WP_PACKET_SIZE == 512) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_0512; + #elif (WP_PACKET_SIZE == 256) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_0256; + #elif (WP_PACKET_SIZE == 128) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_0128; + #elif (WP_PACKET_SIZE == 1024) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_1024; + #endif + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + } + else + { + Monitor_Ping_Reply *cmdReply = (Monitor_Ping_Reply*)msg->m_payload; + + // default is to stop the debugger (backwards compatibility) + fStopOnBoot = (cmdReply != NULL) && (cmdReply->m_dbg_flags & Monitor_Ping_c_Ping_DbgFlag_Stop); + } + + if(CLR_EE_DBG_IS_MASK(StateInitialize, StateMask)) + { + if(fStopOnBoot) CLR_EE_DBG_SET(Stopped); + else CLR_EE_DBG_CLR(Stopped); + } + + return true; +} + +bool CLR_DBG_Debugger::Monitor_FlashSectorMap( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + if((msg->m_header.m_flags & WP_Flags_c_Reply) == 0) + { + struct Flash_BlockRegionInfo + { + unsigned int StartAddress; + unsigned int NumBlocks; + unsigned int BytesPerBlock; + unsigned int Usage; + + } *pData = NULL; + + unsigned int rangeCount = 0; + unsigned int rangeIndex = 0; + + // get the number of available block storage devices + unsigned int numDevices = BlockStorageList_GetNumDevices(); + + // get an array of pointer to all the storage devices in the list and then request the device info + BlockStorageDevice** devices = (BlockStorageDevice**) platform_malloc(numDevices * sizeof(BlockStorageDevice*)); + DeviceBlockInfo** deviceInfos = (DeviceBlockInfo**) platform_malloc(numDevices * sizeof(DeviceBlockInfo*)); + + for(unsigned int i = 0; i < numDevices; i++) + { + if(i == 0) + { + devices[i] = BlockStorageList_GetFirstDevice(); + } + else + { + devices[i] = BlockStorageList_GetNextDevice(devices[i-1]); + } + // sanity check + if(devices[i] == NULL) + { + WP_ReplyToCommand( msg, true, false, NULL, 0 ); + return false; + } + deviceInfos[i] = BlockStorageDevice_GetDeviceInfo(devices[i]); + } + + for(int cnt = 0; cnt < 2; cnt++) + { + if(cnt == 1) + { + pData = (struct Flash_BlockRegionInfo*)platform_malloc(rangeCount * sizeof(struct Flash_BlockRegionInfo)); + + if(pData == NULL) + { + WP_ReplyToCommand( msg, true, false, NULL, 0 ); + return false; + } + } + for(unsigned int i = 0; i < numDevices; i++) + { + for(unsigned int j = 0; j < deviceInfos[i]->NumRegions; j++) + { + const BlockRegionInfo* pRegion = &deviceInfos[i]->Regions[ j ]; + + for(unsigned int k = 0; k < pRegion->NumBlockRanges; k++) + { + + if(cnt == 0) + { + rangeCount++; + } + else + { + pData[ rangeIndex ].StartAddress = BlockRegionInfo_BlockAddress(pRegion, pRegion->BlockRanges[ k ].StartBlock); + pData[ rangeIndex ].NumBlocks = BlockRange_GetBlockCount(pRegion->BlockRanges[k]); + pData[ rangeIndex ].BytesPerBlock = pRegion->BytesPerBlock; + pData[ rangeIndex ].Usage = pRegion->BlockRanges[ k ].RangeType & BlockRange_USAGE_MASK; + rangeIndex++; + } + } + } + } + } + + + WP_ReplyToCommand( msg, true, false, (void*)pData, rangeCount * sizeof (struct Flash_BlockRegionInfo) ); + + platform_free(pData); + platform_free(devices); + platform_free(deviceInfos); + } + + return true; + +} + +//--// + + + + + + + +bool CLR_DBG_Debugger::CheckPermission( ByteAddress address, int mode ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool hasPermission = false; + unsigned int regionIndex, rangeIndex; + + BlockStorageDevice_FindRegionFromAddress(m_deploymentStorageDevice, address, ®ionIndex, &rangeIndex); + const BlockRange& range = BlockStorageDevice_GetDeviceInfo(m_deploymentStorageDevice)->Regions[ regionIndex ].BlockRanges[ rangeIndex ]; + + + switch(mode) + { + case AccessMemory_Check: + hasPermission = true; + break; + case AccessMemory_Read: +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPort)) + break; +#endif + switch(range.RangeType) + { + case BlockRange_BLOCKTYPE_CONFIG: // fall through + case BlockRange_BLOCKTYPE_BOOTSTRAP: // fall through + case BlockRange_BLOCKTYPE_CODE: // fall through + case BlockRange_BLOCKTYPE_DIRTYBIT: // fall through + case BlockRange_BLOCKTYPE_DEPLOYMENT: // fall through + case BlockRange_BLOCKTYPE_FILESYSTEM: // fall through + case BlockRange_BLOCKTYPE_STORAGE_A: // fall through + case BlockRange_BLOCKTYPE_STORAGE_B: + case BlockRange_BLOCKTYPE_SIMPLE_A: + case BlockRange_BLOCKTYPE_SIMPLE_B: + case BlockRange_BLOCKTYPE_UPDATE: + + hasPermission = true; + break; + } + break; + case AccessMemory_Write: +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPort)) + break; +#endif + if(BlockRange_IsDeployment(range) || BlockRange_IsConfig(range)) + { + hasPermission = true; + } + else + { + hasPermission = DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPort) == true; + } + break; + case AccessMemory_Erase: +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPort)) + break; +#endif + switch(range.RangeType) + { + case BlockRange_BLOCKTYPE_DEPLOYMENT: + case BlockRange_BLOCKTYPE_FILESYSTEM: + case BlockRange_BLOCKTYPE_STORAGE_A: + case BlockRange_BLOCKTYPE_STORAGE_B: + case BlockRange_BLOCKTYPE_SIMPLE_A: + case BlockRange_BLOCKTYPE_SIMPLE_B: + case BlockRange_BLOCKTYPE_UPDATE: + case BlockRange_BLOCKTYPE_CONFIG: + hasPermission = true; + break; + } + break; + default: + hasPermission = false; + break; + } + + return hasPermission; +} + +bool CLR_DBG_Debugger::AccessMemory( CLR_UINT32 location, unsigned int lengthInBytes, unsigned char* buf, int mode, unsigned int* errorCode ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TRACE("AccessMemory( 0x%08X, 0x%08x, 0x%08X, %s)\n", location, lengthInBytes, buf, AccessMemoryModeNames[mode] ); + + bool success = false; + + // reset error code + *errorCode = AccessMemoryErrorCode_NoError; + + //--// + unsigned int iRegion, iRange; + + if (BlockStorageDevice_FindRegionFromAddress(m_deploymentStorageDevice, location, &iRegion, &iRange)) + { + const DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(m_deploymentStorageDevice); + + // start from the block where the sector sits. + ByteAddress accessAddress = location; + + unsigned char* bufPtr = buf; + signed int accessLenInBytes = lengthInBytes; + signed int blockOffset = BlockRegionInfo_OffsetFromBlock(((BlockRegionInfo*)(&deviceInfo->Regions[iRegion])), accessAddress); + + for(;iRegion < deviceInfo->NumRegions; iRegion++) + { + const BlockRegionInfo *pRegion = &deviceInfo->Regions[ iRegion ]; + + unsigned int blockIndex = BlockRegionInfo_BlockIndexFromAddress(pRegion, accessAddress); + unsigned int accessMaxLength = pRegion->BytesPerBlock - blockOffset; + + blockOffset = 0; + + for(;blockIndex < pRegion->NumBlocks; blockIndex++) + { + //accessMaxLength =the current largest number of bytes can be read from the block from the address to its block boundary. + unsigned int NumOfBytes = __min(accessMaxLength, (unsigned int)accessLenInBytes); + + accessMaxLength = pRegion->BytesPerBlock; + + if(blockIndex > pRegion->BlockRanges[ iRange ].EndBlock) + { + iRange++; + + if(iRange >= pRegion->NumBlockRanges) + { + ASSERT(false); + break; + } + } + + // since AccessMemory_Check is always true and will not break from here, no need to check AccessMemory_Check to free memory. + if(!CheckPermission( accessAddress, mode )) + { + TRACE0("=> Permission check failed!\n"); + + // set error code + *errorCode = AccessMemoryErrorCode_PermissionDenied; + + // done here + return success; + } + + switch(mode) + { + case AccessMemory_Check: + case AccessMemory_Read: + if(deviceInfo->Attribute & MediaAttribute_SupportsXIP) + { + memcpy( (unsigned char*)bufPtr, (const void*)accessAddress, NumOfBytes ); + success = true; + } + else + { + if (mode == AccessMemory_Check) + { + bufPtr = (unsigned char*) CLR_RT_Memory::Allocate( lengthInBytes, true ); + + if(!bufPtr) + { + TRACE0( "=> Failed to allocate data buffer\n"); + + // set error code + *errorCode = AccessMemoryErrorCode_PermissionDenied; + + // done here + return success; + } + } + + success = BlockStorageDevice_Read(m_deploymentStorageDevice, accessAddress , NumOfBytes, (unsigned char *)bufPtr); + + if (mode == AccessMemory_Check) + { + *(unsigned int*)buf = SUPPORT_ComputeCRC( bufPtr, NumOfBytes, *(unsigned int*)buf ); + + CLR_RT_Memory::Release( bufPtr ); + } + } + break; + + case AccessMemory_Write: + success = BlockStorageDevice_Write(m_deploymentStorageDevice, accessAddress , NumOfBytes, (unsigned char *)bufPtr, false); + break; + + case AccessMemory_Erase: + if (BlockStorageDevice_IsBlockErased(m_deploymentStorageDevice, accessAddress, NumOfBytes)) + { + // block is erased, we are good + success = true; + } + else + { + // need to erase block + success = BlockStorageDevice_EraseBlock(m_deploymentStorageDevice, accessAddress); + } + break; + + default: + break; + } + + if(!success) + { + // set error code + *errorCode = AccessMemoryErrorCode_RequestedOperationFailed; + + break; + } + + accessLenInBytes -= NumOfBytes; + + if (accessLenInBytes <= 0) + { + break; + } + + bufPtr += NumOfBytes; + accessAddress += NumOfBytes; + } + + blockIndex = 0; + iRange = 0; + + if ((accessLenInBytes <= 0) || (!success)) + { + break; + } + } + } + else + { + //--// RAM write + ByteAddress sectAddr = location; + + #if defined(_WIN32) + + bool proceed = false; + void * temp; + temp = (void *) sectAddr; + + switch(mode) + { + case AccessMemory_Check: + break; + + case AccessMemory_Read: + proceed = IsBadReadPtr( temp, lengthInBytes ) == false; + break; + + case AccessMemory_Write: + proceed = IsBadWritePtr( temp, lengthInBytes ) == false; + break; + } + + if(proceed) + #else + + unsigned int sectAddrEnd = sectAddr + lengthInBytes; + unsigned int ramStartAddress = HalSystemConfig.RAM1.Base; + unsigned int ramEndAddress = ramStartAddress + HalSystemConfig.RAM1.Size ; + + if((sectAddr =ramEndAddress) || (sectAddrEnd >ramEndAddress) ) + { + TRACE(" Invalid address %x and range %x Ram Start %x, Ram end %x\r\n", sectAddr, lengthInBytes, ramStartAddress, ramEndAddress); + return success; + } + else + #endif + { + switch(mode) + { + case AccessMemory_Check: + break; + + case AccessMemory_Read: + memcpy( buf, (const void*)sectAddr, lengthInBytes ); + break; + + case AccessMemory_Write: + unsigned char * memPtr; + memPtr = (unsigned char*)sectAddr; + memcpy( memPtr, buf, lengthInBytes ); + break; + + case AccessMemory_Erase: + memPtr = (unsigned char*)sectAddr; + if (lengthInBytes !=0) + memset( memPtr, 0xFF, lengthInBytes ); + break; + + default: + break; + } + } + } + + TRACE0( "=> SUCCESS\n"); + + return success; +} + +bool CLR_DBG_Debugger::Monitor_ReadMemory( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Monitor_ReadMemory* cmd = (CLR_DBG_Commands::Monitor_ReadMemory*)msg->m_payload; + CLR_DBG_Commands::Monitor_ReadMemory::Reply* cmdReply = NULL; + + uint32_t allocationSize = 0; + uint32_t len = cmd->m_length; + + // adjust length, if bigger than the WP packet size + if (len > WP_PACKET_SIZE) + { + len = WP_PACKET_SIZE; + } + + if (m_deploymentStorageDevice != NULL) + { + // start computing allocation size, fist the ErrorCode field... + allocationSize = offsetof(CLR_DBG_Commands::Monitor_ReadMemory::Reply, m_data); + // ... and the buffer + allocationSize += len; + + // allocate memory + cmdReply = (CLR_DBG_Commands::Monitor_ReadMemory::Reply*)platform_malloc(allocationSize); + + // sanity check + if(cmdReply != NULL) + { + // clear allocated memory + memset(cmdReply, 0, allocationSize); + + g_CLR_DBG_Debugger->AccessMemory( cmd->m_address, len, (unsigned char*)&cmdReply->m_data, AccessMemory_Read, &cmdReply->ErrorCode ); + + WP_ReplyToCommand( msg, true, false, cmdReply, allocationSize ); + + // free allocated memory + platform_free(cmdReply); + + // done here + return true; + } + } + + return false; +} + +bool CLR_DBG_Debugger::Monitor_WriteMemory( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Monitor_WriteMemory* cmd = (CLR_DBG_Commands::Monitor_WriteMemory*)msg->m_payload; + CLR_DBG_Commands::Monitor_WriteMemory::Reply cmdReply; + + if (m_deploymentStorageDevice != NULL) + { + + g_CLR_DBG_Debugger->AccessMemory( cmd->m_address, cmd->m_length, cmd->m_data, AccessMemory_Write, &cmdReply.ErrorCode ); + + WP_ReplyToCommand(msg, true, false, &cmdReply, sizeof(cmdReply)); + + return true; + } + + return false; +} + +bool CLR_DBG_Debugger::Monitor_CheckMemory( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Monitor_CheckMemory* cmd = (CLR_DBG_Commands::Monitor_CheckMemory*)msg->m_payload; + CLR_DBG_Commands::Monitor_CheckMemory::Reply cmdReply; + unsigned int errorCode; + + g_CLR_DBG_Debugger->AccessMemory( cmd->m_address, cmd->m_length, (unsigned char*)&cmdReply.m_crc, AccessMemory_Check, &errorCode ); + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + +} + +bool CLR_DBG_Debugger::Monitor_EraseMemory( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Monitor_EraseMemory* cmd = (CLR_DBG_Commands::Monitor_EraseMemory*)msg->m_payload; + CLR_DBG_Commands::Monitor_EraseMemory::Reply cmdReply; + + if (m_deploymentStorageDevice != NULL) + { + g_CLR_DBG_Debugger->AccessMemory( cmd->m_address, cmd->m_length, NULL, AccessMemory_Erase, &cmdReply.ErrorCode ); + + WP_ReplyToCommand(msg, true, false, &cmdReply, sizeof(cmdReply)); + + return true; + } + + return false; +} + +bool CLR_DBG_Debugger::Monitor_Execute( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + + CLR_DBG_Commands::Monitor_Execute* cmd = (CLR_DBG_Commands::Monitor_Execute*)msg->m_payload; + +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPort)) + return false; +#endif + + WP_ReplyToCommand(msg, true, false, NULL, 0); + + ((void (*)())(size_t)cmd->m_address)(); + + return true; +} + +bool CLR_DBG_Debugger::Monitor_Reboot( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Monitor_Reboot* cmd = (CLR_DBG_Commands::Monitor_Reboot*)msg->m_payload; + + if(NULL != cmd) + { + if(CLR_DBG_Commands::Monitor_Reboot::c_EnterBootloader == (cmd->m_flags & CLR_DBG_Commands::Monitor_Reboot::c_EnterBootloader)) + { + WP_ReplyToCommand(msg, true, false, NULL, 0); + + Events_WaitForEvents( 0, 100 ); // give message a little time to be flushed + + HAL_EnterBooterMode(); + } + + g_CLR_RT_ExecutionEngine.m_iReboot_Options = cmd->m_flags; + } + + CLR_EE_DBG_SET( RebootPending ); + + WP_ReplyToCommand(msg, true, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Monitor_MemoryMap( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + MemoryMap_Range map[2]; + + map[0].m_address = HalSystemConfig.RAM1.Base; + map[0].m_length = HalSystemConfig.RAM1.Size; + map[0].m_flags = Monitor_MemoryMap_c_RAM; + + map[1].m_address = HalSystemConfig.FLASH1.Base; + map[1].m_length = HalSystemConfig.FLASH1.Size; + map[1].m_flags = Monitor_MemoryMap_c_FLASH; + + WP_ReplyToCommand(msg, true, false, map, sizeof(map)); + + return true; +} + +bool CLR_DBG_Debugger::Monitor_DeploymentMap( WP_Message* msg) +{ + (void)msg; + + return true; +} + +bool CLR_DBG_Debugger::Monitor_QueryConfiguration( WP_Message* message) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + bool success = false; + + // include handling of configuration block only if feature is available + #if (HAS_CONFIG_BLOCK == TRUE) + + Monitor_QueryConfiguration_Command *cmd = (Monitor_QueryConfiguration_Command*)message->m_payload; + int size = 0; + int sizeOfBlock = 0; + + HAL_Configuration_NetworkInterface* configNetworkInterface; + HAL_Configuration_Wireless80211* configWireless80211NetworkInterface; + HAL_Configuration_X509CaRootBundle* x509Certificate; + + switch((DeviceConfigurationOption)cmd->Configuration) + { + case DeviceConfigurationOption_Network: + + configNetworkInterface = (HAL_Configuration_NetworkInterface*)platform_malloc(sizeof(HAL_Configuration_NetworkInterface)); + memset(configNetworkInterface, 0, sizeof(HAL_Configuration_NetworkInterface)); + + if(ConfigurationManager_GetConfigurationBlock(configNetworkInterface, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex) == true) + { + size = sizeof(HAL_Configuration_NetworkInterface); + success = true; + + WP_ReplyToCommand( message, success, false, (uint8_t*)configNetworkInterface, size ); + } + platform_free(configNetworkInterface); + break; + + case DeviceConfigurationOption_Wireless80211Network: + + configWireless80211NetworkInterface = (HAL_Configuration_Wireless80211*)platform_malloc(sizeof(HAL_Configuration_Wireless80211)); + memset(configWireless80211NetworkInterface, 0, sizeof(HAL_Configuration_Wireless80211)); + + if(ConfigurationManager_GetConfigurationBlock(configWireless80211NetworkInterface, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex) == true) + { + size = sizeof(HAL_Configuration_Wireless80211); + success = true; + + WP_ReplyToCommand( message, success, false, (uint8_t*)configWireless80211NetworkInterface, size ); + } + platform_free(configWireless80211NetworkInterface); + break; + + case DeviceConfigurationOption_X509CaRootBundle: + + if(g_TargetConfiguration.CertificateStore->Count > cmd->BlockIndex ) + { + // because X509 certificate has a variable length need to compute the block size in two steps + sizeOfBlock = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + sizeOfBlock += g_TargetConfiguration.CertificateStore->Certificates[cmd->BlockIndex]->CertificateSize; + } + + x509Certificate = (HAL_Configuration_X509CaRootBundle*)platform_malloc(sizeOfBlock); + memset(x509Certificate, 0, sizeof(sizeOfBlock)); + + if(ConfigurationManager_GetConfigurationBlock(x509Certificate, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex) == true) + { + size = sizeOfBlock; + success = true; + + WP_ReplyToCommand( message, success, false, (uint8_t*)x509Certificate, size ); + } + platform_free(x509Certificate); + break; + + case DeviceConfigurationOption_WirelessNetworkAP: + // TODO missing implementation for now + break; + + default: + break; + } + + if(!success) + { + WP_ReplyToCommand( message, success, false, NULL, size ); + } + + #else + + (void)message; + + #endif // (HAS_CONFIG_BLOCK == TRUE) + + return success; +} + +bool CLR_DBG_Debugger::Monitor_UpdateConfiguration(WP_Message* message) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + bool success = false; + + // include handling of configuration block only if feature is available + #if (HAS_CONFIG_BLOCK == TRUE) + + Monitor_UpdateConfiguration_Command* cmd = (Monitor_UpdateConfiguration_Command*)message->m_payload; + Monitor_UpdateConfiguration_Reply cmdReply; + + switch((DeviceConfigurationOption)cmd->Configuration) + { + case DeviceConfigurationOption_Network: + case DeviceConfigurationOption_Wireless80211Network: + case DeviceConfigurationOption_X509CaRootBundle: + case DeviceConfigurationOption_All: + if(ConfigurationManager_StoreConfigurationBlock(cmd->Data, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex, cmd->Length, cmd->Offset) == true) + { + cmdReply.ErrorCode = 0; + success = true; + } + else + { + cmdReply.ErrorCode = 100; + } + break; + + default: + cmdReply.ErrorCode = 10; + } + + WP_ReplyToCommand(message, success, false, &cmdReply, sizeof(cmdReply)); + + #else + + (void)message; + + #endif // (HAS_CONFIG_BLOCK == TRUE) + + return success; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Execution_BasePtr( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Execution_BasePtr::Reply cmdReply; + + cmdReply.m_EE = (CLR_UINT32)(size_t)&g_CLR_RT_ExecutionEngine; + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Execution_ChangeConditions( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Execution_ChangeConditions* cmd = (CLR_DBG_Commands::Debugging_Execution_ChangeConditions*)msg->m_payload; + + g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions |= cmd->FlagsToSet; + g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions &= ~cmd->FlagsToReset; + + // updating the debugging execution conditions requires sometime to propagate + // make sure we allow enough time for that to happen + OS_DELAY(100); + + if((msg->m_header.m_flags & WP_Flags_c_NonCritical) == 0) + { + CLR_DBG_Commands::Debugging_Execution_ChangeConditions::Reply cmdReply; + + cmdReply.CurrentState = g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions; + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + } + + return true; +} + +//--// + +static void GetClrReleaseInfo(CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::ClrInfo& clrInfo) +{ + NFReleaseInfo::Init( + clrInfo.m_clrReleaseInfo, + VERSION_MAJOR, + VERSION_MINOR, + VERSION_BUILD, + VERSION_REVISION, + OEMSYSTEMINFOSTRING, + ARRAYSIZE(OEMSYSTEMINFOSTRING), + TARGETNAMESTRING, + ARRAYSIZE(TARGETNAMESTRING), + PLATFORMNAMESTRING, + ARRAYSIZE(PLATFORMNAMESTRING) + ); + + if ( g_CLR_RT_TypeSystem.m_assemblyMscorlib && + g_CLR_RT_TypeSystem.m_assemblyMscorlib->m_header) + { + const CLR_RECORD_VERSION* mscorlibVer = & (g_CLR_RT_TypeSystem.m_assemblyMscorlib->m_header->version); + NFVersion::Init( clrInfo.m_TargetFrameworkVersion, + mscorlibVer->iMajorVersion, mscorlibVer->iMinorVersion, + mscorlibVer->iBuildNumber, mscorlibVer->iRevisionNumber + ); + } + else + { + NFVersion::Init( clrInfo.m_TargetFrameworkVersion, 0, 0, 0, 0 ); + } +} + +static bool GetInteropNativeAssemblies( uint8_t* &data, int* size) +{ + extern const CLR_RT_NativeAssemblyData *g_CLR_InteropAssembliesNativeData[]; + + int nativeAssembliesCount = 0; + CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::NativeAssemblyDetails* interopNativeAssemblies = NULL; + + // because the Interop assemblies list is assembled during the build we have to count how many are there before allocating memory for the array + for ( int i = 0; g_CLR_InteropAssembliesNativeData[i]; i++ ) + { + if (g_CLR_InteropAssembliesNativeData[i] != NULL) + { + nativeAssembliesCount++; + } + } + + interopNativeAssemblies = (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::NativeAssemblyDetails*)platform_malloc(sizeof(CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::NativeAssemblyDetails) * nativeAssembliesCount); + + // check for malloc failure + if(interopNativeAssemblies == NULL) + { + return false; + } + + // fill the array + for ( int i = 0; i < nativeAssembliesCount; i++ ) + { + if (g_CLR_InteropAssembliesNativeData[i] != NULL) + { + interopNativeAssemblies[i].CheckSum = g_CLR_InteropAssembliesNativeData[i]->m_checkSum; + hal_strcpy_s((char*)interopNativeAssemblies[i].AssemblyName, ARRAYSIZE(interopNativeAssemblies[i].AssemblyName), g_CLR_InteropAssembliesNativeData[i]->m_szAssemblyName); + + NFVersion::Init(interopNativeAssemblies[i].Version, + g_CLR_InteropAssembliesNativeData[i]->m_Version.iMajorVersion, g_CLR_InteropAssembliesNativeData[i]->m_Version.iMinorVersion, + g_CLR_InteropAssembliesNativeData[i]->m_Version.iBuildNumber, g_CLR_InteropAssembliesNativeData[i]->m_Version.iRevisionNumber + ); + } + } + + data = (uint8_t*)interopNativeAssemblies; + + *size = (sizeof(CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::NativeAssemblyDetails) * nativeAssembliesCount); + + return true; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Execution_QueryCLRCapabilities( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities* cmd = (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities*)msg->m_payload; + + CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::ReplyUnion reply; + reply.u_capsFlags = 0; + + CLR_UINT8* data = NULL; + int size = 0; + bool fSuccess = true; + bool freeAllocFlag = false; + + // set the compiler info string here +#if defined(__GNUC__) +#define COMPILER_INFO "GNU ARM GCC" + const size_t len = MIN(sizeof(COMPILER_INFO), sizeof(reply.u_SoftwareVersion.CompilerInfo)-1); +#else +#define COMPILER_INFO "UNKNOWN" + const size_t len = 0; +#endif + + memset(&reply, 0, sizeof(reply)); + + switch(cmd->m_cmd) + { + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags: + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_FloatingPoint; +#endif + + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_ExceptionFilters; + + // the current version ONLY suports incremental deployment + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_IncrementalDeployment; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_SourceLevelDebugging; + + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_ThreadCreateEx; +#endif + +#if defined(NANOCLR_PROFILE_NEW) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_Profiling; +#if defined(NANOCLR_PROFILE_NEW_CALLS) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_Profiling_Calls; +#endif +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_Profiling_Allocations; +#endif +#endif + +#if defined(NANOCLR_APPDOMAINS) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_AppDomains; +#endif + + if (CPU_IsSoftRebootSupported()) + { + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_SoftReboot; + } + + if (::Target_ConfigUpdateRequiresErase()) + { + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_ConfigBlockRequiresErase; + } + + if (::Target_HasNanoBooter()) + { + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_HasNanoBooter; + } + + reply.u_capsFlags |= (::GetPlatformCapabilities() & + ( CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_PlatformCapabiliy_0 | + CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_PlatformCapabiliy_1)); + + reply.u_capsFlags |= (::GetTargetCapabilities() & + ( CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_TargetCapabiliy_0 | + CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_TargetCapabiliy_1)); + + data = (CLR_UINT8*)&reply.u_capsFlags; + size = sizeof(reply.u_capsFlags); + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityVersion: +#if defined(__GNUC__) + // this is returning the GNU GCC compiler version in coded format: MAJOR x 10000 + MINOR x 100 + PATCH + // example: v6.3.1 shows as 6 x 10000 + 3 x 100 + 1 = 60301 + reply.u_SoftwareVersion.CompilerVersion = (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__); +#else + reply.u_SoftwareVersion.CompilerVersion = -1; +#endif + +#if defined(__DATE__) + hal_strncpy_s( reply.u_SoftwareVersion.BuildDate, sizeof(reply.u_SoftwareVersion.BuildDate), __DATE__, hal_strlen_s(__DATE__) ); +#else +#error "__DATE__ with build timestamp needs to be defined" +#endif + + hal_strncpy_s( (char*)&reply.u_SoftwareVersion.CompilerInfo[ 0 ], sizeof(reply.u_SoftwareVersion.CompilerInfo), COMPILER_INFO, len ); + + data = (CLR_UINT8*)&reply.u_SoftwareVersion; + size = sizeof(reply.u_SoftwareVersion); + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_HalSystemInfo: + if(GetHalSystemInfo( reply.u_HalSystemInfo ) == true) + { + data = (CLR_UINT8*)&reply.u_HalSystemInfo; + size = sizeof(reply.u_HalSystemInfo); + } + else + { + fSuccess = false; + } + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_ClrInfo: + GetClrReleaseInfo(reply.u_ClrInfo); + data = (CLR_UINT8*)&reply.u_ClrInfo; + size = sizeof(reply.u_ClrInfo); + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_TargetReleaseInfo: + if(Target_GetReleaseInfo(reply.u_TargetReleaseInfo) == true) + { + data = (CLR_UINT8*)&reply.u_TargetReleaseInfo; + size = sizeof(reply.u_TargetReleaseInfo); + } + else + { + fSuccess = false; + } + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_InteropNativeAssemblies: + if(GetInteropNativeAssemblies(data, &size) == true) + { + // signal need to free memory + freeAllocFlag = true; + } + else + { + fSuccess = false; + } + break; + + default: + fSuccess = false; + break; + } + + WP_ReplyToCommand( msg, fSuccess, false, data, size ); + + // check if we need to free data pointer + if(freeAllocFlag) + { + platform_free(data); + } + + return true; +} + + +bool CLR_DBG_Debugger::Debugging_Execution_Allocate( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Execution_Allocate* cmd = (CLR_DBG_Commands::Debugging_Execution_Allocate*)msg->m_payload; + CLR_DBG_Commands::Debugging_Execution_Allocate::Reply reply; + + reply.m_address = (CLR_UINT32)(size_t)CLR_RT_Memory::Allocate( cmd->m_size, CLR_RT_HeapBlock::HB_CompactOnFailure ); + + if(!reply.m_address) return false; + + WP_ReplyToCommand( msg, true, false, &reply, sizeof(reply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_UpgradeToSsl(WP_Message* msg) +{ + + CLR_DBG_Commands::Debugging_UpgradeToSsl* cmd = (CLR_DBG_Commands::Debugging_UpgradeToSsl*)msg->m_payload; + CLR_DBG_Commands::Debugging_UpgradeToSsl::Reply reply; + + if(!DebuggerPort_IsSslSupported(HalSystemConfig.DebuggerPort)) + { + return false; + } + + reply.m_success = 1; + + WP_ReplyToCommand( msg, true, true, &reply, sizeof(reply) ); + + Events_WaitForEvents(0, 300); + + return true == DebuggerPort_UpgradeToSsl(HalSystemConfig.DebuggerPort, cmd->m_flags); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +static bool FillValues( CLR_RT_HeapBlock* ptr, CLR_DBG_Commands::Debugging_Value*& array, size_t num, CLR_RT_HeapBlock* reference, CLR_RT_TypeDef_Instance* pTD ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + if(!ptr) return true; + + if(!array || num == 0) return false; + + CLR_DBG_Commands::Debugging_Value* dst = array++; num--; + CLR_RT_TypeDescriptor desc; + + memset( dst, 0, sizeof(*dst) ); + + dst->m_referenceID = (reference != NULL) ? reference : ptr; + dst->m_dt = ptr->DataType (); + dst->m_flags = ptr->DataFlags(); + dst->m_size = ptr->DataSize (); + + if(pTD != NULL) + { + dst->m_td = *pTD; + } + else if(SUCCEEDED(desc.InitializeFromObject( *ptr ))) + { + dst->m_td = desc.m_handlerCls; + } + + switch(dst->m_dt) + { + case DATATYPE_BOOLEAN : + case DATATYPE_I1 : + case DATATYPE_U1 : + + case DATATYPE_CHAR : + case DATATYPE_I2 : + case DATATYPE_U2 : + + case DATATYPE_I4 : + case DATATYPE_U4 : + case DATATYPE_R4 : + + case DATATYPE_I8 : + case DATATYPE_U8 : + case DATATYPE_R8 : + case DATATYPE_DATETIME : + case DATATYPE_TIMESPAN : + case DATATYPE_REFLECTION: + // + // Primitives or optimized value types. + // + memcpy( dst->m_builtinValue, (void*)&ptr->NumericByRefConst().u1, 8 ); + break; + + case DATATYPE_STRING: + { + const char* text = ptr->StringText(); + + if(text != NULL) + { + dst->m_charsInString = text; + dst->m_bytesInString = (CLR_UINT32)hal_strlen_s( text ); + + hal_strncpy_s( (char*)dst->m_builtinValue, ARRAYSIZE(dst->m_builtinValue), text, __min(dst->m_bytesInString, MAXSTRLEN(dst->m_builtinValue)) ); + } + else + { + dst->m_charsInString = NULL; + dst->m_bytesInString = 0; + dst->m_builtinValue[0] = 0; + } + } + break; + + + case DATATYPE_OBJECT: + case DATATYPE_BYREF : + return FillValues( ptr->Dereference(), array, num, NULL, pTD ); + + + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + dst->m_td = ptr->ObjectCls(); + break; + + case DATATYPE_SZARRAY: + { + CLR_RT_HeapBlock_Array* ptr2 = (CLR_RT_HeapBlock_Array*)ptr; + + dst->m_array_numOfElements = ptr2->m_numOfElements; + dst->m_array_depth = ptr2->ReflectionDataConst().m_levels; + dst->m_array_typeIndex = ptr2->ReflectionDataConst().m_data.m_type; + } + break; + + //////////////////////////////////////// + + case DATATYPE_WEAKCLASS : + break; + + case DATATYPE_ARRAY_BYREF : + dst->m_arrayref_referenceID = ptr->Array (); + dst->m_arrayref_index = ptr->ArrayIndex(); + + break; + + case DATATYPE_DELEGATE_HEAD : + break; + + case DATATYPE_DELEGATELIST_HEAD : + break; + + case DATATYPE_FREEBLOCK : + case DATATYPE_CACHEDBLOCK : + case DATATYPE_ASSEMBLY : + case DATATYPE_OBJECT_TO_EVENT : + case DATATYPE_BINARY_BLOB_HEAD : + + case DATATYPE_THREAD : + case DATATYPE_SUBTHREAD : + case DATATYPE_STACK_FRAME : + case DATATYPE_TIMER_HEAD : + case DATATYPE_LOCK_HEAD : + case DATATYPE_LOCK_OWNER_HEAD : + case DATATYPE_LOCK_REQUEST_HEAD : + case DATATYPE_WAIT_FOR_OBJECT_HEAD : + case DATATYPE_FINALIZER_HEAD : + case DATATYPE_MEMORY_STREAM_HEAD : + case DATATYPE_MEMORY_STREAM_DATA : + + case DATATYPE_SERIALIZER_HEAD : + case DATATYPE_SERIALIZER_DUPLICATE : + case DATATYPE_SERIALIZER_STATE : + + case DATATYPE_ENDPOINT_HEAD : + +#if defined(NANOCLR_APPDOMAINS) + case DATATYPE_APPDOMAIN_HEAD : + case DATATYPE_TRANSPARENT_PROXY : + case DATATYPE_APPDOMAIN_ASSEMBLY : +#endif + + break; + } + + return true; +} + +bool CLR_DBG_Debugger::GetValue( WP_Message* msg, CLR_RT_HeapBlock* ptr, CLR_RT_HeapBlock* reference, CLR_RT_TypeDef_Instance *pTD ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Commands::Debugging_Value reply[ 4 ]; + CLR_DBG_Commands::Debugging_Value* array = reply; + + if(FillValues( ptr, array, ARRAYSIZE(reply), reference, pTD )) + { + WP_ReplyToCommand( msg, true, false, reply, (int)((size_t)array - (size_t)reply) ); + + return true; + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return false; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Execution_SetCurrentAppDomain( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +#if defined(NANOCLR_APPDOMAINS) + + CLR_DBG_Commands::Debugging_Execution_SetCurrentAppDomain* cmd = (CLR_DBG_Commands::Debugging_Execution_SetCurrentAppDomain*)msg->m_payload; + CLR_RT_AppDomain* appDomain = g_CLR_DBG_Debugger->GetAppDomainFromID( cmd->m_id ); + + if(appDomain) + { + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomain ); + } + + WP_ReplyToCommand(msg, appDomain != NULL, false, NULL, 0); + + return true; +#else + (void)msg; + return false; +#endif +} + +bool CLR_DBG_Debugger::Debugging_Execution_Breakpoints( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Execution_Breakpoints* cmd = (CLR_DBG_Commands::Debugging_Execution_Breakpoints*)msg->m_payload; + + g_CLR_RT_ExecutionEngine.InstallBreakpoints( cmd->m_data, (msg->m_header.m_size - sizeof(cmd->m_flags)) / sizeof(CLR_DBG_Commands::Debugging_Execution_BreakpointDef) ); + + WP_ReplyToCommand(msg, true, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Execution_BreakpointStatus( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Execution_BreakpointStatus::Reply reply; + + if(g_CLR_RT_ExecutionEngine.DequeueActiveBreakpoint( reply.m_lastHit ) == false) + { + memset( &reply.m_lastHit, 0, sizeof(reply.m_lastHit) ); + } + + WP_ReplyToCommand( msg, true, false, &reply, sizeof(reply) ); + + return true; +} + +//--// + +CLR_RT_Assembly* CLR_DBG_Debugger::IsGoodAssembly( CLR_IDX idxAssm ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + if(pASSM->m_idx == idxAssm) return pASSM; + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + return NULL; +} + +bool CLR_DBG_Debugger::CheckTypeDef( const CLR_RT_TypeDef_Index& td, CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Assembly* assm = IsGoodAssembly( td.Assembly() ); + + if(assm && td.Type() < assm->m_pTablesSize[ TBL_TypeDef ]) + { + return inst.InitializeFromIndex( td ); + } + + return false; +} + +bool CLR_DBG_Debugger::CheckFieldDef( const CLR_RT_FieldDef_Index& fd, CLR_RT_FieldDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Assembly* assm = IsGoodAssembly( fd.Assembly() ); + + if(assm && fd.Field() < assm->m_pTablesSize[ TBL_FieldDef ]) + { + return inst.InitializeFromIndex( fd ); + } + + return false; +} + +bool CLR_DBG_Debugger::CheckMethodDef( const CLR_RT_MethodDef_Index& md, CLR_RT_MethodDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Assembly* assm = IsGoodAssembly( md.Assembly() ); + + if(assm && md.Method() < assm->m_pTablesSize[ TBL_MethodDef ]) + { + return inst.InitializeFromIndex( md ); + } + + return false; +} + +CLR_RT_StackFrame* CLR_DBG_Debugger::CheckStackFrame( CLR_INT32 pid, CLR_UINT32 depth, bool& isInline ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Thread* th = GetThreadFromPid( pid ); + + isInline = false; + + if(th) + { + NANOCLR_FOREACH_NODE(CLR_RT_StackFrame,call,th->m_stackFrames) + { +#ifndef CLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + if(depth-- == 0) + { + isInline = true; + return call; + } + } +#endif + + if(depth-- == 0) return call; + } + NANOCLR_FOREACH_NODE_END(); + } + + return NULL; +} + +//--// + +static HRESULT Debugging_Thread_Create_Helper( CLR_RT_MethodDef_Index& md, CLR_RT_Thread*& th, CLR_INT32 pid ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock ref; ref.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( ref ); + CLR_RT_Thread* realThread = (pid != 0) ? CLR_DBG_Debugger::GetThreadFromPid( pid ) : NULL; + + th = NULL; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( ref, md, NULL )); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewThread( th, ref.DereferenceDelegate(), ThreadPriority::Highest, -1 )); + + + if (realThread) + { + th->m_realThread = realThread; + } + + { + CLR_RT_StackFrame* stack = th->CurrentFrame(); + const CLR_RECORD_METHODDEF* target = stack->m_call.m_target; + CLR_UINT8 numArgs = target->numArgs; + + if(numArgs) + { + CLR_RT_SignatureParser parser; parser.Initialize_MethodSignature( stack->m_call.m_assm, target ); + CLR_RT_SignatureParser::Element res; + CLR_RT_HeapBlock* args = stack->m_arguments; + + if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) + { + args->SetObjectReference( NULL ); + + numArgs--; + args++; + } + + // + // Skip return value. + // + NANOCLR_CHECK_HRESULT(parser.Advance( res )); + + // + // None of the arguments can be ByRef. + // + { + CLR_RT_SignatureParser parser2 = parser; + + for(;parser2.Available() > 0;) + { + NANOCLR_CHECK_HRESULT(parser2.Advance( res )); + + if(res.m_fByRef) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + + for(CLR_UINT8 i=0; iTerminate(); + th = NULL; + } + } + + NANOCLR_CLEANUP_END(); +} + +bool CLR_DBG_Debugger::Debugging_Thread_CreateEx( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_CreateEx* cmd = (CLR_DBG_Commands::Debugging_Thread_CreateEx*)msg->m_payload; + CLR_DBG_Commands::Debugging_Thread_CreateEx::Reply cmdReply; + CLR_RT_Thread* th; + + if(SUCCEEDED(Debugging_Thread_Create_Helper( cmd->m_md, th, cmd->m_pid ))) + { + th->m_scratchPad = cmd->m_scratchPad; + + cmdReply.m_pid = th->m_pid; + } + else + { + cmdReply.m_pid = -1; + } + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_List( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_List::Reply* cmdReply = NULL; + int len = 0; + + if(FAILED(g_CLR_DBG_Debugger->CreateListOfThreads( cmdReply, len ))) + { + WP_ReplyToCommand( msg, false, false, NULL, 0); + } + else + { + WP_ReplyToCommand( msg, true, false, cmdReply, len ); + } + + CLR_RT_Memory::Release( cmdReply ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Stack( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_Stack* cmd = (CLR_DBG_Commands::Debugging_Thread_Stack*)msg->m_payload; + CLR_DBG_Commands::Debugging_Thread_Stack::Reply* cmdReply = NULL; + int len = 0; + + if(FAILED(g_CLR_DBG_Debugger->CreateListOfCalls( cmd->m_pid, cmdReply, len ))) + { + WP_ReplyToCommand(msg, false, false, NULL, 0); + } + else + { + WP_ReplyToCommand( msg, true, false, cmdReply, len ); + } + + CLR_RT_Memory::Release( cmdReply ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Kill( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_Kill* cmd = (CLR_DBG_Commands::Debugging_Thread_Kill*)msg->m_payload; + CLR_DBG_Commands::Debugging_Thread_Kill::Reply cmdReply; + CLR_RT_Thread* th = g_CLR_DBG_Debugger->GetThreadFromPid( cmd->m_pid ); + + if(th) + { + th->Terminate(); + + cmdReply.m_result = 1; + } + else + { + cmdReply.m_result = 0; + } + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Suspend( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_Suspend* cmd = (CLR_DBG_Commands::Debugging_Thread_Suspend*)msg->m_payload; + CLR_RT_Thread* th = g_CLR_DBG_Debugger->GetThreadFromPid( cmd->m_pid ); + + if(th) + { + th->Suspend(); + } + + WP_ReplyToCommand(msg, th != NULL, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Resume( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_Resume* cmd = (CLR_DBG_Commands::Debugging_Thread_Resume*)msg->m_payload; + CLR_RT_Thread* th = g_CLR_DBG_Debugger->GetThreadFromPid( cmd->m_pid ); + + if(th) + { + th->Resume(); + } + + WP_ReplyToCommand(msg, th != NULL, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Get( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)&g_scratchDebugger[0]; + CLR_DBG_Commands::Debugging_Thread_Get* cmd = (CLR_DBG_Commands::Debugging_Thread_Get*)msg->m_payload; + CLR_RT_Thread* th = dbg->GetThreadFromPid( cmd->m_pid ); + CLR_RT_HeapBlock* pThread; + bool fFound = false; + + if(th == NULL) return false; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + //If we are a thread spawned by the debugger to perform evaluations, + //return the thread object that correspond to thread that has focus in debugger. + th = th->m_realThread; +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Find an existing managed thread, if it exists + //making sure to only return the managed object association with the current appdomain + //to prevent leaking of managed Thread objects across AD boundaries. + + NANOCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,src,th->m_references) + { + CLR_RT_HeapBlock* pManagedThread = src->m_objectPtr; + _ASSERTE(pManagedThread != NULL); + +#if defined(NANOCLR_APPDOMAINS) + { + CLR_RT_ObjectToEvent_Source* appDomainSrc = CLR_RT_ObjectToEvent_Source::ExtractInstance( pManagedThread[ Library_corlib_native_System_Threading_Thread::FIELD___appDomain ] ); + + if(appDomainSrc == NULL) break; + + fFound = (appDomainSrc->m_eventPtr == g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()); + } +#else + fFound = true; +#endif + + if(fFound) + { + pThread = pManagedThread; + + break; + } + } + NANOCLR_FOREACH_NODE_END(); + + if(!fFound) + { + pThread = (CLR_RT_HeapBlock*)platform_malloc(sizeof(CLR_RT_HeapBlock)); + + //Create the managed thread. + //This implies that there is no state in the managed object. This is not exactly true, as the managed thread + //contains the priority as well as the delegate to start. However, that state is really just used as a placeholder for + //the data before the thread is started. Once the thread is started, they are copied over to the unmanaged thread object + //and no longer used. The managed object is then used simply as a wrapper for the unmanaged thread. Therefore, it is safe + //to simply make another managed thread here. + if(SUCCEEDED(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *pThread, g_CLR_RT_WellKnownTypes.m_Thread ))) + { + CLR_RT_HeapBlock* pRes = pThread->Dereference(); + + int pri = th->GetThreadPriority(); + + pRes[Library_corlib_native_System_Threading_Thread::FIELD___priority].NumericByRef().s4 = pri; + + if(SUCCEEDED(CLR_RT_ObjectToEvent_Source::CreateInstance( th, *pRes, pRes[ Library_corlib_native_System_Threading_Thread::FIELD___thread ] ))) + { +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_ObjectToEvent_Source::CreateInstance( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(), *pRes, pRes[ Library_corlib_native_System_Threading_Thread::FIELD___appDomain ] ); +#endif + fFound = true; + } + + } + } + + if(!fFound) return false; + + return g_CLR_DBG_Debugger->GetValue( msg, pThread, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Thread_GetException( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_GetException* cmd = (CLR_DBG_Commands::Debugging_Thread_GetException*)msg->m_payload; + CLR_RT_Thread* th = g_CLR_DBG_Debugger->GetThreadFromPid( cmd->m_pid ); + CLR_RT_HeapBlock* blk = NULL; + + if(th) + { + blk = &th->m_currentException; + } + + return g_CLR_DBG_Debugger->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Thread_Unwind( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Thread_Unwind* cmd = (CLR_DBG_Commands::Debugging_Thread_Unwind*)msg->m_payload; + CLR_RT_StackFrame* call; + CLR_RT_Thread* th; + bool isInline = false; + + if((call = g_CLR_DBG_Debugger->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { + _ASSERTE((call->m_flags & CLR_RT_StackFrame::c_MethodKind_Native) == 0); + + th = call->m_owningThread; + _ASSERTE(th->m_nestedExceptionsPos); + + CLR_RT_Thread::UnwindStack& us = th->m_nestedExceptions[ th->m_nestedExceptionsPos - 1 ]; + _ASSERTE(th->m_currentException.Dereference() == us.m_exception); + _ASSERTE(us.m_flags & CLR_RT_Thread::UnwindStack::c_ContinueExceptionHandler); + + us.m_handlerStack = call; + us.m_flags |= CLR_RT_Thread::UnwindStack::c_MagicCatchForInteceptedException; + + us.SetPhase(CLR_RT_Thread::UnwindStack::p_2_RunningFinallys_0); + } + + return true; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Stack_Info( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Stack_Info* cmd = (CLR_DBG_Commands::Debugging_Stack_Info*)msg->m_payload; + CLR_DBG_Commands::Debugging_Stack_Info::Reply cmdReply; + CLR_RT_StackFrame* call; + bool isInline = false; + + if((call = g_CLR_DBG_Debugger->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { +#ifndef CLR_NO_IL_INLINE + if(isInline) + { + cmdReply.m_md = call->m_inlineFrame->m_frame.m_call; + cmdReply.m_IP = (CLR_UINT32)(call->m_inlineFrame->m_frame.m_IP - call->m_inlineFrame->m_frame.m_IPStart); + cmdReply.m_numOfArguments = call->m_inlineFrame->m_frame.m_call.m_target->numArgs; + cmdReply.m_numOfLocals = call->m_inlineFrame->m_frame.m_call.m_target->numLocals; + cmdReply.m_depthOfEvalStack = (CLR_UINT32)(call->m_evalStack - call->m_inlineFrame->m_frame.m_evalStack); + } + else +#endif + { + cmdReply.m_md = call->m_call; + cmdReply.m_IP = (CLR_UINT32)(call->m_IP - call->m_IPstart); + cmdReply.m_numOfArguments = call->m_call.m_target->numArgs; + cmdReply.m_numOfLocals = call->m_call.m_target->numLocals; + cmdReply.m_depthOfEvalStack = (CLR_UINT32) call->TopValuePosition(); + } + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Stack_SetIP( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Stack_SetIP* cmd = (CLR_DBG_Commands::Debugging_Stack_SetIP*)msg->m_payload; + CLR_RT_StackFrame* call; + bool isInline = false; + + if((call = g_CLR_DBG_Debugger->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { +#ifndef CLR_NO_IL_INLINE + if(isInline) + { + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; + } + else +#endif + { + call->m_IP = call->m_IPstart + cmd->m_IP; + call->m_evalStackPos = call->m_evalStack + cmd->m_depthOfEvalStack; + } + + call->m_flags &= ~CLR_RT_StackFrame::c_InvalidIP; + + WP_ReplyToCommand(msg, true, false, NULL, 0); + + return true; + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; +} + +//--// + +static bool IsBlockEnumMaybe( CLR_RT_HeapBlock* blk ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + const CLR_UINT32 c_MaskForPrimitive = CLR_RT_DataTypeLookup::c_Integer | CLR_RT_DataTypeLookup::c_Numeric; + + CLR_RT_TypeDescriptor desc; + + if(FAILED(desc.InitializeFromObject( *blk ))) return false; + + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ desc.m_handlerCls.m_target->dataType ]; + + return (dtl.m_flags & c_MaskForPrimitive) == c_MaskForPrimitive; +} + +static bool SetBlockHelper( CLR_RT_HeapBlock* blk, CLR_DataType dt, CLR_UINT8* builtinValue ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool fCanAssign = false; + + if(blk) + { + CLR_DataType dtDst; + CLR_RT_HeapBlock src; + + dtDst = blk->DataType(); + + src.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt, 0, 1) ); + memcpy( (void*)&src.NumericByRef().u1, builtinValue, sizeof(CLR_UINT64) ); + + if(dtDst == dt) + { + fCanAssign = true; + } + else + { + if(dt == DATATYPE_REFLECTION) + { + fCanAssign = (dtDst == DATATYPE_OBJECT && blk->Dereference() == NULL); + } + else if(dt == DATATYPE_OBJECT) + { + fCanAssign = (src .Dereference() == NULL && dtDst == DATATYPE_REFLECTION); + } + else + { + _ASSERTE(c_CLR_RT_DataTypeLookup[ dtDst ].m_flags & CLR_RT_DataTypeLookup::c_Numeric); + + if(c_CLR_RT_DataTypeLookup[ dtDst ].m_sizeInBytes == sizeof(CLR_INT32) && + c_CLR_RT_DataTypeLookup[ dt ].m_sizeInBytes < sizeof(CLR_INT32)) + { + dt = dtDst; + fCanAssign = true; + } + } + } + + if(fCanAssign) + { + blk->ChangeDataType( dt ); + memcpy( (void*)&blk->NumericByRef().u1, builtinValue, sizeof(CLR_UINT64) ); + } + } + + return fCanAssign; +} + +static CLR_RT_HeapBlock* GetScratchPad_Helper( int idx ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_HeapBlock_Array* array = g_CLR_RT_ExecutionEngine.m_scratchPadArray; + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock ref; + + tmp.SetObjectReference( array ); + + if(SUCCEEDED(ref.InitializeArrayReference( tmp, idx ))) + { + return (CLR_RT_HeapBlock*)array->GetElement( idx ); + } + + return NULL; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Value_ResizeScratchPad( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_ResizeScratchPad* cmd = (CLR_DBG_Commands::Debugging_Value_ResizeScratchPad*)msg->m_payload; + CLR_RT_HeapBlock ref; + bool fRes = true; + + if(cmd->m_size == 0) + { + g_CLR_RT_ExecutionEngine.m_scratchPadArray = NULL; + } + else + { + if(SUCCEEDED(CLR_RT_HeapBlock_Array::CreateInstance( ref, cmd->m_size, g_CLR_RT_WellKnownTypes.m_Object ))) + { + CLR_RT_HeapBlock_Array* pOld = g_CLR_RT_ExecutionEngine.m_scratchPadArray; + CLR_RT_HeapBlock_Array* pNew = ref.DereferenceArray(); + + if(pOld) + { + memcpy( pNew->GetFirstElement(), pOld->GetFirstElement(), sizeof(CLR_RT_HeapBlock) * __min( pNew->m_numOfElements, pOld->m_numOfElements ) ); + } + + g_CLR_RT_ExecutionEngine.m_scratchPadArray = pNew; + } + else + { + fRes = false; + } + } + + WP_ReplyToCommand(msg, fRes, false, NULL, 0); + + return false; +} + +bool CLR_DBG_Debugger::Debugging_Value_GetStack( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_GetStack* cmd = (CLR_DBG_Commands::Debugging_Value_GetStack*)msg->m_payload; + CLR_RT_StackFrame* call; + bool isInline = false; + + if((call = g_CLR_DBG_Debugger->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { + CLR_RT_HeapBlock* array; + CLR_UINT32 num; +#ifndef CLR_NO_IL_INLINE + CLR_RT_MethodDef_Instance& md = isInline ? call->m_inlineFrame->m_frame.m_call : call->m_call; +#else + CLR_RT_MethodDef_Instance& md = call->m_call; +#endif + + switch(cmd->m_kind) + { + case CLR_DBG_Commands::Debugging_Value_GetStack::c_Argument: +#ifndef CLR_NO_IL_INLINE + array = isInline ? call->m_inlineFrame->m_frame.m_args : call->m_arguments; + num = isInline ? md.m_target->numArgs : md.m_target->numArgs; +#else + array = call->m_arguments; + num = call->m_call.m_target->numArgs; +#endif + break; + + case CLR_DBG_Commands::Debugging_Value_GetStack::c_Local: +#ifndef CLR_NO_IL_INLINE + array = isInline ? call->m_inlineFrame->m_frame.m_locals : call->m_locals; + num = isInline ? md.m_target->numLocals : md.m_target->numLocals; +#else + array = call->m_locals; + num = call->m_call.m_target->numLocals; +#endif + break; + + case CLR_DBG_Commands::Debugging_Value_GetStack::c_EvalStack: +#ifndef CLR_NO_IL_INLINE + array = isInline ? call->m_inlineFrame->m_frame.m_evalStack : call->m_evalStack; + num = isInline ? (CLR_UINT32)(call->m_evalStack - call->m_inlineFrame->m_frame.m_evalStack) : (CLR_UINT32)call->TopValuePosition(); +#else + array = call->m_evalStack; + num = (CLR_UINT32)call->TopValuePosition(); +#endif + break; + + default: + return false; + } + + if(cmd->m_index >= num) return false; + + CLR_RT_HeapBlock* blk = &array[ cmd->m_index ]; + CLR_RT_HeapBlock* reference = NULL; + CLR_RT_HeapBlock tmp; + CLR_RT_TypeDef_Instance* pTD = NULL; + CLR_RT_TypeDef_Instance td; + + if(cmd->m_kind != CLR_DBG_Commands::Debugging_Value_GetStack::c_EvalStack && IsBlockEnumMaybe( blk )) + { + CLR_UINT32 iElement = cmd->m_index; + CLR_RT_SignatureParser parser; + CLR_RT_SignatureParser::Element res; + CLR_RT_TypeDescriptor desc; + + if(cmd->m_kind == CLR_DBG_Commands::Debugging_Value_GetStack::c_Argument) + { + parser.Initialize_MethodSignature( md.m_assm, md.m_target ); + + iElement++; // Skip the return value, always at the head of the signature. + + if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) + { + if(iElement == 0) return false; // The requested argument is the "this" argument, it can never be a primitive. + + iElement--; + } + } + else + { + parser.Initialize_MethodLocals( md.m_assm, md.m_target ); + } + + do + { + parser.Advance( res ); + } + while(iElement--); + + // + // Arguments to a methods come from the eval stack and we don't fix up the eval stack for each call. + // So some arguments have the wrong datatype, since an eval stack push always promotes to 32 bits. + // + if(c_CLR_RT_DataTypeLookup[ blk->DataType() ].m_sizeInBytes == sizeof(CLR_INT32) && + c_CLR_RT_DataTypeLookup[ res.m_dt ].m_sizeInBytes < sizeof(CLR_INT32) ) + { + tmp.Assign ( *blk ); + tmp.ChangeDataType( res.m_dt ); + + reference = blk; blk = &tmp; + } + + // + // Check for enum. + // + desc.InitializeFromType( res.m_cls ); + + if(desc.m_handlerCls.m_target->IsEnum()) + { + td = desc.m_handlerCls; pTD = &td; + } + } + + return g_CLR_DBG_Debugger->GetValue( msg, blk, reference, pTD ); + } + + return false; +} + +bool CLR_DBG_Debugger::Debugging_Value_GetField( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_GetField* cmd = (CLR_DBG_Commands::Debugging_Value_GetField*)msg->m_payload; + CLR_RT_HeapBlock* blk = cmd->m_heapblock; + CLR_RT_HeapBlock* reference = NULL; + CLR_RT_HeapBlock tmp; + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDef_Instance td; + CLR_RT_TypeDef_Instance* pTD = NULL; + CLR_RT_FieldDef_Instance inst; + CLR_UINT32 offset; + + if(blk != NULL && cmd->m_offset > 0) + { + if(FAILED(desc.InitializeFromObject( *blk ))) return false; + + td = desc.m_handlerCls; + offset = cmd->m_offset - 1; + + while(true) + { + CLR_UINT32 iFields = td.m_target->iFields_Num; + CLR_UINT32 totalFields = td.CrossReference().m_totalFields; + CLR_UINT32 dFields = totalFields - iFields; + + if(offset >= dFields) + { + offset -= dFields; + break; + } + + if(!td.SwitchToParent()) return false; + } + + cmd->m_fd.Set( td.Assembly(), td.m_target->iFields_First + offset ); + } + + if(!g_CLR_DBG_Debugger->CheckFieldDef( cmd->m_fd, inst )) return false; + + if(blk == NULL) + { + blk = CLR_RT_ExecutionEngine::AccessStaticField( cmd->m_fd ); + } + else + { + if(cmd->m_offset == 0) + { + cmd->m_offset = inst.CrossReference().m_offset; + } + + if(cmd->m_offset == 0) return false; + + switch(blk->DataType()) + { + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + break; + + default: + if(FAILED(blk->EnsureObjectReference( blk ))) return false; + break; + } + + switch(blk->DataType()) + { + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + tmp.SetInteger( (CLR_INT64)blk->NumericByRefConst().s8 ); + reference = blk; blk = &tmp; + break; + + default: + blk = &blk[ cmd->m_offset ]; + break; + } + } + + if(IsBlockEnumMaybe( blk )) + { + if(SUCCEEDED(desc.InitializeFromFieldDefinition( inst ))) + { + if(desc.m_handlerCls.m_target->IsEnum()) + { + pTD = &desc.m_handlerCls; + } + } + } + + return g_CLR_DBG_Debugger->GetValue( msg, blk, reference, pTD ); +} + +bool CLR_DBG_Debugger::Debugging_Value_GetArray( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_GetArray* cmd = (CLR_DBG_Commands::Debugging_Value_GetArray*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* reference = NULL; + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock ref; + CLR_RT_TypeDef_Instance* pTD = NULL; + CLR_RT_TypeDef_Instance td; + + tmp.SetObjectReference( cmd->m_heapblock ); + + if(SUCCEEDED(ref.InitializeArrayReference( tmp, cmd->m_index ))) + { + CLR_RT_HeapBlock_Array* array = ref.Array(); + + if(array->m_fReference) + { + blk = (CLR_RT_HeapBlock*)array->GetElement( cmd->m_index ); + } + else + { + if(FAILED(tmp.LoadFromReference( ref ))) return false; + + blk = &tmp; reference = (CLR_RT_HeapBlock*)-1; + } + + if(IsBlockEnumMaybe( blk )) + { + if(td.InitializeFromIndex( array->ReflectionDataConst().m_data.m_type )) + { + if(td.m_target->IsEnum()) + { + pTD = &td; + } + } + } + } + + return g_CLR_DBG_Debugger->GetValue( msg, blk, reference, pTD ); +} + +bool CLR_DBG_Debugger::Debugging_Value_GetBlock( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_GetBlock* cmd = (CLR_DBG_Commands::Debugging_Value_GetBlock*)msg->m_payload; + CLR_RT_HeapBlock* blk = cmd->m_heapblock; + + return g_CLR_DBG_Debugger->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_GetScratchPad( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_GetScratchPad* cmd = (CLR_DBG_Commands::Debugging_Value_GetScratchPad*)msg->m_payload; + CLR_RT_HeapBlock* blk = GetScratchPad_Helper( cmd->m_idx ); + + return g_CLR_DBG_Debugger->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_SetBlock( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_SetBlock* cmd = (CLR_DBG_Commands::Debugging_Value_SetBlock*)msg->m_payload; + CLR_RT_HeapBlock* blk = cmd->m_heapblock; + + WP_ReplyToCommand(msg, SetBlockHelper( blk, (CLR_DataType)cmd->m_dt, cmd->m_builtinValue ), false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Value_SetArray( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_SetArray* cmd = (CLR_DBG_Commands::Debugging_Value_SetArray*)msg->m_payload; + CLR_RT_HeapBlock_Array* array = cmd->m_heapblock; + CLR_RT_HeapBlock tmp; + bool fSuccess = false; + + tmp.SetObjectReference( cmd->m_heapblock ); + + // + // We can only set values in arrays of primitive types. + // + if(array != NULL && !array->m_fReference) + { + CLR_RT_HeapBlock ref; + + if(SUCCEEDED(ref.InitializeArrayReference( tmp, cmd->m_index ))) + { + if(SUCCEEDED(tmp.LoadFromReference( ref ))) + { + if(SetBlockHelper( &tmp, tmp.DataType(), cmd->m_builtinValue )) + { + if(SUCCEEDED(tmp.StoreToReference( ref, 0 ))) + { + fSuccess = true; + } + } + } + } + } + + WP_ReplyToCommand(msg, fSuccess, false, NULL, 0); + + return true; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Value_AllocateObject( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_AllocateObject* cmd = (CLR_DBG_Commands::Debugging_Value_AllocateObject*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* ptr = GetScratchPad_Helper( cmd->m_index ); + + if(ptr) + { + if(SUCCEEDED(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *ptr, cmd->m_td ))) + { + blk = ptr; + } + } + + return g_CLR_DBG_Debugger->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_AllocateString( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_AllocateString* cmd = (CLR_DBG_Commands::Debugging_Value_AllocateString*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* ptr = GetScratchPad_Helper( cmd->m_index ); + + if(ptr) + { + CLR_RT_HeapBlock_String* str = CLR_RT_HeapBlock_String::CreateInstance( *ptr, cmd->m_size ); + + if(str) + { + char* dst = (char*)str->StringText(); + + // + // Fill the string with spaces, it will be set at a later stage. + // + memset( dst, ' ', cmd->m_size ); dst[ cmd->m_size ] = 0; + + blk = ptr; + } + } + + return g_CLR_DBG_Debugger->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_AllocateArray( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_AllocateArray* cmd = (CLR_DBG_Commands::Debugging_Value_AllocateArray*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* ptr = GetScratchPad_Helper( cmd->m_index ); + + if(ptr) + { + CLR_RT_ReflectionDef_Index reflex; + + reflex.m_kind = REFLECTION_TYPE; + reflex.m_levels = cmd->m_depth; + reflex.m_data.m_type = cmd->m_td; + + if(SUCCEEDED(CLR_RT_HeapBlock_Array::CreateInstance( *ptr, cmd->m_numOfElements, reflex ))) + { + blk = ptr; + } + } + + return g_CLR_DBG_Debugger->GetValue( msg, blk, NULL, NULL ); +} + +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(NANOCLR_PROFILE_NEW) +bool CLR_DBG_Debugger::Profiling_Command( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)&g_scratchDebugger[0]; + CLR_DBG_Commands::Profiling_Command* cmd = (CLR_DBG_Commands::Profiling_Command*)msg->m_payload; + CLR_UINT8 command = cmd->m_command; + + switch(command) + { + case CLR_DBG_Commands::Profiling_Command::c_Command_ChangeConditions: + return dbg->Profiling_ChangeConditions( msg ); + + case CLR_DBG_Commands::Profiling_Command::c_Command_FlushStream: + return dbg->Profiling_FlushStream( msg ); + + default: + return false; + } +} + +bool CLR_DBG_Debugger::Profiling_ChangeConditions( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Commands::Profiling_Command* parent_cmd = (CLR_DBG_Commands::Profiling_Command*)msg->m_payload; + CLR_DBG_Commands::Profiling_ChangeConditions* cmd = (CLR_DBG_Commands::Profiling_ChangeConditions*)&parent_cmd[1]; + + g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions |= cmd->m_set; + g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions &= ~cmd->m_reset; + + CLR_DBG_Commands::Profiling_Command::Reply cmdReply; + + cmdReply.m_raw = g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions; + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + _ASSERTE(FIMPLIES(CLR_EE_PRF_IS(Allocations), CLR_EE_PRF_IS(Enabled))); + _ASSERTE(FIMPLIES(CLR_EE_PRF_IS(Calls) , CLR_EE_PRF_IS(Enabled))); + + if((cmd->m_set & CLR_RT_ExecutionEngine::c_fProfiling_Enabled) != 0) + { + g_CLR_PRF_Profiler.SendMemoryLayout(); + } + + return true; +} + +bool CLR_DBG_Debugger::Profiling_FlushStream( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Commands::Profiling_Command::Reply cmdReply; + + g_CLR_PRF_Profiler.Stream_Flush(); + + cmdReply.m_raw = 0; + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +#endif //#if defined(NANOCLR_PROFILE_NEW) + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +//--// + +struct AnalyzeObject +{ + CLR_RT_HeapBlock* m_ptr; + bool m_fNull; + bool m_fBoxed; + bool m_fCanBeNull; + CLR_RT_TypeDescriptor m_desc; + CLR_RT_HeapBlock m_value; +}; + +static HRESULT AnalyzeObject_Helper( CLR_RT_HeapBlock* ptr, AnalyzeObject& ao ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + if(ptr && ptr->DataType() == DATATYPE_BYREF) ptr = ptr->Dereference(); + + ao.m_ptr = ptr; + + if(ptr == NULL || (ptr->DataType() == DATATYPE_OBJECT && ptr->Dereference() == NULL)) + { + ao.m_fNull = true; + ao.m_fBoxed = false; + ao.m_fCanBeNull = true; + } + else + { + NANOCLR_CHECK_HRESULT(ao.m_desc.InitializeFromObject( *ptr )); + + ao.m_fNull = false; + ao.m_fBoxed = (ptr->DataType() == DATATYPE_OBJECT && ptr->Dereference()->IsBoxed()); + + switch(ao.m_desc.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask2 & ~CLR_RT_DataTypeLookup::c_SemanticMask) + { + case CLR_RT_DataTypeLookup::c_Array: + case CLR_RT_DataTypeLookup::c_ArrayList: + ao.m_fCanBeNull = true; + break; + default: + { + switch(ao.m_desc.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask) + { + case CLR_RT_DataTypeLookup::c_Primitive: + case CLR_RT_DataTypeLookup::c_ValueType: + case CLR_RT_DataTypeLookup::c_Enum: + ao.m_fCanBeNull = ao.m_fBoxed || (ao.m_desc.m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_String.m_data); + break; + + default: + ao.m_fCanBeNull = true; + break; + } + + break; + } + } + } + + NANOCLR_NOCLEANUP(); +} + +static HRESULT Assign_Helper( CLR_RT_HeapBlock* blkDst, CLR_RT_HeapBlock* blkSrc ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_HEADER(); + + AnalyzeObject aoDst; + AnalyzeObject aoSrc; + CLR_RT_HeapBlock srcVal; srcVal.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( srcVal ); + + NANOCLR_CHECK_HRESULT(AnalyzeObject_Helper( blkDst, aoDst )); + NANOCLR_CHECK_HRESULT(AnalyzeObject_Helper( blkSrc, aoSrc )); + + if(aoSrc.m_fNull) + { + if(aoDst.m_fCanBeNull == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_CHECK_HRESULT(srcVal.StoreToReference( *blkDst, 0 )); + } + else + { + NANOCLR_CHECK_HRESULT(srcVal.LoadFromReference( *blkSrc )); + + if(aoDst.m_fNull) + { + if(aoSrc.m_fCanBeNull == false) + { + NANOCLR_CHECK_HRESULT(srcVal.PerformBoxing( aoSrc.m_desc.m_handlerCls )); + } + + blkDst->Assign( srcVal ); + } + else + { + if(srcVal.IsAValueType()) + { + if(blkDst->IsAValueType() == false) + { + NANOCLR_CHECK_HRESULT(srcVal.PerformBoxing( aoSrc.m_desc.m_handlerCls )); + } + } + else + { + if(blkDst->IsAValueType() == true) + { + NANOCLR_CHECK_HRESULT(srcVal.PerformUnboxing( aoSrc.m_desc.m_handlerCls )); + } + } + + NANOCLR_CHECK_HRESULT(blkDst->Reassign( srcVal )); + } + } + + NANOCLR_NOCLEANUP(); +} + + +bool CLR_DBG_Debugger::Debugging_Value_Assign( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Value_Assign* cmd = (CLR_DBG_Commands::Debugging_Value_Assign*)msg->m_payload; + CLR_RT_HeapBlock* blkDst = cmd->m_heapblockDst; + CLR_RT_HeapBlock* blkSrc = cmd->m_heapblockSrc; + + if(blkDst && FAILED(Assign_Helper( blkDst, blkSrc ))) + { + blkDst = NULL; + } + + return g_CLR_DBG_Debugger->GetValue( msg, blkDst, NULL, NULL ); +} + +//--// + +bool CLR_DBG_Debugger::Debugging_TypeSys_Assemblies( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_RT_Assembly_Index assemblies[ CLR_RT_TypeSystem::c_MaxAssemblies ]; + int num = 0; + + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + assemblies[ num++ ].Set( pASSM->m_idx ); + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + WP_ReplyToCommand( msg, true, false, assemblies, sizeof(CLR_RT_Assembly_Index) * num ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_TypeSys_AppDomains( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +#if defined(NANOCLR_APPDOMAINS) + + int num = 0; + CLR_UINT32 appDomainIDs[ 256 ]; + + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain, appDomain, g_CLR_RT_ExecutionEngine.m_appDomains) + { + appDomainIDs[ num++ ] = appDomain->m_id; + + if(num >= ARRAYSIZE(appDomainIDs)) break; + } + NANOCLR_FOREACH_NODE_END(); + + WP_ReplyToCommand( msg, true, false, appDomainIDs, sizeof(CLR_UINT32) * num ); + + return true; +#else + (void)msg; + return false; +#endif +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Resolve_AppDomain( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +#if defined(NANOCLR_APPDOMAINS) + + CLR_DBG_Commands::Debugging_Resolve_AppDomain* cmd = (CLR_DBG_Commands::Debugging_Resolve_AppDomain*)msg->m_payload; + CLR_RT_AppDomain* appDomain = g_CLR_DBG_Debugger->GetAppDomainFromID( cmd->m_id ); + CLR_UINT32 numAssemblies = 0; + CLR_DBG_Commands::Debugging_Resolve_AppDomain::Reply* cmdReply; + CLR_UINT8 buf[ sizeof(CLR_DBG_Commands::Debugging_Resolve_AppDomain::Reply) + sizeof(CLR_RT_Assembly_Index)*CLR_RT_TypeSystem::c_MaxAssemblies ]; + size_t count; + const char* name; + CLR_RT_Assembly_Index* pAssemblyIndex; + + if(appDomain) + { + cmdReply = (CLR_DBG_Commands::Debugging_Resolve_AppDomain::Reply*)&buf; + + cmdReply->m_state = appDomain->m_state; + + name = appDomain->m_strName->StringText(); + count = __min( hal_strlen_s( name ) + 1, sizeof(cmdReply->m_szName) - 1 ); + + hal_strncpy_s( cmdReply->m_szName, ARRAYSIZE(cmdReply->m_szName), name, count ); + + pAssemblyIndex = (CLR_RT_Assembly_Index*)(&cmdReply->m_assemblies); + + NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(appDomain) + { + pAssemblyIndex->Set( pASSM->m_idx ); + pAssemblyIndex++; + numAssemblies++; + } + NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END(); + + WP_ReplyToCommand( msg, true, false, cmdReply, sizeof(*cmdReply) + sizeof(CLR_RT_Assembly_Index) * (numAssemblies - 1) ); + } + else + { + WP_ReplyToCommand(msg, false, false, NULL, 0); + } + + return true; +#else + (void)msg; + return false; +#endif +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Assembly( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Resolve_Assembly* cmd = (CLR_DBG_Commands::Debugging_Resolve_Assembly*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Assembly::Reply cmdReply; + CLR_RT_Assembly* assm = g_CLR_DBG_Debugger->IsGoodAssembly( cmd->m_idx.Assembly() ); + + if(assm) + { +#if defined(_WIN32) + //append path + if(assm->m_strPath != NULL) + { + sprintf_s( cmdReply.m_szName, ARRAYSIZE(cmdReply.m_szName), "%s,%s", assm->m_szName, assm->m_strPath->c_str() ); + } + else +#endif + { + hal_strncpy_s( cmdReply.m_szName, ARRAYSIZE(cmdReply.m_szName), assm->m_szName, MAXSTRLEN(cmdReply.m_szName) ); + } + + cmdReply.m_flags = assm->m_flags; + cmdReply.m_version = assm->m_header->version; + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Type( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Resolve_Type* cmd = (CLR_DBG_Commands::Debugging_Resolve_Type*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Type::Reply cmdReply; + CLR_RT_TypeDef_Instance inst; + + if(g_CLR_DBG_Debugger->CheckTypeDef( cmd->m_td, inst )) + { + char* szBuffer = cmdReply.m_type; + size_t iBuffer = MAXSTRLEN(cmdReply.m_type); + + if(SUCCEEDED(g_CLR_RT_TypeSystem.BuildTypeName( inst, szBuffer, iBuffer ))) + { + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Field( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Resolve_Field* cmd = (CLR_DBG_Commands::Debugging_Resolve_Field*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Field::Reply cmdReply; + CLR_RT_FieldDef_Instance inst; + + if(g_CLR_DBG_Debugger->CheckFieldDef( cmd->m_fd, inst )) + { + char* szBuffer = cmdReply.m_name; + size_t iBuffer = MAXSTRLEN(cmdReply.m_name); + + if(SUCCEEDED(g_CLR_RT_TypeSystem.BuildFieldName( inst, szBuffer, iBuffer ))) + { + CLR_RT_TypeDef_Instance instClass; instClass.InitializeFromField( inst ); + + cmdReply.m_td = instClass; + cmdReply.m_index = inst.CrossReference().m_offset; + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Method( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Resolve_Method* cmd = (CLR_DBG_Commands::Debugging_Resolve_Method*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Method::Reply cmdReply; + CLR_RT_MethodDef_Instance inst; + CLR_RT_TypeDef_Instance instOwner; + + if(g_CLR_DBG_Debugger->CheckMethodDef( cmd->m_md, inst ) && instOwner.InitializeFromMethod( inst )) + { + char* szBuffer = cmdReply.m_method; + size_t iBuffer = MAXSTRLEN(cmdReply.m_method); + + cmdReply.m_td = instOwner; + + CLR_SafeSprintf( szBuffer, iBuffer, "%s", inst.m_assm->GetString( inst.m_target->name ) ); + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_VirtualMethod( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Resolve_VirtualMethod* cmd = (CLR_DBG_Commands::Debugging_Resolve_VirtualMethod*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_VirtualMethod::Reply cmdReply; + CLR_RT_TypeDef_Index cls; + CLR_RT_MethodDef_Index md; + + cmdReply.m_md.Clear(); + + if(SUCCEEDED(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( *cmd->m_obj, cls ))) + { + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, cmd->m_md, md )) + { + cmdReply.m_md = md; + } + } + + WP_ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + + +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +//--// + + +bool CLR_DBG_Debugger::Debugging_Deployment_Status( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Deployment_Status::Reply* cmdReply; + CLR_UINT32 totLength; + CLR_UINT32 deploySectorsNum = 0; + CLR_UINT32 deploySectorStart = 0; + CLR_UINT32 deployLength = 0; + + // find the first device in list with DEPLOYMENT blocks + if (m_deploymentStorageDevice != NULL) + { + BlockStorageStream stream; + + if(BlockStorageStream_InitializeWithBlockStorageDevice(&stream, BlockUsage_DEPLOYMENT, m_deploymentStorageDevice )) + { + do + { + if(deploySectorsNum == 0) + { + deploySectorStart = BlockStorageStream_CurrentAddress(&stream); + } + deployLength += stream.Length; + deploySectorsNum ++; + } + while(BlockStorageStream_NextStream(&stream) && stream.BaseAddress == (deploySectorStart + deployLength)); + } + + totLength = sizeof(CLR_DBG_Commands::Debugging_Deployment_Status::Reply); + + cmdReply = (CLR_DBG_Commands::Debugging_Deployment_Status::Reply*)CLR_RT_Memory::Allocate( totLength, true ); + + if(!cmdReply) return false; + + CLR_RT_Memory::ZeroFill( cmdReply, totLength ); + + cmdReply->EntryPoint = g_CLR_RT_TypeSystem.m_entryPoint.m_data; + cmdReply->StorageStart = deploySectorStart; + cmdReply->StorageLength = deployLength; + + WP_ReplyToCommand( msg, true, false, cmdReply, totLength ); + + CLR_RT_Memory::Release( cmdReply ); + + return true; + } + else + { + WP_ReplyToCommand( msg, false, false, NULL, 0 ); + return false; + } +} + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +bool CLR_DBG_Debugger::Debugging_Info_SetJMC_Method( const CLR_RT_MethodDef_Index& idx, bool fJMC ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_MethodDef_Instance inst; + + if(!CheckMethodDef( idx, inst ) ) return false; + if(inst.m_target->RVA == CLR_EmptyIndex) return false; + + inst.DebuggingInfo().SetJMC( fJMC ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Info_SetJMC_Type( const CLR_RT_TypeDef_Index& idx, bool fJMC ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + const CLR_RECORD_TYPEDEF* td; + CLR_RT_TypeDef_Instance inst; + int totMethods; + CLR_RT_MethodDef_Index md; + + if(!CheckTypeDef( idx, inst )) return false; + + td = inst.m_target; + totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num; + + for(int i=0; imethods_First + i ); + + Debugging_Info_SetJMC_Method( md, fJMC ); + } + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Info_SetJMC( WP_Message* msg) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Commands::Debugging_Info_SetJMC* cmd = (CLR_DBG_Commands::Debugging_Info_SetJMC*)msg->m_payload; + bool fJMC = (cmd->m_fIsJMC != 0); + + switch(cmd->m_kind) + { + case REFLECTION_ASSEMBLY: + { + CLR_RT_Assembly* assm = g_CLR_DBG_Debugger->IsGoodAssembly( cmd->m_data.m_assm.Assembly() ); + + if(!assm) return false; + + for(int i=0; im_pTablesSize[ TBL_TypeDef ]; i++) + { + CLR_RT_TypeDef_Index idx; + + idx.Set( cmd->m_data.m_assm.Assembly(), i ); + + g_CLR_DBG_Debugger->Debugging_Info_SetJMC_Type( idx, fJMC ); + } + + return true; + } + + case REFLECTION_TYPE: + return g_CLR_DBG_Debugger->Debugging_Info_SetJMC_Type( cmd->m_data.m_type, fJMC ); + + case REFLECTION_METHOD: + return g_CLR_DBG_Debugger->Debugging_Info_SetJMC_Method( cmd->m_data.m_method, fJMC ); + + default: + return false; + } +} + +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger.h b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.h new file mode 100644 index 00000000..5c82eff7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.h @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _DEBUGGER_H_ +#define _DEBUGGER_H_ + +// enum with CLR debugging commands +// backwards compatible with .NETMF +typedef enum CLR_DBG_Commands_Debugging +{ + CLR_DBG_Commands_c_Debugging_Execution_BasePtr = 0x00020000, // Returns the pointer for the ExecutionEngine object. + CLR_DBG_Commands_c_Debugging_Execution_ChangeConditions = 0x00020001, // Sets/resets the state of the debugger. + CLR_DBG_Commands_c_Debugging_Execution_SecurityKey = 0x00020002, // Sets security key. + CLR_DBG_Commands_c_Debugging_Execution_Unlock = 0x00020003, // Unlock the low-level command, for mfg. test programs. + CLR_DBG_Commands_c_Debugging_Execution_Allocate = 0x00020004, // Permanently allocate some memory. + CLR_DBG_Commands_c_Debugging_Execution_Breakpoints = 0x00020005, // Sets breakpoints. + CLR_DBG_Commands_c_Debugging_Execution_BreakpointHit = 0x00020006, // Notification that a breakpoint was hit. + CLR_DBG_Commands_c_Debugging_Execution_BreakpointStatus = 0x00020007, // Queries last breakpoint hit. + CLR_DBG_Commands_c_Debugging_Execution_QueryCLRCapabilities = 0x00020008, // Queries capabilities of the CLR. + CLR_DBG_Commands_c_Debugging_Execution_SetCurrentAppDomain = 0x00020009, // Sets the current AppDomain. This is required before + // performing certain debugging operations, such as + // accessing a static field, or doing function evaluation, + + CLR_DBG_Commands_c_Debugging_Thread_Create = 0x00020010, // OBSOLETE - Use c_Debugging_Thread_CreateEx instead. + CLR_DBG_Commands_c_Debugging_Thread_List = 0x00020011, // Lists the active/waiting threads. + CLR_DBG_Commands_c_Debugging_Thread_Stack = 0x00020012, // Lists the call stack for a thread. + CLR_DBG_Commands_c_Debugging_Thread_Kill = 0x00020013, // Kills a thread. + CLR_DBG_Commands_c_Debugging_Thread_Suspend = 0x00020014, // Suspends the execution of a thread. + CLR_DBG_Commands_c_Debugging_Thread_Resume = 0x00020015, // Resumes the execution of a thread. + CLR_DBG_Commands_c_Debugging_Thread_GetException = 0x00020016, // Gets the current exception. + CLR_DBG_Commands_c_Debugging_Thread_Unwind = 0x00020017, // Unwinds to given stack frame. + CLR_DBG_Commands_c_Debugging_Thread_CreateEx = 0x00020018, // Creates a new thread but Thread.CurrentThread will return the identity of the passed thread. + CLR_DBG_Commands_c_Debugging_Thread_Get = 0x00021000, // Gets the current thread. + + CLR_DBG_Commands_c_Debugging_Stack_Info = 0x00020020, // Gets more info on a stack frame. + CLR_DBG_Commands_c_Debugging_Stack_SetIP = 0x00020021, // Sets the IP on a given thread. + + CLR_DBG_Commands_c_Debugging_Value_ResizeScratchPad = 0x00020030, // Resizes the scratchpad area. + CLR_DBG_Commands_c_Debugging_Value_GetStack = 0x00020031, // Reads a value from the stack frame. + CLR_DBG_Commands_c_Debugging_Value_GetField = 0x00020032, // Reads a value from an object's field. + CLR_DBG_Commands_c_Debugging_Value_GetArray = 0x00020033, // Reads a value from an array's element. + CLR_DBG_Commands_c_Debugging_Value_GetBlock = 0x00020034, // Reads a value from a heap block. + CLR_DBG_Commands_c_Debugging_Value_GetScratchPad = 0x00020035, // Reads a value from the scratchpad area. + CLR_DBG_Commands_c_Debugging_Value_SetBlock = 0x00020036, // Writes a value to a heap block. + CLR_DBG_Commands_c_Debugging_Value_SetArray = 0x00020037, // Writes a value to an array's element. + CLR_DBG_Commands_c_Debugging_Value_AllocateObject = 0x00020038, // Creates a new instance of an object. + CLR_DBG_Commands_c_Debugging_Value_AllocateString = 0x00020039, // Creates a new instance of a string. + CLR_DBG_Commands_c_Debugging_Value_AllocateArray = 0x0002003A, // Creates a new instance of an array. + CLR_DBG_Commands_c_Debugging_Value_Assign = 0x0002003B, // Assigns a value to another value. + + CLR_DBG_Commands_c_Debugging_TypeSys_Assemblies = 0x00020040, // Lists all the assemblies in the system. + CLR_DBG_Commands_c_Debugging_TypeSys_AppDomains = 0x00020044, // Lists all the AppDomans loaded. + + CLR_DBG_Commands_c_Debugging_Resolve_Assembly = 0x00020050, // Resolves an assembly. + CLR_DBG_Commands_c_Debugging_Resolve_Type = 0x00020051, // Resolves a type to a string. + CLR_DBG_Commands_c_Debugging_Resolve_Field = 0x00020052, // Resolves a field to a string. + CLR_DBG_Commands_c_Debugging_Resolve_Method = 0x00020053, // Resolves a method to a string. + CLR_DBG_Commands_c_Debugging_Resolve_VirtualMethod = 0x00020054, // Resolves a virtual method to the actual implementation. + CLR_DBG_Commands_c_Debugging_Resolve_AppDomain = 0x00020055, // Resolves an AppDomain to it's name, and list its loaded assemblies. + + + CLR_DBG_Commands_c_Debugging_MFUpdate_Start = 0x00020056, // + CLR_DBG_Commands_c_Debugging_MFUpdate_AddPacket = 0x00020057, // + CLR_DBG_Commands_c_Debugging_MFUpdate_Install = 0x00020058, // + CLR_DBG_Commands_c_Debugging_MFUpdate_AuthCommand = 0x00020059, // + CLR_DBG_Commands_c_Debugging_MFUpdate_Authenticate = 0x00020060, // + CLR_DBG_Commands_c_Debugging_MFUpdate_GetMissingPkts = 0x00020061, // + + CLR_DBG_Commands_c_Debugging_UpgradeToSsl = 0x00020069, // + + //--// + + CLR_DBG_Commands_c_Debugging_Button_Report = 0x00020080, // Reports a button press/release. + CLR_DBG_Commands_c_Debugging_Button_Inject = 0x00020081, // Injects a button press/release. + + CLR_DBG_Commands_c_Debugging_Deployment_Status = 0x000200B0, // Returns entryPoint and boundary of deployment area. + + CLR_DBG_Commands_c_Debugging_Info_SetJMC = 0x000200C0, // Sets code to be flagged as JMC (Just my code). + + CLR_DBG_Commands_c_Profiling_Command = 0x00030000, // Various incoming commands regarding profiling + CLR_DBG_Commands_c_Profiling_Stream = 0x00030001, // Stream for MFProfiler information. + +}CLR_DBG_Commands_Debugging; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.WireProtocol.AccessMemoryErrorCodes (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// enum with AccessMemoryErrorCodes +typedef enum AccessMemoryErrorCodes +{ + AccessMemoryErrorCode_NoError = 0x0000, // no error + AccessMemoryErrorCode_PermissionDenied = 0x0010, // permission denied to execute operation + AccessMemoryErrorCode_FailedToAllocateReadBuffer = 0x0020, // failed to allocate buffer for read operation. better check heap + AccessMemoryErrorCode_RequestedOperationFailed = 0x0030, // the requested operation failed + +}AccessMemoryErrorCodes; + +#endif //_DEBUGGER_H_ diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj new file mode 100644 index 00000000..281ab691 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj @@ -0,0 +1,169 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + {58e950cc-2ff6-423c-b006-a70a19272f20} + false + false + + + {6dabcbf1-245a-4e76-bd36-8bc300c7dd82} + + + + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00} + Win32Proj + Debugger + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj.filters new file mode 100644 index 00000000..808f2bd0 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger_full.cpp b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_full.cpp new file mode 100644 index 00000000..9ab70cb0 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_full.cpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include + +#define DEFINE_CMD(cmd) { CLR_DBG_Debugger::Debugging_##cmd, CLR_DBG_Commands::c_Debugging_##cmd } +#define DEFINE_CMD2(cmd) { CLR_DBG_Debugger::Monitor_##cmd , CLR_DBG_Commands::c_Monitor_##cmd } +#define DEFINE_CMD3(cmd) { &CLR_DBG_Debugger::Profiling_##cmd, CLR_DBG_Commands::c_Profiling_##cmd } + +const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Request[] = +{ + DEFINE_CMD(Execution_QueryCLRCapabilities), + DEFINE_CMD2(Ping ), + DEFINE_CMD2(ReadMemory ), + DEFINE_CMD2(WriteMemory), + DEFINE_CMD2(CheckMemory), + DEFINE_CMD2(EraseMemory), + DEFINE_CMD2(QueryConfiguration), + DEFINE_CMD2(UpdateConfiguration), + // + DEFINE_CMD2(Execute ), + DEFINE_CMD2(Reboot ), + DEFINE_CMD2(MemoryMap ), + DEFINE_CMD2(FlashSectorMap), + DEFINE_CMD2(DeploymentMap), + // + DEFINE_CMD(Execution_BasePtr ), + DEFINE_CMD(Execution_ChangeConditions), + // + DEFINE_CMD(Execution_Allocate ), + + DEFINE_CMD(UpgradeToSsl), + + + + + + + + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + DEFINE_CMD(Execution_SetCurrentAppDomain), + DEFINE_CMD(Execution_Breakpoints ), + DEFINE_CMD(Execution_BreakpointStatus ), + // + DEFINE_CMD(Thread_CreateEx ), + DEFINE_CMD(Thread_List ), + DEFINE_CMD(Thread_Stack ), + DEFINE_CMD(Thread_Kill ), + DEFINE_CMD(Thread_Suspend ), + DEFINE_CMD(Thread_Resume ), + DEFINE_CMD(Thread_GetException ), + DEFINE_CMD(Thread_Unwind ), + DEFINE_CMD(Thread_Get ), + // + DEFINE_CMD(Stack_Info ), + DEFINE_CMD(Stack_SetIP ), + // + DEFINE_CMD(Value_ResizeScratchPad ), + DEFINE_CMD(Value_GetStack ), + DEFINE_CMD(Value_GetField ), + DEFINE_CMD(Value_GetArray ), + DEFINE_CMD(Value_GetBlock ), + DEFINE_CMD(Value_GetScratchPad ), + DEFINE_CMD(Value_SetBlock ), + DEFINE_CMD(Value_SetArray ), + DEFINE_CMD(Value_AllocateObject ), + DEFINE_CMD(Value_AllocateString ), + DEFINE_CMD(Value_AllocateArray ), + DEFINE_CMD(Value_Assign ), + // + DEFINE_CMD(TypeSys_Assemblies ), + DEFINE_CMD(TypeSys_AppDomains ), + // + DEFINE_CMD(Resolve_AppDomain ), + DEFINE_CMD(Resolve_Assembly ), + DEFINE_CMD(Resolve_Type ), + DEFINE_CMD(Resolve_Field ), + DEFINE_CMD(Resolve_Method ), + DEFINE_CMD(Resolve_VirtualMethod ), +#endif + // +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + DEFINE_CMD(Deployment_Status ), + DEFINE_CMD(Info_SetJMC ), +#endif + // +#if defined(NANOCLR_PROFILE_NEW) + DEFINE_CMD3(Command), +#endif + // +}; + +const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Reply[] = +{ + DEFINE_CMD2(Ping), +}; + +#undef DEFINE_CMD +#undef DEFINE_CMD2 +#undef DEFINE_CMD3 + +const CLR_UINT32 c_Debugger_Lookup_Request_count = ARRAYSIZE(c_Debugger_Lookup_Request); +const CLR_UINT32 c_Debugger_Lookup_Reply_count = ARRAYSIZE(c_Debugger_Lookup_Reply); + diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger_minimal.cpp b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_minimal.cpp new file mode 100644 index 00000000..c63267cc --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_minimal.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include + +#define DEFINE_CMD(cmd) { CLR_DBG_Debugger::Debugging_##cmd, CLR_DBG_Commands::c_Debugging_##cmd } +#define DEFINE_CMD2(cmd) { CLR_DBG_Debugger::Monitor_##cmd , CLR_DBG_Commands::c_Monitor_##cmd } + +const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Request[] = +{ + DEFINE_CMD2(Ping ), + DEFINE_CMD2(Reboot ), + DEFINE_CMD(Execution_QueryCLRCapabilities), + + DEFINE_CMD2(ReadMemory ), + DEFINE_CMD2(WriteMemory), + DEFINE_CMD2(EraseMemory), + DEFINE_CMD2(QueryConfiguration), + DEFINE_CMD2(UpdateConfiguration), + // + DEFINE_CMD2(Execute ), + DEFINE_CMD2(MemoryMap ), + DEFINE_CMD2(FlashSectorMap), + + DEFINE_CMD(UpgradeToSsl), + + + + + + + +}; + +const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Reply[] = +{ + DEFINE_CMD2(Ping), +}; + +#undef DEFINE_CMD +#undef DEFINE_CMD2 + +const CLR_UINT32 c_Debugger_Lookup_Request_count = ARRAYSIZE(c_Debugger_Lookup_Request); +const CLR_UINT32 c_Debugger_Lookup_Reply_count = ARRAYSIZE(c_Debugger_Lookup_Reply); diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.cpp b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.cpp new file mode 100644 index 00000000..13df702f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.cpp @@ -0,0 +1,105 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak void CLR_DBG_Debugger::Debugger_WaitForCommands() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +__nfweak void CLR_DBG_Debugger::PurgeCache() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +__nfweak HRESULT CLR_DBG_Debugger::CreateInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + g_CLR_DBG_Debugger = (CLR_DBG_Debugger*)&g_scratchDebugger[0]; + NANOCLR_SYSTEM_STUB_RETURN(); +} + +//--// + +__nfweak HRESULT CLR_DBG_Debugger::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + NANOCLR_SYSTEM_STUB_RETURN(); +} + +__nfweak void CLR_DBG_Debugger::BroadcastEvent( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ) +{ + (void)cmd; + (void)payloadSize; + (void)payload; + (void)flags; + + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +__nfweak void NFReleaseInfo::Init( + NFReleaseInfo& NFReleaseInfo, + unsigned short int major, + unsigned short int minor, + unsigned short int build, + unsigned short int revision, + const char *info, + size_t infoLen, + const char *target, + size_t targetLen, + const char *platform, + size_t platformLen) +{ + size_t len; + + NFVersion::Init( NFReleaseInfo.Version, major, minor, build, revision ); + + // better set these to empty strings, in case there is nothing to fill in + NFReleaseInfo.InfoString[ 0 ] = 0; + NFReleaseInfo.TargetName[ 0 ] = 0; + NFReleaseInfo.PlatformName[ 0 ] = 0; + + // fill each one, if it was provided + if (NULL != info) + { + len = MIN(infoLen, sizeof(NFReleaseInfo.InfoString) - 1); + memcpy(NFReleaseInfo.InfoString, info, len); + NFReleaseInfo.InfoString[len] = 0; + } + + if (NULL != target) + { + len = MIN(targetLen, sizeof(NFReleaseInfo.TargetName) - 1); + memcpy(NFReleaseInfo.TargetName, target, len); + NFReleaseInfo.TargetName[len] = 0; + } + + if (NULL != platform) + { + len = MIN(platformLen, sizeof(NFReleaseInfo.PlatformName) - 1); + memcpy(NFReleaseInfo.PlatformName, platform, len); + NFReleaseInfo.PlatformName[len] = 0; + } +} + +__nfweak bool SOCKETS_DbgInitialize( int ComPortNum ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + (void)ComPortNum; + return true; +} + +__nfweak bool SOCKETS_DbgUninitialize( int ComPortNum ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + (void)ComPortNum; + return true; +} diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj new file mode 100644 index 00000000..0bc8b206 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82} + Win32Proj + Debugger_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj.filters new file mode 100644 index 00000000..3397cd3f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Debugger/Debugger_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj new file mode 100644 index 00000000..1aaf7502 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B} + Win32Proj + Diagnostics + 10.0.17763.0 + Diagnostics + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj.filters new file mode 100644 index 00000000..b2219695 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics-vs2019.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.h b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.h new file mode 100644 index 00000000..aabf7238 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include +//#include +//#include +//#include +//#include + +#include +#if !defined(_WIN32) +#include +#endif // !defined(_WIN32) +//#include + diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj new file mode 100644 index 00000000..cb2c02bd --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B} + Win32Proj + Diagnostics + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj.filters new file mode 100644 index 00000000..b2219695 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.cpp b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.cpp new file mode 100644 index 00000000..cfb883d5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.cpp @@ -0,0 +1,561 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +__nfweak void CLR_Debug::RedirectToString( std::string* str ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +__nfweak HRESULT NANOCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, const char* szFunc, const char* szFile, int line ) +{ + (void)szFunc; + (void)szFile; + (void)line; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return hr; +} + +__nfweak bool CLR_SafeSprintfV( char*& szBuffer, size_t& iBuffer, const char* format, va_list arg ) +{ + (void)szBuffer; + (void)iBuffer; + (void)format; + (void)arg; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + + return FALSE; +} + +__nfweak bool CLR_SafeSprintf( char*& szBuffer, size_t& iBuffer, const char* format, ... ) +{ + (void)szBuffer; + (void)iBuffer; + (void)format; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + + return FALSE; +} + +//--// + +__nfweak void CLR_Debug::Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_Debug::Emit( const char *text, int len ) +{ + (void)text; + (void)len; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak int CLR_Debug::PrintfV( const char *format, va_list arg ) +{ + (void)format; + (void)arg; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +__nfweak int CLR_Debug::Printf( const char *format, ... ) +{ + (void)format; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +//--// + +__nfweak CLR_UINT32 CLR_ReadTokenCompressed( const CLR_UINT8*& ip, CLR_OPCODE opcode ) +{ + (void)ip; + (void)opcode; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +__nfweak const CLR_UINT8* CLR_SkipBodyOfOpcode( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + (void)ip; + (void)opcode; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +__nfweak const CLR_UINT8* CLR_SkipBodyOfOpcodeCompressed( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + (void)ip; + (void)opcode; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +#if defined(NANOCLR_TRACE_INSTRUCTIONS) + +__nfweak void CLR_RT_Assembly::DumpToken( CLR_UINT32 tk ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_Assembly::DumpSignature( CLR_SIG sig ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_Assembly::DumpSignature( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_Assembly::DumpSignatureToken( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +__nfweak void CLR_RT_Assembly::DumpOpcode( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_Assembly::DumpOpcodeDirect( CLR_RT_MethodDef_Instance& call, CLR_PMETADATA ip, CLR_PMETADATA ipStart, int pid ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +#if defined(NANOCLR_TRACE_CALLS) + +__nfweak void CLR_RT_Assembly::DumpCall( CLR_RT_StackFrame& stack, bool fPush ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_Assembly::DumpCall( CLR_RT_MethodDef_Instance& md, const char* szPrefix ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_TRACE_ERRORS) + +__nfweak void CLR_RT_DUMP::TYPE( const CLR_RT_TypeDef_Index& cls ) +{ + (void)cls; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_DUMP::TYPE( const CLR_RT_ReflectionDef_Index& reflex ) +{ + (void)reflex; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_DUMP::METHOD( const CLR_RT_MethodDef_Index& method ) +{ + (void)method; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_DUMP::FIELD( const CLR_RT_FieldDef_Index& field ) +{ + (void)field; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_DUMP::OBJECT( CLR_RT_HeapBlock* ptr, const char* text ) +{ + (void)ptr; + (void)text; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +//--// + +#if defined(NANOCLR_TRACE_EXCEPTIONS) + +__nfweak void CLR_RT_DUMP::EXCEPTION( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref ) +{ + (void)stack; + (void)ref; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_RT_DUMP::POST_PROCESS_EXCEPTION( CLR_RT_HeapBlock& ref ) +{ + (void)ref; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +//--// + +__nfweak const char* CLR_RT_DUMP::GETERRORMESSAGE( HRESULT hrError ) +{ + (void)hrError; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return NULL; +} + +//--// + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + +__nfweak void* CLR_PROF_CounterCallChain::Prepare( CLR_PROF_Handler* handler ) +{ + (void)handler; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return NULL; +} + +__nfweak void CLR_PROF_CounterCallChain::Complete( CLR_UINT64& t, CLR_PROF_Handler* handler ) +{ + (void)t; + (void)handler; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PROF_CounterCallChain::Enter( CLR_RT_StackFrame* stack ) +{ + (void)stack; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PROF_CounterCallChain::Leave() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} +#endif + +//--// + +#if defined(NANOCLR_PROFILE_HANDLER) + +__nfweak void CLR_PROF_Handler::Constructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#if defined(NANOCLR_PROFILE_NEW_CALLS) +__nfweak void CLR_PROF_Handler::Constructor( CLR_PROF_CounterCallChain& target ) +{ + (void)target; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} +#endif + +__nfweak void CLR_PROF_Handler::Destructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + + +__nfweak void CLR_PROF_Handler::Init( void* target ) +{ + (void)target; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + + +//--// + +__nfweak void CLR_PROF_Handler::Calibrate() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PROF_Handler::SuspendTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak CLR_UINT64 CLR_PROF_Handler::GetFrozenTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +__nfweak CLR_UINT64 CLR_PROF_Handler::ResumeTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +__nfweak CLR_UINT64 CLR_PROF_Handler::ResumeTime( CLR_INT64 t ) +{ + (void)t; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +#endif //#if defined(NANOCLR_PROFILE_HANDLER) + +//////////////////////////////////////////////////////////////////////////////// + +//--// + +#if defined(NANOCLR_PROFILE_NEW) + +__nfweak CLR_PRF_Profiler g_CLR_PRF_Profiler; + +__nfweak HRESULT CLR_PRF_Profiler::CreateInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak HRESULT CLR_PRF_Profiler::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak HRESULT CLR_PRF_Profiler::Profiler_Cleanup() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak void CLR_PRF_Profiler::SendMemoryLayout() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak HRESULT CLR_PRF_Profiler::DumpHeap() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak HRESULT CLR_PRF_Profiler::DumpRoots() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak void CLR_PRF_Profiler::DumpRoot(CLR_RT_HeapBlock* root, CLR_UINT32 type, CLR_UINT32 flags, CLR_RT_MethodDef_Index* source) +{ + (void)root; + (void)type; + (void)flags; + (void)source; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::DumpObject(CLR_RT_HeapBlock* ptr) +{ + (void)ptr; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak CLR_RT_HeapBlock* CLR_PRF_Profiler::FindReferencedObject(CLR_RT_HeapBlock* ref) +{ + (void)ref; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return NULL; +} + +__nfweak void CLR_PRF_Profiler::DumpEndOfRefsList() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::DumpPointer(void* ptr) +{ + (void)ptr; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::DumpSingleReference(CLR_RT_HeapBlock* ptr) +{ + (void)ptr; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_HeapBlock* firstItem, CLR_UINT16 count) +{ + (void)firstItem; + (void)count; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_DblLinkedList& list) +{ + (void)list; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +__nfweak void CLR_PRF_Profiler::Timestamp() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +__nfweak HRESULT CLR_PRF_Profiler::RecordContextSwitch(CLR_RT_Thread* nextThread) +{ + (void)nextThread; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak HRESULT CLR_PRF_Profiler::RecordFunctionCall(CLR_RT_Thread* th, CLR_RT_MethodDef_Index md) +{ + (void)th; + (void)md; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak HRESULT CLR_PRF_Profiler::RecordFunctionReturn(CLR_RT_Thread* th, CLR_PROF_CounterCallChain& prof) +{ + (void)th; + (void)prof; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +//--// + +__nfweak void CLR_PRF_Profiler::TrackObjectCreation( CLR_RT_HeapBlock* ptr ) +{ + (void)ptr; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::TrackObjectDeletion( CLR_RT_HeapBlock* ptr ) +{ + (void)ptr; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::TrackObjectRelocation() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::RecordGarbageCollectionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::RecordGarbageCollectionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::RecordHeapCompactionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::RecordHeapCompactionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +__nfweak void CLR_PRF_Profiler::SendTrue() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::SendFalse() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::PackAndWriteBits(CLR_UINT32 value) +{ + (void)value; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_TypeDef_Index& typeDef) +{ + (void)typeDef; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +__nfweak void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_MethodDef_Index& methodDef) +{ + (void)methodDef; + + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +__nfweak HRESULT CLR_PRF_Profiler::Stream_Send() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +__nfweak HRESULT CLR_PRF_Profiler::Stream_Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +#endif //#if defined(NANOCLR_PROFILE_NEW) diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj new file mode 100644 index 00000000..0776978b --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3} + Win32Proj + Diagnostics_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters new file mode 100644 index 00000000..7fa5fc72 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Info.cpp b/source/native/nf-interpreter/src/CLR/Diagnostics/Info.cpp new file mode 100644 index 00000000..ca54f55b --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Info.cpp @@ -0,0 +1,859 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +static std::string* s_redirectedString = NULL; + +void CLR_Debug::RedirectToString( std::string* str ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + s_redirectedString = str; +} + +static std::string s_messageString = ""; + +void CLR_Debug::SaveMessage(std::string str) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + + // clear LR & CR + int pos; + if ((pos = str.find('\n')) != std::string::npos) + { + str.erase(pos); + } + if ((pos = str.find('\r')) != std::string::npos) + { + str.erase(pos); + } + + s_messageString = str; +} + +HRESULT NANOCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, const char* szFunc, const char* szFile, int line ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + switch(hr) + { + case CLR_E_ENTRY_NOT_FOUND: + case CLR_E_PROCESS_EXCEPTION: + case CLR_E_THREAD_WAITING: + case CLR_E_RESTART_EXECUTION: + case CLR_E_RESCHEDULE: + case CLR_E_OUT_OF_MEMORY: + return hr; + } + + if(s_CLR_RT_fTrace_StopOnFAILED >= c_CLR_RT_Trace_Info) + { + if(::IsDebuggerPresent()) + { + ::DebugBreak(); + } + } + return hr; +} + +#else + +#if defined(NANOCLR_TRACE_HRESULT) +HRESULT NANOCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, const char* szFunc, const char* szFile, int line ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + switch(hr) + { + case CLR_E_ENTRY_NOT_FOUND: + + case CLR_E_PROCESS_EXCEPTION: + case CLR_E_THREAD_WAITING: + case CLR_E_RESTART_EXECUTION: + return hr; + } + + CLR_Debug::Printf( "HRESULT %08x: %s %s:%d\r\n", hr, szFunc, szFile, line ); + return hr; +} +#endif + +#endif + +//--// + +bool CLR_SafeSprintfV( char*& szBuffer, size_t& iBuffer, const char* format, va_list arg ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + + int chars = vsnprintf( szBuffer, iBuffer, format, arg ); + bool fRes = (chars >= 0); + + if(fRes == false) chars = (int)iBuffer; + + szBuffer += chars; szBuffer[ 0 ] = 0; + iBuffer -= chars; + + return fRes; +} + +bool CLR_SafeSprintf( char*& szBuffer, size_t& iBuffer, const char* format, ... ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + va_list arg; + bool fRes; + + va_start( arg, format ); + + fRes = CLR_SafeSprintfV( szBuffer, iBuffer, format, arg ); + + va_end( arg ); + + return fRes; +} + + +//--// + +void CLR_Debug::Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + DebuggerPort_Flush( HalSystemConfig.DebugTextPort ); +} + +void CLR_Debug::Emit( const char *text, int len ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + static char s_buffer[ 128 ]; + static int s_chars = 0; + + if(CLR_EE_DBG_IS( RebootPending)) return; + + if(len == -1) len = (int)hal_strlen_s( text ); + +#if defined(_WIN32) + if(s_redirectedString) + { + s_redirectedString->append( text, len ); + return; + } + + if(s_CLR_RT_fTrace_RedirectOutput.size()) + { + static HANDLE hFile = INVALID_HANDLE_VALUE; + static int lines = 0; + static int num = 0; + + if(hFile == INVALID_HANDLE_VALUE) + { + std::wstring file = s_CLR_RT_fTrace_RedirectOutput; + + if(s_CLR_RT_fTrace_RedirectLinesPerFile) + { + wchar_t rgBuf[ 64 ]; + + swprintf( rgBuf, ARRAYSIZE(rgBuf), L".%08d", num++ ); + + file.append( rgBuf ); + } + + hFile = ::CreateFileW( file.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0 ); + + lines = 0; + } + + if(hFile != INVALID_HANDLE_VALUE) + { + unsigned long dwWritten; + + ::WriteFile( hFile, text, (unsigned long)len, &dwWritten, NULL ); + + if(s_CLR_RT_fTrace_RedirectLinesPerFile) + { + while((text = strchr( text, '\n' )) != NULL) + { + lines++; + text++; + + if(text[ 0 ] == 0) + { + if(lines > s_CLR_RT_fTrace_RedirectLinesPerFile) + { + ::CloseHandle( hFile ); hFile = INVALID_HANDLE_VALUE; + } + + break; + } + } + } + + return; + } + } +#endif + + while(len > 0) + { + int avail = MAXSTRLEN(s_buffer) - s_chars; + + if(len < avail) avail = len; + + memcpy( &s_buffer[ s_chars ], text, avail ); + + s_chars += avail; + text += avail; + len -= avail; + s_buffer[ s_chars ] = 0; + + if(s_chars > 80 || strchr( s_buffer, '\n' )) + { + Watchdog_Reset(); + +#if defined(PLATFORM_WINDOWS_EMULATOR) + HAL_Windows_Debug_Print( s_buffer ); +#endif + + if(CLR_EE_DBG_IS( Enabled ) && !CLR_EE_DBG_IS( Quiet )) + { + CLR_EE_DBG_EVENT_BROADCAST( CLR_DBG_Commands::c_Monitor_Message, s_chars, s_buffer, WP_Flags_c_NonCritical | WP_Flags_c_NoCaching ); + } + + if(HalSystemConfig.DebugTextPort != HalSystemConfig.DebuggerPort) + { +#if !defined(_WIN32) + DebuggerPort_Write( HalSystemConfig.DebugTextPort, s_buffer, s_chars, 0 ); // skip null terminator and don't bother retrying + DebuggerPort_Flush( HalSystemConfig.DebugTextPort ); // skip null terminator +#endif + } + + s_chars = 0; + } + } +} + +int CLR_Debug::PrintfV( const char *format, va_list arg ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + +#if defined(_WIN32) + char buffer[512]; + char* szBuffer = buffer; + int16_t bufferSize = MAXSTRLEN(buffer); + size_t iBuffer = bufferSize; +#else + // this should be more than enough for the existing output needs + const int16_t c_BufferSize = 512; + + char* buffer = (char*)platform_malloc(c_BufferSize); + char* szBuffer = buffer; + size_t iBuffer = c_BufferSize; + int16_t bufferSize = c_BufferSize; +#endif + + bool fRes = CLR_SafeSprintfV(szBuffer, iBuffer, format, arg ); + + _ASSERTE(fRes); + + iBuffer = bufferSize - iBuffer; + + Emit( buffer, (int)iBuffer ); + +#if defined(_WIN32) + OutputDebugStringA(buffer); + + std::string outputString(buffer, iBuffer); + SaveMessage(outputString); + +#endif + +#if !defined(_WIN32) + if(buffer != NULL) + { + platform_free(buffer); + } +#endif + + return (int)iBuffer; +} + +int CLR_Debug::Printf( const char *format, ... ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + va_list arg; + int chars; + + va_start( arg, format ); + + chars = CLR_Debug::PrintfV( format, arg ); + + va_end( arg ); + + return chars; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +const CLR_UINT8 c_CLR_opParamSize[] = +{ + 4, // CLR_OpcodeParam_Field + 4, // CLR_OpcodeParam_Method + 4, // CLR_OpcodeParam_Type + 4, // CLR_OpcodeParam_String + 4, // CLR_OpcodeParam_Tok + 4, // CLR_OpcodeParam_Sig + 4, // CLR_OpcodeParam_BrTarget + 1, // CLR_OpcodeParam_ShortBrTarget + 4, // CLR_OpcodeParam_I + 8, // CLR_OpcodeParam_I8 + 0, // CLR_OpcodeParam_None + 8, // CLR_OpcodeParam_R + 4, // CLR_OpcodeParam_Switch + 2, // CLR_OpcodeParam_Var + 1, // CLR_OpcodeParam_ShortI + 4, // CLR_OpcodeParam_ShortR + 1, // CLR_OpcodeParam_ShortVar +}; + +const CLR_UINT8 c_CLR_opParamSizeCompressed[] = +{ + 2, // CLR_OpcodeParam_Field + 2, // CLR_OpcodeParam_Method + 2, // CLR_OpcodeParam_Type + 2, // CLR_OpcodeParam_String + 4, // CLR_OpcodeParam_Tok + 4, // CLR_OpcodeParam_Sig + 2, // CLR_OpcodeParam_BrTarget + 1, // CLR_OpcodeParam_ShortBrTarget + 4, // CLR_OpcodeParam_I + 8, // CLR_OpcodeParam_I8 + 0, // CLR_OpcodeParam_None + 8, // CLR_OpcodeParam_R + 1, // CLR_OpcodeParam_Switch + 2, // CLR_OpcodeParam_Var + 1, // CLR_OpcodeParam_ShortI + 4, // CLR_OpcodeParam_ShortR + 1, // CLR_OpcodeParam_ShortVar +}; + +CLR_UINT32 CLR_ReadTokenCompressed( const CLR_UINT8*& ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT32 arg; + const CLR_UINT8* ptr = ip; + + switch(c_CLR_RT_OpcodeLookup[ opcode ].m_opParam) + { + case CLR_OpcodeParam_Field : NANOCLR_READ_UNALIGNED_COMPRESSED_FIELDTOKEN ( arg, ptr ); break; + case CLR_OpcodeParam_Method: NANOCLR_READ_UNALIGNED_COMPRESSED_METHODTOKEN( arg, ptr ); break; + case CLR_OpcodeParam_Type : NANOCLR_READ_UNALIGNED_COMPRESSED_TYPETOKEN ( arg, ptr ); break; + case CLR_OpcodeParam_String: NANOCLR_READ_UNALIGNED_COMPRESSED_STRINGTOKEN( arg, ptr ); break; + case CLR_OpcodeParam_Tok : + case CLR_OpcodeParam_Sig : NANOCLR_READ_UNALIGNED_UINT32 ( arg, ptr ); break; + default : arg = 0; break; + } + + ip = ptr; + + return arg; +} + +// +// SkipBodyOfOpcode skips past the opcode argument & returns the address of the +// next instruction in the instruction stream. Note that this is +// not necessarily the next instruction which will be executed. +// +// ip -> address of argument for the opcode specified in +// the instruction stream. Note that this is not an +// instruction boundary, it is past the opcode. +// +const CLR_UINT8* CLR_SkipBodyOfOpcode( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_OpcodeParam opParam = c_CLR_RT_OpcodeLookup[ opcode ].m_opParam; + + if(opParam == CLR_OpcodeParam_Switch) + { + CLR_UINT32 numcases; NANOCLR_READ_UNALIGNED_UINT32( numcases, ip ); + + ip += numcases * sizeof(CLR_UINT32); + } + else + { + ip += c_CLR_opParamSize[ opParam ]; + } + + return ip; +} + +const CLR_UINT8* CLR_SkipBodyOfOpcodeCompressed( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_OpcodeParam opParam = c_CLR_RT_OpcodeLookup[ opcode ].m_opParam; + + if(opParam == CLR_OpcodeParam_Switch) + { + CLR_UINT32 numcases; NANOCLR_READ_UNALIGNED_UINT8(numcases, ip); + + ip += numcases * sizeof(CLR_UINT16); + } + else + { + ip += c_CLR_opParamSizeCompressed[ opParam ]; + } + + return ip; +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#define LOOKUP_ELEMENT(idx,tblName,tblNameUC) \ + const CLR_RECORD_##tblNameUC* p = Get##tblName( idx ) + +#define LOOKUP_ELEMENT_REF(idx,tblName,tblNameUC,tblName2) \ + const CLR_RECORD_##tblNameUC* p = Get##tblName( idx );\ + const CLR_RT_##tblName2##_Index* s = &m_pCrossReference_##tblName[ idx ].m_target; if(s->m_data == 0) s = NULL + +#define LOOKUP_ELEMENT_IDX(idx,tblName,tblNameUC) \ + const CLR_RECORD_##tblNameUC* p = Get##tblName( idx );\ + CLR_RT_##tblName##_Index s; s.Set( m_idx, idx ) + +#if defined(NANOCLR_TRACE_INSTRUCTIONS) + +void CLR_RT_Assembly::DumpToken( CLR_UINT32 tk ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk(tk)) + { + case TBL_AssemblyRef: { LOOKUP_ELEMENT ( idx, AssemblyRef, ASSEMBLYREF ); { CLR_Debug::Printf( "[%s]" , GetString( p->name ) ); } break; } + case TBL_TypeRef : { LOOKUP_ELEMENT_REF( idx, TypeRef , TYPEREF , TypeDef ); if(s) { CLR_RT_DUMP::TYPE ( *s ); } else { CLR_Debug::Printf( "%s.%s", GetString( p->nameSpace ), GetString( p->name ) ); } break; } + case TBL_FieldRef : { LOOKUP_ELEMENT_REF( idx, FieldRef , FIELDREF , FieldDef ); if(s) { CLR_RT_DUMP::FIELD ( *s ); } else { CLR_Debug::Printf( "%s" , GetString( p->name ) ); } break; } + case TBL_MethodRef : { LOOKUP_ELEMENT_REF( idx, MethodRef , METHODREF , MethodDef); if(s) { CLR_RT_DUMP::METHOD( *s ); } else { CLR_Debug::Printf( "%s" , GetString( p->name ) ); } break; } + case TBL_TypeDef : { LOOKUP_ELEMENT_IDX( idx, TypeDef , TYPEDEF ); CLR_RT_DUMP::TYPE ( s ); break; } + case TBL_FieldDef : { LOOKUP_ELEMENT_IDX( idx, FieldDef , FIELDDEF ); CLR_RT_DUMP::FIELD ( s ); break; } + case TBL_MethodDef : { LOOKUP_ELEMENT_IDX( idx, MethodDef , METHODDEF ); CLR_RT_DUMP::METHOD( s ); break; } + case TBL_Strings : { const char* p = GetString( idx ); CLR_Debug::Printf( "'%s'" , p ); break; } + + default: + CLR_Debug::Printf( "[%08x]", tk ); + } +} + +void CLR_RT_Assembly::DumpSignature( CLR_SIG sig ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + const CLR_UINT8* p = GetSignature( sig ); + CLR_UINT32 len; + + CLR_CorCallingConvention cc = (CLR_CorCallingConvention)*p++; + + switch(cc & PIMAGE_CEE_CS_CALLCONV_MASK) + { + case PIMAGE_CEE_CS_CALLCONV_FIELD: + CLR_Debug::Printf( "FIELD " ); + DumpSignature( p ); + break; + + case PIMAGE_CEE_CS_CALLCONV_LOCAL_SIG: + break; + + case PIMAGE_CEE_CS_CALLCONV_DEFAULT: + len = *p++; + + CLR_Debug::Printf( "METHOD " ); + DumpSignature( p ); + CLR_Debug::Printf( "(" ); + + while(len-- > 0) + { + CLR_Debug::Printf( " " ); + DumpSignature( p ); + if(len) CLR_Debug::Printf( "," ); + else CLR_Debug::Printf( " " ); + } + CLR_Debug::Printf( ")" ); + break; + } +} + +void CLR_RT_Assembly::DumpSignature( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_DataType opt = CLR_UncompressElementType( p ); + + switch(opt) + { + case DATATYPE_VOID : CLR_Debug::Printf( "VOID" ); break; + case DATATYPE_BOOLEAN : CLR_Debug::Printf( "BOOLEAN" ); break; + case DATATYPE_CHAR : CLR_Debug::Printf( "char" ); break; + case DATATYPE_I1 : CLR_Debug::Printf( "I1" ); break; + case DATATYPE_U1 : CLR_Debug::Printf( "U1" ); break; + case DATATYPE_I2 : CLR_Debug::Printf( "I2" ); break; + case DATATYPE_U2 : CLR_Debug::Printf( "U2" ); break; + case DATATYPE_I4 : CLR_Debug::Printf( "I4" ); break; + case DATATYPE_U4 : CLR_Debug::Printf( "U4" ); break; + case DATATYPE_I8 : CLR_Debug::Printf( "I8" ); break; + case DATATYPE_U8 : CLR_Debug::Printf( "U8" ); break; + case DATATYPE_R4 : CLR_Debug::Printf( "R4" ); break; + case DATATYPE_R8 : CLR_Debug::Printf( "R8" ); break; + case DATATYPE_STRING : CLR_Debug::Printf( "STRING" ); break; + case DATATYPE_BYREF : CLR_Debug::Printf( "BYREF " ); DumpSignature ( p ); break; + case DATATYPE_VALUETYPE : CLR_Debug::Printf( "VALUETYPE " ); DumpSignatureToken( p ); break; + case DATATYPE_CLASS : CLR_Debug::Printf( "CLASS " ); DumpSignatureToken( p ); break; + case DATATYPE_OBJECT : CLR_Debug::Printf( "OBJECT" ); break; + case DATATYPE_SZARRAY : CLR_Debug::Printf( "SZARRAY " ); DumpSignature ( p ); break; + + default : CLR_Debug::Printf( "[UNKNOWN: %08x]", opt ); break; + } + +} + +void CLR_RT_Assembly::DumpSignatureToken( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT32 tk = CLR_TkFromStream( p ); + + CLR_Debug::Printf( "[%08x]", tk ); +} + +//--// + +void CLR_RT_Assembly::DumpOpcode( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(s_CLR_RT_fTrace_Instructions < c_CLR_RT_Trace_Info) return; + + CLR_RT_MethodDef_Instance inst; + + if(s_CLR_RT_fTrace_Instructions >= c_CLR_RT_Trace_Verbose) + { + inst = stack->m_call; + } + else + { + inst.Clear(); + } + + DumpOpcodeDirect( inst, ip, stack->m_IPstart, stack->m_owningThread->m_pid ); +} + +void CLR_RT_Assembly::DumpOpcodeDirect( CLR_RT_MethodDef_Instance& call, CLR_PMETADATA ip, CLR_PMETADATA ipStart, int pid ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_Debug::Printf( " [%04x:%04x:%08x", pid, (int)(ip - ipStart), (size_t)ip ); + + if(NANOCLR_INDEX_IS_VALID(call)) + { + CLR_Debug::Printf( ":" ); + CLR_RT_DUMP::METHOD( call ); + } + + CLR_OPCODE op = CLR_ReadNextOpcodeCompressed( ip ); + CLR_OpcodeParam opParam = c_CLR_RT_OpcodeLookup[ op ].m_opParam; + + CLR_Debug::Printf( "] %-12s", c_CLR_RT_OpcodeLookup[ op ].m_name ); + + if(IsOpParamToken( opParam )) + { + DumpToken( CLR_ReadTokenCompressed( ip, op ) ); + } + else + { + CLR_UINT32 argLo; + CLR_UINT32 argHi; + + switch(c_CLR_opParamSizeCompressed[ opParam ]) + { + case 8: NANOCLR_READ_UNALIGNED_UINT32( argLo, ip ); NANOCLR_READ_UNALIGNED_UINT32( argHi, ip ); CLR_Debug::Printf( "%08X,%08X", argHi, argLo ); break; + case 4: NANOCLR_READ_UNALIGNED_UINT32( argLo, ip ); CLR_Debug::Printf( "%08X" , argLo ); break; + case 2: NANOCLR_READ_UNALIGNED_UINT16( argLo, ip ); CLR_Debug::Printf( "%04X" , argLo ); break; + case 1: NANOCLR_READ_UNALIGNED_UINT8 ( argLo, ip ); CLR_Debug::Printf( "%02X" , argLo ); break; + } + } + + CLR_Debug::Printf( "\r\n" ); +} + +#endif // defined(NANOCLR_TRACE_INSTRUCTIONS) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_TRACE_ERRORS) + +void CLR_RT_DUMP::TYPE( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + char rgBuffer[ 512 ]; + char* szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildTypeName( cls, szBuffer, iBuffer ); rgBuffer[ MAXSTRLEN(rgBuffer) ] = 0; + + CLR_Debug::Printf( "%s", rgBuffer ); +} + +void CLR_RT_DUMP::TYPE( const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_RT_TypeDef_Instance inst; + CLR_UINT32 levels; + + if(inst.InitializeFromReflection( reflex, &levels )) + { + CLR_RT_DUMP::TYPE( inst ); + + while(levels-- > 0) + { + CLR_Debug::Printf( "[]" ); + } + } +} + +void CLR_RT_DUMP::METHOD( const CLR_RT_MethodDef_Index& method ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + char rgBuffer[ 512 ]; + char* szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildMethodName( method, szBuffer, iBuffer ); + + CLR_Debug::Printf( "%s", rgBuffer ); +} + +void CLR_RT_DUMP::FIELD( const CLR_RT_FieldDef_Index& field ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + char rgBuffer[ 512 ]; + char* szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildFieldName( field, szBuffer, iBuffer ); + + CLR_Debug::Printf( "%s", rgBuffer ); +} + +void CLR_RT_DUMP::OBJECT( CLR_RT_HeapBlock* ptr, const char* text ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + #define PELEMENT_TO_STRING(elem) case DATATYPE_##elem: CLR_Debug::Printf( "%s", #elem ); break + + CLR_Debug::Printf( "%s - ", text ); + + while(ptr->DataType() == DATATYPE_OBJECT && ptr->Dereference()) + { + ptr = ptr->Dereference(); + + CLR_Debug::Printf( "PTR " ); + } + + CLR_Debug::Printf( "%04x blocks at %08x [%02x] ", ptr->DataSize(), (int)(size_t)ptr, ptr->DataType() ); + + switch(ptr->DataType()) + { + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + CLR_RT_DUMP::TYPE( ptr->ObjectCls() ); + } + break; + + case DATATYPE_STRING: + { + CLR_Debug::Printf( "'%s'", ptr->StringText() ); + } + break; + + case DATATYPE_SZARRAY: + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + CLR_RT_DUMP::TYPE( array->ReflectionData() ); + } + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + + CLR_RT_DUMP::METHOD( dlg->DelegateFtn() ); + } + break; + + + PELEMENT_TO_STRING(BOOLEAN); + PELEMENT_TO_STRING(CHAR ); + PELEMENT_TO_STRING(I1 ); + PELEMENT_TO_STRING(U1 ); + PELEMENT_TO_STRING(I2 ); + PELEMENT_TO_STRING(U2 ); + PELEMENT_TO_STRING(I4 ); + PELEMENT_TO_STRING(U4 ); + PELEMENT_TO_STRING(I8 ); + PELEMENT_TO_STRING(U8 ); + PELEMENT_TO_STRING(R4 ); + PELEMENT_TO_STRING(R8 ); + + PELEMENT_TO_STRING(FREEBLOCK ); + PELEMENT_TO_STRING(CACHEDBLOCK ); + PELEMENT_TO_STRING(ASSEMBLY ); + PELEMENT_TO_STRING(WEAKCLASS ); + PELEMENT_TO_STRING(REFLECTION ); + PELEMENT_TO_STRING(ARRAY_BYREF ); + PELEMENT_TO_STRING(DELEGATELIST_HEAD ); + PELEMENT_TO_STRING(OBJECT_TO_EVENT ); + PELEMENT_TO_STRING(BINARY_BLOB_HEAD ); + + PELEMENT_TO_STRING(THREAD ); + PELEMENT_TO_STRING(SUBTHREAD ); + PELEMENT_TO_STRING(STACK_FRAME ); + PELEMENT_TO_STRING(TIMER_HEAD ); + PELEMENT_TO_STRING(LOCK_HEAD ); + PELEMENT_TO_STRING(LOCK_OWNER_HEAD ); + PELEMENT_TO_STRING(LOCK_REQUEST_HEAD ); + PELEMENT_TO_STRING(WAIT_FOR_OBJECT_HEAD ); + PELEMENT_TO_STRING(FINALIZER_HEAD ); + PELEMENT_TO_STRING(MEMORY_STREAM_HEAD ); + PELEMENT_TO_STRING(MEMORY_STREAM_DATA ); + + default: + // the remaining data types aren't to be handled + break; + } + + CLR_Debug::Printf( "\r\n" ); + + #undef PELEMENT_TO_STRING +} + +#endif // defined(NANOCLR_TRACE_ERRORS) + +//--// + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_TRACE_EXCEPTIONS) + +void CLR_RT_DUMP::EXCEPTION( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + const char* msg; + + CLR_RT_HeapBlock* obj = Library_corlib_native_System_Exception::GetTarget( ref ); if(!obj) return; + + CLR_Debug::Printf( " ++++ Exception " ); CLR_RT_DUMP::TYPE( obj->ObjectCls() ); CLR_Debug::Printf( " - %s (%d) ++++\r\n", CLR_RT_DUMP::GETERRORMESSAGE( Library_corlib_native_System_Exception::GetHResult( obj ) ), stack.m_owningThread->m_pid ); + + msg = Library_corlib_native_System_Exception::GetMessage( obj ); + + CLR_Debug::Printf( " ++++ Message: %s\r\n", msg == NULL ? "" : msg ); + + CLR_UINT32 depth; + Library_corlib_native_System_Exception::StackTrace* stackTrace = Library_corlib_native_System_Exception::GetStackTrace( obj, depth ); if(!stackTrace) return; + + while(depth-- > 0) + { + CLR_Debug::Printf( " ++++ " ); CLR_RT_DUMP::METHOD( stackTrace->m_md ); CLR_Debug::Printf( " [IP: %04x] ++++\r\n", stackTrace->m_IP ); + + stackTrace++; + } +} + +void CLR_RT_DUMP::POST_PROCESS_EXCEPTION( CLR_RT_HeapBlock& ref ) +{ + (void)ref; +} + +const char* CLR_RT_DUMP::GETERRORMESSAGE( HRESULT hrError ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +#define CASE_HRESULT_TO_STRING(hr) case hr: return #hr + switch(hrError) + { + CASE_HRESULT_TO_STRING(CLR_E_UNKNOWN_INSTRUCTION); + CASE_HRESULT_TO_STRING(CLR_E_UNSUPPORTED_INSTRUCTION); + CASE_HRESULT_TO_STRING(CLR_E_STACK_OVERFLOW); + CASE_HRESULT_TO_STRING(CLR_E_STACK_UNDERFLOW); + CASE_HRESULT_TO_STRING(CLR_E_ENTRY_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_ASSM_WRONG_CHECKSUM); + CASE_HRESULT_TO_STRING(CLR_E_ASSM_PATCHING_NOT_SUPPORTED); + CASE_HRESULT_TO_STRING(CLR_E_SHUTTING_DOWN); + CASE_HRESULT_TO_STRING(CLR_E_OBJECT_DISPOSED); + CASE_HRESULT_TO_STRING(CLR_E_WATCHDOG_TIMEOUT); + CASE_HRESULT_TO_STRING(CLR_E_NULL_REFERENCE); + CASE_HRESULT_TO_STRING(CLR_E_WRONG_TYPE); + CASE_HRESULT_TO_STRING(CLR_E_TYPE_UNAVAILABLE); + CASE_HRESULT_TO_STRING(CLR_E_INVALID_CAST); + CASE_HRESULT_TO_STRING(CLR_E_OUT_OF_RANGE); + CASE_HRESULT_TO_STRING(CLR_E_SERIALIZATION_VIOLATION); + CASE_HRESULT_TO_STRING(CLR_E_SERIALIZATION_BADSTREAM); + CASE_HRESULT_TO_STRING(CLR_E_DIVIDE_BY_ZERO); + CASE_HRESULT_TO_STRING(CLR_E_BUSY); + CASE_HRESULT_TO_STRING(CLR_E_PROCESS_EXCEPTION); + CASE_HRESULT_TO_STRING(CLR_E_THREAD_WAITING); + CASE_HRESULT_TO_STRING(CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION); + CASE_HRESULT_TO_STRING(CLR_E_APPDOMAIN_EXITED); + CASE_HRESULT_TO_STRING(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + CASE_HRESULT_TO_STRING(CLR_E_UNKNOWN_TYPE); + CASE_HRESULT_TO_STRING(CLR_E_ARGUMENT_NULL); + CASE_HRESULT_TO_STRING(CLR_E_IO); + CASE_HRESULT_TO_STRING(CLR_E_ENTRYPOINT_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_DRIVER_NOT_REGISTERED); + CASE_HRESULT_TO_STRING(CLR_E_PIN_UNAVAILABLE); + CASE_HRESULT_TO_STRING(CLR_E_PIN_DEAD); + CASE_HRESULT_TO_STRING(CLR_E_INVALID_OPERATION); + CASE_HRESULT_TO_STRING(CLR_E_WRONG_INTERRUPT_TYPE); + CASE_HRESULT_TO_STRING(CLR_E_NO_INTERRUPT); + CASE_HRESULT_TO_STRING(CLR_E_DISPATCHER_ACTIVE); + CASE_HRESULT_TO_STRING(CLR_E_FILE_IO); + CASE_HRESULT_TO_STRING(CLR_E_INVALID_DRIVER); + CASE_HRESULT_TO_STRING(CLR_E_FILE_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_DIRECTORY_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_VOLUME_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_PATH_TOO_LONG); + CASE_HRESULT_TO_STRING(CLR_E_DIRECTORY_NOT_EMPTY); + CASE_HRESULT_TO_STRING(CLR_E_UNAUTHORIZED_ACCESS); + CASE_HRESULT_TO_STRING(CLR_E_PATH_ALREADY_EXISTS); + CASE_HRESULT_TO_STRING(CLR_E_TOO_MANY_OPEN_HANDLES); + CASE_HRESULT_TO_STRING(CLR_E_NOT_SUPPORTED); + CASE_HRESULT_TO_STRING(CLR_E_RESCHEDULE); + CASE_HRESULT_TO_STRING(CLR_E_OUT_OF_MEMORY); + CASE_HRESULT_TO_STRING(CLR_E_RESTART_EXECUTION); + CASE_HRESULT_TO_STRING(CLR_E_TIMEOUT); + CASE_HRESULT_TO_STRING(CLR_E_FAIL); + //--// + CASE_HRESULT_TO_STRING(CLR_S_THREAD_EXITED); + CASE_HRESULT_TO_STRING(CLR_S_QUANTUM_EXPIRED); + CASE_HRESULT_TO_STRING(CLR_S_NO_READY_THREADS); + CASE_HRESULT_TO_STRING(CLR_S_NO_THREADS); + CASE_HRESULT_TO_STRING(CLR_S_RESTART_EXECUTION); + } +#undef CASE_HRESULT_TO_STRING + + static char s_tmp[ 32 ]; + + snprintf( s_tmp, MAXSTRLEN(s_tmp), "0x%08x", hrError ); + + return s_tmp; +} + +#if defined(_WIN32) +const char* CLR_RT_DUMP::GETERRORDETAIL() +{ + return s_messageString.c_str(); +} +#endif + +#endif // defined(NANOCLR_TRACE_EXCEPTIONS) + +//--// + diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Profile.cpp b/source/native/nf-interpreter/src/CLR/Diagnostics/Profile.cpp new file mode 100644 index 00000000..0d63a9de --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Profile.cpp @@ -0,0 +1,268 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + +//--// + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + +void* CLR_PROF_CounterCallChain::Prepare( CLR_PROF_Handler* handler ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(m_owningHandler) + { + CLR_UINT64 t = handler->GetFrozenTime() - m_owningHandler->m_time_start; + + Complete( t, m_owningHandler ); + + handler->m_target_Mode = CLR_PROF_Handler::c_Mode_Ignore; + + return NULL; + } + else + { + m_owningHandler = handler; + + handler->m_target_Mode = CLR_PROF_Handler::c_Mode_CallChain; + + return this; + } +} + +void CLR_PROF_CounterCallChain::Complete( CLR_UINT64& t, CLR_PROF_Handler* handler ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(m_owningHandler) + { + m_time_exclusive += t; + + m_owningHandler->m_target = NULL; + m_owningHandler = NULL; + } +} + +void CLR_PROF_CounterCallChain::Enter( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_PROF_Handler::SuspendTime(); + + NANOCLR_CLEAR(*this); + + m_owningStackFrame = stack; + + CLR_PROF_Handler::ResumeTime(); +} + +void CLR_PROF_CounterCallChain::Leave() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_PROF_Handler::SuspendTime(); + CLR_PROF_Handler::ResumeTime(); +} + +#endif + +//--// + +#if defined(NANOCLR_PROFILE_HANDLER) + + bool CLR_PROF_Handler::s_initialized; + CLR_PROF_Handler* CLR_PROF_Handler::s_current; +volatile CLR_UINT64 CLR_PROF_Handler::s_time_overhead; +volatile CLR_UINT64 CLR_PROF_Handler::s_time_freeze; +volatile CLR_UINT64 CLR_PROF_Handler::s_time_adjusted; + +//--// + + +// TODO: roll this entire function into the HAL so that +// hardware with a HighRes counter can be used, this +// implementation is easy enough to move to the HAL as +// a support function for systems with only a lowres +// counter +static CLR_UINT64 GetPerformanceCounter() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +#if defined(_WIN32) + return 0; // UNDONE: FIXME: return HAL_Windows_GetPerformanceTicks(); +#else + static CLR_UINT32 rollover = 0; + static CLR_UINT32 lastValue = 0; + + CLR_UINT32 value = ::PAL_PerformanceCounter(); + + if(lastValue > value) rollover++; + + lastValue = value; + + return ((CLR_UINT64)rollover << 32) | (CLR_UINT64)value; +#endif +} + +//--// + +void CLR_PROF_Handler::Constructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SuspendTime(); + + m_target_Mode = c_Mode_Ignore; + + Init( NULL ); +} + +#if defined(NANOCLR_PROFILE_NEW_CALLS) +void CLR_PROF_Handler::Constructor( CLR_PROF_CounterCallChain& target ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SuspendTime(); + + Init( target.Prepare( this ) ); +} +#endif + +void CLR_PROF_Handler::Destructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SuspendTime(); + + CLR_UINT64 t = GetFrozenTime() - m_time_start; + + if(m_target_Mode == c_Mode_Ignore) + { + s_time_adjusted += t; + } + else + { + if(m_containing) + { + m_containing->m_time_correction += t; + } + + if(m_target) + { + switch(m_target_Mode) + { +#if defined(NANOCLR_PROFILE_NEW_CALLS) + case c_Mode_CallChain: ((CLR_PROF_CounterCallChain*)m_target)->Complete( t, this ); break; +#endif + } + } + } + + s_current = m_containing; + + ResumeTime(); +} + + +void CLR_PROF_Handler::Init( void* target ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_target = target; + m_containing = s_current; s_current = this; + + if(m_target) + { + if(m_containing && m_containing->m_target == NULL) + { + m_target = NULL; + } + } + + if(m_target == NULL) + { + m_target_Mode = c_Mode_Ignore; + } + + m_time_correction = 0; + m_time_start = ResumeTime(); +} + +static void TestCalibrate( CLR_PROF_CounterCallChain& cnt ) +{ + CLR_PROF_Handler c( cnt ); +} + +void CLR_PROF_Handler::Calibrate() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +#if defined(PLATFORM_ARM) || defined(PLATFORM_ESP32) + const int c_training = 10; +#else + const int c_training = 1024; +#endif + + if(s_initialized) return; + + s_current = NULL; + s_time_overhead = 0; + s_time_freeze = 0; + s_time_adjusted = 0; + +#if defined(PLATFORM_ARM) || defined(PLATFORM_ESP32) + ::PAL_PerformanceCounter_Initialize(); +#endif + + int i; + CLR_PROF_CounterCallChain tmp; + + for(i=0; i 100 && i > c_training/2) + { + i--; + continue; + } + + s_time_overhead += diff; + } + + s_time_adjusted = GetPerformanceCounter(); + + s_initialized = true; +} + +void CLR_PROF_Handler::SuspendTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + s_time_freeze = GetPerformanceCounter(); +} + +CLR_UINT64 CLR_PROF_Handler::GetFrozenTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return s_time_freeze - s_time_adjusted; +} + +CLR_UINT64 CLR_PROF_Handler::ResumeTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT64 res = GetFrozenTime(); + + s_time_adjusted = (GetPerformanceCounter() - res) + s_time_overhead; + + return res; +} + +CLR_UINT64 CLR_PROF_Handler::ResumeTime( CLR_INT64 t ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + s_time_adjusted += t; + + return ResumeTime(); +} +#endif //defined(NANOCLR_PROFILE_HANDLER) + +//--// + diff --git a/source/native/nf-interpreter/src/CLR/Diagnostics/Profiler.cpp b/source/native/nf-interpreter/src/CLR/Diagnostics/Profiler.cpp new file mode 100644 index 00000000..d29473c1 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Diagnostics/Profiler.cpp @@ -0,0 +1,858 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + +#if defined(NANOCLR_PROFILE_NEW) + +CLR_PRF_Profiler g_CLR_PRF_Profiler; + +HRESULT CLR_PRF_Profiler::CreateInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + + g_CLR_PRF_Profiler.m_packetSeqId = 0; + g_CLR_PRF_Profiler.m_stream = NULL; + g_CLR_PRF_Profiler.m_lastTimestamp = (CLR_UINT32)((CLR_UINT64)(HAL_Time_CurrentTime() + ((1ull << CLR_PRF_CMDS::Bits::TimestampShift) - 1)) + >> CLR_PRF_CMDS::Bits::TimestampShift); + g_CLR_PRF_Profiler.m_currentAssembly = 0; + g_CLR_PRF_Profiler.m_currentThreadPID = 0; + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_MemoryStream::CreateInstance(g_CLR_PRF_Profiler.m_stream, NULL, 0)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return g_CLR_PRF_Profiler.Profiler_Cleanup(); +} + +HRESULT CLR_PRF_Profiler::Profiler_Cleanup() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_RT_HeapBlock_MemoryStream::DeleteInstance(m_stream); + return S_OK; +} + +void CLR_PRF_Profiler::SendMemoryLayout() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + //Send Memory Layout + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Memory_Layout, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( 0 ); + PackAndWriteBits(s_CLR_RT_Heap.m_size); + Stream_Send(); +} + +HRESULT CLR_PRF_Profiler::DumpHeap() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_UINT32 heapSize = 0; + + if(CLR_EE_PRF_IS_NOT(Enabled)) { NANOCLR_SET_AND_LEAVE(S_OK); } + + { + //Send HeapDump Begin Marker + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Start, CLR_PRF_CMDS::Bits::CommandHeader ); + NANOCLR_CHECK_HRESULT(Stream_Send()); + } + + DumpRoots(); + + NANOCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr; + CLR_UINT32 size; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + for(ptr = hc->m_payloadStart, size = ptr->DataSize(); ptr < end; ptr+= size, size = ptr->DataSize()) + { + if(ptr->DataType() != DATATYPE_FREEBLOCK && ptr->DataType() != DATATYPE_CACHEDBLOCK) + { + heapSize += ptr->DataSize(); + } + DumpObject(ptr); + //Don't let the stream get too big. + NANOCLR_CHECK_HRESULT(Stream_Send()); + } + } + NANOCLR_FOREACH_NODE_END(); + + { + //Send HeapDump End Marker + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Stop, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( heapSize ); + NANOCLR_CHECK_HRESULT(Stream_Send()); + } + + NANOCLR_CLEANUP(); + + //Flush out all data we've collected. Stopping the device without informing the program is a bad idea. + Stream_Flush(); + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_PRF_Profiler::DumpRoots() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + + //Root proto: + //8bits: CLR_PRF_CMDS::c_Profiling_HeapDump_Root + //32bits: Address of Root + //3bits: Source of Root: Finalizer, AppDomain, Assembly, Thread, Stack? + //Only when source is Stack??: 32bits: CLR_RT_MethodDef_Index + + //Iterate through all the finalizers + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersPending) + { + _ASSERTE(fin->m_object); + _ASSERTE(fin->m_object->DataType() != DATATYPE_FREEBLOCK); + _ASSERTE(fin->m_object->DataType() != DATATYPE_CACHEDBLOCK); + + DumpRoot(fin->m_object, CLR_PRF_CMDS::RootTypes::Root_Finalizer, 0, NULL); + } + NANOCLR_FOREACH_NODE_END(); + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersAlive) + { + _ASSERTE(fin->m_object); + _ASSERTE(fin->m_object->DataType() != DATATYPE_FREEBLOCK); + _ASSERTE(fin->m_object->DataType() != DATATYPE_CACHEDBLOCK); + + DumpRoot(fin->m_object, CLR_PRF_CMDS::RootTypes::Root_Finalizer, 0, NULL); + } + NANOCLR_FOREACH_NODE_END(); + +#if defined(NANOCLR_APPDOMAINS) + //Iterate through all the appdomains + NANOCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + DumpRoot(appDomain, CLR_PRF_CMDS::RootTypes::Root_AppDomain, 0, NULL); + } + NANOCLR_FOREACH_NODE_END(); +#endif + + //Iterate through all the assemblies. + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + DumpRoot( pASSM, CLR_PRF_CMDS::RootTypes::Root_Assembly, 0, NULL ); + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + { //Iterate through all threads. + CLR_RT_DblLinkedList* threadLists[ 2 ] = { &g_CLR_RT_ExecutionEngine.m_threadsReady, &g_CLR_RT_ExecutionEngine.m_threadsWaiting }; + for(int list = 0; list < 2; list++) + { + NANOCLR_FOREACH_NODE(CLR_RT_Thread,th,*threadLists[ list ]) + { + DumpRoot( th, CLR_PRF_CMDS::RootTypes::Root_Thread, 0, NULL ); + } + NANOCLR_FOREACH_NODE_END(); + } + } + + NANOCLR_CHECK_HRESULT(Stream_Send()); + + NANOCLR_NOCLEANUP(); +} + +void CLR_PRF_Profiler::DumpRoot( CLR_RT_HeapBlock* root, CLR_UINT32 type, CLR_UINT32 flags, CLR_RT_MethodDef_Index* source ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Root, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( root ); + m_stream->WriteBits( type, CLR_PRF_CMDS::Bits::RootTypes ); + + _ASSERTE(!flags); + if(type == CLR_PRF_CMDS::RootTypes::Root_Stack) + { + PackAndWriteBits(*source); + } else { + _ASSERTE(source == NULL); + } +} + +void CLR_PRF_Profiler::DumpObject( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + //Object Proto: + // Free blocked and cached blocks are considered free memory and are not dumped. + // All other types: + // 8 bits - Profiling_HeapDump_Object + // 32 bit pointer + // 16 bit size + // 8 bit - DataType() const + // 32 bits are TypeDef info >>>> iff DataType == CLASSTYPE || DataType == VALUETYPE || DataType == SZARRAY <<<< + // 16 bits are Array Level info >>>> iff DataType == SZARRAY <<<< + // 1 bit - Reference Follows + // 0 - No more references. End of Packet + // 1 - 32-bit pointer to reference follows. Repeat. + + CLR_DataType dt = ptr->DataType(); + _ASSERTE(dt < DATATYPE_FIRST_INVALID); + _ASSERTE(sizeof(CLR_RT_HeapBlock) == 12); //HeapBlockObjectPacket in ProfilerPackets.cs assumes sizeof(CLR_RT_HeapBlock) == 12 + + if(dt != DATATYPE_FREEBLOCK && dt != DATATYPE_CACHEDBLOCK) + { + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Object, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( ptr ); + PackAndWriteBits( ptr->DataSize() ); + m_stream->WriteBits( (CLR_UINT32)dt,CLR_PRF_CMDS::Bits::DataType ); + + switch(dt) + { + case DATATYPE_BOOLEAN: + case DATATYPE_I1: + case DATATYPE_U1: + case DATATYPE_CHAR: + case DATATYPE_I2: + case DATATYPE_U2: + case DATATYPE_I4: + case DATATYPE_U4: + case DATATYPE_R4: + case DATATYPE_I8: + case DATATYPE_U8: + case DATATYPE_R8: + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + case DATATYPE_STRING: + //Boxed primitives.. All are non-pointer types -- no references. + case DATATYPE_REFLECTION: + //Has a reference to an assembly, but it's unlikely to be the only thing keeping the assembly alive. + case DATATYPE_BINARY_BLOB_HEAD: + //Unknown/unmanaged data-type. No references. + case DATATYPE_SUBTHREAD: + //Owned by a DATATYPE_THREAD; Don't dump back-reference. + case DATATYPE_MEMORY_STREAM_DATA: + //No references at all -- usually, and when not, its a pointer to an externally shown character buffer used for deserialization. + case DATATYPE_IO_PORT: + //No references for normal GPIO; there is a structure for interrupts, but that doesn't seem to be stored on the managed heap. + case DATATYPE_TIMER_HEAD: + case DATATYPE_LOCK_OWNER_HEAD: + case DATATYPE_LOCK_REQUEST_HEAD: + case DATATYPE_SERIALIZER_DUPLICATE: + case DATATYPE_SERIALIZER_STATE: + //No unique forward-looking references. + break; + + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + case DATATYPE_ARRAY_BYREF: +#if defined(NANOCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: +#endif + { + DumpSingleReference( ptr ); + break; + } + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + CLR_RT_TypeDef_Index idx = ptr->ObjectCls(); + _ASSERTE(NANOCLR_INDEX_IS_VALID(idx)); + PackAndWriteBits( idx ); + DumpSingleReference( ptr->ObjectLock() ); + DumpListOfReferences( ptr + 1, ptr->DataSize() - 1 ); //All items in list should have DataSize() == 1 therefore ptr->DataSize() - 1 == number of items in list. + break; + } + + case DATATYPE_SZARRAY: + { + //Special case needed to dump out array data type and levels. + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + PackAndWriteBits( array->ReflectionDataConst().m_data.m_type ); + PackAndWriteBits( array->ReflectionDataConst().m_levels ); + + if(array->m_fReference) + { + DumpListOfReferences( (CLR_RT_HeapBlock*)array->GetFirstElement(), array->m_numOfElements ); + } + break; + } + + case DATATYPE_ASSEMBLY: + { + CLR_RT_Assembly* assembly = (CLR_RT_Assembly*)ptr; + DumpSingleReference( assembly->m_pFile ); +#if !defined(NANOCLR_APPDOMAINS) + DumpListOfReferences( assembly->m_pStaticFields, assembly->m_iStaticFields ); +#endif + break; + } + + case DATATYPE_WEAKCLASS: + { + CLR_RT_HeapBlock_WeakReference* wr = (CLR_RT_HeapBlock_WeakReference*)ptr; + DumpSingleReference( wr->m_targetDirect ); + break; + } + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + DumpSingleReference( &dlg->m_object ); + break; + } + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* dlgList = (CLR_RT_HeapBlock_Delegate_List*)ptr; + DumpListOfReferences( dlgList->GetDelegates(), dlgList->m_length ); + break; + } + + case DATATYPE_THREAD: + { + CLR_RT_Thread* th = (CLR_RT_Thread*)ptr; + + DumpSingleReference( th->m_dlg ); + DumpSingleReference( th->m_currentException.Dereference() ); + + for(int i=0; im_nestedExceptionsPos; i++) + { + CLR_RT_HeapBlock* except = th->m_nestedExceptions[ i ].m_exception; + _ASSERTE(!except || except->DataType() == DATATYPE_CLASS || except->DataType() == DATATYPE_OBJECT); + DumpSingleReference( except ); + } + + DumpListOfReferences( th->m_locks); + DumpSingleReference ( th->m_waitForObject ); + DumpListOfReferences( th->m_stackFrames ); + DumpListOfReferences( th->m_subThreads ); + break; + } + + case DATATYPE_STACK_FRAME: + { + CLR_RT_StackFrame* stack = (CLR_RT_StackFrame*)ptr; + DumpListOfReferences( stack->m_arguments, stack->m_call.m_target->numArgs ); + DumpListOfReferences( stack->m_locals , stack->m_call.m_target->numLocals ); + DumpListOfReferences( stack->m_evalStack, stack->TopValuePosition() ); + break; + } + + case DATATYPE_OBJECT_TO_EVENT: + { + CLR_RT_ObjectToEvent_Source* otes = (CLR_RT_ObjectToEvent_Source*)ptr; + DumpSingleReference( otes->m_eventPtr ); //The managed object should reference this obj, which references the event. + break; + } + + case DATATYPE_LOCK_HEAD: + { + //Object points to Lock Head, Thread points to Lock Head, Lock Head points to list of lock owners and requests + CLR_RT_HeapBlock_Lock* lock = (CLR_RT_HeapBlock_Lock*)ptr; + DumpListOfReferences( lock->m_owners ); + DumpListOfReferences( lock->m_requests ); + break; + } + + case DATATYPE_ENDPOINT_HEAD: + { + CLR_RT_HeapBlock_EndPoint* ep = (CLR_RT_HeapBlock_EndPoint*)ptr; + DumpListOfReferences( ep->m_messages ); + break; + } + + case DATATYPE_WAIT_FOR_OBJECT_HEAD: + { + CLR_RT_HeapBlock_WaitForObject* wfo = (CLR_RT_HeapBlock_WaitForObject*)ptr; + DumpListOfReferences(wfo->GetWaitForObjects(), wfo->m_cObjects); + break; + } + + case DATATYPE_FINALIZER_HEAD: + { + CLR_RT_HeapBlock_Finalizer* f = (CLR_RT_HeapBlock_Finalizer*)ptr; + DumpSingleReference( f->m_object ); + break; + } + + case DATATYPE_MEMORY_STREAM_HEAD: + { + CLR_RT_HeapBlock_MemoryStream* ms = (CLR_RT_HeapBlock_MemoryStream*)ptr; + DumpListOfReferences( ms->m_buffers ); + break; + } + + case DATATYPE_SERIALIZER_HEAD: + { + CLR_RT_BinaryFormatter* bf = (CLR_RT_BinaryFormatter*)ptr; + DumpSingleReference ( bf->m_stream ); + DumpListOfReferences( bf->m_duplicates ); + DumpListOfReferences( bf->m_states ); + break; + } + +#if defined(NANOCLR_APPDOMAINS) + case DATATYPE_APPDOMAIN_HEAD: + { + CLR_RT_AppDomain* appDomain = (CLR_RT_AppDomain*)ptr; + DumpListOfReferences( appDomain->m_appDomainAssemblies ); + DumpSingleReference ( appDomain->m_globalLock ); + DumpSingleReference ( appDomain->m_strName ); + DumpSingleReference ( appDomain->m_outOfMemoryException ); + break; + } + + case DATATYPE_APPDOMAIN_ASSEMBLY: + { + CLR_RT_AppDomainAssembly* appDomainAssembly = (CLR_RT_AppDomainAssembly*)ptr; + DumpListOfReferences( appDomainAssembly->m_pStaticFields, appDomainAssembly->m_assembly->m_iStaticFields ); + break; + } +#endif + + default: + _ASSERTE(false); + break; + } + DumpEndOfRefsList(); + } //if(dt != DATATYPE_FREEBLOCK && dt != DATATYPE_CACHEDBLOCK) +} + +CLR_RT_HeapBlock* CLR_PRF_Profiler::FindReferencedObject(CLR_RT_HeapBlock* ref) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + while(ref) + { + CLR_DataType dt = ref->DataType(); + switch(dt) + { + case DATATYPE_BYREF: + case DATATYPE_OBJECT: + ref = ref->Dereference(); + break; +#if defined(NANOCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + ref = ref->TransparentProxyDereference(); + break; +#endif + case DATATYPE_ARRAY_BYREF: + ref = ref->Array(); + default: + return ref; + } + } + return NULL; +} + +void CLR_PRF_Profiler::DumpEndOfRefsList() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SendFalse(); +} + +void CLR_PRF_Profiler::DumpPointer(void* ptr) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + PackAndWriteBits( (CLR_UINT32)((CLR_UINT8*)ptr - s_CLR_RT_Heap.m_location) ); +} + +void CLR_PRF_Profiler::DumpSingleReference(CLR_RT_HeapBlock* ptr) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + ptr = FindReferencedObject(ptr); + if(ptr) + { + SendTrue(); + DumpPointer(ptr); + } +} + +void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_HeapBlock* firstItem, CLR_UINT16 count) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_RT_HeapBlock* ptr; + for(ptr = firstItem; count > 0; ptr += ptr->DataSize(), count--) + { + DumpSingleReference(ptr); + } +} + +void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_DblLinkedList& list) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node, ptr, list) + { + DumpSingleReference(ptr); + } + NANOCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_PRF_Profiler::Timestamp() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + //Send Profiling Timestamp + CLR_UINT32 time = (CLR_UINT32)((HAL_Time_CurrentTime() + ((CLR_UINT64)((1ull << CLR_PRF_CMDS::Bits::TimestampShift) - 1))) + >> CLR_PRF_CMDS::Bits::TimestampShift); + if(time > m_lastTimestamp) + { + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Timestamp, CLR_PRF_CMDS::Bits::CommandHeader); + PackAndWriteBits(time - m_lastTimestamp); + Stream_Send(); + m_lastTimestamp = time; + } +} + +//--// + +#if defined(NANOCLR_PROFILE_NEW_CALLS) +HRESULT CLR_PRF_Profiler::RecordContextSwitch(CLR_RT_Thread* nextThread) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + _ASSERTE(nextThread); + + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + if(CLR_EE_PRF_IS(Calls)) + { + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Calls_CtxSwitch, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( nextThread->m_pid ); + m_currentThreadPID = nextThread->m_pid; + NANOCLR_CHECK_HRESULT(Stream_Send()); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::RecordFunctionCall(CLR_RT_Thread* th, CLR_RT_MethodDef_Index md) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + _ASSERTE(th); + + if(CLR_EE_PRF_IS(Calls)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + if(th->m_pid != m_currentThreadPID) + { + NANOCLR_CHECK_HRESULT(RecordContextSwitch( th )); + } + else + { + Timestamp(); + } + + _ASSERTE(th->m_pid == m_currentThreadPID); + + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Calls_Call, CLR_PRF_CMDS::Bits::CommandHeader); + + if(md.Assembly() == m_currentAssembly) + { + SendFalse(); + } + else + { + SendTrue(); + m_currentAssembly = md.Assembly(); + PackAndWriteBits(m_currentAssembly); + } + PackAndWriteBits(md.Method()); + NANOCLR_CHECK_HRESULT(Stream_Send()); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::RecordFunctionReturn(CLR_RT_Thread* th, CLR_PROF_CounterCallChain& prof) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + _ASSERTE(th); + + if(CLR_EE_PRF_IS(Calls)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + if(th->m_pid != m_currentThreadPID) + { + NANOCLR_CHECK_HRESULT(RecordContextSwitch( th )); + } + else + { + Timestamp(); + } + + _ASSERTE(th->m_pid == m_currentThreadPID); + + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Calls_Return, CLR_PRF_CMDS::Bits::CommandHeader); + PackAndWriteBits((CLR_UINT32)(prof.m_time_exclusive >> CLR_PRF_CMDS::Bits::CallTimingShift)); + NANOCLR_CHECK_HRESULT(Stream_Send()); + } + + NANOCLR_NOCLEANUP(); +} +#endif + +//--// + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + +void CLR_PRF_Profiler::TrackObjectCreation( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + _ASSERTE(ptr); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_UINT8 dt = ptr->DataType(); + if(dt != DATATYPE_STACK_FRAME && dt != DATATYPE_BINARY_BLOB_HEAD) + { + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Allocs_Alloc, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( ptr ); + PackAndWriteBits( ptr->DataSize() ); + m_stream->WriteBits( (CLR_UINT32)dt, CLR_PRF_CMDS::Bits::DataType ); + if(dt == DATATYPE_CLASS || dt == DATATYPE_VALUETYPE) + { + PackAndWriteBits( ptr->ObjectCls() ); + } + else if(dt == DATATYPE_SZARRAY) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + PackAndWriteBits( array->ReflectionDataConst().m_data.m_type ); + PackAndWriteBits( array->ReflectionDataConst().m_levels ); + } + Stream_Send(); + } + } +} + +void CLR_PRF_Profiler::TrackObjectDeletion( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + _ASSERTE(ptr); + + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_UINT8 dt = ptr->DataType(); + if(dt != DATATYPE_STACK_FRAME && dt != DATATYPE_CACHEDBLOCK ) + { + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Allocs_Delete, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( ptr ); + Stream_Send(); + } + } +} + +void CLR_PRF_Profiler::TrackObjectRelocation() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_RT_GarbageCollector::RelocationRegion* relocBlocks = g_CLR_RT_GarbageCollector.m_relocBlocks; + size_t relocCount = g_CLR_RT_GarbageCollector.m_relocCount; + + Timestamp(); + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Allocs_Relloc, CLR_PRF_CMDS::Bits::CommandHeader); + PackAndWriteBits(( CLR_UINT32)relocCount ); + + for(size_t i = 0; i < relocCount; i++) + { + DumpPointer( relocBlocks[ i ].m_start); + DumpPointer( relocBlocks[ i ].m_end ); + PackAndWriteBits( relocBlocks[i].m_offset ); + } + } +} + +void CLR_PRF_Profiler::RecordGarbageCollectionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_GarbageCollect_Begin, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +void CLR_PRF_Profiler::RecordGarbageCollectionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_GarbageCollect_End, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +void CLR_PRF_Profiler::RecordHeapCompactionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapCompact_Begin, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +void CLR_PRF_Profiler::RecordHeapCompactionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapCompact_End, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +#endif + +//--// + +void CLR_PRF_Profiler::SendTrue() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_stream->WriteBits( (CLR_UINT32)1, 1 ); +} + +void CLR_PRF_Profiler::SendFalse() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_stream->WriteBits( (CLR_UINT32)0, 1 ); +} + +void CLR_PRF_Profiler::PackAndWriteBits(CLR_UINT32 value) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + /* In three different scenarios tested, sending nibbles instead of bytes and 2-bit hunks resulted + * in the most efficiency over the wire. It also involves less code than 2-bit hunks that I expected to win, + * so that's the method used. + */ + _ASSERTE(sizeof(CLR_UINT32) == 4); + + const CLR_UINT32 SHIFT_PER_NIBBLE = 2; //2^2 = 4 bits per nibble + CLR_UINT32 nibbles = 1; + if( value & 0xF0000000) { nibbles = 8; } + else if(value & 0x0F000000) { nibbles = 7; } + else if(value & 0x00F00000) { nibbles = 6; } + else if(value & 0x000F0000) { nibbles = 5; } + else if(value & 0x0000F000) { nibbles = 4; } + else if(value & 0x00000F00) { nibbles = 3; } + else if(value & 0x000000F0) { nibbles = 2; } + + m_stream->WriteBits( nibbles - 1, CLR_PRF_CMDS::Bits::NibbleCount ); + m_stream->WriteBits( value, nibbles << SHIFT_PER_NIBBLE ); +} + +void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_TypeDef_Index& typeDef) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + PackAndWriteBits( typeDef.Assembly() ); + PackAndWriteBits( typeDef.Type() ); +} + +void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_MethodDef_Index& methodDef) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + PackAndWriteBits( methodDef.Assembly() ); + PackAndWriteBits( methodDef.Method() ); +} + +//--// + +HRESULT CLR_PRF_Profiler::Stream_Send() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + + const int BUFFER_THRESHOLD_BYTES = CLR_RT_HeapBlock_MemoryStream::Buffer::c_PayloadSize * 2 / 3; + const int BUFFER_THRESHOLD_BITS = BUFFER_THRESHOLD_BYTES << 3; + + if(m_stream->BitsWritten() >= BUFFER_THRESHOLD_BITS) + { + NANOCLR_CHECK_HRESULT(Stream_Flush()); + } + //else { Stream isn't above threshold; allow to cache. } + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::Stream_Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + NANOCLR_HEADER(); + + //These need to be paired; If this function is ever used to send multiple stream types, each should get their own packet sequence id. + const CLR_UINT32 messageType = CLR_DBG_Commands::c_Profiling_Stream; + + CLR_UINT8 buffer[ 2*sizeof(CLR_UINT16) + CLR_RT_HeapBlock_MemoryStream::Buffer::c_PayloadSize ]; + CLR_DBG_Commands::Profiling_Stream* packet = (CLR_DBG_Commands::Profiling_Stream*)buffer; + + NANOCLR_FOREACH_NODE(CLR_RT_HeapBlock_MemoryStream::Buffer, ptr, m_stream->m_buffers) + { + int payloadLength = ptr->m_length; + if(payloadLength > 0) + { + _ASSERTE(sizeof(ptr->m_payload) == CLR_RT_HeapBlock_MemoryStream::Buffer::c_PayloadSize); + + int bitLength = payloadLength * 8; + if(ptr == m_stream->m_current) + { + bitLength -= m_stream->m_avail; + } + + packet->m_bitLen = bitLength; + packet->m_seqId = m_packetSeqId++; + memcpy(&packet[ 1 ], ptr->m_payload, payloadLength); + + int packetLength = sizeof(CLR_DBG_Commands::Profiling_Stream) + payloadLength; + if(!CLR_EE_DBG_EVENT_SEND(messageType, packetLength, buffer, WP_Flags_c_NonCritical)) + { + _ASSERTE(false); + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + //Don't go past the cursor. + if(ptr == m_stream->m_current) { break; } + } + NANOCLR_FOREACH_NODE_END(); + + m_stream->Reset(); + + NANOCLR_NOCLEANUP(); +} + +#endif //#if defined(NANOCLR_PROFILE_NEW) + diff --git a/source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.c b/source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.c new file mode 100644 index 00000000..7c07298a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.c @@ -0,0 +1,104 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) https://www.mycplus.com. All Rights Reserved. +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////////////////////// +// we are using the function declarations matching the mbedTLS ones BUT with weak attribute // +// if the image includes the mbedTLS, these will be replaced by the strong ones from there // +// thus there will be no duplicate code // +////////////////////////////////////////////////////////////////////////////////////////////// + +#include "base64.h" + +void build_decoding_table(char *decoding_table ) +{ + if(decoding_table != NULL) + { + for (int i = 0; i < 64; i++) + decoding_table[(unsigned char) base64_enc_map[i]] = i; + } +} + +__nfweak int mbedtls_base64_encode( + unsigned char *dst, + size_t dlen, + size_t *olen, + const unsigned char *src, size_t slen ) +{ + // parameter not used + (void)dlen; + + for (unsigned int i = 0, j = 0; i < slen;) + { + int octet_a = i < slen ? (unsigned char)src[i++] : 0; + int octet_b = i < slen ? (unsigned char)src[i++] : 0; + int octet_c = i < slen ? (unsigned char)src[i++] : 0; + + int triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; + + dst[j++] = base64_enc_map[(triple >> 3 * 6) & 0x3F]; + dst[j++] = base64_enc_map[(triple >> 2 * 6) & 0x3F]; + dst[j++] = base64_enc_map[(triple >> 1 * 6) & 0x3F]; + dst[j++] = base64_enc_map[(triple >> 0 * 6) & 0x3F]; + } + + for (unsigned int i = 0; i < mod_table[slen % 3]; i++) + dst[*olen - 1 - i] = '='; + + // add terminator + dst[*olen] = 0; + + return 0; +} + +__nfweak int mbedtls_base64_decode( + unsigned char *dst, + size_t dlen, + size_t *olen, + const unsigned char *src, size_t slen ) +{ + // parameter not used + (void)dlen; + + char *decoding_table = (char*)platform_malloc(256); + + if (decoding_table == NULL) + { + // OK to return anything but 0 + // we are forced to use mbedTLS behaviour anyway + return -1; + } + + build_decoding_table(decoding_table); + + if (slen % 4 != 0) + { + // OK to return anything but 0 + // we are forced to use mbedTLS behaviour anyway + return -1; + } + + for (unsigned int i = 0, j = 0; i < slen;) { + + int sextet_a = src[i] == '=' ? 0 & i++ : decoding_table[src[i++]]; + int sextet_b = src[i] == '=' ? 0 & i++ : decoding_table[src[i++]]; + int sextet_c = src[i] == '=' ? 0 & i++ : decoding_table[src[i++]]; + int sextet_d = src[i] == '=' ? 0 & i++ : decoding_table[src[i++]]; + + int triple = (sextet_a << 3 * 6) + + (sextet_b << 2 * 6) + + (sextet_c << 1 * 6) + + (sextet_d << 0 * 6); + + if (j < *olen) dst[j++] = (triple >> 2 * 8) & 0xFF; + if (j < *olen) dst[j++] = (triple >> 1 * 8) & 0xFF; + if (j < *olen) dst[j++] = (triple >> 0 * 8) & 0xFF; + } + + // free table + platform_free(decoding_table); + + return( 0 ); +} diff --git a/source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.h b/source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.h new file mode 100644 index 00000000..03ab6e61 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Helpers/Base64/base64.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) ARM Limited. All Rights Reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef __BASE64_H__ +#define __BASE64_H__ + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////////////////////// +// we are using the function declarations matching the mbedTLS ones BUT with weak attribute // +// if the image includes the mbedTLS, these will be replaced by the strong ones from there // +// thus there will be no duplicate code // +////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned int mod_table[3] = {0, 2, 1}; + +#ifdef __cplusplus +} +#endif + +#endif //__BASE64_H__ diff --git a/source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.c b/source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.c new file mode 100644 index 00000000..ab902bfc --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.c @@ -0,0 +1,496 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2001, 2002 Georges Menie. All rights reserved. +// Portions Copyright (c) 2009-2013 Daniel D Miller. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "printf.h" + +// ASCII character set... +#define NUL 0x00 +#define STX 0x02 +#define ETX 0x03 +#define EOT 0x04 +#define ACK 0x06 +#define BS 0x08 +#define LF 0x0A +#define CR 0x0D +#define DLE 0x10 +#define ESC 0x1B +#define SPC 0x20 +#define MAX_PRN 0x7E +#define DEL 0x7F + +//extern int putchar (int c); + +static unsigned int use_leading_plus = 0 ; + +static int max_output_len = -1 ; +static int curr_output_len = 0 ; + +unsigned int fixed_overrun = 0 ; +int last_bad_char = 0 ; +unsigned int invalid_char = 0 ; + +static void printchar (char **str, int c) +{ + if (max_output_len >= 0 && curr_output_len >= max_output_len) { + fixed_overrun++ ; + return ; + } + + // check for overrun of our stuff_talkf[] buffer +// if (curr_output_len >= TALK_LINE_LEN) { +// fixed_overrun++ ; +// return ; +// } + if (c > MAX_PRN) { + invalid_char++ ; + last_bad_char = c ; + c = '?' ; + } else + if (c < SPC) { // ASCII 32 = Space + switch (c) { + case CR: + case LF: + case STX: + case ETX: + break; + + default: + invalid_char++ ; + last_bad_char = c ; + c = '?' ; + break; + } + } + + if (str) { + **str = (char) c; + ++(*str); + curr_output_len++ ; + } +} + +//**************************************************************************** +// This version returns the length of the output string. +// It is more useful when implementing a walking-string function. +//**************************************************************************** +static const double round_nums[8] = { + 0.5, + 0.05, + 0.005, + 0.0005, + 0.00005, + 0.000005, + 0.0000005, + 0.00000005 +}; + +static unsigned dbl2stri(char *outbfr, double dbl, unsigned dec_digits) +{ + static char local_bfr[128] ; + char *output = (outbfr == 0) ? local_bfr : outbfr ; + + //******************************************* + // extract negative info + //******************************************* + if (dbl < 0.0) { + *output++ = '-' ; + dbl *= -1.0 ; + } else { + if (use_leading_plus) { + *output++ = '+' ; + } + + } + + // handling rounding by adding .5LSB to the floating-point data + if (dec_digits < 8) { + dbl += round_nums[dec_digits] ; + } + + //************************************************************************** + // construct fractional multiplier for specified number of digits. + //************************************************************************** + unsigned long long mult = 1 ; + unsigned int idx ; + for (idx=0; idx < dec_digits; idx++) + mult *= 10 ; + + // printf("mult=%u\n", mult) ; + unsigned int wholeNum = (unsigned int) dbl ; + unsigned long long decimalNum = (unsigned long long) ((dbl - wholeNum) * mult); + + //******************************************* + // convert integer portion + //******************************************* + char tbfr[40] ; + idx = 0 ; + while (wholeNum != 0) { + tbfr[idx++] = '0' + (wholeNum % 10) ; + wholeNum /= 10 ; + } + // printf("%.3f: whole=%s, dec=%d\n", dbl, tbfr, decimalNum) ; + if (idx == 0) { + *output++ = '0' ; + } else { + while (idx > 0) { + *output++ = tbfr[idx-1] ; //lint !e771 + idx-- ; + } + } + if (dec_digits > 0) { + *output++ = '.' ; + + //******************************************* + // convert fractional portion + //******************************************* + idx = 0 ; + while (decimalNum != 0) { + tbfr[idx++] = '0' + (decimalNum % 10) ; + decimalNum /= 10 ; + } + // pad the decimal portion with 0s as necessary; + // We wouldn't want to report 3.093 as 3.93, would we?? + while (idx < dec_digits) { + tbfr[idx++] = '0' ; + } + // printf("decimal=%s\n", tbfr) ; + if (idx == 0) { + *output++ = '0' ; + } else { + while (idx > 0) { + *output++ = tbfr[idx-1] ; + idx-- ; + } + } + } + *output = 0 ; + + // prepare output + output = (outbfr == 0) ? local_bfr : outbfr ; + return strlen(output) ; +} + +//**************************************************************************** +#define PAD_RIGHT 1 +#define PAD_ZERO 2 + +static int prints (char **out, const char *string, int width, int pad) +{ + // [831326121984], width=0, pad=0 + // printf("[%s], width=%u, pad=%u\n", string, width, pad) ; + register int pc = 0, padchar = ' '; + if (width > 0) { + int len = 0; + const char *ptr; + for (ptr = string; *ptr; ++ptr) + ++len; + if (len >= width) + width = 0; + else + width -= len; + if (pad & PAD_ZERO) + padchar = '0'; + } + if (!(pad & PAD_RIGHT)) { + for (; width > 0; --width) { + printchar (out, padchar); + ++pc; + } + } + for (; *string; ++string) { + printchar (out, *string); + ++pc; + } + for (; width > 0; --width) { + printchar (out, padchar); + ++pc; + } + return pc; +} + +//**************************************************************************** +/* the following should be enough for 32 bit int */ +// -2,147,483,648 +#define PRINT_BUF_LEN 12 + +static int printi (char **out, int i, unsigned int base, int sign, int width, int pad, int letbase) +{ + char print_buf[PRINT_BUF_LEN]; + char *s; + int t, neg = 0, pc = 0; + unsigned u = (unsigned) i; + if (i == 0) { + print_buf[0] = '0'; + print_buf[1] = '\0'; + return prints (out, print_buf, width, pad); + } + if (sign && base == 10 && i < 0) { + neg = 1; + u = (unsigned) -i; + } + // make sure print_buf is NULL-term + s = print_buf + PRINT_BUF_LEN - 1; + *s = '\0'; + + while (u) { + t = u % base; //lint !e573 !e737 !e713 Warning 573: Signed-unsigned mix with divide + if (t >= 10) + t += letbase - '0' - 10; + *--s = (char) t + '0'; + u /= base; //lint !e573 !e737 Signed-unsigned mix with divide + } + if (neg) { + if (width && (pad & PAD_ZERO)) { + printchar (out, '-'); + ++pc; + --width; + } + else { + *--s = '-'; + } + } else { + if (use_leading_plus) { + *--s = '+'; + } + } + return pc + prints (out, s, width, pad); +} + +//**************************************************************************** +/* the following should be enough for 64 bit int, without commas */ +// _UI64_MAX +// Maximum value for a variable of type unsigned __int64 +// xx..xx..xx..xx.. +// 18446744073709551615 (0xffffffffffffffff) +// -9223372036854775808 +// 18,446,744,073,709,551,615 +#define PRINT_LLBUF_LEN 22 + +static int printlli (char **out, long long i, unsigned int base, int sign, int width, int pad, int letbase) +{ + char print_buf[PRINT_LLBUF_LEN]; + char *s; + int t, neg = 0, pc = 0; + unsigned long long u = (unsigned long long) i; + if (i == 0) { + print_buf[0] = '0'; + print_buf[1] = '\0'; + return prints (out, print_buf, width, pad); + } + if (sign && base == 10 && i < 0) { + neg = 1; + u = (unsigned long long) -i; + } + // make sure print_buf is NULL-term + s = print_buf + PRINT_LLBUF_LEN - 1; + *s = '\0'; + + while (u) { + t = u % base; //lint !e573 !e737 !e713 Warning 573: Signed-unsigned mix with divide + if (t >= 10) + t += letbase - '0' - 10; + *--s = (char) t + '0'; + u /= base; //lint !e573 !e737 Signed-unsigned mix with divide + } + if (neg) { + if (width && (pad & PAD_ZERO)) { + printchar (out, '-'); + ++pc; + --width; + } + else { + *--s = '-'; + } + } else { + if (use_leading_plus) { + *--s = '+'; + } + } + return pc + prints (out, s, width, pad); +} + +//**************************************************************************** +static int print (char **out, const char *format, va_list va) +{ + int post_decimal ; + int width, pad ; + unsigned dec_width = 6 ; + int pc = 0; + char scr[2]; + + use_leading_plus = 0 ; // start out with this clear + for (; *format != 0; ++format) { + if (*format == '%') { + dec_width = 6 ; + ++format; + width = pad = 0; + if (*format == '\0') + break; + if (*format == '%') + goto out_lbl; + if (*format == '-') { + ++format; + pad = PAD_RIGHT; + } + if (*format == '+') { + ++format; + use_leading_plus = 1 ; + } + while (*format == '0') { + ++format; + pad |= PAD_ZERO; + } + post_decimal = 0 ; + if (*format == '.' || + (*format >= '0' && *format <= '9')) { + + while (1) { + if (*format == '.') { + post_decimal = 1 ; + dec_width = 0 ; + format++ ; + } else if ((*format >= '0' && *format <= '9')) { + if (post_decimal) { + dec_width *= 10; + dec_width += (unsigned int) (char) (*format - '0'); + } else { + width *= 10; + width += *format - '0'; + } + format++ ; + } else { + break; + } + } + } + unsigned int use_longlong = 0 ; + if (*format == 'l') { + ++format; + if (*format == 'l') { + ++format; + use_longlong = 1 ; + } + } + switch (*format) { + case 's': + { + char *s = va_arg(va, char *); + pc += prints (out, s ? s : "(null)", width, pad); + use_leading_plus = 0 ; // reset this flag after printing one value + } + break; + case 'd': + if (use_longlong) { + pc += printlli(out, va_arg(va, long long), 10, 1, width, pad, 'a'); + } + else { + pc += printi (out, va_arg(va, int), 10, 1, width, pad, 'a'); + } + use_leading_plus = 0 ; // reset this flag after printing one value + break; + case 'x': + if (use_longlong) { + pc += printlli(out, va_arg(va, long long), 16, 0, width, pad, 'a'); + } + else { + pc += printi (out, va_arg(va, int), 16, 0, width, pad, 'a'); + } + use_leading_plus = 0 ; // reset this flag after printing one value + break; + case 'X': + if (use_longlong) { + pc += printlli(out, va_arg(va, long long), 16, 0, width, pad, 'A'); + } + else { + pc += printi (out, va_arg(va, int), 16, 0, width, pad, 'A'); + } + use_leading_plus = 0 ; // reset this flag after printing one value + break; + case 'p': + case 'u': + if (use_longlong) { + pc += printlli(out, va_arg(va, unsigned long long), 10, 0, width, pad, 'a'); + } + else { + pc += printi (out, va_arg(va, unsigned int), 10, 0, width, pad, 'a'); + } + use_leading_plus = 0 ; // reset this flag after printing one value + break; + case 'c': + /* char are converted to int then pushed on the stack */ + scr[0] = (char)va_arg(va, int); + scr[1] = '\0'; + pc += prints (out, scr, width, pad); + use_leading_plus = 0 ; // reset this flag after printing one value + break; + + case 'f': + { + char bfr[81] ; + dbl2stri(bfr, va_arg(va, double), dec_width) ; + // stuff_talkf("[%s], width=%u, dec_width=%u\n", bfr, width, dec_width) ; + pc += prints (out, bfr, width, pad); + use_leading_plus = 0 ; // reset this flag after printing one value + } + break; + + default: + printchar (out, '%'); + printchar (out, *format); + use_leading_plus = 0 ; // reset this flag after printing one value + break; + } + } else + // if (*format == '\\') { + // + // } else + { +out_lbl: + printchar (out, *format); + ++pc; + } + } // for each char in format string + if (out) //lint !e850 + **out = '\0'; + return pc; +} + +//**************************************************************************** +int tiny_sprintf (char *out, const char *format, ...) +{ + max_output_len = -1 ; + curr_output_len = 0 ; + + va_list va; + va_start(va,format); + int count = print (&out, format, va); + va_end(va); + + return count; +} + +//**************************************************************************** +int tiny_snprintf(char *out, unsigned int max_len, const char *format, ...) +{ + max_output_len = (int) max_len ; + curr_output_len = 0 ; + + va_list va; + va_start(va,format); + int count = print (&out, format, va); + va_end(va); + + return count; +} + +int tiny_vsnprintf(char *out, unsigned int max_len, const char *format, va_list va) +{ + max_output_len = (int) max_len; + curr_output_len = 0; + + return print(&out, format, va); +} diff --git a/source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.h b/source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.h new file mode 100644 index 00000000..4ff4c076 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Helpers/TinyPrintf/printf.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2001, 2002 Georges Menie. All rights reserved. +// Portions Copyright (c) 2009-2013 Daniel D Miller. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef __TFP_PRINTF__ +#define __TFP_PRINTF__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int tiny_sprintf (char *out, const char *format, ...); +int tiny_snprintf(char *out, unsigned int max_len, const char *format, ...); +int tiny_vsnprintf(char *out, unsigned int max_len, const char *format, va_list va); + +#ifdef __cplusplus +} +#endif + +// the defines below allow using the regular calls to sprintf +#define sprintf tiny_sprintf +#define snprintf tiny_snprintf +#define vsnprintf tiny_vsnprintf + +#endif diff --git a/source/native/nf-interpreter/src/CLR/Include/WireProtocol.h b/source/native/nf-interpreter/src/CLR/Include/WireProtocol.h new file mode 100644 index 00000000..6a69c753 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/WireProtocol.h @@ -0,0 +1,211 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_H_ +#define _WIREPROTOCOL_H_ + +#include +#include +#include +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) +#endif + +#define MARKER_DEBUGGER_V1 "NFDBGV1" // Used to identify the debugger at boot time. +#define MARKER_PACKET_V1 "NFPKTV1" // Used to identify the start of a packet. + +#ifndef WP_PACKET_SIZE +// no Wire Protocol defined at target_common, set to default as 1024 +#define WP_PACKET_SIZE 1024U +#endif + +// enum with Wire Protocol flags +// backwards compatible with .NETMF +typedef enum WP_Flags +{ + WP_Flags_c_NonCritical = 0x0001, // This doesn't need an acknowledge. + WP_Flags_c_Reply = 0x0002, // This is the result of a command. + WP_Flags_c_BadHeader = 0x0004, + WP_Flags_c_BadPayload = 0x0008, + WP_Flags_c_Spare0010 = 0x0010, + WP_Flags_c_Spare0020 = 0x0020, + WP_Flags_c_Spare0040 = 0x0040, + WP_Flags_c_Spare0080 = 0x0080, + WP_Flags_c_Spare0100 = 0x0100, + WP_Flags_c_Spare0200 = 0x0200, + WP_Flags_c_Spare0400 = 0x0400, + WP_Flags_c_Spare0800 = 0x0800, + WP_Flags_c_Spare1000 = 0x1000, + WP_Flags_c_NoCaching = 0x2000, + WP_Flags_c_NACK = 0x4000, + WP_Flags_c_ACK = 0x8000 +}WP_Flags; + +// enum with machine states for Wire Procotol receiver +typedef enum ReceiveState +{ + ReceiveState_Idle = (1 << 0), + ReceiveState_Initialize = (2 << 0), + ReceiveState_WaitingForHeader = (3 << 0), + ReceiveState_ReadingHeader = (4 << 0), + ReceiveState_CompleteHeader = (5 << 0), + ReceiveState_ReadingPayload = (6 << 0), + ReceiveState_CompletePayload = (7 << 0), +}ReceiveState; + +// enum with CLR monitor commands +// backwards compatible with .NETMF +typedef enum CLR_DBG_Commands_Monitor +{ + CLR_DBG_Commands_c_Monitor_Ping = 0x00000000, // The payload is empty, this command is used to let the other side know we are here... + CLR_DBG_Commands_c_Monitor_Message = 0x00000001, // The payload is composed of the string characters, no zero at the end. + CLR_DBG_Commands_c_Monitor_ReadMemory = 0x00000002, + CLR_DBG_Commands_c_Monitor_WriteMemory = 0x00000003, + CLR_DBG_Commands_c_Monitor_CheckMemory = 0x00000004, + CLR_DBG_Commands_c_Monitor_EraseMemory = 0x00000005, + CLR_DBG_Commands_c_Monitor_Execute = 0x00000006, + CLR_DBG_Commands_c_Monitor_Reboot = 0x00000007, + CLR_DBG_Commands_c_Monitor_MemoryMap = 0x00000008, + CLR_DBG_Commands_c_Monitor_ProgramExit = 0x00000009, // The payload is empty, this command is used to tell the PC of a program termination + CLR_DBG_Commands_c_Monitor_CheckSignature = 0x0000000A, + CLR_DBG_Commands_c_Monitor_DeploymentMap = 0x0000000B, + CLR_DBG_Commands_c_Monitor_FlashSectorMap = 0x0000000C, + CLR_DBG_Commands_c_Monitor_OemInfo = 0x0000000E, + CLR_DBG_Commands_c_Monitor_QueryConfiguration = 0x0000000F, + CLR_DBG_Commands_c_Monitor_UpdateConfiguration = 0x00000010, +}CLR_DBG_Commands_Monitor; + +// structure for Wire Protocol packet +// backwards compatible with .NETMF +typedef struct WP_Packet +{ + uint8_t m_signature[8]; + uint32_t m_crcHeader; + uint32_t m_crcData; + + uint32_t m_cmd; + uint16_t m_seq; + uint16_t m_seqReply; + uint32_t m_flags; + uint32_t m_size; +}WP_Packet; + +typedef struct WP_Controller +{ + uint8_t* m_szMarker; + + uint16_t m_lastOutboundMessage; + + bool (*AdvanceState)(void); + void (*Initialize)(void* szMarker, void* phy, void* app, void* state ); + //bool (*SendProtocolMessage)( const void* msg ); + bool (*SendProtocolMessage)( uint32_t cmd, uint32_t flags, uint32_t payloadSize, uint8_t* payload); + +}WP_Controller; + +// structure for Wire Protocol message +// backwards compatible with .NETMF equivalent in names and types to help code reuse +typedef struct WP_Message +{ + WP_Packet m_header; + uint8_t* m_payload; + + uint8_t* m_pos; + uint16_t m_size; + uint64_t m_payloadTicks; + int m_rxState; + + void (*Initialize)(WP_Controller* parent); + void (*PrepareReception)(void); + void (*PrepareRequest)(unsigned int cmd, unsigned int flags, unsigned int payloadSize, unsigned char* payload); + void (*PrepareReply)(const void** req, unsigned int flags, unsigned int payloadSize, unsigned char* payload); + void (*SetPayload)(unsigned char* payload); + void (*Release)(void); + bool (*Process)(void); + + bool (*VerifyHeader)(void); + bool (*VerifyPayload)(void); + void (*ReplyBadPacket)(unsigned int flags); + +}WP_Message; + + +// enum with flags for Monitor ping source and debugger flags +/////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Monitor_Ping (in debugger library code) !!! // +/////////////////////////////////////////////////////////////////////// +typedef enum Monitor_Ping_Source_Flags +{ + Monitor_Ping_c_Ping_Source_NanoCLR = 0x00010000, + Monitor_Ping_c_Ping_Source_NanoBooter = 0x00010001, + + Monitor_Ping_c_Ping_DbgFlag_Stop = 0x00000001, + Monitor_Ping_c_Ping_DbgFlag_AppExit = 0x00000004, + + // flags specific to Wire Protocol capabilities + Monitor_Ping_c_Ping_WPFlag_SupportsCRC32 = 0x00000010, + + // Wire Protocol packet size (3rd position) + Monitor_Ping_c_PacketSize_1024 = 0x00000100, + Monitor_Ping_c_PacketSize_0512 = 0x00000200, + Monitor_Ping_c_PacketSize_0256 = 0x00000300, + Monitor_Ping_c_PacketSize_0128 = 0x00000400, + +}Monitor_Ping_Source_Flags; + + +// structure to hold 'standard' version information +// equivalent with .NETMF MFVersion +typedef struct VersionInfo +{ + unsigned short usMajor; + unsigned short usMinor; + unsigned short usBuild; + unsigned short usRevision; + +}VersionInfo; + +// structure to hold nanoFramework release information +// equivalent with .NETMF MfReleaseInfo +typedef struct ReleaseInfo +{ + + VersionInfo version; + uint8_t InfoString[128]; + uint8_t TargetName[32]; + uint8_t PlatformName[32]; + +}ReleaseInfo; + +// structure for Wire Protocol command handler lookup +typedef struct CommandHandlerLookup +{ + // command code goes here + uint32_t command; + + // pointer to handler function + void* handler; + +}CommandHandlerLookup; + +// This structure is never used, its purpose is to generate a compiler error in case the size of any structure changes. +struct WP_CompileCheck +{ + char buf1[ sizeof(WP_Packet) == 8 * 4 ? 1 : -1 ]; +}; + +#endif // _WIREPROTOCOL_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/WireProtocol_App_Interface.h b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_App_Interface.h new file mode 100644 index 00000000..fa3c1335 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_App_Interface.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_APP_INTERFACE_H_ +#define _WIREPROTOCOL_APP_INTERFACE_H_ + +#include "WireProtocol.h" + +////////////////////////////////////////// +extern uint8_t receptionBuffer[sizeof(WP_Packet) + WP_PACKET_SIZE]; +extern void ReplyToCommand(WP_Message* message, int fSuccess, int fCritical, void* ptr, int size); + +////////////////////////////////////////// +int WP_App_ProcessHeader(WP_Message* message); +int WP_App_ProcessPayload(WP_Message* message); + +#endif // _WIREPROTOCOL_APP_INTERFACE_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/WireProtocol_HAL_Interface.h b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_HAL_Interface.h new file mode 100644 index 00000000..9bcbb463 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_HAL_Interface.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_HAL_INTERFACE_H_ +#define _WIREPROTOCOL_HAL_INTERFACE_H_ + +#include "WireProtocol.h" + +////////////////////////////////////////// +int WP_ReceiveBytes(uint8_t* ptr, unsigned short* size); +int WP_TransmitMessage(WP_Message* message); +void WP_CheckAvailableIncomingData(); + +#endif // _WIREPROTOCOL_HAL_INTERFACE_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/WireProtocol_Message.h b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_Message.h new file mode 100644 index 00000000..703058b3 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_Message.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_MESSAGE_H_ +#define _WIREPROTOCOL_MESSAGE_H_ + +#include "WireProtocol.h" +#include "WireProtocol_App_Interface.h" +#include "WireProtocol_HAL_Interface.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#define TRACE_ERRORS 1 +#define TRACE_HEADERS 2 +#define TRACE_STATE 4 +#define TRACE_NODATA 8 + +#if TRACE_MASK != 0 +#define TRACE0( f, msg ) if((f) & TRACE_MASK ) debug_printf( msg ) +#define TRACE( f, msg, ...) if((f) & TRACE_MASK ) debug_printf( msg, __VA_ARGS__ ) +#else +#define TRACE0(msg,...) +#define TRACE(msg,...) +#endif + +//////////////////////////////////////////////////// +// function declarations (related with WP_Message) + +#ifdef __cplusplus +extern "C" { +#endif + +void WP_Message_Initialize(WP_Message* message); +void WP_Message_PrepareReception(WP_Message* message); +void WP_Message_PrepareRequest(WP_Message* message, uint32_t cmd, uint32_t flags, uint32_t payloadSize, uint8_t* payload); +void WP_Message_PrepareReply(WP_Message* message, const WP_Packet* req, uint32_t flags, uint32_t payloadSize, uint8_t* payload); +void WP_Message_SetPayload(WP_Message* message, uint8_t* payload); +void WP_Message_Release(WP_Message* message); +int WP_Message_VerifyHeader(WP_Message* message); +int WP_Message_VerifyPayload(WP_Message* message); +void WP_Message_ReplyBadPacket(uint32_t flags); +int WP_Message_Process(WP_Message* message); + +#ifdef __cplusplus +} +#endif + +////////////////////////////////////////// +// helper functions + +#ifdef __cplusplus +extern "C" { +#endif + +void WP_ReplyToCommand(WP_Message* message, int fSuccess, int fCritical, void* ptr, int size); +void WP_SendProtocolMessage(WP_Message *message); +void WP_PrepareAndSendProtocolMessage(uint32_t cmd, uint32_t payloadSize, uint8_t* payload, uint32_t flags); + +#ifdef __cplusplus +} +#endif + +#endif // _WIREPROTOCOL_MESSAGE_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/WireProtocol_MonitorCommands.h b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_MonitorCommands.h new file mode 100644 index 00000000..f2cea51c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/WireProtocol_MonitorCommands.h @@ -0,0 +1,198 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_COMMANDS_H_ +#define _WIREPROTOCOL_COMMANDS_H_ + +#include "WireProtocol.h" +#include "WireProtocol_Message.h" + +////////////////////////////////////////// +// enums + +// structure for Monitor Reboot options +// backwards compatible with .NETMF +typedef enum Monitor_Reboot_Options +{ + Monitor_Reboot_c_NormalReboot = 0, + Monitor_Reboot_c_EnterBootloader = 1, + Monitor_Reboot_c_ClrRebootOnly = 2, + Monitor_Reboot_c_ClrStopDebugger = 4 +}Monitor_Reboot_Options; + +// structure for Access Memory operations +typedef enum AccessMemory_Operations +{ + // check if memory space is erased + AccessMemory_Check = 0x00, + + // read block of data starting at a given address + AccessMemory_Read = 0x01, + + // write block of data starting at a given address + AccessMemory_Write = 0x02, + + // erase sector/block/page at a given address + AccessMemory_Erase = 0x03, + + + AccessMemory_Mask = 0x0F + +}AccessMemory_Operations; + +typedef enum MemoryMap_Options +{ + Monitor_MemoryMap_c_RAM = 0x00000001, + Monitor_MemoryMap_c_FLASH = 0x00000002, + +}MemoryMap_Options; + + +////////////////////////////////////////// +// typedefs + +// structure for Monitor Ping Reply +// backwards compatible with .NETMF +typedef struct Monitor_Ping_Reply +{ + uint32_t m_source; + uint32_t m_dbg_flags; + +}Monitor_Ping_Reply; + +// structure for command Monitor Ping +// backwards compatible with .NETMF +typedef struct Monitor_Ping_Command +{ + uint32_t m_source; + uint32_t m_dbg_flags; + +}Monitor_Ping_Command; + + +// structure with reply for OEM information command +typedef struct Monitor_OemInfo_Reply +{ + ReleaseInfo m_releaseInfo; + +}Monitor_OemInfo_Reply; + +typedef struct CLR_DBG_Commands_Monitor_ReadMemory +{ + uint32_t address; + uint32_t length; + unsigned char data[1]; + +}CLR_DBG_Commands_Monitor_ReadMemory; + +typedef struct CLR_DBG_Commands_Monitor_WriteMemory +{ + uint32_t address; + uint32_t length; + unsigned char data[1]; + +}CLR_DBG_Commands_Monitor_WriteMemory; + +typedef struct Monitor_Reboot_Command +{ + uint32_t m_flags; + +}Monitor_Reboot_Command; + +typedef struct CLR_DBG_Commands_Monitor_EraseMemory +{ + uint32_t address; + uint32_t length; + +}CLR_DBG_Commands_Monitor_EraseMemory; + +typedef struct CLR_DBG_Commands_Monitor_CheckMemory +{ + uint32_t address; + uint32_t length; + +}CLR_DBG_Commands_Monitor_CheckMemory; + +typedef struct CLR_DBG_Commands_Monitor_CheckMemory_Reply +{ + uint32_t crc; + +}CLR_DBG_Commands_Monitor_CheckMemory_Reply; + +typedef struct CLR_DBG_Commands_Monitor_EraseMemory_Reply +{ + uint32_t ErrorCode; + +}CLR_DBG_Commands_Monitor_EraseMemory_Reply; + +typedef struct CLR_DBG_Commands_Monitor_WriteMemory_Reply +{ + uint32_t ErrorCode; + +}CLR_DBG_Commands_Monitor_WriteMemory_Reply; + +typedef struct MemoryMap_Range +{ + uint32_t m_address; + uint32_t m_length; + uint32_t m_flags; + +}MemoryMap_Range; + + +typedef struct CLR_DBG_Commands_Monitor_MemoryMap +{ + MemoryMap_Range m_map[1]; + +}CLR_DBG_Commands_Monitor_MemoryMap; + +typedef struct Monitor_QueryConfiguration_Command +{ + uint32_t Configuration; + uint32_t BlockIndex; + +}Monitor_QueryConfiguration_Command; + +typedef struct Monitor_UpdateConfiguration_Command +{ + uint32_t Configuration; + uint32_t BlockIndex; + uint32_t Length; + uint32_t Offset; + uint8_t Data[1]; + +}Monitor_UpdateConfiguration_Command; + +typedef struct Monitor_UpdateConfiguration_Reply +{ + uint32_t ErrorCode; + +}Monitor_UpdateConfiguration_Reply; + +////////////////////////////////////////// +// function declarations (commands) + +#ifdef __cplusplus +extern "C" { +#endif + +int Monitor_Ping(WP_Message* message); +int Monitor_OemInfo(WP_Message* message); +int Monitor_WriteMemory(WP_Message* message); +int Monitor_ReadMemory(WP_Message* message); +int Monitor_Reboot(WP_Message* message); +int Monitor_EraseMemory(WP_Message* message); +int Monitor_QueryConfiguration(WP_Message* message); +int Monitor_UpdateConfiguration(WP_Message* message); +int Monitor_CheckMemory(WP_Message* message); +int Monitor_MemoryMap(WP_Message* message); +int Monitor_FlashSectorMap(WP_Message* message); + +#ifdef __cplusplus +} +#endif + +#endif //_WIREPROTOCOL_COMMANDS_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Application.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Application.h new file mode 100644 index 00000000..6cba90eb --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Application.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOCLR_APPLICATION_H_ +#define _NANOCLR_APPLICATION_H_ + +#include + +typedef struct CLR_SETTINGS +{ + // this is the maximum number of context switches that execution engine thread scheduler can handle + // higher number: more threads and timers can be handled + unsigned short MaxContextSwitches; + + // set this to TRUE if the default behaviour is for the execution engine to wait for a debugger to be connected + // when building is set for RTM this configuration is ignored + bool WaitForDebugger; + + // set this to TRUE if a connection from a debugger is to be awaited after the execution engine terminates + // this is required for launching a debug session in Visual Studio + // when building is set for RTM this configuration is ignored + bool EnterDebuggerLoopAfterExit; +}CLR_SETTINGS; + +#ifdef __cplusplus +extern "C" { +#endif + + extern void ClrStartup(CLR_SETTINGS params); + + extern void ClrExit(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Checks.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Checks.h new file mode 100644 index 00000000..a2398d8d --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Checks.h @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_CHECKS_H_ +#define _NANOCLR_CHECKS_H_ + +#include + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_DUMP +{ +#undef DECL_POSTFIX +#if defined(NANOCLR_TRACE_ERRORS) +#define DECL_POSTFIX +#else +#define DECL_POSTFIX {} +#endif + + static void TYPE ( const CLR_RT_TypeDef_Index& cls ) DECL_POSTFIX; + static void TYPE ( const CLR_RT_ReflectionDef_Index& reflex ) DECL_POSTFIX; + static void METHOD( const CLR_RT_MethodDef_Index& method ) DECL_POSTFIX; + static void FIELD ( const CLR_RT_FieldDef_Index& field ) DECL_POSTFIX; + static void OBJECT( CLR_RT_HeapBlock* ptr , const char* text ) DECL_POSTFIX; + + //--// + +#undef DECL_POSTFIX +#if defined(NANOCLR_TRACE_EXCEPTIONS) +#define DECL_POSTFIX +#else +#define DECL_POSTFIX {} +#endif + static void EXCEPTION ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref ) DECL_POSTFIX; + static void POST_PROCESS_EXCEPTION( CLR_RT_HeapBlock& ref ) DECL_POSTFIX; + + static const char* GETERRORMESSAGE( HRESULT hrError ); +#if defined(_WIN32) + static const char* GETERRORDETAIL (); +#endif +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_Checks +{ + static HRESULT VerifyStackOK( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock* top, int num ) { return S_OK; } + + static HRESULT VerifyObject ( CLR_RT_HeapBlock& top ); + + static HRESULT VerifyArrayReference ( CLR_RT_HeapBlock& ref ); + + static HRESULT VerifyUnknownInstruction ( CLR_OPCODE op ); + static HRESULT VerifyUnsupportedInstruction( CLR_OPCODE op ); +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _NANOCLR_CHECKS_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Debugging.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Debugging.h new file mode 100644 index 00000000..08f08ec7 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Debugging.h @@ -0,0 +1,1166 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_DEBUGGING_H_ +#define _NANOCLR_DEBUGGING_H_ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//#if defined(_MSC_VER) +struct CLR_DBG_Commands +{ + static const unsigned int c_Monitor_Ping = 0x00000000; // The payload is empty, this command is used to let the other side know we are here... + static const unsigned int c_Monitor_Message = 0x00000001; // The payload is composed of the string characters, no zero at the end. + static const unsigned int c_Monitor_ReadMemory = 0x00000002; + static const unsigned int c_Monitor_WriteMemory = 0x00000003; + static const unsigned int c_Monitor_CheckMemory = 0x00000004; + static const unsigned int c_Monitor_EraseMemory = 0x00000005; + static const unsigned int c_Monitor_Execute = 0x00000006; + static const unsigned int c_Monitor_Reboot = 0x00000007; + static const unsigned int c_Monitor_MemoryMap = 0x00000008; + static const unsigned int c_Monitor_ProgramExit = 0x00000009; // The payload is empty, this command is used to tell the PC of a program termination + static const unsigned int c_Monitor_CheckSignature = 0x0000000A; + static const unsigned int c_Monitor_DeploymentMap = 0x0000000B; + static const unsigned int c_Monitor_FlashSectorMap = 0x0000000C; + static const unsigned int c_Monitor_OemInfo = 0x0000000E; + static const unsigned int c_Monitor_QueryConfiguration = 0x0000000F; + static const unsigned int c_Monitor_UpdateConfiguration= 0x00000010; + + //--// + + + + + + + + + + + + + + + + + + + + + + struct Monitor_OemInfo + { + struct Reply + { + NFReleaseInfo m_releaseInfo; + }; + }; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.WireProtocol.RebootOptions (in managed code) !!! // + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + struct Monitor_Reboot + { + static const unsigned int c_NormalReboot = 0; + static const unsigned int c_EnterBootloader = 1; + static const unsigned int c_ClrOnly = 2; + static const unsigned int c_WaitForDebugger = 4; + + unsigned int m_flags; + }; + + struct Monitor_ReadMemory + { + unsigned int m_address; + unsigned int m_length; + + struct Reply + { + unsigned int ErrorCode; + unsigned char m_data[ 1 ]; + }; + }; + + struct Monitor_WriteMemory + { + unsigned int m_address; + unsigned int m_length; + unsigned char m_data[ 1 ]; + + struct Reply + { + unsigned int ErrorCode; + }; + }; + + struct Monitor_Signature + { + unsigned int m_keyIndex; + unsigned int m_length; + unsigned char m_signature[ 1 ]; + }; + + struct Monitor_CheckMemory + { + unsigned int m_address; + unsigned int m_length; + + struct Reply + { + unsigned int m_crc; + }; + }; + + struct Monitor_EraseMemory + { + unsigned int m_address; + unsigned int m_length; + + struct Reply + { + unsigned int ErrorCode; + }; + }; + + struct Monitor_Execute + { + unsigned int m_address; + }; + + + + + + + + + + + + + + + + + + struct Monitor_DeploymentMap + { + static const CLR_UINT32 c_CRC_Erased_Sentinel = 0x0; + + struct FlashSector + { + CLR_UINT32 m_start; + CLR_UINT32 m_length; + + CLR_UINT32 m_crc; + }; + + struct Reply + { + + FlashSector m_data[ 1 ]; + }; + }; + + + + + struct Monitor_SignatureKeyUpdate + { + unsigned int m_keyIndex; + unsigned char m_newKeySignature[ 128 ]; + unsigned char m_newKey[ 260 ]; + unsigned int m_reserveLength; + unsigned char m_reserveData[ 1 ]; + }; + + //--------------------------------------------------------------// + + static const unsigned int c_Debugging_Execution_BasePtr = 0x00020000; // Returns the pointer for the ExecutionEngine object. + static const unsigned int c_Debugging_Execution_ChangeConditions = 0x00020001; // Sets/resets the state of the debugger. + static const unsigned int c_Debugging_Execution_SecurityKey = 0x00020002; // Sets security key. + static const unsigned int c_Debugging_Execution_Unlock = 0x00020003; // Unlock the low-level command, for mfg. test programs. + static const unsigned int c_Debugging_Execution_Allocate = 0x00020004; // Permanently allocate some memory. + static const unsigned int c_Debugging_Execution_Breakpoints = 0x00020005; // Sets breakpoints. + static const unsigned int c_Debugging_Execution_BreakpointHit = 0x00020006; // Notification that a breakpoint was hit. + static const unsigned int c_Debugging_Execution_BreakpointStatus = 0x00020007; // Queries last breakpoint hit. + static const unsigned int c_Debugging_Execution_QueryCLRCapabilities = 0x00020008; // Queries capabilities of the CLR. + static const unsigned int c_Debugging_Execution_SetCurrentAppDomain = 0x00020009; // Sets the current AppDomain. This is required before + // performing certain debugging operations, such as + // accessing a static field, or doing function evaluation, + + static const unsigned int c_Debugging_Thread_Create = 0x00020010; // OBSOLETE - Use c_Debugging_Thread_CreateEx instead. + static const unsigned int c_Debugging_Thread_List = 0x00020011; // Lists the active/waiting threads. + static const unsigned int c_Debugging_Thread_Stack = 0x00020012; // Lists the call stack for a thread. + static const unsigned int c_Debugging_Thread_Kill = 0x00020013; // Kills a thread. + static const unsigned int c_Debugging_Thread_Suspend = 0x00020014; // Suspends the execution of a thread. + static const unsigned int c_Debugging_Thread_Resume = 0x00020015; // Resumes the execution of a thread. + static const unsigned int c_Debugging_Thread_GetException = 0x00020016; // Gets the current exception. + static const unsigned int c_Debugging_Thread_Unwind = 0x00020017; // Unwinds to given stack frame. + static const unsigned int c_Debugging_Thread_CreateEx = 0x00020018; // Creates a new thread but Thread.CurrentThread will return the identity of the passed thread. + static const unsigned int c_Debugging_Thread_Get = 0x00021000; // Gets the current thread. + + static const unsigned int c_Debugging_Stack_Info = 0x00020020; // Gets more info on a stack frame. + static const unsigned int c_Debugging_Stack_SetIP = 0x00020021; // Sets the IP on a given thread. + + static const unsigned int c_Debugging_Value_ResizeScratchPad = 0x00020030; // Resizes the scratchpad area. + static const unsigned int c_Debugging_Value_GetStack = 0x00020031; // Reads a value from the stack frame. + static const unsigned int c_Debugging_Value_GetField = 0x00020032; // Reads a value from an object's field. + static const unsigned int c_Debugging_Value_GetArray = 0x00020033; // Reads a value from an array's element. + static const unsigned int c_Debugging_Value_GetBlock = 0x00020034; // Reads a value from a heap block. + static const unsigned int c_Debugging_Value_GetScratchPad = 0x00020035; // Reads a value from the scratchpad area. + static const unsigned int c_Debugging_Value_SetBlock = 0x00020036; // Writes a value to a heap block. + static const unsigned int c_Debugging_Value_SetArray = 0x00020037; // Writes a value to an array's element. + static const unsigned int c_Debugging_Value_AllocateObject = 0x00020038; // Creates a new instance of an object. + static const unsigned int c_Debugging_Value_AllocateString = 0x00020039; // Creates a new instance of a string. + static const unsigned int c_Debugging_Value_AllocateArray = 0x0002003A; // Creates a new instance of an array. + static const unsigned int c_Debugging_Value_Assign = 0x0002003B; // Assigns a value to another value. + + static const unsigned int c_Debugging_TypeSys_Assemblies = 0x00020040; // Lists all the assemblies in the system. + static const unsigned int c_Debugging_TypeSys_AppDomains = 0x00020044; // Lists all the AppDomans loaded. + + static const unsigned int c_Debugging_Resolve_Assembly = 0x00020050; // Resolves an assembly. + static const unsigned int c_Debugging_Resolve_Type = 0x00020051; // Resolves a type to a string. + static const unsigned int c_Debugging_Resolve_Field = 0x00020052; // Resolves a field to a string. + static const unsigned int c_Debugging_Resolve_Method = 0x00020053; // Resolves a method to a string. + static const unsigned int c_Debugging_Resolve_VirtualMethod = 0x00020054; // Resolves a virtual method to the actual implementation. + static const unsigned int c_Debugging_Resolve_AppDomain = 0x00020055; // Resolves an AppDomain to it's name, and list its loaded assemblies. + + + + + + + + + + static const unsigned int c_Debugging_UpgradeToSsl = 0x00020069; // + + //--// + + static const unsigned int c_Debugging_Button_Report = 0x00020080; // Reports a button press/release. + static const unsigned int c_Debugging_Button_Inject = 0x00020081; // Injects a button press/release. + + static const unsigned int c_Debugging_Deployment_Status = 0x000200B0; // Returns entryPoint and boundary of deployment area. + + static const unsigned int c_Debugging_Info_SetJMC = 0x000200C0; // Sets code to be flagged as JMC (Just my code). + + static const unsigned int c_Profiling_Command = 0x00030000; // Various incoming commands regarding profiling + static const unsigned int c_Profiling_Stream = 0x00030001; // Stream for MFProfiler information. + + //--// + + struct Debugging_Execution_Unlock + { + unsigned char m_command[ 128 ]; + unsigned char m_hash [ 128 ]; + }; + + struct Debugging_Execution_QueryCLRCapabilities + { + static const CLR_UINT32 c_CapabilityFlags = 1; + static const CLR_UINT32 c_CapabilityVersion = 3; + static const CLR_UINT32 c_HalSystemInfo = 5; + static const CLR_UINT32 c_ClrInfo = 6; + static const CLR_UINT32 c_TargetReleaseInfo = 7; + static const CLR_UINT32 c_InteropNativeAssemblies = 8; + + static const CLR_UINT32 c_CapabilityFlags_FloatingPoint = 0x00000001; + static const CLR_UINT32 c_CapabilityFlags_SourceLevelDebugging = 0x00000002; + static const CLR_UINT32 c_CapabilityFlags_AppDomains = 0x00000004; + static const CLR_UINT32 c_CapabilityFlags_ExceptionFilters = 0x00000008; + static const CLR_UINT32 c_CapabilityFlags_IncrementalDeployment = 0x00000010; + static const CLR_UINT32 c_CapabilityFlags_SoftReboot = 0x00000020; + static const CLR_UINT32 c_CapabilityFlags_Profiling = 0x00000040; + static const CLR_UINT32 c_CapabilityFlags_Profiling_Allocations = 0x00000080; + static const CLR_UINT32 c_CapabilityFlags_Profiling_Calls = 0x00000100; + static const CLR_UINT32 c_CapabilityFlags_ThreadCreateEx = 0x00000400; + static const CLR_UINT32 c_CapabilityFlags_ConfigBlockRequiresErase = 0x00000800; + static const CLR_UINT32 c_CapabilityFlags_HasNanoBooter = 0x00001000; + static const CLR_UINT32 c_CapabilityFlags_PlatformCapabiliy_0 = 0x00010000; + static const CLR_UINT32 c_CapabilityFlags_PlatformCapabiliy_1 = 0x00020000; + static const CLR_UINT32 c_CapabilityFlags_TargetCapabiliy_0 = 0x00040000; + static const CLR_UINT32 c_CapabilityFlags_TargetCapabiliy_1 = 0x00080000; + + CLR_UINT32 m_cmd; + + struct __nfpack SoftwareVersion + { + char BuildDate[ 22 ]; + char CompilerInfo[16]; + unsigned int CompilerVersion; + }; + + struct __nfpack ClrInfo + { + NFReleaseInfo m_clrReleaseInfo; + NFVersion m_TargetFrameworkVersion; + }; + + struct __nfpack NativeAssemblyDetails + { + uint32_t CheckSum; + NFVersion Version; + uint8_t AssemblyName[128]; + + }; + + union ReplyUnion + { + CLR_UINT32 u_capsFlags; + SoftwareVersion u_SoftwareVersion; + HalSystemInfo u_HalSystemInfo; + ClrInfo u_ClrInfo; + NFReleaseInfo u_TargetReleaseInfo; + }; + }; + + //--// + + struct Debugging_Messaging_Query + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + struct Debugging_Messaging_Send + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + unsigned char m_data[ 1 ]; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + struct Debugging_Messaging_Reply + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + unsigned char m_data[ 1 ]; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + //--// + + + struct Debugging_Execution_BasePtr + { + struct Reply + { + CLR_UINT32 m_EE; + }; + }; + + struct Debugging_Execution_ChangeConditions + { + CLR_UINT32 FlagsToSet; + CLR_UINT32 FlagsToReset; + + struct Reply + { + CLR_UINT32 CurrentState; + }; + }; + + struct Debugging_Execution_SecurityKey + { + CLR_UINT8 m_key[ 32 ]; + }; + + struct Debugging_Execution_Allocate + { + CLR_UINT32 m_size; + + struct Reply + { + CLR_UINT32 m_address; + }; + }; + + struct Debugging_UpgradeToSsl + { + CLR_UINT32 m_flags; + + struct Reply + { + CLR_UINT32 m_success; + }; + }; + + + //struct Debugging_MFUpdate_Start + //{ + // char m_provider[64]; + // CLR_UINT32 m_updateId; + // CLR_UINT32 m_updateType; + // CLR_UINT32 m_updateSubType; + // CLR_UINT32 m_updateSize; + // CLR_UINT32 m_updatePacketSize; + // CLR_UINT16 m_versionMajor; + // CLR_UINT16 m_versionMinor; + + // struct Reply + // { + // CLR_INT32 m_updateHandle; + // }; + //}; + + //struct Debugging_MFUpdate_AuthCommand + //{ + // CLR_UINT32 m_updateHandle; + // CLR_UINT32 m_authCommand; + // CLR_UINT32 m_authArgsSize; + // CLR_UINT8 m_authArgs[1]; + + // struct Reply + // { + // CLR_INT32 m_success; + // CLR_UINT32 m_responseSize; + // CLR_UINT8 m_response[1]; + // }; + //}; + + //struct Debugging_MFUpdate_Authenticate + //{ + // CLR_UINT32 m_updateHandle; + // CLR_UINT32 m_authenticationLen; + // CLR_UINT8 m_authenticationData[1]; + + // struct Reply + // { + // CLR_INT32 m_success; + // }; + //}; + + //struct Debugging_MFUpdate_GetMissingPkts + //{ + // CLR_UINT32 m_updateHandle; + // + // struct Reply + // { + // CLR_INT32 m_success; + // CLR_INT32 m_missingPktCount; + // CLR_UINT32 m_missingPkts[1]; + // }; + //}; + + //struct Debugging_MFUpdate_AddPacket + //{ + // CLR_INT32 m_updateHandle; + // CLR_UINT32 m_packetIndex; + // CLR_UINT32 m_packetValidation; + // CLR_UINT32 m_packetLength; + // CLR_UINT8 m_packetData[1]; + + // struct Reply + // { + // CLR_UINT32 m_success; + // }; + //}; + + //struct Debugging_MFUpdate_Install + //{ + // CLR_INT32 m_updateHandle; + // CLR_UINT32 m_updateValidationSize; + // CLR_UINT8 m_updateValidation[1]; + + // struct Reply + // { + // CLR_UINT32 m_success; + // }; + //}; + + + struct Debugging_Execution_BreakpointDef + { + static const CLR_UINT16 c_STEP_IN = 0x0001; + static const CLR_UINT16 c_STEP_OVER = 0x0002; + static const CLR_UINT16 c_STEP_OUT = 0x0004; + static const CLR_UINT16 c_HARD = 0x0008; + static const CLR_UINT16 c_EXCEPTION_THROWN = 0x0010; + static const CLR_UINT16 c_EXCEPTION_CAUGHT = 0x0020; + static const CLR_UINT16 c_EXCEPTION_UNCAUGHT = 0x0040; + static const CLR_UINT16 c_THREAD_TERMINATED = 0x0080; + static const CLR_UINT16 c_THREAD_CREATED = 0x0100; + static const CLR_UINT16 c_ASSEMBLIES_LOADED = 0x0200; + static const CLR_UINT16 c_LAST_BREAKPOINT = 0x0400; + static const CLR_UINT16 c_STEP_JMC = 0x0800; + static const CLR_UINT16 c_BREAK = 0x1000; + static const CLR_UINT16 c_EVAL_COMPLETE = 0x2000; + static const CLR_UINT16 c_EXCEPTION_UNWIND = 0x4000; + static const CLR_UINT16 c_EXCEPTION_FINALLY = 0x8000; + + static const CLR_UINT16 c_STEP = c_STEP_IN | c_STEP_OVER | c_STEP_OUT; + + static const CLR_INT32 c_PID_ANY = 0x7FFFFFFF; + + static const CLR_UINT32 c_DEPTH_EXCEPTION_FIRST_CHANCE = 0x00000000; + static const CLR_UINT32 c_DEPTH_EXCEPTION_USERS_CHANCE = 0x00000001; + static const CLR_UINT32 c_DEPTH_EXCEPTION_HANDLER_FOUND = 0x00000002; + + static const CLR_UINT32 c_DEPTH_STEP_NORMAL = 0x00000010; + static const CLR_UINT32 c_DEPTH_STEP_RETURN = 0x00000020; + static const CLR_UINT32 c_DEPTH_STEP_CALL = 0x00000030; + static const CLR_UINT32 c_DEPTH_STEP_EXCEPTION_FILTER = 0x00000040; + static const CLR_UINT32 c_DEPTH_STEP_EXCEPTION_HANDLER = 0x00000050; + static const CLR_UINT32 c_DEPTH_STEP_INTERCEPT = 0x00000060; + static const CLR_UINT32 c_DEPTH_STEP_EXIT = 0x00000070; + + static const CLR_UINT32 c_DEPTH_UNCAUGHT = 0xFFFFFFFF; + + + CLR_UINT16 m_id; + CLR_UINT16 m_flags; + + CLR_INT32 m_pid; + CLR_UINT32 m_depth; + + // + // m_IPStart, m_IPEnd are used for optimizing stepping operations. + // A STEP_IN | STEP_OVER breakpoint will be hit in the given stack frame + // only if the IP is outside of the given range [m_IPStart m_IPEnd). + // + CLR_UINT32 m_IPStart; + CLR_UINT32 m_IPEnd; + + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; + + CLR_RT_TypeDef_Index m_td; + + CLR_UINT32 m_depthExceptionHandler; + }; + + struct Debugging_Execution_Breakpoints + { + CLR_UINT32 m_flags; + + Debugging_Execution_BreakpointDef m_data[ 1 ]; + }; + + struct Debugging_Execution_BreakpointHit + { + Debugging_Execution_BreakpointDef m_hit; + }; + + struct Debugging_Execution_BreakpointStatus + { + struct Reply + { + Debugging_Execution_BreakpointDef m_lastHit; + }; + }; + + struct Debugging_Execution_SetCurrentAppDomain + { + CLR_UINT32 m_id; + }; + + //--//--// + + struct Debugging_Thread_CreateEx + { + CLR_RT_MethodDef_Index m_md; + int m_scratchPad; + CLR_UINT32 m_pid; + + struct Reply + { + CLR_UINT32 m_pid; + }; + }; + + //--// + + struct Debugging_Thread_List + { + struct Reply + { + CLR_UINT32 m_num; + CLR_UINT32 m_pids[ 1 ]; + }; + }; + + //--// + + struct Debugging_Thread_Stack + { + CLR_UINT32 m_pid; + + struct Reply + { + struct Call + { + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; +#if defined(NANOCLR_APPDOMAINS) + CLR_UINT32 m_appDomainID; + CLR_UINT32 m_flags; +#endif + + }; + + CLR_UINT32 m_num; + CLR_UINT32 m_status; + CLR_UINT32 m_flags; + Call m_data[ 1 ]; + }; + }; + + struct Debugging_Thread_Kill + { + CLR_UINT32 m_pid; + + struct Reply + { + int m_result; + }; + }; + + struct Debugging_Thread_Suspend + { + CLR_UINT32 m_pid; + }; + + struct Debugging_Thread_Resume + { + CLR_UINT32 m_pid; + }; + + struct Debugging_Thread_Get + { + CLR_UINT32 m_pid; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Thread_GetException + { + CLR_UINT32 m_pid; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Thread_Unwind + { + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + }; + + //--// + + struct Debugging_Stack_Info + { + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + + struct Reply + { + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; + CLR_UINT32 m_numOfArguments; + CLR_UINT32 m_numOfLocals; + CLR_UINT32 m_depthOfEvalStack; + }; + }; + + struct Debugging_Stack_SetIP + { + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + + CLR_UINT32 m_IP; + CLR_UINT32 m_depthOfEvalStack; + }; + + //--// + + struct Debugging_Value + { + CLR_RT_HeapBlock* m_referenceID; + CLR_UINT32 m_dt; // CLR_RT_HeapBlock::DataType () + CLR_UINT32 m_flags; // CLR_RT_HeapBlock::DataFlags() + CLR_UINT32 m_size; // CLR_RT_HeapBlock::DataSize () + + // + // For primitive types + // + CLR_UINT8 m_builtinValue[ 128 ]; // Space for string preview... + + // + // For DATATYPE_STRING + // + CLR_UINT32 m_bytesInString; + const char* m_charsInString; + + // + // For DATATYPE_VALUETYPE or DATATYPE_CLASSTYPE + // + CLR_RT_TypeDef_Index m_td; + + // + // For DATATYPE_SZARRAY + // + CLR_UINT32 m_array_numOfElements; + CLR_UINT32 m_array_depth; + CLR_RT_TypeDef_Index m_array_typeIndex; + + // + // For values from an array. + // + CLR_RT_HeapBlock_Array* m_arrayref_referenceID; + CLR_UINT32 m_arrayref_index; + }; + + struct Debugging_Value_ResizeScratchPad + { + CLR_UINT32 m_size; + }; + + struct Debugging_Value_GetStack + { + static const CLR_UINT32 c_Local = 0; + static const CLR_UINT32 c_Argument = 1; + static const CLR_UINT32 c_EvalStack = 2; + + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + CLR_UINT32 m_kind; + CLR_UINT32 m_index; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetField + { + CLR_RT_HeapBlock* m_heapblock; + CLR_UINT32 m_offset; + CLR_RT_FieldDef_Index m_fd; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetArray + { + CLR_RT_HeapBlock* m_heapblock; + CLR_UINT32 m_index; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetBlock + { + CLR_RT_HeapBlock* m_heapblock; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetScratchPad + { + CLR_UINT32 m_idx; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_SetBlock + { + CLR_RT_HeapBlock* m_heapblock; + CLR_UINT32 m_dt; // CLR_RT_HeapBlock::DataType () + CLR_UINT8 m_builtinValue[ 8 ]; + }; + + struct Debugging_Value_SetArray + { + CLR_RT_HeapBlock_Array* m_heapblock; + CLR_UINT32 m_index; + CLR_UINT8 m_builtinValue[ 8 ]; + }; + + //--// + + struct Debugging_Value_AllocateObject + { + int m_index; + CLR_RT_TypeDef_Index m_td; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_AllocateString + { + int m_index; + CLR_UINT32 m_size; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_AllocateArray + { + int m_index; + CLR_RT_TypeDef_Index m_td; + CLR_UINT32 m_depth; + CLR_UINT32 m_numOfElements; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_Assign + { + CLR_RT_HeapBlock* m_heapblockSrc; + CLR_RT_HeapBlock* m_heapblockDst; + + // + // The reply is an array of Debugging_Value + // + }; + + //--// + + struct Debugging_TypeSys_Assemblies + { + // + // The reply is just an array of CLR_RT_Assembly_Index. + // + }; + + struct Debugging_TypeSys_AppDomains + { + // + // The reply is just an array of AppDomainIDs + // + }; + + //--// + + struct Debugging_Resolve_AppDomain + { + CLR_UINT32 m_id; + + struct Reply + { + CLR_UINT32 m_state; + char m_szName[ 512 ]; + CLR_UINT32 m_assemblies[ 1 ]; //Array of CLR_RT_Assembly_Index + }; + }; + + struct Debugging_Resolve_Assembly + { + CLR_RT_Assembly_Index m_idx; + + struct Reply + { + CLR_UINT32 m_flags; + CLR_RECORD_VERSION m_version; + char m_szName[ 512 ]; + }; + }; + + struct Debugging_Resolve_Type + { + CLR_RT_TypeDef_Index m_td; + + struct Reply + { + char m_type[ 512 ]; + }; + }; + + struct Debugging_Resolve_Field + { + CLR_RT_FieldDef_Index m_fd; + + struct Reply + { + CLR_RT_TypeDef_Index m_td; + CLR_UINT32 m_index; + char m_name[ 512 ]; + }; + }; + + struct Debugging_Resolve_Method + { + CLR_RT_MethodDef_Index m_md; + + struct Reply + { + CLR_RT_TypeDef_Index m_td; + char m_method[ 512 ]; + }; + }; + + struct Debugging_Resolve_VirtualMethod + { + CLR_RT_MethodDef_Index m_md; + CLR_RT_HeapBlock* m_obj; + + struct Reply + { + CLR_RT_MethodDef_Index m_md; + }; + }; + + //--// + + struct Debugging_Deployment_Status + { + struct FlashSector + { + CLR_UINT32 Start; + CLR_UINT32 Length; + }; + + struct Reply + { + CLR_UINT32 EntryPoint; + CLR_UINT32 StorageStart; + CLR_UINT32 StorageLength; + + // FlashSector SectorData[ 1 ]; + }; + }; + + //--// + + struct Debugging_Info_SetJMC + { + CLR_UINT32 m_fIsJMC; + CLR_UINT32 m_kind; // CLR_ReflectionType + + union + { + CLR_RT_Assembly_Index m_assm; + CLR_RT_TypeDef_Index m_type; + CLR_RT_MethodDef_Index m_method; + CLR_UINT32 m_raw; + } m_data; + }; + + struct Profiling_Command + { + static const CLR_UINT8 c_Command_ChangeConditions = 0x01; + static const CLR_UINT8 c_Command_FlushStream = 0x02; + + CLR_UINT8 m_command; + + struct Reply + { + CLR_UINT32 m_raw; + }; + }; + + struct Profiling_ChangeConditions + { + CLR_UINT32 m_set; + CLR_UINT32 m_reset; + }; + + struct Profiling_Stream + { + CLR_UINT16 m_seqId; + CLR_UINT16 m_bitLen; + }; + +}; +//#endif + +struct CLR_DBG_Debugger +{ + CLR_Messaging* m_messaging; + static BlockStorageDevice* m_deploymentStorageDevice; + + + //--// + + static void Debugger_WaitForCommands(); + + static HRESULT CreateInstance(); + + HRESULT Debugger_Initialize( COM_HANDLE port ); + + static HRESULT DeleteInstance(); + + void Debugger_Cleanup(); + + static void BroadcastEvent( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ); + + void PurgeCache (); + +private: + + bool CheckPermission( ByteAddress address, int mode ); + + bool AccessMemory( CLR_UINT32 location, unsigned int lengthInBytes, unsigned char* buf, int mode, unsigned int* errorCode ); + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* GetAppDomainFromID ( CLR_UINT32 id ); +#endif + + CLR_RT_StackFrame* CheckStackFrame ( CLR_INT32 pid, CLR_UINT32 depth, bool& isInline ); + HRESULT CreateListOfThreads( CLR_DBG_Commands::Debugging_Thread_List ::Reply*& cmdReply, int& totLen ); + HRESULT CreateListOfCalls ( CLR_INT32 pid, CLR_DBG_Commands::Debugging_Thread_Stack::Reply*& cmdReply, int& totLen ); + + CLR_RT_Assembly* IsGoodAssembly( CLR_IDX idxAssm ); + bool CheckTypeDef ( const CLR_RT_TypeDef_Index& td , CLR_RT_TypeDef_Instance& inst ); + bool CheckFieldDef ( const CLR_RT_FieldDef_Index& fd , CLR_RT_FieldDef_Instance& inst ); + bool CheckMethodDef( const CLR_RT_MethodDef_Index& md , CLR_RT_MethodDef_Instance& inst ); + + bool GetValue( WP_Message* msg, CLR_RT_HeapBlock* ptr, CLR_RT_HeapBlock* reference, CLR_RT_TypeDef_Instance* pTD ); + + bool AllocateAndQueueMessage( CLR_UINT32 cmd, unsigned int length, unsigned char* data, CLR_RT_HeapBlock_EndPoint::Port port, CLR_RT_HeapBlock_EndPoint::Address addr, CLR_UINT32 found ); + + bool ProcessHeader ( WP_Message* msg ); + bool ProcessPayload ( WP_Message* msg ); + + +public: + static CLR_RT_Thread* GetThreadFromPid ( CLR_INT32 pid ); + + static bool Monitor_Ping ( WP_Message* msg ); + static bool Monitor_Reboot ( WP_Message* msg ); + static bool Debugging_Execution_QueryCLRCapabilities( WP_Message* msg ); + + static bool Monitor_ReadMemory ( WP_Message* msg ); + static bool Monitor_WriteMemory ( WP_Message* msg ); + static bool Monitor_CheckMemory ( WP_Message* msg ); + static bool Monitor_EraseMemory ( WP_Message* msg ); + static bool Monitor_Execute ( WP_Message* msg ); + static bool Monitor_MemoryMap ( WP_Message* msg ); + static bool Monitor_FlashSectorMap ( WP_Message* msg ); + static bool Monitor_DeploymentMap ( WP_Message* msg ); + static bool Monitor_QueryConfiguration ( WP_Message* msg ); + static bool Monitor_UpdateConfiguration ( WP_Message* msg ); + + + static bool Debugging_Execution_BasePtr ( WP_Message* msg ); + static bool Debugging_Execution_ChangeConditions ( WP_Message* msg ); + + static bool Debugging_Execution_Allocate ( WP_Message* msg ); + + static bool Debugging_UpgradeToSsl ( WP_Message* msg ); + + + + + + + + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + static bool Debugging_Execution_Breakpoints ( WP_Message* msg ); + static bool Debugging_Execution_BreakpointStatus ( WP_Message* msg ); + static bool Debugging_Execution_SetCurrentAppDomain ( WP_Message* msg ); + + static bool Debugging_Thread_CreateEx ( WP_Message* msg ); + static bool Debugging_Thread_List ( WP_Message* msg ); + static bool Debugging_Thread_Stack ( WP_Message* msg ); + static bool Debugging_Thread_Kill ( WP_Message* msg ); + static bool Debugging_Thread_Suspend ( WP_Message* msg ); + static bool Debugging_Thread_Resume ( WP_Message* msg ); + static bool Debugging_Thread_GetException ( WP_Message* msg ); + static bool Debugging_Thread_Unwind ( WP_Message* msg ); + static bool Debugging_Thread_Get ( WP_Message* msg ); + + static bool Debugging_Stack_Info ( WP_Message* msg ); + static bool Debugging_Stack_SetIP ( WP_Message* msg ); + + static bool Debugging_Value_ResizeScratchPad ( WP_Message* msg ); + static bool Debugging_Value_GetStack ( WP_Message* msg ); + static bool Debugging_Value_GetField ( WP_Message* msg ); + static bool Debugging_Value_GetArray ( WP_Message* msg ); + static bool Debugging_Value_GetBlock ( WP_Message* msg ); + static bool Debugging_Value_GetScratchPad ( WP_Message* msg ); + static bool Debugging_Value_SetBlock ( WP_Message* msg ); + static bool Debugging_Value_SetArray ( WP_Message* msg ); + static bool Debugging_Value_AllocateObject ( WP_Message* msg ); + static bool Debugging_Value_AllocateString ( WP_Message* msg ); + static bool Debugging_Value_AllocateArray ( WP_Message* msg ); + static bool Debugging_Value_Assign ( WP_Message* msg ); + + static bool Debugging_TypeSys_Assemblies ( WP_Message* msg ); + static bool Debugging_TypeSys_AppDomains ( WP_Message* msg ); + + static bool Debugging_Resolve_AppDomain ( WP_Message* msg ); + static bool Debugging_Resolve_Assembly ( WP_Message* msg ); + static bool Debugging_Resolve_Type ( WP_Message* msg ); + static bool Debugging_Resolve_Field ( WP_Message* msg ); + static bool Debugging_Resolve_Method ( WP_Message* msg ); + static bool Debugging_Resolve_VirtualMethod ( WP_Message* msg ); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + static bool Debugging_Deployment_Status ( WP_Message* msg ); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + static bool Debugging_Info_SetJMC ( WP_Message* msg ); + + bool Debugging_Info_SetJMC_Type ( const CLR_RT_TypeDef_Index& idx, bool fJMC ); + bool Debugging_Info_SetJMC_Method ( const CLR_RT_MethodDef_Index& idx, bool fJMC ); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + static bool Profiling_Command ( WP_Message* msg ); + bool Profiling_ChangeConditions ( WP_Message* msg ); + bool Profiling_FlushStream ( WP_Message* msg ); +}; + +//--// + +extern CLR_UINT32 g_scratchDebugger[]; +extern CLR_UINT32 g_scratchDebuggerMessaging[]; +extern CLR_DBG_Debugger *g_CLR_DBG_Debugger; + +//--// + +extern const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Request[]; +extern const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Reply[]; +extern const CLR_UINT32 c_Debugger_Lookup_Request_count; +extern const CLR_UINT32 c_Debugger_Lookup_Reply_count; + +//--// + +#endif // _NANOCLR_DEBUGGING_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_ErrorCodes.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_ErrorCodes.h new file mode 100644 index 00000000..e757a622 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_ErrorCodes.h @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_ERRORCODES_H_ +#define _NANOCLR_ERRORCODES_H_ +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +// +// PARSER error codes. +// +#define CLR_E_PARSER_BAD_TEXT_SIGNATURE MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0001) +#define CLR_E_PARSER_BAD_CUSTOM_ATTRIBUTE MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0002) +#define CLR_E_PARSER_UNSUPPORTED_MULTIDIM_ARRAY MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0003) +#define CLR_E_PARSER_UNKNOWN_MEMBER_REF MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0004) +#define CLR_E_PARSER_MISSING_FIELD MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0005) +#define CLR_E_PARSER_MISSING_METHOD MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0006) +#define CLR_E_PARSER_MISSING_INTERFACE MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0007) +#define CLR_E_PARSER_MISSING_TOKEN MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0008) +#define CLR_E_PARSER_UNSUPPORTED_GENERICS MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0009) + + +#endif // _NANOCLR_ERRORCODES_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Hardware.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Hardware.h new file mode 100644 index 00000000..8bbee835 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Hardware.h @@ -0,0 +1,132 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_HARDWARE_H_ +#define _NANOCLR_HARDWARE_H_ + +#include +#include +//#include + +//--// + + + + + + + + + + + + + + + + + + + + + + + + +#if defined(_WIN32) +#include "nanoCLR_Win32.h" +#endif + +//--// + +struct CLR_HW_Hardware +{ + static const CLR_UINT32 c_Default_PowerLevel = PowerLevel__Sleep; + static const CLR_UINT32 c_Default_WakeupEvents = SYSTEM_EVENT_FLAG_COM_IN | + SYSTEM_EVENT_FLAG_COM_OUT | + SYSTEM_EVENT_FLAG_STORAGE_IO | + SYSTEM_EVENT_FLAG_SYSTEM_TIMER | + SYSTEM_EVENT_FLAG_SPI_MASTER | + SYSTEM_EVENT_FLAG_I2C_MASTER | + SYSTEM_EVENT_HW_INTERRUPT | + SYSTEM_EVENT_FLAG_SOCKET | + SYSTEM_EVENT_FLAG_DEBUGGER_ACTIVITY | + SYSTEM_EVENT_FLAG_MESSAGING_ACTIVITY| + SYSTEM_EVENT_FLAG_ONEWIRE_MASTER; + + //--// + + struct HalInterruptRecord + { + CLR_INT64 m_time; + CLR_RT_HeapBlock_Node* m_context; + + CLR_UINT32 m_data1; + CLR_UINT32 m_data2; + CLR_UINT32 m_data3; + + void AssignFrom( const HalInterruptRecord &recFrom ) + { + m_time = recFrom.m_time; + m_context = recFrom.m_context; + m_data1 = recFrom.m_data1; + m_data2 = recFrom.m_data2; + } + }; + + struct InterruptData + { + Hal_Queue_UnknownSize m_HalQueue; + CLR_RT_DblLinkedList m_applicationQueue; + CLR_UINT32 m_queuedInterrupts; + }; + + //--// + + bool m_fInitialized; + + InterruptData m_interruptData; + + CLR_UINT32 m_DebuggerEventsMask; + + PowerLevel_type m_powerLevel; + CLR_UINT32 m_wakeupEvents; + + //--// + + static HRESULT CreateInstance(); + + HRESULT Hardware_Initialize(); + + static HRESULT DeleteInstance(); + + void Hardware_Cleanup(); + + void PrepareForGC (); + void ProcessActivity(); + + HRESULT ManagedHardware_Initialize(); + HRESULT ProcessInterrupts(); + HRESULT SpawnDispatcher(); + HRESULT TransferAllInterruptsToApplicationQueue(); +}; + +extern CLR_HW_Hardware g_CLR_HW_Hardware; + +//--// + + +//////////////////////////////////////////////////////////////////////////////////////// +// keep under control the size of the HalInterruptRecord, since we will use externally +// defined arrays to handle those data structures in the interrupt dispatching + +CT_ASSERT(sizeof(CLR_HW_Hardware::HalInterruptRecord) == 24) + +//////////////////////////////////////////////////////////////////////////////////////// + +//--// + +#endif // _NANOCLR_HARDWARE_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Interop.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Interop.h new file mode 100644 index 00000000..ae4b5029 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Interop.h @@ -0,0 +1,473 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_INTEROP_H_ +#define _NANOCLR_INTEROP_H_ + +#include +#include + + +/////////////////////////////////////////////////////////////////////////////////////////////////// + + extern HRESULT NANOCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, const char* szFunc, const char* szFile, int line ); + +#if defined(_WIN32) + +#define NANOCLR_LEAVE() { if(FAILED(hr)) NANOCLR_DEBUG_PROCESS_EXCEPTION( hr, NULL, NULL, 0 ); goto nanoCLR_Cleanup; } +#define NANOCLR_RETURN() return hr + +#else + +#if defined(NANOCLR_TRACE_HRESULT) + +#define NANOCLR_LEAVE() { if(FAILED(hr)) NANOCLR_DEBUG_PROCESS_EXCEPTION( hr, __func__, __FILE__, __LINE__ ); goto nanoCLR_Cleanup; } +#define NANOCLR_RETURN() return hr + +#else + +#define NANOCLR_LEAVE() goto nanoCLR_Cleanup +#define NANOCLR_RETURN() return hr + +#endif + +#endif + + +#define NANOCLR_HEADER() HRESULT hr +#define NANOCLR_CHECK_HRESULT(expr) { if(FAILED(hr = (expr))) NANOCLR_LEAVE(); } +#define NANOCLR_EXIT_ON_SUCCESS(expr) { if(SUCCEEDED(hr = (expr))) NANOCLR_LEAVE(); } +#define NANOCLR_SET_AND_LEAVE(expr) { hr = (expr); NANOCLR_LEAVE(); } +#if defined(_MSC_VER) +#define NANOCLR_MSG_SET_AND_LEAVE(expr, msg) { wprintf(msg); hr = (expr); NANOCLR_LEAVE(); } +#define NANOCLR_MSG1_SET_AND_LEAVE(expr, msg, ...) { wprintf(msg, __VA_ARGS__); hr = (expr); NANOCLR_LEAVE(); } +#define NANOCLR_CHARMSG_SET_AND_LEAVE(expr, msg, ...) { printf(msg, __VA_ARGS__); hr = (expr); NANOCLR_LEAVE(); } +#else +#define NANOCLR_MSG_SET_AND_LEAVE(expr, msg) { hr = (expr); NANOCLR_LEAVE(); } +#define NANOCLR_MSG1_SET_AND_LEAVE(expr, msg, arg) { hr = (expr); NANOCLR_LEAVE(); } +#endif +#define NANOCLR_CLEANUP() hr = S_OK; nanoCLR_Cleanup: +#define NANOCLR_CLEANUP_END() NANOCLR_RETURN() +#define NANOCLR_NOCLEANUP() NANOCLR_CLEANUP(); NANOCLR_CLEANUP_END() +#define NANOCLR_NOCLEANUP_NOLABEL() hr = S_OK; NANOCLR_RETURN() +#define FAULT_ON_NULL(ptr) if(!(ptr)) NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE) +#define FAULT_ON_NULL_ARG(ptr) if(!(ptr)) NANOCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL) + + +// Correspondence between CLR C# and C++ native types: +// CLR Type C/C++ type C/C++ Ref Type + +// System.Byte unsigned char unsigned char& +// System.UInt16 unsigned short int unsigned short int& +// System.UInt32 unsigned int unsigned int& +// System.UInt64 unsigned __int64 unsigned __int64& +// System.Char char char & +// System.SByte signed char signed char & +// System.Int16 signed short int signed short int& +// System.Int32 signed int signed int& +// System.Int64 signed __int64 signed __int64& +// System.Single float float& +// System.Double double double& +// System.String const char * char * +// System.Byte[] unsigned char * Same as C/C++ type + +// Forward declaration for managed stack frame. +// This is internal CLR type, reference to managed stack frame is exposed to marshaling code. +struct CLR_RT_StackFrame; +/********************************************************************** +** +** Forward structure declarations . +** CLR_RT_HeapBlock - generic structure that keeps C# basic types +** CLR_RT_HeapBlock_NativeEventDispatcher - Object that supports managed callback initiated by Interrupts +**********************************************************************/ +struct CLR_RT_HeapBlock; +struct CLR_RT_HeapBlock_NativeEventDispatcher; + +// Do not support marshaling of struct and class. For these types we create params of CLR_RT_HeapBlock* +// and then set it to zero. +typedef CLR_RT_HeapBlock* UNSUPPORTED_TYPE; + +#define CLR_RT_HEAP_BLOCK_SIZE 12 + +#define NANOCLR_NATIVE_DECLARE(mtd) static HRESULT mtd( CLR_RT_StackFrame& stack ) + +typedef HRESULT (*CLR_RT_MethodHandler)( CLR_RT_StackFrame& stack ); + +struct CLR_RT_NativeAssemblyData + +{ // Assembly name or static name provided by driver developer to enable interrups. + const char *m_szAssemblyName; + + // Check sum for the assembly. + unsigned int m_checkSum; + + // Pointer to array of functions that implement native methods. + // It could be different type of the function depending if it is assembly Interop Method + // or function enabling Interrupts by user driver. + const void *m_pNativeMethods; + + // Assembly version + CLR_RECORD_VERSION m_Version; +}; + +// Looks up in interop assemblies table for assembly with specified name. +const CLR_RT_NativeAssemblyData *GetAssemblyNativeData( const char *lpszAssemblyName ); + +// C++ by value parameters ( not reference types ). +/********************************************************************** +** +** Functions: Interop_Marshal_* +** +** Synopsis: This group of functions retrienves by value parameters ( not reference types ) +** Each function gets reference to managed stack frame in index of parameter to extract. +** The C++ value is returned in "param". +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** [param] - Reference to native C++ variable. Filled by the function. +** This variable is filled with value passed from managed code. +** +** Returns: S_OK on success or error in case of paramter mismatch or invalid data passed from managed code. +**********************************************************************/ + +HRESULT Interop_Marshal_bool ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, bool ¶m ); +HRESULT Interop_Marshal_UINT8 ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, unsigned char ¶m ); +HRESULT Interop_Marshal_UINT16( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, unsigned short int ¶m ); +HRESULT Interop_Marshal_UINT32( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, unsigned int ¶m ); +HRESULT Interop_Marshal_UINT64( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, unsigned __int64 ¶m ); +HRESULT Interop_Marshal_CHAR ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, char ¶m ); +HRESULT Interop_Marshal_INT8 ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed char ¶m ); +HRESULT Interop_Marshal_INT16 ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed short int ¶m ); +HRESULT Interop_Marshal_INT32 ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed int ¶m ); +HRESULT Interop_Marshal_INT64 ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed __int64 ¶m ); +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +HRESULT Interop_Marshal_float ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, float ¶m ); +HRESULT Interop_Marshal_double( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, double ¶m ); + +#else +HRESULT Interop_Marshal_float ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed int ¶m ); +HRESULT Interop_Marshal_double( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, signed __int64 ¶m ); +#endif + +HRESULT Interop_Marshal_LPCSTR( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, const char* ¶m ); +// For unsupported types we set param to NULL. +HRESULT Interop_Marshal_UNSUPPORTED_TYPE( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, UNSUPPORTED_TYPE ¶m ); +/********************************************************************** +** +** Functions: Interop_Marshal_*_ARRAY +** +** Synopsis: This group of functions retrienves C++ by value parameters ( not reference types ) +** Each function gets reference to managed stack frame in index of parameter to extract. +** The C++ value is returned in "param". +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** [pByteParam] - Reference to pointer filled by the function. +** On return pParam points to native C++ array with values passed from managed code. +** This variable is filled with value passed from managed code. +** [arraySize] - Count of elements in array. Filled by the function. +** +** Returns: S_OK on success or error in case of paramter mismatch or invalid data passed from managed code. +**********************************************************************/ + + +template class CLR_RT_TypedArray + +{ + T *m_pData; + unsigned int m_ElemCount; + +friend HRESULT Interop_Marshal_bool_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT16_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT32_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT64_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_CHAR_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT16_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT32_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT64_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +friend HRESULT Interop_Marshal_float_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +#else +friend HRESULT Interop_Marshal_float_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray &typedArray ); + +#endif + + +public : + CLR_RT_TypedArray() { m_pData = NULL; m_ElemCount = 0; } + + T GetValue( unsigned int i ) { return m_pData[ i ];} + void SetValue( unsigned int i, T &val ) { m_pData[ i ] = val; } + T& operator[]( unsigned int i ) { return m_pData[ i ];} + + unsigned int GetSize() { return m_ElemCount; } + + // Direct access to buffer is provided for cases when other + // native functions require access to buffer and cannot use CLR_RT_TypedArray object + T *GetBuffer() { return m_pData; } + + }; + +typedef CLR_RT_TypedArray CLR_RT_TypedArray_CHAR; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT8; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT16; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT32; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT64; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT8; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT16; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT32; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT64; +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +typedef CLR_RT_TypedArray CLR_RT_TypedArray_float; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_double; +#else +typedef CLR_RT_TypedArray CLR_RT_TypedArray_float; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_double; + + +#endif + +HRESULT Interop_Marshal_bool_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT8 &typedArray ); +HRESULT Interop_Marshal_UINT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT8 &typedArray ); +HRESULT Interop_Marshal_UINT16_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT16 &typedArray ); +HRESULT Interop_Marshal_UINT32_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT32 &typedArray ); +HRESULT Interop_Marshal_UINT64_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_UINT64 &typedArray ); +HRESULT Interop_Marshal_CHAR_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_CHAR &typedArray ); +HRESULT Interop_Marshal_INT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT8 &typedArray ); +HRESULT Interop_Marshal_INT16_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT16 &typedArray ); +HRESULT Interop_Marshal_INT32_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT32 &typedArray ); +HRESULT Interop_Marshal_INT64_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_INT64 &typedArray ); +HRESULT Interop_Marshal_float_ARRAY ( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_float &typedArray ); +HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, unsigned int paramIndex, CLR_RT_TypedArray_double &typedArray ); + +/********************************************************************** +** +** Functions: SetResult_* +** +** Synopsis: This group of functions set value returned by managed method call. +** Value passed to this function will be the return value of the managed function. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [value] - Return value. This value is stored on managed stack frame and passed to managed code. +**********************************************************************/ + +void SetResult_bool ( CLR_RT_StackFrame &stackFrame, bool value ); +void SetResult_CHAR ( CLR_RT_StackFrame &stackFrame, char value ); +void SetResult_INT8 ( CLR_RT_StackFrame &stackFrame, signed char value ); +void SetResult_INT16 ( CLR_RT_StackFrame &stackFrame, signed short int value ); +void SetResult_INT32 ( CLR_RT_StackFrame &stackFrame, signed int value ); +void SetResult_INT64 ( CLR_RT_StackFrame &stackFrame, signed __int64 value ); +void SetResult_UINT8 ( CLR_RT_StackFrame &stackFrame, unsigned char value ); +void SetResult_UINT16( CLR_RT_StackFrame &stackFrame, unsigned short int value ); +void SetResult_UINT32( CLR_RT_StackFrame &stackFrame, unsigned int value ); +void SetResult_UINT64( CLR_RT_StackFrame &stackFrame, unsigned __int64 value ); +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +void SetResult_float ( CLR_RT_StackFrame &stackFrame, float value ); +void SetResult_double( CLR_RT_StackFrame &stackFrame, double value ); +#else +void SetResult_float ( CLR_RT_StackFrame &stackFrame, signed int value ); +void SetResult_double( CLR_RT_StackFrame &stackFrame, signed __int64 value ); + +#endif + +void SetResult_LPCSTR( CLR_RT_StackFrame &stackFrame, const char* value ); + +/********************************************************************** +** +** Functions: Interop_Marshal_LoadRef_* +** +** Synopsis: This group of functions pointer to reference parameter passed from managed code. +** On return of this function pParam points to reference parameter of managed code. +** Native code can retrieve and modidy the reference parameter using pParam +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** [pByteParam] - Reference to pointer filled by the function. +** On return pParam points to native C++ array with values passed from managed code. +** This variable is filled with value passed from managed code. +** [pParam] - Address of reference parameter passed from managed code. Filled by the function. +** +** Returns: S_OK on success or error in case of paramter mismatch or invalid data passed from managed code. +**********************************************************************/ +HRESULT Interop_Marshal_bool_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned char *&pParam ); +HRESULT Interop_Marshal_UINT8_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned char *&pParam ); +HRESULT Interop_Marshal_UINT16_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned short int *&pParam ); +HRESULT Interop_Marshal_UINT32_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned int *&pParam ); +HRESULT Interop_Marshal_UINT64_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, unsigned __int64 *&pParam ); +HRESULT Interop_Marshal_CHAR_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, char *&pParam ); +HRESULT Interop_Marshal_INT8_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed char *&pParam ); +HRESULT Interop_Marshal_INT16_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed short int *&pParam ); +HRESULT Interop_Marshal_INT32_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed int *&pParam ); +HRESULT Interop_Marshal_INT64_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed __int64 *&pParam ); +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +HRESULT Interop_Marshal_float_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, float *&pParam ); +HRESULT Interop_Marshal_double_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, double *&pParam ); +#else +HRESULT Interop_Marshal_float_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed int *&pParam ); +HRESULT Interop_Marshal_double_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, signed __int64 *&pParam ); + +#endif + + +// For unsuppoted types return NULL reference + +HRESULT Interop_Marshal_UNSUPPORTED_TYPE_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, unsigned int paramIndex, UNSUPPORTED_TYPE *&pParam ); +/********************************************************************** +** +** Function: Interop_Marshal_StoreRef +** +** Synopsis: This function is used to store updated parameter or basic type passed by reference from managed code. +** It stores data from heap block pointed by pVoidHeapBlock back to the managed stack frame. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [pVoidHeapBlock] - Pointer to heap block that keeps updated basic type value +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** +** Returns: S_OK on success or error from StoreToReference. Error return would cause exception thrown in managed code. +**********************************************************************/ +HRESULT Interop_Marshal_StoreRef( CLR_RT_StackFrame &stackFrame, void *pVoidHeapBlock, unsigned int paramIndex ); + +/********************************************************************** +** +** Function: Interop_Marshal_RetrieveManagedObject +** +** Synopsis: Retrieves pointer to managed object from managed stack frame. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** +** Returns: Pointer to managed object or NULL in case of error. +**********************************************************************/ +CLR_RT_HeapBlock* Interop_Marshal_RetrieveManagedObject( CLR_RT_StackFrame &stackFrame ); + +/********************************************************************** +** +** Functions: Interop_Marshal_GetField_ +** +** Synopsis: Retrieves C++ reference ( pointer ) to the field in managed object. +** +** Arguments: [pThis] - Pointer to the managed object retrieved by Interop_Marshal_RetrieveManagedObject. +** [fieldIndex] - Field index. +** +** Returns: Reference to the field. +**********************************************************************/ +bool &Interop_Marshal_GetField_bool ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +unsigned char &Interop_Marshal_GetField_UINT8 ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +unsigned short int &Interop_Marshal_GetField_UINT16( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +unsigned int &Interop_Marshal_GetField_UINT32( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +unsigned __int64 &Interop_Marshal_GetField_UINT64( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +char &Interop_Marshal_GetField_CHAR ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +signed char &Interop_Marshal_GetField_INT8 ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +signed short int &Interop_Marshal_GetField_INT16 ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +signed int &Interop_Marshal_GetField_INT32 ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +signed __int64 &Interop_Marshal_GetField_INT64 ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +//----------------- Float point types - float and double +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +float &Interop_Marshal_GetField_float ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +double &Interop_Marshal_GetField_double( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +#else +signed int &Interop_Marshal_GetField_float ( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +signed __int64 &Interop_Marshal_GetField_double( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); +#endif + +// For all other unsupported types we always return NULL reference. +UNSUPPORTED_TYPE &Interop_Marshal_GetField_UNSUPPORTED_TYPE( CLR_RT_HeapBlock *pThis, unsigned int fieldIndex ); + +/********************************************************************** +** +** Function Signatures that should be supported by drivers to enable managed callbacks. +** +** InitializeInterruptsProc +** This driver function is called in native code by constructor of managed NativeEventDispatcher object. +** Parameters: +** [pContext] - Pointer to the context that should be passed to the ISR ( INterrupt Service Routine ). +** [userData] - User data passed to constructor of NativeEventDispatcher. +**********************************************************************/ +typedef HRESULT (*InitializeInterruptsProc )( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, unsigned __int64 userData ); + +/********************************************************************** +** EnableorDisableInterruptsProc +** This function is called by EnableInterrupt/DisableInterrupt functions of managed NativeEventDispatcher object. +** It should enable or disable HW interrupts. +** [pContext] - Pointer to the context, same as passed to InitializeInterruptsProc +** [fEnable] - If "true" - enable interrupts +** If "false" - disable interrupts +**********************************************************************/ +typedef HRESULT (*EnableorDisableInterruptsProc)( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, bool fEnable ); + +/********************************************************************** +** +** CleanupInterruptsProc +** This function is called to release hardware that generates interrups and release associated resources +** [pContext] - Pointer to the context, same as passed to InitializeInterruptsProc +** +**********************************************************************/ +typedef HRESULT (*CleanupInterruptsProc)( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ); + +/********************************************************************** +** +** InterruptServiceProc +** This is the prototype for the interrupt service routie. +** [pContext] - Pointer to the context, same as passed to InitializeInterruptsProc +** +** This function should call SaveNativeEventToHALQueue in order to create managed callback. +** The minimal implementation for this function would be: +** static void ISR_TestProc( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +** +** { +** GLOBAL_LOCK(); +** // To do - Initialize userData1 and userData2 to userData. +** unsigned int userData1; +** unsigned int userData2; +** // Saves data to queue. Each call to SaveNativeEventToHALQueue initiates managed callback. +** SaveNativeEventToHALQueue( pContext, userData1, userData2 ); +** } +**********************************************************************/ +typedef HRESULT (*InterruptServiceProc)( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ); + + + +/********************************************************************** +** +** Structure that keeps pointers to driver functions. +** The driver functions are accessed by CLR through global instance of this structure. +** See Spot_InteropSample_Native_Microsoft_SPOT_Interop_TestCallback.cpp file for use of this structure. +** +**********************************************************************/ +struct CLR_RT_DriverInterruptMethods + +{ + InitializeInterruptsProc initProcessor; + EnableorDisableInterruptsProc enableProcessor; + CleanupInterruptsProc cleanupProcessor; +}; + +// Randomly generated 32 bit number. +// This check sum validates that m_pNativeMethods points to CLR_RT_DriverInterruptMethods structure +#define DRIVER_INTERRUPT_METHODS_CHECKSUM 0xf32f4c3e + +// Creates instance of CLR_RT_HeapBlock_NativeEventDispatcher. +CLR_RT_HeapBlock_NativeEventDispatcher *CreateNativeEventInstance( CLR_RT_StackFrame& stack ); + +// Saves data from ISR. The data from this queue is used to call managed callbacks. +// Should be called from ISR. + void SaveNativeEventToHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, uint32_t data1, uint32_t data2 ); + +// Cleans up the data in the queue after interrupts were closed and no managed callbacks are expected. + void CleanupNativeEventsFromHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ); + +void CLR_RetrieveCurrentMethod( unsigned int& assmIdx, unsigned int& methodIdx ); + +void CLR_SoftReboot(); + +void CLR_DebuggerBreak(); + +#endif // _NANOCLR_INTEROP_H_ + + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Messaging.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Messaging.h new file mode 100644 index 00000000..854e056e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Messaging.h @@ -0,0 +1,143 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_MESSAGING_H_ +#define _NANOCLR_MESSAGING_H_ + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef bool (*CLR_Messaging_CommandHandler)( WP_Message* msg ); + +struct CLR_Messaging_CommandHandlerLookup +{ + CLR_Messaging_CommandHandler hnd; + unsigned int cmd; +}; + +struct CLR_Messaging_CommandHandlerLookups +{ + const CLR_Messaging_CommandHandlerLookup* table; + CLR_UINT32 size; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_Messaging_Commands +{ + static const unsigned int c_Messaging_Query = 0x00020090; // Checks the presence of an EndPoint. + static const unsigned int c_Messaging_Send = 0x00020091; // Sends a message to an EndPoint. + static const unsigned int c_Messaging_Reply = 0x00020092; // Response from an EndPoint. + + struct Messaging_Query + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + struct Messaging_Send + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + unsigned char m_data[ 1 ]; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + struct Messaging_Reply + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + unsigned char m_data[ 1 ]; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + +}; + + +struct CLR_Messaging +{ + struct CachedMessage : public CLR_RT_HeapBlock_Node + { + static const CLR_UINT32 c_Processed = 0x00000001; + + CLR_UINT32 m_flags; + + CLR_UINT32 m_size; + CLR_INT64 m_lastSeen; + WP_Message m_message; + }; + + //--// + + CLR_Messaging_CommandHandlerLookups m_Lookup_Requests[ 2 ]; + CLR_Messaging_CommandHandlerLookups m_Lookup_Replies[ 2 ]; + + COM_HANDLE m_port; + + //--// + + static HRESULT CreateInstance(); + + void Initialize(const CLR_Messaging_CommandHandlerLookup* requestLookup, const CLR_UINT32 requestLookupCount, const CLR_Messaging_CommandHandlerLookup* replyLookup, const CLR_UINT32 replyLookupCount ); + void Cleanup(); + + static HRESULT DeleteInstance(); + + //void ProcessCommands(); + + bool SendEvent ( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ); + static void BroadcastEvent( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ); + + static bool App_ProcessHeader ( void* state, WP_Message* msg ); + static bool App_ProcessPayload( void* state, WP_Message* msg ); + static bool App_Release ( void* state, WP_Message* msg ); + + bool IsDebuggerInitialized() { return m_fDebuggerInitialized; } + void InitializeDebugger() { m_fDebuggerInitialized = (DebuggerPort_Initialize( m_port ) == true); } + +private: + + bool m_fInitialized; + bool m_fDebuggerInitialized; + + bool AllocateAndQueueMessage( CLR_UINT32 cmd, unsigned int length, unsigned char* data, CLR_RT_HeapBlock_EndPoint::Port port, CLR_RT_HeapBlock_EndPoint::Address addr, CLR_UINT32 found ); + + bool ProcessHeader ( WP_Message* msg ); + + + + + + + +public: + bool ProcessPayload( WP_Message* msg ); + static bool Messaging_Query ( WP_Message* msg ); + static bool Messaging_Query__Reply ( WP_Message* msg ); + static bool Messaging_Send ( WP_Message* msg ); + static bool Messaging_Send__Reply ( WP_Message* msg ); + static bool Messaging_Reply ( WP_Message* msg ); + static bool Messaging_Reply__Reply ( WP_Message* msg ); +}; + +//--// + +#endif // _NANOCLR_MESSAGING_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_ParseOptions.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_ParseOptions.h new file mode 100644 index 00000000..497e0a1c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_ParseOptions.h @@ -0,0 +1,136 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_PARSEOPTIONS_H_ +#define _NANOCLR_PARSEOPTIONS_H_ + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +struct CLR_RT_ParseOptions +{ + typedef std::map< std::wstring, CLR_RT_Buffer* > BufferMap; + typedef BufferMap::iterator BufferMapIter; + + struct Parameter + { + const wchar_t* m_szName; + const wchar_t* m_szDescription; + + Parameter( const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( const wchar_t* val ) = 0; + }; + + typedef std::vector< Parameter* > ParameterList; + typedef ParameterList::iterator ParameterListIter; + + CLR_RT_StringVector CommandLineArgs; + + //--// + + struct Parameter_Generic : Parameter + { + std::wstring m_data; + + Parameter_Generic( const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( const wchar_t* arg ); + }; + + struct Parameter_String : Parameter + { + std::wstring m_dataParsed; + std::wstring* m_dataPtr; + + Parameter_String( std::wstring* data, const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( const wchar_t* arg ); + }; + + struct Parameter_Boolean : Parameter + { + bool m_dataParsed; + bool* m_dataPtr; + + Parameter_Boolean( bool* data, const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( const wchar_t* arg ); + }; + + struct Parameter_Integer : Parameter + { + int m_dataParsed; + int* m_dataPtr; + + Parameter_Integer( int* data, const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( const wchar_t* arg ); + }; + + struct Parameter_Float : Parameter + { + float m_dataParsed; + float* m_dataPtr; + + Parameter_Float( float* data, const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( const wchar_t* arg ); + }; + + //--// + + struct Command + { + const wchar_t* m_szName; + const wchar_t* m_szDescription; + ParameterList m_params; + + Command( const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options ); + + virtual HRESULT Execute(); + }; + + typedef std::list< Command* > CommandList; + typedef CommandList::iterator CommandListIter; + + //--// + + struct Command_SetFlag : Command + { + bool m_dataParsed; + bool* m_dataPtr; + + Command_SetFlag( bool* data, const wchar_t* szName, const wchar_t* szDescription ); + + virtual bool Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options ); + }; + + //--// + + bool m_fVerbose; + CommandList m_commands; + + //--// + + CLR_RT_ParseOptions(); + + HRESULT ExtractOptionsFromFile( const wchar_t* szFileName ); + + HRESULT ReprocessOptions(); + HRESULT ProcessOptions( CLR_RT_StringVector& vec ); + void PushArguments ( int argc, wchar_t* argv[], CLR_RT_StringVector& vec ); + + virtual void Usage(); +}; + +#endif + +#endif // _NANOCLR_PARSEOPTIONS_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_PlatformDef.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_PlatformDef.h new file mode 100644 index 00000000..e3059cf1 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_PlatformDef.h @@ -0,0 +1,246 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_PLATFORMDEF_H_ +#define _NANOCLR_PLATFORMDEF_H_ + +//#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// DEFINITIONS +#define NANOCLR_VALIDATE_HEAP_0_None 0 // No Trace +#define NANOCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink 1 // Validate HeapBlocks and Unlink. +#define NANOCLR_VALIDATE_HEAP_2_DblLinkedList 2 // Validate a DblLinkedList before each operation. +#define NANOCLR_VALIDATE_HEAP_3_Compaction 3 // Trace Compaction +#define NANOCLR_VALIDATE_HEAP_4_CompactionPlus 4 // Trace Compaction Plus + +#define NANOCLR_MAX_ASSEMBLY_NAME 128 + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FEATURES + + +#if defined(PLATFORM_EMULATED_FLOATINGPOINT) +#define NANOCLR_EMULATED_FLOATINGPOINT // use the fixed point floating point notation in the clr codes +#endif + +#if defined(NANOCLR_USE_APPDOMAINS) +#define NANOCLR_APPDOMAINS // enables application doman support +#endif +#define NANOCLR_TRACE_EXCEPTIONS // enables exception dump support +#define NANOCLR_TRACE_ERRORS // enables rich exception dump support +#if defined(DEBUG) || defined(_DEBUG) +#define NANOCLR_TRACE_STACK // enables rich eval stack tracing +#endif +//#define TINYCLR_TRACE_INSTRUCTIONS 1 // enables tracing of instructions execution +//#define NANOCLR_TRACE_HRESULT // enable tracing of HRESULTS from interop libraries + +//-o-//-o-//-o-//-o-//-o-//-o-// +// PLATFORMS +//-o-//-o-//-o-//-o-//-o-//-o-// + + +//--// +// Setting the threshold value to start Garbagge collector +// PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD should set in the file platform.settings file, eg sam7x_ek.settings. +// defaults are 32Kb and 48 kb for lower and upper threshold respectively + +#ifdef PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD +#define HEAP_SIZE_THRESHOLD PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD +#else +#define HEAP_SIZE_THRESHOLD 48 * 1024 +#endif + +#ifdef PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD_UPPER +#define HEAP_SIZE_THRESHOLD_UPPER PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD_UPPER +#else +#define HEAP_SIZE_THRESHOLD_UPPER HEAP_SIZE_THRESHOLD + 16 * 1024 +#endif + +//--// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// WINDOWS +#if defined(_WIN32) + +#define NANOCLR_GC_VERBOSE +#define NANOCLR_TRACE_MEMORY_STATS +#define NANOCLR_PROFILE_NEW +#define NANOCLR_PROFILE_NEW_CALLS +#define NANOCLR_PROFILE_NEW_ALLOCATIONS +#if defined(DEBUG) || defined(_DEBUG) +#define NANOCLR_VALIDATE_HEAP NANOCLR_VALIDATE_HEAP_2_DblLinkedList +//#define NANOCLR_TRACE_MALLOC +#define NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN +#define NANOCLR_TRACE_EARLYCOLLECTION +#define NANOCLR_DELEGATE_PRESERVE_STACK +//#define NANOCLR_VALIDATE_APPDOMAIN_ISOLATION +#define NANOCLR_TRACE_HRESULT // enable tracing of HRESULTS from interop libraries +#else //RELEASE +#define NANOCLR_VALIDATE_HEAP NANOCLR_VALIDATE_HEAP_0_None +#endif +#define NANOCLR_ENABLE_SOURCELEVELDEBUGGING +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// ARM & ESP32 +#if defined(PLATFORM_ARM) || defined(PLATFORM_ESP32) +// #define NANOCLR_STRESS_GC +// #define NANOCLR_GC_VERBOSE +// #define NANOCLR_PROFILE_NEW +// #define NANOCLR_PROFILE_NEW_CALLS +// #define NANOCLR_PROFILE_NEW_ALLOCATIONS +// #define NANOCLR_TRACE_MEMORY_STATS +// #define NANOCLR_FORCE_GC_BEFORE_EVERY_ALLOCATION +#define NANOCLR_VALIDATE_HEAP NANOCLR_VALIDATE_HEAP_0_CompactionPlus +#endif + +//-o-//-o-//-o-//-o-//-o-//-o-// +// RULES AND DEPENDENCIES +//-o-//-o-//-o-//-o-//-o-//-o-// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// GENERAL RTM RULES +#if defined(BUILD_RTM) || defined(PLATFORM_NO_CLR_TRACE) +#undef NANOCLR_TRACE_MEMORY_STATS +#undef NANOCLR_TRACE_EXCEPTIONS +#undef NANOCLR_TRACE_ERRORS +#undef NANOCLR_TRACE_EARLYCOLLECTION +#undef NANOCLR_VALIDATE_HEAP +#undef NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// TRACE DEPENDENCIES +#if defined(_WIN32) +#define NANOCLR_OPCODE_NAMES +#define NANOCLR_OPCODE_PARSER +#define NANOCLR_OPCODE_STACKCHANGES +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if !defined(NANOCLR_VALIDATE_HEAP) +#define NANOCLR_VALIDATE_HEAP NANOCLR_VALIDATE_HEAP_0_None +#endif + +#if defined(NANOCLR_PROFILE_NEW_CALLS) && !defined(NANOCLR_PROFILE_HANDLER) +#define NANOCLR_PROFILE_HANDLER +#endif + +#if defined(NANOCLR_PROFILE_NEW_CALLS) && !defined(NANOCLR_PROFILE_NEW) +#define NANOCLR_PROFILE_NEW +#endif + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) && !defined(NANOCLR_PROFILE_NEW) +#define NANOCLR_PROFILE_NEW +#endif + +//-o-//-o-//-o-//-o-//-o-//-o-// +// CODE +//-o-//-o-//-o-//-o-//-o-//-o-// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// LANGUAGE +#if defined(_WIN32) +#define PROHIBIT_ALL_CONSTRUCTORS(cls) \ + private: \ + cls(); \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS(cls) \ + public: \ + cls() {} \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS2(cls) \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define LONGLONGCONSTANT(v) (v##I64) +#define ULONGLONGCONSTANT(v) (v##UI64) +#endif + +#if defined(PLATFORM_ARM) | defined(PLATFORM_ESP32) +#define PROHIBIT_ALL_CONSTRUCTORS(cls) \ + private: \ + cls(); \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS(cls) \ + public: \ + cls() {} \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS2(cls) \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define LONGLONGCONSTANT(v) (v##ll) +#define ULONGLONGCONSTANT(v) (v##ull) +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// INCLUDES +#if defined(_WIN32) + +#define _WIN32_WINNT 0x0501 + +//Unsafe string functions be avoided, but there isn't a safe crt for the arm, so +//a bunch of macros, cleanup code needs to be done first + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#else + +#include + +#include +#include +#include +#include +#include + +#ifndef MAKE_HRESULT +#define MAKE_HRESULT(sev,fac,code) \ + ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) +#endif + +#ifndef SEVERITY_SUCCESS +#define SEVERITY_SUCCESS 0 +#endif + +#ifndef SEVERITY_ERROR +#define SEVERITY_ERROR 1 +#endif + +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _NANOCLR_PLATFORMDEF_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Profiling.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Profiling.h new file mode 100644 index 00000000..4bcc9f0c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Profiling.h @@ -0,0 +1,219 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_PROFILING_H_ +#define _NANOCLR_PROFILING_H_ + +#if defined(NANOCLR_PROFILE_NEW) + +/* + * See RFC2234 for Augmented Backus Naur form documentation. + * All terminal literals are bits, not ASCII characters. + * Bits are packed such that the first bit goes to the most significant bit, + * the second goes to the second-most significant, etc. + +short = 16BIT +int = 32BIT +long = 64BIT +pointer = 32BIT +datatype = 8BIT +typedef-idx = 32BIT +method-idx = 32BIT + nanoCLR Method_Idx value for identifying a specific function + +stream-packet = sequence-id length stream-payload + A chunk of data sent out over the WireProtocol. + +sequence-id = short + Number used to order the packets + +length = short + Number in bits in stream-payload + +stream-payload = *profiler-packet + Payload is a sequence of profiler packets. + +profiling-stream = *stream-payload + The reconstructed stream of data to be processed. + +profiler-packet = timestamp-packet / memory-layout-packet heapdump-start-packet / heapdump-root-packet / + heapdump-object-packet / heapdump-stop-packet + +timestamp-header = "0000001" +timestamp-time = long +timestamp-packet = timestamp-header timestamp-time + Marks time intervals to allow object lifetime estimates and histograms + +memory-layout-packet = memory-layout-header memory-layout-heap-address memory-layout-heap-length +memory-layout-header = "00000010" +memory-layout-heap-address = pointer +memory-layout-heap-length = int + Contains heap layout information useful for showing memory usage statistics. + +heapdump = heapdump-start-packet *heapdump-root-packet *heapdump-object-packet heapdump-stop-packet + Heapdumps always occur in this form. All roots are listed before all objects, and both roots and objects fall between + a pair of 'start' and 'stop' packets. Heap dumps may be split up across stream-payload boundaries, but they may not be + nested, and packets may not be sent in any other order. + +heapdump-start-header = "00000011" +heapdump-start-packet = heapdump-start-header + Marks the beginning of a heap dump. Multiple can exist in the same profiling-stream + if and only if there is a heapdump-stop-packet between every pair of heapdump-start-packets. + +heapdump-root-packet = heapdump-root-header ( heapdump-root-stack / heapdump-root-other ) +heapdump-root-header = "00000011" + +heapdump-root-stack = heapdump-root-stack-header method-idx +heapdump-root-stack-header = "101" + +heapdump-root-other = heapdump-root-finalizer / heapdump-root-appdomain / heapdump-root-assembly / heapdump-root-thread +heapdump-root-finalizer = "001" +heapdump-root-appdomain = "010" +heapdump-root-assembly = "011" +heapdump-root-thread = "100" + +heapdump-object-packet = heapdump-object-header heapdump-object-type heapdump-object-references +heapdump-object-header = heapdump-object-address heapdump-object-size +heapdump-object-address = pointer +heapdump-object-size = short + Size is the number of HeapBlock chunks used, not the number of bytes used. + +heapdump-object-type = heapdump-object-classvaluetype / heapdump-object-array / heapdump-object-other + +heapdump-object-classvaluetype = heapdump-object-classvaluetype-header heapdump-object-classvaluetype-typedef +heapdump-object-classvaluetype-header = "00010001" / "00010010" +heapdump-object-classvaluetype-typedef = typedef-idx + +heapdump-object-array = heapdump-object-array-header heapdump-object-array-datatype heapdump-object-array-levels +heapdump-object-array-header = "00010011" +heapdump-object-array-typedef = typedef-idx +heapdump-object-array-levels = short + Rank of the array + +heapdump-object-special-cases = heapdump-object-classvaluetype-header / heapdump-object-array-header +heapdump-object-other = datatype + datatype must not be one of ; If it is, the appropriate special case should be used instead. + +heapdump-object-references = *heapdump-object-reference heapdump-object-end-of-references +heapdump-object-reference = "1" pointer +heapdump-object-end-of-references = "0" + +heapdump-stop-packet = heapdump-stop-header heapdump-stop-blocks-used + Used to mark the end of a specific heap-dump. Must not follow another + unless another came first. + +heapdump-stop-header = "00000110" +heapdump-stop-blocks-used = int + Reports how many heap-blocks were used by objects, including objects that might have been filtered out from reporting. + + */ + +class CLR_PRF_CMDS +{ + public: + static const CLR_UINT32 c_Profiling_Timestamp = 0x01; + static const CLR_UINT32 c_Profiling_Memory_Layout = 0x02; + + static const CLR_UINT32 c_Profiling_HeapDump_Start = 0x03; + static const CLR_UINT32 c_Profiling_HeapDump_Root = 0x04; + static const CLR_UINT32 c_Profiling_HeapDump_Object = 0x05; + static const CLR_UINT32 c_Profiling_HeapDump_Stop = 0x06; + + static const CLR_UINT32 c_Profiling_Calls_Call = 0x07; + static const CLR_UINT32 c_Profiling_Calls_Return = 0x08; + static const CLR_UINT32 c_Profiling_Calls_CtxSwitch = 0x09; + + static const CLR_UINT32 c_Profiling_Allocs_Alloc = 0x0a; + static const CLR_UINT32 c_Profiling_Allocs_Relloc = 0x0b; + static const CLR_UINT32 c_Profiling_Allocs_Delete = 0x0c; + + static const CLR_UINT32 c_Profiling_GarbageCollect_Begin = 0x0d; + static const CLR_UINT32 c_Profiling_GarbageCollect_End = 0x0e; + + static const CLR_UINT32 c_Profiling_HeapCompact_Begin = 0x0f; + static const CLR_UINT32 c_Profiling_HeapCompact_End = 0x10; + + class Bits + { + public: + static const CLR_UINT32 CommandHeader = 8; + static const CLR_UINT32 DataType = 8; + static const CLR_UINT32 NibbleCount = 3; + static const CLR_UINT32 RootTypes = 3; + static const CLR_UINT32 TimestampShift = 8; + static const CLR_UINT32 CallTimingShift = 4; + }; + + class RootTypes + { + public: + static const CLR_UINT32 Root_Finalizer = 0x01; + static const CLR_UINT32 Root_AppDomain = 0x02; + static const CLR_UINT32 Root_Assembly = 0x03; + static const CLR_UINT32 Root_Thread = 0x04; + static const CLR_UINT32 Root_Stack = 0x05; + }; +}; + +struct CLR_PRF_Profiler +{ + // This is not implemented: + // Write formatter functions to send only as many bits as needed for uint32,uint64 numbers, cast bytes, etc. + static HRESULT CreateInstance(); + static HRESULT DeleteInstance(); + + HRESULT Stream_Send(); + HRESULT Stream_Flush(); + + HRESULT Profiler_Cleanup(); + HRESULT DumpHeap(); + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + HRESULT RecordContextSwitch( CLR_RT_Thread* nextThread ); + HRESULT RecordFunctionCall( CLR_RT_Thread* th, CLR_RT_MethodDef_Index md ); + HRESULT RecordFunctionReturn( CLR_RT_Thread* th, CLR_PROF_CounterCallChain& prof ); +#endif + +#if defined(NANOCLR_PROFILE_NEW_ALLOCATIONS) + void TrackObjectCreation( CLR_RT_HeapBlock* ptr ); + void TrackObjectDeletion( CLR_RT_HeapBlock* ptr ); + void TrackObjectRelocation(); + void RecordGarbageCollectionBegin(); + void RecordGarbageCollectionEnd(); + void RecordHeapCompactionBegin(); + void RecordHeapCompactionEnd(); +#endif + + void SendMemoryLayout(); + +private: + void SendTrue(); + void SendFalse(); + void Timestamp(); + void PackAndWriteBits( CLR_UINT32 value ); + void PackAndWriteBits( const CLR_RT_TypeDef_Index& typeDef ); + void PackAndWriteBits( const CLR_RT_MethodDef_Index& methodDef ); + CLR_RT_HeapBlock* FindReferencedObject( CLR_RT_HeapBlock* ref ); + HRESULT DumpRoots(); + void DumpRoot( CLR_RT_HeapBlock* root, CLR_UINT32 type, CLR_UINT32 flags, CLR_RT_MethodDef_Index* source ); + void DumpObject( CLR_RT_HeapBlock* ptr ); + void DumpEndOfRefsList(); + void DumpPointer( void* ref ); + void DumpSingleReference( CLR_RT_HeapBlock* ptr ); + void DumpListOfReferences( CLR_RT_DblLinkedList& list ); + void DumpListOfReferences( CLR_RT_HeapBlock* firstItem, CLR_UINT16 count ); + + CLR_RT_HeapBlock_MemoryStream* m_stream; + CLR_UINT16 m_packetSeqId; + CLR_UINT32 m_lastTimestamp; + CLR_IDX m_currentAssembly; + int m_currentThreadPID; +}; + +extern CLR_PRF_Profiler g_CLR_PRF_Profiler; + +#endif //defined(NANOCLR_PROFILE_NEW) +#endif // _NANOCLR_PROFILING_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime.h new file mode 100644 index 00000000..72c940d6 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime.h @@ -0,0 +1,3246 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_RUNTIME_H_ +#define _NANOCLR_RUNTIME_H_ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +struct CLR_RADIAN +{ + short cos; + short sin; +}; + +extern const CLR_RADIAN c_CLR_radians[]; + +//--// + +#if defined(_WIN32) + +#include +#include +#include +#include +#include +#include +#include + +typedef std::set< std::wstring > CLR_RT_StringSet; +typedef CLR_RT_StringSet::iterator CLR_RT_StringSetIter; + +typedef std::map< std::string,int > CLR_RT_StringMap; +typedef CLR_RT_StringMap::iterator CLR_RT_StringMapIter; + +typedef std::vector< std::wstring > CLR_RT_StringVector; +typedef CLR_RT_StringVector::iterator CLR_RT_StringVectorIter; + +typedef std::map< std::wstring, CLR_UINT32 > CLR_RT_SymbolToAddressMap; +typedef CLR_RT_SymbolToAddressMap::iterator CLR_RT_SymbolToAddressMapIter; + +typedef std::map< CLR_UINT32, std::wstring > CLR_RT_AddressToSymbolMap; +typedef CLR_RT_AddressToSymbolMap::iterator CLR_RT_AddressToSymbolMapIter; + +#else + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_4_CompactionPlus +#include +#include +#endif + +#endif // #if defined(_WIN32) + +#if defined(_MSC_VER) +#pragma pack(push, NANOCLR_RUNTIME_H, 4) +#endif + +#if defined(_WIN32) +//--// + +#define _COM_SMRT_PTR(i) typedef _com_ptr_t<_com_IIID> i ## Ptr +#define _COM_SMRT_PTR_2(i,u) typedef _com_ptr_t<_com_IIID> i ## Ptr + + +_COM_SMRT_PTR(IXMLDOMDocument); +_COM_SMRT_PTR(IXMLDOMNode); + +class CLR_XmlUtil +{ + IXMLDOMDocumentPtr m_xddDoc; + IXMLDOMNodePtr m_xdnRoot; + HANDLE m_hEvent; // Used to abort a download. + unsigned long m_dwTimeout; // Used to limit a download. + + void Init (); + void Clean(); + + HRESULT LoadPost( /*[in] */ const wchar_t* szRootTag , + /*[out]*/ bool& fLoaded , + /*[out]*/ bool* fFound ); + + HRESULT CreateParser(); + +public: + CLR_XmlUtil( /*[in]*/ const CLR_XmlUtil& xml ); + CLR_XmlUtil( /*[in]*/ IXMLDOMDocument* xddDoc , /*[in]*/ const wchar_t* szRootTag = NULL ); + CLR_XmlUtil( /*[in]*/ IXMLDOMNode* xdnRoot = NULL, /*[in]*/ const wchar_t* szRootTag = NULL ); + + ~CLR_XmlUtil(); + + + CLR_XmlUtil& operator=( /*[in]*/ const CLR_XmlUtil& xml ); + CLR_XmlUtil& operator=( /*[in]*/ IXMLDOMNode* xdnRoot ); + + HRESULT DumpError(); + + HRESULT New ( /*[in]*/ IXMLDOMNode* xdnRoot , /*[in] */ bool fDeep = false ); + HRESULT New ( /*[in]*/ const wchar_t* szRootTag, /*[in] */ const wchar_t* szEncoding = L"utf-8" /*L"unicode"*/ ); + HRESULT Load ( /*[in ]*/ const wchar_t* szFile , /*[in]*/ const wchar_t* szRootTag, /*[out]*/ bool& fLoaded, /*[out]*/ bool* fFound = NULL ); + HRESULT LoadAsStream( /*[in ]*/ IUnknown* pStream , /*[in]*/ const wchar_t* szRootTag, /*[out]*/ bool& fLoaded, /*[out]*/ bool* fFound = NULL ); + HRESULT LoadAsString( /*[in ]*/ BSTR bstrData, /*[in]*/ const wchar_t* szRootTag, /*[out]*/ bool& fLoaded, /*[out]*/ bool* fFound = NULL ); + HRESULT Save ( /*[in ]*/ const wchar_t* szFile ); + HRESULT SaveAsStream( /*[out]*/ IUnknown* *ppStream ); + HRESULT SaveAsString( /*[out]*/ BSTR *pbstrData ); + + HRESULT SetTimeout( /*[in]*/ unsigned long dwTimeout ); + HRESULT Abort ( ); + + HRESULT SetVersionAndEncoding( /*[in]*/ const wchar_t* szVersion, /*[in]*/ const wchar_t* szEncoding ); + + HRESULT GetDocument ( /*[out]*/ IXMLDOMDocument* * pVal ) const; + HRESULT GetRoot ( /*[out]*/ IXMLDOMNode* * pVal ) const; + HRESULT GetNodes ( /*[in]*/ const wchar_t* szTag, /*[out]*/ IXMLDOMNodeList* * pVal ) const; + HRESULT GetNode ( /*[in]*/ const wchar_t* szTag, /*[out]*/ IXMLDOMNode* * pVal ) const; + HRESULT CreateNode ( /*[in]*/ const wchar_t* szTag, /*[out]*/ IXMLDOMNode* * pVal, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT GetAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[out]*/ IXMLDOMAttribute* * pValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[out]*/ _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[out]*/ std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[out]*/ signed int& lValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetValue ( /*[in]*/ const wchar_t* szTag, /*[out]*/ _variant_t& vValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetValue ( /*[in]*/ const wchar_t* szTag, /*[out]*/ _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetValue ( /*[in]*/ const wchar_t* szTag, /*[out]*/ std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT ModifyAttribute( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyAttribute( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyAttribute( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ const wchar_t* szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyAttribute( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ signed int lValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyValue ( /*[in]*/ const wchar_t* szTag, /*[in] */ const _variant_t& vValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyValue ( /*[in]*/ const wchar_t* szTag, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyValue ( /*[in]*/ const wchar_t* szTag, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT PutAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ IXMLDOMAttribute* * pValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ const wchar_t* szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in] */ signed int lValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ const wchar_t* szTag, /*[in] */ const _variant_t& vValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ const wchar_t* szTag, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ const wchar_t* szTag, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ const wchar_t* szTag, /*[in] */ const wchar_t* szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT RemoveAttribute( /*[in]*/ const wchar_t* szTag, /*[in]*/ const wchar_t* szAttr, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT RemoveValue ( /*[in]*/ const wchar_t* szTag, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT RemoveNode ( /*[in]*/ const wchar_t* szTag, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); +}; + +//--// + + +typedef std::vector< CLR_UINT8 > CLR_RT_Buffer; + +struct CLR_RT_FileStore +{ + static HRESULT LoadFile( const wchar_t* szFile, CLR_RT_Buffer& vec ); + static HRESULT SaveFile( const wchar_t* szFile, const CLR_RT_Buffer& vec ); + static HRESULT SaveFile( const wchar_t* szFile, const CLR_UINT8* buf, size_t size ); + + static HRESULT ExtractTokensFromFile( const wchar_t* szFileName, CLR_RT_StringVector& vec, const wchar_t* separators = L" \t", bool fNoComments = true ); + + static void ExtractTokens ( const CLR_RT_Buffer& buf , CLR_RT_StringVector& vec, const wchar_t* separators = L" \t", bool fNoComments = true ); + static void ExtractTokensFromBuffer( wchar_t* szLine, CLR_RT_StringVector& vec, const wchar_t* separators = L" \t", bool fNoComments = true ); + static void ExtractTokensFromString( const wchar_t* szLine, CLR_RT_StringVector& vec, const wchar_t* separators = L" \t" ); +}; + +#endif + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#if !defined(MAX) +#define MAX(a,b) (a > b ? a : b) +#endif +#if !defined(MIN) +#define MIN(a,b) (a < b ? a : b) +#endif +#define ABS(x) (x > 0 ? x : (-x)) +#define FLOOR32(x) ((CLR_INT32)x) +#define FRAC(x) (x - FLOOR32(x)) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +struct CLR_RT_HeapBlock; +struct CLR_RT_HeapBlock_Node; + +struct CLR_RT_HeapBlock_WeakReference; +struct CLR_RT_HeapBlock_String; +struct CLR_RT_HeapBlock_Array; +struct CLR_RT_HeapBlock_Delegate; +struct CLR_RT_HeapBlock_Delegate_List; +struct CLR_RT_HeapBlock_BinaryBlob; + +struct CLR_RT_HeapBlock_Button; +struct CLR_RT_HeapBlock_Lock; +struct CLR_RT_HeapBlock_LockRequest; +struct CLR_RT_HeapBlock_Timer; +struct CLR_RT_HeapBlock_WaitForObject; +struct CLR_RT_HeapBlock_Finalizer; +struct CLR_RT_HeapBlock_MemoryStream; + +struct CLR_RT_HeapCluster; +struct CLR_RT_GarbageCollector; + +struct CLR_RT_DblLinkedList; + +#if defined(NANOCLR_APPDOMAINS) +struct CLR_RT_AppDomain; +struct CLR_RT_AppDomainAssembly; +#endif //NANOCLR_APPDOMAINS + +struct CLR_RT_Assembly; +struct CLR_RT_TypeSystem; +struct CLR_RT_TypeDescriptor; + +struct CLR_RT_Assembly_Instance; +struct CLR_RT_TypeSpec_Instance; +struct CLR_RT_TypeDef_Instance; +struct CLR_RT_MethodDef_Instance; +struct CLR_RT_FieldDef_Instance; + +struct CLR_RT_StackFrame; +struct CLR_RT_SubThread; +struct CLR_RT_Thread; +struct CLR_RT_ExecutionEngine; + +struct CLR_RT_ExecutionEngine_PerfCounters; + +struct CLR_HW_Hardware; + +typedef void (*CLR_RT_MarkingHandler )( CLR_RT_HeapBlock_BinaryBlob* ptr ); +typedef void (*CLR_RT_RelocationHandler)( CLR_RT_HeapBlock_BinaryBlob* ptr ); +typedef void (*CLR_RT_HardwareHandler )(); + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_PROFILE_HANDLER) + +struct CLR_PROF_CounterSimple; +struct CLR_PROF_Counter; +struct CLR_PROF_Counter_Value; +struct CLR_PROF_Counter_Value2; +struct CLR_PROF_Handler; + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + +struct CLR_PROF_CounterCallChain +{ + CLR_UINT64 m_time_exclusive; + CLR_RT_StackFrame* m_owningStackFrame; + CLR_PROF_Handler* m_owningHandler; + + + //--// + + void* Prepare ( CLR_PROF_Handler* handler ); + void Complete( CLR_UINT64& t, CLR_PROF_Handler* handler ); + + void Enter( CLR_RT_StackFrame* stack ); + void Leave( ); + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_PROF_CounterCallChain); +}; +#endif + +//--// + +struct CLR_PROF_Handler +{ + static const int c_Mode_Ignore = 0; + static const int c_Mode_Plain = 1; + static const int c_Mode_Simple = 2; +#if defined(NANOCLR_PROFILE_NEW_CALLS) + static const int c_Mode_CallChain = 3; +#endif + + static bool s_initialized; + static CLR_PROF_Handler* s_current; + static volatile CLR_UINT64 s_time_overhead; + static volatile CLR_UINT64 s_time_freeze; + static volatile CLR_UINT64 s_time_adjusted; + + int m_target_Mode; + void* m_target; + + CLR_PROF_Handler* m_containing; + CLR_UINT64 m_time_correction; + CLR_UINT64 m_time_start; + + //--// + + CLR_PROF_Handler( ) { Constructor( ); } + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + CLR_PROF_Handler( CLR_PROF_CounterCallChain& target ) { Constructor( target ); } +#endif + + ~CLR_PROF_Handler() { Destructor(); } + + //--// + + static void Calibrate ( ); + static void SuspendTime ( ); + static CLR_UINT64 GetFrozenTime( ); + static CLR_UINT64 ResumeTime ( ); + static CLR_UINT64 ResumeTime ( CLR_INT64 t ); + + //--// + +private: + void Constructor( ); +#if defined(NANOCLR_PROFILE_NEW_CALLS) + void Constructor( CLR_PROF_CounterCallChain& target ); +#endif + + void Destructor(); + + void Init( void* target ); + + PROHIBIT_COPY_CONSTRUCTORS2(CLR_PROF_Handler); +}; + +//--// + +#define CLR_PROF_HANDLER_SUSPEND_TIME() CLR_PROF_Handler::SuspendTime() +#define CLR_PROF_HANDLER_RESUME_TIME() CLR_PROF_Handler::ResumeTime() + +#else + +#define CLR_PROF_HANDLER_SUSPEND_TIME() +#define CLR_PROF_HANDLER_RESUME_TIME() + +#endif + +#if defined(NANOCLR_PROFILE_NEW_CALLS) + +#define CLR_PROF_HANDLER_CALLCHAIN_VOID(v) CLR_PROF_Handler v +#define CLR_PROF_HANDLER_CALLCHAIN(v,t) CLR_PROF_Handler v( t ) + +#else + +#define CLR_PROF_HANDLER_CALLCHAIN_VOID(v) +#define CLR_PROF_HANDLER_CALLCHAIN(v,t) + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_MemoryRange +{ + unsigned char* m_location; + unsigned int m_size; + + bool LimitToRange( CLR_RT_MemoryRange& filtered, unsigned char* address, unsigned int length ) const; +}; + +extern CLR_RT_MemoryRange s_CLR_RT_Heap; + +//--// + +struct CLR_RT_Memory +{ + static void ZeroFill( void* buf, size_t len ) { memset( buf, 0, len ); } + + //--// + + static void Reset ( ); + static void* SubtractFromSystem( size_t len ); + static void Release ( void* ptr ); + static void* Allocate ( size_t len, CLR_UINT32 flags = 0 ); + static void* ReAllocate ( void* ptr, size_t len ); + static void* Allocate_And_Erase( size_t len, CLR_UINT32 flags = 0 ); +}; + +//--// + +struct CLR_RT_Random +{ +public: + void Initialize(); + void Initialize( int seed ); + + uint32_t Next(); + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + double NextDouble(); +#else + CLR_INT64 NextDouble(); +#endif + void NextBytes( unsigned char* buffer, unsigned int count ); +}; + +//--// + +extern void CLR_RT_GetVersion( unsigned short int* pMajor, unsigned short int* pMinor, unsigned short int* pBuild, unsigned short int* pRevision ); + +#define NANOCLR_CLEAR(ref) CLR_RT_Memory::ZeroFill( &ref, sizeof(ref) ) + +//--// + +static const int c_CLR_RT_Trace_None = 0; +static const int c_CLR_RT_Trace_Info = 1; +static const int c_CLR_RT_Trace_Verbose = 2; +static const int c_CLR_RT_Trace_Annoying = 3; +static const int c_CLR_RT_Trace_Obnoxious = 4; + +extern int s_CLR_RT_fTrace_Errors; +extern int s_CLR_RT_fTrace_Exceptions; +extern int s_CLR_RT_fTrace_Instructions; +extern int s_CLR_RT_fTrace_Memory; +extern int s_CLR_RT_fTrace_MemoryStats; +extern int s_CLR_RT_fTrace_StopOnFAILED; +extern int s_CLR_RT_fTrace_GC; +extern int s_CLR_RT_fTrace_GC_Depth; +extern int s_CLR_RT_fTrace_SimulateSpeed; +extern int s_CLR_RT_fTrace_AssemblyOverhead; + +#if defined(_WIN32) +extern int s_CLR_RT_fTrace_ARM_Execution; + +extern int s_CLR_RT_fTrace_RedirectLinesPerFile; +extern std::wstring s_CLR_RT_fTrace_RedirectOutput; +extern std::wstring s_CLR_RT_fTrace_RedirectCallChain; + +extern std::wstring s_CLR_RT_fTrace_HeapDump_FilePrefix; +extern bool s_CLR_RT_fTrace_HeapDump_IncludeCreators; + +extern bool s_CLR_RT_fTimeWarp; + +#endif + +static const int MAXHOSTNAMELEN = 256; // Typical of many sockets implementations, incl. Windows +static const int MAXTYPENAMELEN = 256; // Including terminating null byte. Enforced in MetadataProcessor. The standard imposes no limit, but we necessarily do. + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define NANOCLR_INDEX_IS_VALID(idx) ((idx).m_data != 0) +#define NANOCLR_INDEX_IS_INVALID(idx) ((idx).m_data == 0) + +// +// IMPORTANT: THE ASSEMBLY IDX IN ALL THE CLR_RT_*_Index STRUCTURES SHOULD ALWAYS BE ENCODED THE SAME WAY!!! +// +// For details, go to "bool CLR_RT_GarbageCollector::ComputeReachabilityGraphForMultipleBlocks( CLR_RT_HeapBlock* lstExt, CLR_UINT32 numExt )" +// + +struct CLR_RT_Assembly_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm ) + { + m_data = idxAssm << 16; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } +}; + +struct CLR_RT_TypeSpec_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxType ) + { + m_data = idxAssm << 16 | idxType; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX TypeSpec() const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_TypeDef_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxType ) + { + m_data = idxAssm << 16 | idxType; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX Type () const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_FieldDef_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxField ) + { + m_data = idxAssm << 16 | idxField; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX Field () const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_MethodDef_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxMethod ) + { + m_data = idxAssm << 16 | idxMethod; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX Method () const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_ReflectionDef_Index +{ + CLR_UINT16 m_kind; // CLR_ReflectionType + CLR_UINT16 m_levels; + + union + { + CLR_RT_Assembly_Index m_assm; + CLR_RT_TypeDef_Index m_type; + CLR_RT_MethodDef_Index m_method; + CLR_RT_FieldDef_Index m_field; + CLR_UINT32 m_raw; + } m_data; + + //--// + + void Clear(); + + CLR_UINT32 GetTypeHash() const; + + void InitializeFromHash( CLR_UINT32 hash ); + + CLR_UINT64 GetRawData( ) const; + void SetRawData( CLR_UINT64 data ); + + //--// + + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_Assembly_Instance& inst ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Instance& inst, CLR_UINT32* levels ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_MethodDef_Instance& inst ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_FieldDef_Instance& inst ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_UINT32& hash ); +}; + + +//--// + +struct CLR_RT_AssemblyRef_CrossReference +{ + CLR_RT_Assembly* m_target; // EVENT HEAP - NO RELOCATION - +}; + +struct CLR_RT_TypeRef_CrossReference +{ + CLR_RT_TypeDef_Index m_target; +}; + +struct CLR_RT_FieldRef_CrossReference +{ + CLR_RT_FieldDef_Index m_target; +}; + +struct CLR_RT_MethodRef_CrossReference +{ + CLR_RT_MethodDef_Index m_target; +}; + +struct CLR_RT_FieldDef_CrossReference +{ + CLR_IDX m_offset; +}; + +struct CLR_RT_TypeDef_CrossReference +{ + static const CLR_UINT32 TD_CR_StaticConstructorCalled = 0x0001; + static const CLR_UINT32 TD_CR_HasFinalizer = 0x0002; + static const CLR_UINT32 TD_CR_IsMarshalByRefObject = 0x0004; + + CLR_UINT16 m_flags; + CLR_IDX m_totalFields; + CLR_UINT32 m_hash; +}; + +struct CLR_RT_MethodDef_CrossReference +{ + static const CLR_UINT16 MD_CR_Patched = 0x8000; + static const CLR_UINT16 MD_CR_OwnerMask = 0x7FFF; + + CLR_UINT16 m_data; + + CLR_IDX GetOwner () const { return (CLR_IDX)(m_data); } +}; + +struct CLR_RT_MethodDef_Patch +{ + CLR_IDX m_orig; + CLR_IDX m_patched; +}; + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +struct CLR_RT_MethodDef_DebuggingInfo +{ + static const CLR_UINT8 MD_DI_JustMyCode = 0x01; + static const CLR_UINT8 MD_DI_HasBreakpoint = 0x02; + + CLR_UINT8 m_flags; + + bool IsJMC () const { return IsFlagSet( MD_DI_JustMyCode ) ; } + bool HasBreakpoint() const { return IsFlagSet( MD_DI_HasBreakpoint ); } + + void SetJMC ( bool b ) { SetResetFlags( b, MD_DI_JustMyCode ); } + void SetBreakpoint( bool b ) { SetResetFlags( b, MD_DI_HasBreakpoint ); } + +private: + void SetFlags ( CLR_UINT8 flags ) { m_flags |= flags ; } + void ResetFlags ( CLR_UINT8 flags ) { m_flags &= ~flags ; } + bool IsFlagSet ( CLR_UINT8 flags ) const { return (m_flags & flags) != 0 ; } + void SetResetFlags( bool b, CLR_UINT8 flags ) { if(b) SetFlags( flags ); else ResetFlags( flags ); } +}; + +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//TODO: Change this to an extern method that is defined in the HAL +#if defined(PLATFORM_WINDOWS_EMULATOR) + #define SYSTEM_CLOCK_HZ g_HAL_Configuration_Windows.SystemClock + #define SLOW_CLOCKS_PER_SECOND g_HAL_Configuration_Windows.SlowClockPerSecond +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_UnicodeHelper +{ + static const CLR_UINT32 SURROGATE_HALFSHIFT = 10; + static const CLR_UINT32 SURROGATE_HALFBASE = 0x00010000; + static const CLR_UINT32 SURROGATE_HALFMASK = 0x000003FF; + +#ifdef HIGH_SURROGATE_START +#undef HIGH_SURROGATE_START +#undef HIGH_SURROGATE_END +#undef LOW_SURROGATE_START +#undef LOW_SURROGATE_END +#endif + static const CLR_UINT16 HIGH_SURROGATE_START = 0xD800; + static const CLR_UINT16 HIGH_SURROGATE_END = 0xDBFF; + static const CLR_UINT16 LOW_SURROGATE_START = 0xDC00; + static const CLR_UINT16 LOW_SURROGATE_END = 0xDFFF; + + const CLR_UINT8* m_inputUTF8; + const CLR_UINT16* m_inputUTF16; + + CLR_UINT8* m_outputUTF8; + int m_outputUTF8_size; + + CLR_UINT16* m_outputUTF16; + int m_outputUTF16_size; + + //--// + + void SetInputUTF8 ( const char* src ) { m_inputUTF8 = (const CLR_UINT8*)src; } + void SetInputUTF16( const CLR_UINT16* src ) { m_inputUTF16 = src; } + + int CountNumberOfCharacters( int max = -1 ); + int CountNumberOfBytes ( int max = -1 ); + + //--// + + bool ConvertFromUTF8( int iMaxChars, bool fJustMove, int iMaxBytes = -1 ); + bool ConvertToUTF8 ( int iMaxChars, bool fJustMove ); + + bool MoveBackwardInUTF8( const char* utf8StringStart, int iMaxChars ); + +#if defined(_WIN32) + static void ConvertToUTF8 ( const std::wstring& src, std:: string& dst ); + static void ConvertFromUTF8( const std:: string& src, std::wstring& dst ); +#endif +}; + +class UnicodeString +{ +private: + CLR_RT_UnicodeHelper m_unicodeHelper; + CLR_RT_HeapBlock m_uHeapBlock; + CLR_UINT16* m_wCharArray; + int m_length; /// Length in wide characters (not bytes). + +public: + UnicodeString(); + ~UnicodeString(); + + HRESULT Assign( const char* string ); + operator const wchar_t*() { return (const wchar_t*)m_wCharArray; } + unsigned int Length(){ return m_length; } + +private: + void Release(); +}; + +//--// + +struct CLR_RT_ArrayListHelper +{ + static const int c_defaultCapacity = 2; + + static const int FIELD___items = 1; + static const int FIELD___size = 2; + + //--// + + static HRESULT PrepareArrayList ( CLR_RT_HeapBlock& pThisRef, int count, int capacity ); + static HRESULT ExtractArrayFromArrayList( CLR_RT_HeapBlock& pThisRef, CLR_RT_HeapBlock_Array* & array, int& count, int& capacity ); +}; + +//--// + +struct CLR_RT_ByteArrayReader +{ + HRESULT Init( const unsigned char* src, unsigned int srcSize ); + + HRESULT Read( void* dst, unsigned int size ); + HRESULT Read1Byte( void* dst ); + + HRESULT Skip( unsigned int size ); + + bool IsValid() { return (source && sourceSize > 0); } + + const unsigned char* source; + unsigned int sourceSize; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_SignatureParser +{ + static const int c_TypeSpec = 0; + static const int c_Interfaces = 1; + static const int c_Field = 2; + static const int c_Method = 3; + static const int c_Locals = 4; + static const int c_Object = 5; + + struct Element + { + bool m_fByRef; + int m_levels; + CLR_DataType m_dt; + CLR_RT_TypeDef_Index m_cls; + }; + + CLR_RT_HeapBlock* m_lst; + CLR_RT_Assembly* m_assm; + CLR_PMETADATA m_sig; + + int m_type; + CLR_UINT32 m_flags; + int m_count; + + //--// + + void Initialize_TypeSpec ( CLR_RT_Assembly* assm, const CLR_RECORD_TYPESPEC* ts ); + void Initialize_Interfaces ( CLR_RT_Assembly* assm, const CLR_RECORD_TYPEDEF* td ); + void Initialize_FieldDef ( CLR_RT_Assembly* assm, const CLR_RECORD_FIELDDEF* fd ); + void Initialize_MethodSignature( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ); + void Initialize_MethodLocals ( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ); + + void Initialize_TypeSpec ( CLR_RT_Assembly* assm, CLR_PMETADATA ts ); + void Initialize_FieldDef ( CLR_RT_Assembly* assm, CLR_PMETADATA fd ); + void Initialize_MethodSignature( CLR_RT_Assembly* assm, CLR_PMETADATA md ); + + void Initialize_Objects ( CLR_RT_HeapBlock* lst, int count, bool fTypes ); + + int Available() const { return m_count; } + + HRESULT Advance( Element& res ); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define NANOCLR_FOREACH_ASSEMBLY(ts) \ + { \ + CLR_RT_Assembly** ppASSM = (ts).m_assemblies; \ + size_t iASSM = (ts).m_assembliesMax; \ + for( ;iASSM--; ppASSM++) \ + { \ + CLR_RT_Assembly* pASSM = *ppASSM; \ + if(pASSM) + +#define NANOCLR_FOREACH_ASSEMBLY_END() \ + } \ + } + +#define NANOCLR_FOREACH_ASSEMBLY_NULL(ts) \ + { \ + CLR_RT_Assembly** ppASSM = (ts).m_assemblies; \ + size_t iASSM = ARRAYSIZE((ts).m_assemblies); \ + CLR_IDX idx = 1; \ + for( ;iASSM--; ppASSM++,idx++) \ + { \ + if(*ppASSM == NULL) + +#define NANOCLR_FOREACH_ASSEMBLY_NULL_END() \ + } \ + } + +#if defined(NANOCLR_APPDOMAINS) + #define NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(ad) \ + NANOCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly, appDomainAssembly, (ad)->m_appDomainAssemblies) \ + { \ + CLR_RT_Assembly* pASSM = appDomainAssembly->m_assembly; + + #define NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END() \ + } \ + NANOCLR_FOREACH_NODE_END() + + #define NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(ts) NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()) + #define NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END() NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END() +#else + #define NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(ts, ad) NANOCLR_FOREACH_ASSEMBLY(ts) + #define NANOCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END() NANOCLR_FOREACH_ASSEMBLY_END() + #define NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(ts) NANOCLR_FOREACH_ASSEMBLY(ts) + #define NANOCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END() NANOCLR_FOREACH_ASSEMBLY_END() +#endif +// This type is needed on PC only for Interop code generation. For device code forward declaration only +class CLR_RT_VectorOfManagedElements; + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_Assembly : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + struct Offsets + { + size_t iBase; + size_t iAssemblyRef; + size_t iTypeRef; + size_t iFieldRef; + size_t iMethodRef; + size_t iTypeDef; + size_t iFieldDef; + size_t iMethodDef; + + #if !defined(NANOCLR_APPDOMAINS) + size_t iStaticFields; + #endif + + #if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + size_t iDebuggingInfoMethods; + #endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + }; + + //--// + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // NEED TO KEEP THESE IN SYNC WITH Enum 'Commands.DebuggingResolveAssembly.ResolvedStatus' on debugger library code // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + static const CLR_UINT32 Resolved = 0x00000001; + static const CLR_UINT32 ResolutionCompleted = 0x00000002; + static const CLR_UINT32 PreparedForExecution = 0x00000004; + static const CLR_UINT32 Deployed = 0x00000008; + static const CLR_UINT32 PreparingForExecution = 0x00000010; + static const CLR_UINT32 StaticConstructorsExecuted = 0x00000020; + + CLR_UINT32 m_idx; // Relative to the type system (for static fields access). + CLR_UINT32 m_flags; + + const CLR_RECORD_ASSEMBLY* m_header; // ANY HEAP - DO RELOCATION - + const char* m_szName; // ANY HEAP - DO RELOCATION - + + const CLR_RT_MethodHandler* m_nativeCode; + + int m_pTablesSize[ TBL_Max ]; + + #if !defined(NANOCLR_APPDOMAINS) + CLR_RT_HeapBlock* m_pStaticFields; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + #endif + + int m_iStaticFields; + + CLR_RT_HeapBlock_Array* m_pFile; // ANY HEAP - DO RELOCATION - + + CLR_RT_AssemblyRef_CrossReference* m_pCrossReference_AssemblyRef; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_TypeRef_CrossReference * m_pCrossReference_TypeRef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_FieldRef_CrossReference * m_pCrossReference_FieldRef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_MethodRef_CrossReference * m_pCrossReference_MethodRef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_TypeDef_CrossReference * m_pCrossReference_TypeDef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_FieldDef_CrossReference * m_pCrossReference_FieldDef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_MethodDef_CrossReference * m_pCrossReference_MethodDef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + + #if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_MethodDef_DebuggingInfo * m_pDebuggingInfo_MethodDef ; //EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + #endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + #if defined(NANOCLR_TRACE_STACK_HEAVY) && defined(_WIN32) + int m_maxOpcodes; + int* m_stackDepth; + #endif + + + #if defined(_WIN32) + std::string* m_strPath; + #endif + + //--// + + static void InitString(); + + bool IsSameAssembly( const CLR_RT_Assembly& assm ) const; + + #if defined(_WIN32) + + static void InitString( std::map& map ); + static HRESULT CreateInstance ( const CLR_RECORD_ASSEMBLY* data, CLR_RT_Assembly*& assm, const wchar_t* szName ); + + #endif + + //--// + + static HRESULT CreateInstance ( const CLR_RECORD_ASSEMBLY* data, CLR_RT_Assembly*& assm ); + void DestroyInstance( ); + + void Assembly_Initialize( CLR_RT_Assembly::Offsets& offsets ); + + bool Resolve_AssemblyRef ( bool fOutput ); + HRESULT Resolve_TypeRef ( ); + HRESULT Resolve_FieldRef ( ); + HRESULT Resolve_MethodRef ( ); + void Resolve_TypeDef ( ); + void Resolve_MethodDef ( ); + void Resolve_Link ( ); + HRESULT Resolve_ComputeHashes ( ); + HRESULT Resolve_AllocateStaticFields ( CLR_RT_HeapBlock* pStaticFields ); + + HRESULT PrepareForExecution(); + + CLR_UINT32 ComputeAssemblyHash( ); + CLR_UINT32 ComputeAssemblyHash( const CLR_RECORD_ASSEMBLYREF* ar ); + + + bool FindTypeDef ( const char* name, const char* nameSpace , CLR_RT_TypeDef_Index& idx ); + bool FindTypeDef ( const char* name, CLR_IDX scope , CLR_RT_TypeDef_Index& idx ); + bool FindTypeDef ( CLR_UINT32 hash , CLR_RT_TypeDef_Index& idx ); + + bool FindFieldDef ( const CLR_RECORD_TYPEDEF* src, const char* name, CLR_RT_Assembly* base, CLR_SIG sig, CLR_RT_FieldDef_Index& idx ); + bool FindMethodDef( const CLR_RECORD_TYPEDEF* src, const char* name, CLR_RT_Assembly* base, CLR_SIG sig, CLR_RT_MethodDef_Index& idx ); + + bool FindNextStaticConstructor( CLR_RT_MethodDef_Index& idx ); + + bool FindMethodBoundaries( CLR_IDX i, CLR_OFFSET& start, CLR_OFFSET& end ); + + void Relocate(); + + //--// + + CLR_RT_HeapBlock* GetStaticField( const int index ); + + //--// + + CLR_PMETADATA GetTable( CLR_TABLESENUM tbl ) { return (CLR_PMETADATA)m_header + m_header->startOfTables[ tbl ]; } + + #define NANOCLR_ASSEMBLY_RESOLVE(cls,tbl,idx) (const cls *)((CLR_UINT8*)m_header + m_header->startOfTables[ tbl ] + (sizeof(cls) * idx)) + const CLR_RECORD_ASSEMBLYREF * GetAssemblyRef ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_ASSEMBLYREF , TBL_AssemblyRef , i); } + const CLR_RECORD_TYPEREF * GetTypeRef ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_TYPEREF , TBL_TypeRef , i); } + const CLR_RECORD_FIELDREF * GetFieldRef ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_FIELDREF , TBL_FieldRef , i); } + const CLR_RECORD_METHODREF * GetMethodRef ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_METHODREF , TBL_MethodRef , i); } + const CLR_RECORD_TYPEDEF * GetTypeDef ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_TYPEDEF , TBL_TypeDef , i); } + const CLR_RECORD_FIELDDEF * GetFieldDef ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_FIELDDEF , TBL_FieldDef , i); } + const CLR_RECORD_METHODDEF * GetMethodDef ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_METHODDEF , TBL_MethodDef , i); } + const CLR_RECORD_ATTRIBUTE * GetAttribute ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_ATTRIBUTE , TBL_Attributes , i); } + const CLR_RECORD_TYPESPEC * GetTypeSpec ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_TYPESPEC , TBL_TypeSpec , i); } + const CLR_RECORD_RESOURCE_FILE* GetResourceFile( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_RESOURCE_FILE, TBL_ResourcesFiles, i); } + const CLR_RECORD_RESOURCE * GetResource ( CLR_IDX i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_RECORD_RESOURCE , TBL_Resources , i); } + CLR_PMETADATA GetResourceData( CLR_UINT32 i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_UINT8 , TBL_ResourcesData , i); } + const char* GetString ( CLR_STRING i ); + CLR_PMETADATA GetSignature ( CLR_SIG i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_UINT8 , TBL_Signatures , i); } + CLR_PMETADATA GetByteCode ( CLR_OFFSET i ) { return NANOCLR_ASSEMBLY_RESOLVE(CLR_UINT8 , TBL_ByteCode , i); } + #undef NANOCLR_ASSEMBLY_RESOLVE + + //--// + + #undef DECL_POSTFIX + #if defined(NANOCLR_TRACE_INSTRUCTIONS) + #define DECL_POSTFIX + #else + #define DECL_POSTFIX {} + #endif + + public: + void DumpOpcode ( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) DECL_POSTFIX; + void DumpOpcodeDirect( CLR_RT_MethodDef_Instance& call , CLR_PMETADATA ip, CLR_PMETADATA ipStart, int pid ) DECL_POSTFIX; + + private: + void DumpToken ( CLR_UINT32 tk ) DECL_POSTFIX; + void DumpSignature ( CLR_SIG sig ) DECL_POSTFIX; + void DumpSignature ( CLR_PMETADATA& p ) DECL_POSTFIX; + void DumpSignatureToken( CLR_PMETADATA& p ) DECL_POSTFIX; + + //--// + + #if defined(_WIN32) + static FILE* s_output; + static FILE* s_toclose; + + public: + static void Dump_SetDevice ( FILE *&outputDeviceFile, const wchar_t* szFileName ); + static void Dump_SetDevice ( const wchar_t* szFileName ); + + static void Dump_CloseDevice( FILE *&outputDeviceFile); + static void Dump_CloseDevice( ); + + static void Dump_Printf ( FILE *outputDeviceFile, const char *format, ... ); + static void Dump_Printf ( const char *format, ... ); + + static void Dump_Indent( const CLR_RECORD_METHODDEF* md, size_t offset, size_t level ); + + void Dump( bool fNoByteCode ); + + unsigned int GenerateSignatureForNativeMethods(); + + bool AreInternalMethodsPresent( const CLR_RECORD_TYPEDEF* td ); + void GenerateSkeleton( const wchar_t* szFileName, const wchar_t* szProjectName ); + void GenerateSkeletonFromComplientNames( const wchar_t* szFileName, const wchar_t* szProjectName ); + + void BuildParametersList( CLR_PMETADATA pMetaData, CLR_RT_VectorOfManagedElements &elemPtrArray ); + void GenerateSkeletonStubFieldsDef( const CLR_RECORD_TYPEDEF *pClsType, FILE *pFileStubHead, std::string strIndent, std::string strMngClassName ); + void GenerateSkeletonStubCode( const wchar_t* szFilePath, FILE *pFileDotNetProj ); + + void BuildMethodName_NoInterop(const CLR_RECORD_METHODDEF* md, std::string& name, CLR_RT_StringMap& mapMethods); + void GenerateSkeleton_NoInterop(LPCWSTR szFileName, LPCWSTR szProjectName); + + void BuildMethodName( const CLR_RECORD_METHODDEF* md, std::string& name , CLR_RT_StringMap& mapMethods ); + void BuildClassName ( const CLR_RECORD_TYPEREF* tr, std::string& cls_name, bool fEscape ); + void BuildClassName ( const CLR_RECORD_TYPEDEF* td, std::string& cls_name, bool fEscape ); + void BuildTypeName ( const CLR_RECORD_TYPEDEF* td, std::string& type_name ); + + #endif + private: + + #if defined(_WIN32) + void Dump_Token ( CLR_UINT32 tk ); + void Dump_FieldOwner ( CLR_UINT32 idx ); + void Dump_MethodOwner ( CLR_UINT32 idx ); + void Dump_Signature ( CLR_SIG sig ); + void Dump_Signature ( CLR_PMETADATA& p ); + void Dump_SignatureToken( CLR_PMETADATA& p ); + #endif + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_Assembly); + + //--// + + private: + + CLR_UINT32 ComputeHashForName( const CLR_RT_TypeDef_Index& td, CLR_UINT32 hash ); + + static CLR_UINT32 ComputeHashForType( CLR_DataType dt, CLR_UINT32 hash ); +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +//--// + +#if defined(NANOCLR_APPDOMAINS) + +struct CLR_RT_AppDomain : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + enum AppDomainState + { + AppDomainState_Loaded, + AppDomainState_Unloading, + AppDomainState_Unloaded + }; + + AppDomainState m_state; + int m_id; + CLR_RT_DblLinkedList m_appDomainAssemblies; + CLR_RT_HeapBlock* m_globalLock; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock_String* m_strName; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock* m_outOfMemoryException; // OBJECT HEAP - DO RELOCATION - + CLR_RT_AppDomainAssembly* m_appDomainAssemblyLastAccess; // EVENT HEAP - NO RELOCATION - + bool m_fCanBeUnloaded; + + static HRESULT CreateInstance ( const char* szName, CLR_RT_AppDomain*& appDomain); + + void DestroyInstance (); + void AppDomain_Initialize (); + void AppDomain_Uninitialize(); + bool IsLoaded (); + + void Relocate (); + void RecoverFromGC(); + + CLR_RT_AppDomainAssembly* FindAppDomainAssembly( CLR_RT_Assembly* assm ); + + HRESULT MarshalObject ( CLR_RT_HeapBlock& src , CLR_RT_HeapBlock& dst, CLR_RT_AppDomain* appDomainSrc = NULL ); + HRESULT MarshalParameters( CLR_RT_HeapBlock* callerArgs, CLR_RT_HeapBlock* calleeArgs, int count, bool fOnReturn, CLR_RT_AppDomain* appDomainSrc = NULL ); + + HRESULT VerifyTypeIsLoaded( const CLR_RT_TypeDef_Index& idx ); + HRESULT GetAssemblies ( CLR_RT_HeapBlock& ref ); + HRESULT LoadAssembly ( CLR_RT_Assembly* assm ); + HRESULT GetManagedObject ( CLR_RT_HeapBlock& obj ); +}; + +struct CLR_RT_AppDomainAssembly : public CLR_RT_HeapBlock_Node //EVENT HEAP - NO RELOCATION - +{ + static const CLR_UINT32 StaticConstructorsExecuted = 0x00000001; + + CLR_UINT32 m_flags; + CLR_RT_AppDomain* m_appDomain; // EVENT HEAP - NO RELOCATION - + CLR_RT_Assembly* m_assembly; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_pStaticFields; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + + + static HRESULT CreateInstance( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm, CLR_RT_AppDomainAssembly*& appDomainAssembly ); + + void DestroyInstance(); + HRESULT AppDomainAssembly_Initialize( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm ); + + void Relocate(); +}; + +#endif //NANOCLR_APPDOMAINS + +//--// + +struct CLR_RT_WellKnownTypes +{ + CLR_RT_TypeDef_Index m_Boolean; + CLR_RT_TypeDef_Index m_Int8; + CLR_RT_TypeDef_Index m_UInt8; + + CLR_RT_TypeDef_Index m_Char; + CLR_RT_TypeDef_Index m_Int16; + CLR_RT_TypeDef_Index m_UInt16; + + CLR_RT_TypeDef_Index m_Int32; + CLR_RT_TypeDef_Index m_UInt32; + CLR_RT_TypeDef_Index m_Single; + + CLR_RT_TypeDef_Index m_Int64; + CLR_RT_TypeDef_Index m_UInt64; + CLR_RT_TypeDef_Index m_Double; + CLR_RT_TypeDef_Index m_DateTime; + CLR_RT_TypeDef_Index m_TimeSpan; + CLR_RT_TypeDef_Index m_String; + + CLR_RT_TypeDef_Index m_Void; + CLR_RT_TypeDef_Index m_Object; + CLR_RT_TypeDef_Index m_ValueType; + CLR_RT_TypeDef_Index m_Enum; + + CLR_RT_TypeDef_Index m_AppDomainUnloadedException; + CLR_RT_TypeDef_Index m_ArgumentNullException; + CLR_RT_TypeDef_Index m_ArgumentException; + CLR_RT_TypeDef_Index m_ArgumentOutOfRangeException; + CLR_RT_TypeDef_Index m_Exception; + CLR_RT_TypeDef_Index m_IndexOutOfRangeException; + CLR_RT_TypeDef_Index m_ThreadAbortException; + CLR_RT_TypeDef_Index m_InvalidOperationException; + CLR_RT_TypeDef_Index m_InvalidCastException; + CLR_RT_TypeDef_Index m_NotSupportedException; + CLR_RT_TypeDef_Index m_NotImplementedException; + CLR_RT_TypeDef_Index m_NullReferenceException; + CLR_RT_TypeDef_Index m_OutOfMemoryException; + CLR_RT_TypeDef_Index m_ObjectDisposedException; + CLR_RT_TypeDef_Index m_ConstraintException; + CLR_RT_TypeDef_Index m_WatchdogException; + + CLR_RT_TypeDef_Index m_Delegate; + CLR_RT_TypeDef_Index m_MulticastDelegate; + + CLR_RT_TypeDef_Index m_Array; + CLR_RT_TypeDef_Index m_ArrayList; + CLR_RT_TypeDef_Index m_ICloneable; + CLR_RT_TypeDef_Index m_IList; + + CLR_RT_TypeDef_Index m_Assembly; + CLR_RT_TypeDef_Index m_TypeStatic; + CLR_RT_TypeDef_Index m_Type; + CLR_RT_TypeDef_Index m_ConstructorInfo; + CLR_RT_TypeDef_Index m_MethodInfo; + CLR_RT_TypeDef_Index m_FieldInfo; + + CLR_RT_TypeDef_Index m_WeakReference; + + CLR_RT_TypeDef_Index m_SerializationHintsAttribute; + + CLR_RT_TypeDef_Index m_NetworkInterface; + CLR_RT_TypeDef_Index m_Wireless80211Configuration; + CLR_RT_TypeDef_Index m_WirelessAPConfiguration; + CLR_RT_TypeDef_Index m_WirelessAPStation; + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_TypeDef_Index m_AppDomain; + CLR_RT_TypeDef_Index m_MarshalByRefObject; +#endif + + CLR_RT_TypeDef_Index m_Thread; + CLR_RT_TypeDef_Index m_ResourceManager; + + CLR_RT_TypeDef_Index m_SocketException; + + CLR_RT_TypeDef_Index m_I2cTransferResult; + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_WellKnownTypes); +}; + +extern CLR_RT_WellKnownTypes g_CLR_RT_WellKnownTypes; + +struct CLR_RT_WellKnownMethods +{ + CLR_RT_MethodDef_Index m_ResourceManager_GetObjectFromId; + CLR_RT_MethodDef_Index m_ResourceManager_GetObjectChunkFromId; + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_WellKnownMethods); +}; + +extern CLR_RT_WellKnownMethods g_CLR_RT_WellKnownMethods; + +//--// + +typedef void (CLR_RT_HeapBlock::*CLR_RT_HeapBlockRelocate)(); + +struct CLR_RT_DataTypeLookup +{ + static const CLR_UINT8 c_NA = 0x00; + static const CLR_UINT8 c_VariableSize = 0xFF; + + static const CLR_UINT32 c_Primitive = 0x00000001; + static const CLR_UINT32 c_Interface = 0x00000002; + static const CLR_UINT32 c_Class = 0x00000004; + static const CLR_UINT32 c_ValueType = 0x00000008; + static const CLR_UINT32 c_Enum = 0x00000010; + static const CLR_UINT32 c_SemanticMask = 0x0000001F; + + static const CLR_UINT32 c_Array = 0x00000020; + static const CLR_UINT32 c_ArrayList = 0x00000040; + static const CLR_UINT32 c_SemanticMask2 = 0x0000007F; + + static const CLR_UINT32 c_Reference = 0x00010000; + static const CLR_UINT32 c_Numeric = 0x00020000; + static const CLR_UINT32 c_Integer = 0x00040000; + static const CLR_UINT32 c_Signed = 0x00080000; + static const CLR_UINT32 c_Direct = 0x00100000; // This isn't an indirect reference. + static const CLR_UINT32 c_OptimizedValueType = 0x00200000; // A value type that is kept in a single HeapBlock. + static const CLR_UINT32 c_ManagedType = 0x00400000; // this dt represents a managed type, or a pointer to a managed type + // More specificly, TypeDescriptor::InitializeFromObject will succeed + // when starting from an object of with this dt + + CLR_UINT32 m_flags; + CLR_UINT8 m_sizeInBits; + CLR_UINT8 m_sizeInBytes; + CLR_UINT8 m_promoteTo; + CLR_UINT8 m_convertToElementType; + + CLR_RT_TypeDef_Index* m_cls; + CLR_RT_HeapBlockRelocate m_relocate; + +#if defined(_WIN32) || defined(NANOCLR_TRACE_MEMORY_STATS) + const char* m_name; +#endif +}; + +extern const CLR_RT_DataTypeLookup c_CLR_RT_DataTypeLookup[]; + +//--// + +struct CLR_RT_OpcodeLookup +{ + static const CLR_UINT16 COND_BRANCH_NEVER = 0x0000; + static const CLR_UINT16 COND_BRANCH_ALWAYS = 0x0001; + static const CLR_UINT16 COND_BRANCH_IFTRUE = 0x0002; + static const CLR_UINT16 COND_BRANCH_IFFALSE = 0x0003; + static const CLR_UINT16 COND_BRANCH_IFEQUAL = 0x0004; + static const CLR_UINT16 COND_BRANCH_IFNOTEQUAL = 0x0005; + static const CLR_UINT16 COND_BRANCH_IFGREATER = 0x0006; + static const CLR_UINT16 COND_BRANCH_IFGREATEROREQUAL = 0x0007; + static const CLR_UINT16 COND_BRANCH_IFLESS = 0x0008; + static const CLR_UINT16 COND_BRANCH_IFLESSOREQUAL = 0x0009; + static const CLR_UINT16 COND_BRANCH_IFMATCH = 0x000A; + static const CLR_UINT16 COND_BRANCH_THROW = 0x000B; + static const CLR_UINT16 COND_BRANCH_MASK = 0x000F; + + static const CLR_UINT16 COND_OVERFLOW = 0x0010; + static const CLR_UINT16 COND_UNSIGNED = 0x0020; + + static const CLR_UINT16 STACK_RESET = 0x0080; + + static const CLR_UINT16 ATTRIB_HAS_TARGET = 0x0100; + static const CLR_UINT16 ATTRIB_HAS_DT = 0x0200; + static const CLR_UINT16 ATTRIB_HAS_INDEX = 0x0400; + static const CLR_UINT16 ATTRIB_HAS_TOKEN = 0x0800; + static const CLR_UINT16 ATTRIB_HAS_I4 = 0x1000; + static const CLR_UINT16 ATTRIB_HAS_R4 = 0x2000; + static const CLR_UINT16 ATTRIB_HAS_I8 = 0x4000; + static const CLR_UINT16 ATTRIB_HAS_R8 = 0x8000; + +#if defined(NANOCLR_OPCODE_NAMES) + const char* m_name; +#endif + +#if defined(NANOCLR_OPCODE_STACKCHANGES) + CLR_UINT8 m_stackChanges; +#endif + + CLR_OpcodeParam m_opParam; + + //--// + +#if defined(NANOCLR_OPCODE_PARSER) + CLR_LOGICAL_OPCODE m_logicalOpcode; + CLR_DataType m_dt; + CLR_INT8 m_index; + CLR_UINT16 m_flags; +#endif +#if defined(NANOCLR_OPCODE_STACKCHANGES) + CLR_UINT32 StackPop () const { return m_stackChanges >> 4; } + CLR_UINT32 StackPush () const { return m_stackChanges & 0xF; } + CLR_INT32 StackChanges() const { return StackPush() - StackPop(); } +#endif + +#if defined(NANOCLR_OPCODE_NAMES) + const char* Name() const { return m_name; } +#else + const char* Name() const { return ""; } +#endif +}; + +extern const CLR_RT_OpcodeLookup c_CLR_RT_OpcodeLookup[]; + +//--// + +struct CLR_RT_LogicalOpcodeLookup +{ + static const CLR_UINT32 RESTARTPOINT_NEXT = 0x00000001; + static const CLR_UINT32 EXCEPTION = 0x00000002; + static const CLR_UINT32 EXCEPTION_IF_OVERFLOW = 0x00000010; + static const CLR_UINT32 EXCEPTION_IF_ZERO = 0x00000020; + static const CLR_UINT32 EXCEPTION_ON_CAST = 0x00000040; + +#if defined(NANOCLR_OPCODE_NAMES) + const char* m_name; +#endif + + CLR_UINT32 m_flags; + + +#if defined(NANOCLR_OPCODE_NAMES) + const char* Name() const { return m_name; } +#else + const char* Name() const { return ""; } +#endif +}; + +extern const CLR_RT_LogicalOpcodeLookup c_CLR_RT_LogicalOpcodeLookup[]; + +//--// + + +struct CLR_RT_TypeSystem // EVENT HEAP - NO RELOCATION - +{ + struct CompatibilityLookup + { + const char* name; + CLR_RECORD_VERSION version; + }; + + //--// + + static const int c_MaxAssemblies = 64; + + //--// + + static const CLR_UINT32 TYPENAME_FLAGS_FULL = 0x1; + static const CLR_UINT32 TYPENAME_NESTED_SEPARATOR_DOT = 0x2; + + //--// + + CLR_RT_Assembly* m_assemblies[ c_MaxAssemblies ]; // EVENT HEAP - NO RELOCATION - array of CLR_RT_Assembly + size_t m_assembliesMax; + CLR_RT_Assembly* m_assemblyMscorlib; + CLR_RT_Assembly* m_assemblyNative; + + CLR_RT_MethodDef_Index m_entryPoint; + + //--// + + void TypeSystem_Initialize(); + void TypeSystem_Cleanup(); + + void Link ( CLR_RT_Assembly* assm ); + void PostLinkageProcessing( CLR_RT_Assembly* assm ); + + HRESULT ResolveAll ( ); + HRESULT PrepareForExecution ( ); + HRESULT PrepareForExecutionHelper( const char* szAssembly ); + + CLR_RT_Assembly* FindAssembly( const char* name, const CLR_RECORD_VERSION* ver, bool fExact ); + + bool FindTypeDef ( const char* name, const char* nameSpace, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( const char* name, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( const char* name, const char* nameSpace, CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( CLR_UINT32 hash , CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( const char* name , CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( const char* name , CLR_RT_Assembly* assm, CLR_RT_ReflectionDef_Index& reflex ); + + HRESULT LocateResourceFile( CLR_RT_Assembly_Instance assm, const char* name, CLR_INT32& idxResourceFile ); + HRESULT LocateResource ( CLR_RT_Assembly_Instance assm, CLR_INT32 idxResourceFile, CLR_INT16 id, const CLR_RECORD_RESOURCE*& res, CLR_UINT32& size ); + + HRESULT BuildTypeName ( const CLR_RT_TypeDef_Index& cls, char*& szBuffer, size_t& size, CLR_UINT32 flags, CLR_UINT32 levels ); + HRESULT BuildTypeName ( const CLR_RT_TypeDef_Index& cls, char*& szBuffer, size_t& size ); + HRESULT BuildMethodName ( const CLR_RT_MethodDef_Index& md , char*& szBuffer, size_t& size ); + HRESULT BuildFieldName ( const CLR_RT_FieldDef_Index& fd , char*& szBuffer, size_t& size ); + HRESULT QueueStringToBuffer( char*& szBuffer, size_t& size, const char* szText ); + + bool FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD , CLR_RT_MethodDef_Index& idx ); + bool FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD, const char* calleeName, CLR_RT_MethodDef_Index& idx ); + + static bool MatchSignature ( CLR_RT_SignatureParser& parserLeft , CLR_RT_SignatureParser& parserRight ); + static bool MatchSignatureDirect ( CLR_RT_SignatureParser& parserLeft , CLR_RT_SignatureParser& parserRight , bool fIsInstanceOfOK ); + static bool MatchSignatureElement( CLR_RT_SignatureParser::Element& resLeft, CLR_RT_SignatureParser::Element& resRight, bool fIsInstanceOfOK ); + + static CLR_DataType MapElementTypeToDataType( CLR_UINT32 et ); + static CLR_UINT32 MapDataTypeToElementType( CLR_DataType dt ); + +#if defined(_WIN32) + void Dump( const wchar_t* szFileName, bool fNoByteCode ); +#endif + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_TypeSystem); +}; + +extern CLR_RT_TypeSystem g_CLR_RT_TypeSystem; + +//--// + +struct CLR_RT_Assembly_Instance : public CLR_RT_Assembly_Index +{ + CLR_RT_Assembly* m_assm; + + //--// + + bool InitializeFromIndex( const CLR_RT_Assembly_Index& idx ); + void Clear ( ); +}; + +struct CLR_RT_TypeSpec_Instance : public CLR_RT_TypeSpec_Index +{ + CLR_RT_Assembly* m_assm; + CLR_PMETADATA m_target; + + //--// + + bool InitializeFromIndex( const CLR_RT_TypeSpec_Index& idx ); + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); +}; + +//--// + +struct CLR_RT_TypeDef_Instance : public CLR_RT_TypeDef_Index +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_TYPEDEF* m_target; + + //--// + + bool InitializeFromReflection ( const CLR_RT_ReflectionDef_Index& reflex, CLR_UINT32* levels ); + bool InitializeFromIndex ( const CLR_RT_TypeDef_Index& idx ); + bool InitializeFromMethod ( const CLR_RT_MethodDef_Instance& md ); + bool InitializeFromField ( const CLR_RT_FieldDef_Instance& fd ); + + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); + + //--// + + CLR_RT_TypeDef_CrossReference& CrossReference() const { return m_assm->m_pCrossReference_TypeDef[ Type() ]; } + + bool SwitchToParent(); + bool HasFinalizer () const; + + bool IsATypeHandler(); +}; + +//--// + +struct CLR_RT_FieldDef_Instance : public CLR_RT_FieldDef_Index +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_FIELDDEF* m_target; + + //--// + + bool InitializeFromIndex( const CLR_RT_FieldDef_Index& idx ); + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); + + //--// + + CLR_RT_FieldDef_CrossReference& CrossReference() const { return m_assm->m_pCrossReference_FieldDef[ Field() ]; } +}; + +//--// + +struct CLR_RT_MethodDef_Instance : public CLR_RT_MethodDef_Index +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_METHODDEF* m_target; + + //--// + + bool InitializeFromIndex( const CLR_RT_MethodDef_Index& idx ); + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); + + //--// + + CLR_RT_MethodDef_CrossReference& CrossReference() const { return m_assm->m_pCrossReference_MethodDef[ Method() ]; } + CLR_UINT32 Hits() const { return 0; } + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_MethodDef_DebuggingInfo& DebuggingInfo() const { return m_assm->m_pDebuggingInfo_MethodDef[ Method() ]; } +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_AttributeEnumerator +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_ATTRIBUTE* m_ptr; + int m_num; + CLR_RECORD_ATTRIBUTE m_data; + + CLR_RT_MethodDef_Index m_match; + CLR_PMETADATA m_blob; + + void Initialize( const CLR_RT_TypeDef_Instance & inst ); + void Initialize( const CLR_RT_FieldDef_Instance & inst ); + void Initialize( const CLR_RT_MethodDef_Instance& inst ); + + bool Advance(); + + bool MatchNext( const CLR_RT_TypeDef_Instance* instTD, const CLR_RT_MethodDef_Instance* instMD ); + + void GetCurrent(CLR_RT_TypeDef_Instance* instTD); + +private: + void Initialize( CLR_RT_Assembly* assm ); +}; + +struct CLR_RT_AttributeParser +{ + struct Value + { + static const int c_ConstructorArgument = 1; + static const int c_NamedField = 2; + static const int c_NamedProperty = 3; + + int m_mode; + CLR_RT_HeapBlock m_value; + + int m_pos; + const char* m_name; + }; + + //--// + + CLR_RT_Assembly* m_assm; + CLR_PMETADATA m_blob; + + CLR_RT_MethodDef_Instance m_md; + CLR_RT_TypeDef_Instance m_td; + CLR_RT_SignatureParser m_parser; + CLR_RT_SignatureParser::Element m_res; + + int m_currentPos; + int m_fixed_Count; + int m_named_Count; + Value m_lastValue; + + //--// + + HRESULT Initialize( const CLR_RT_AttributeEnumerator& en ); + + HRESULT Next( Value*& res ); + +private: + const char* GetString(); +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_TypeDescriptor +{ + CLR_UINT32 m_flags; + CLR_RT_TypeDef_Instance m_handlerCls; + + CLR_RT_ReflectionDef_Index m_reflex; + + CLR_DataType GetDataType() const { return (CLR_DataType)m_handlerCls.m_target->dataType; } + + //--// + + void TypeDescriptor_Initialize(); + + HRESULT InitializeFromDataType ( CLR_DataType dt ); + HRESULT InitializeFromReflection ( const CLR_RT_ReflectionDef_Index& reflex ); + HRESULT InitializeFromTypeSpec ( const CLR_RT_TypeSpec_Index& sig ); + HRESULT InitializeFromType ( const CLR_RT_TypeDef_Index& cls ); + HRESULT InitializeFromFieldDefinition( const CLR_RT_FieldDef_Instance& fd ); + HRESULT InitializeFromSignatureParser( CLR_RT_SignatureParser& parser ); + HRESULT InitializeFromObject ( const CLR_RT_HeapBlock& ref ); + + void ConvertToArray(); + bool ShouldEmitHash(); + + bool GetElementType( CLR_RT_TypeDescriptor& sub ); + + static HRESULT ExtractTypeIndexFromObject( const CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Index& res ); + static HRESULT ExtractObjectAndDataType( CLR_RT_HeapBlock*& ref, CLR_DataType& dt ); +}; + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_HeapCluster : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_DblLinkedList m_freeList; // list of CLR_RT_HeapBlock_Node + CLR_RT_HeapBlock_Node* m_payloadStart; + CLR_RT_HeapBlock_Node* m_payloadEnd; + + //--// + + void HeapCluster_Initialize( CLR_UINT32 size, CLR_UINT32 blockSize ); // Memory is not erased by the caller. + + CLR_RT_HeapBlock* ExtractBlocks( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + + void RecoverFromGC(); + + CLR_RT_HeapBlock_Node* InsertInOrder( CLR_RT_HeapBlock_Node* node, CLR_UINT32 size ); + + //--// + + #undef DECL_POSTFIX + #if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink + #define DECL_POSTFIX + #else + #define DECL_POSTFIX {} + #endif + void ValidateBlock( CLR_RT_HeapBlock* ptr ) DECL_POSTFIX; + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_HeapCluster); +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +//--// + +#ifndef CLR_NO_IL_INLINE +struct CLR_RT_InlineFrame +{ + CLR_RT_HeapBlock* m_locals; + CLR_RT_HeapBlock* m_args; + CLR_RT_HeapBlock* m_evalStack; + CLR_RT_HeapBlock* m_evalPos; + CLR_RT_MethodDef_Instance m_call; + CLR_PMETADATA m_IP; + CLR_PMETADATA m_IPStart; +}; + +struct CLR_RT_InlineBuffer +{ + union + { + CLR_RT_InlineBuffer* m_pNext; + + CLR_RT_InlineFrame m_frame; + }; +}; +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_StackFrame : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + static const int c_OverheadForNewObjOrInteropMethod = 2; // We need to have more slots in the stack to process a 'newobj' opcode. + static const int c_MinimumStack = 10; + + + static const CLR_UINT32 c_MethodKind_Native = 0x00000000; + static const CLR_UINT32 c_MethodKind_Interpreted = 0x00000001; + static const CLR_UINT32 c_UNUSED_00000002 = 0x00000002; // c_MethodKind_Jitted + static const CLR_UINT32 c_MethodKind_Mask = 0x00000003; + + static const CLR_UINT32 c_NativeProfiled = 0x00000004; + static const CLR_UINT32 c_MethodKind_Inlined = 0x00000008; + + static const CLR_UINT32 c_ExecutingConstructor = 0x00000010; + static const CLR_UINT32 c_CompactAndRestartOnOutOfMemory = 0x00000020; + static const CLR_UINT32 c_CallOnPop = 0x00000040; + static const CLR_UINT32 c_CalledOnPop = 0x00000080; + + static const CLR_UINT32 c_NeedToSynchronize = 0x00000100; + static const CLR_UINT32 c_PendingSynchronize = 0x00000200; + static const CLR_UINT32 c_Synchronized = 0x00000400; + static const CLR_UINT32 c_UNUSED_00000800 = 0x00000800; + + static const CLR_UINT32 c_NeedToSynchronizeGlobally = 0x00001000; + static const CLR_UINT32 c_PendingSynchronizeGlobally = 0x00002000; + static const CLR_UINT32 c_SynchronizedGlobally = 0x00004000; + static const CLR_UINT32 c_UNUSED_00008000 = 0x00008000; + + static const CLR_UINT32 c_ExecutingIL = 0x00010000; + static const CLR_UINT32 c_CallerIsCompatibleForCall = 0x00020000; + static const CLR_UINT32 c_CallerIsCompatibleForRet = 0x00040000; + static const CLR_UINT32 c_PseudoStackFrameForFilter = 0x00080000; + + static const CLR_UINT32 c_InlineMethodHasReturnValue = 0x00100000; + static const CLR_UINT32 c_UNUSED_00200000 = 0x00200000; + static const CLR_UINT32 c_UNUSED_00400000 = 0x00400000; + static const CLR_UINT32 c_UNUSED_00800000 = 0x00800000; + + static const CLR_UINT32 c_UNUSED_01000000 = 0x01000000; + static const CLR_UINT32 c_UNUSED_02000000 = 0x02000000; + + static const CLR_UINT32 c_AppDomainMethodInvoke = 0x04000000; + static const CLR_UINT32 c_AppDomainInjectException = 0x08000000; + static const CLR_UINT32 c_AppDomainTransition = 0x10000000; + static const CLR_UINT32 c_InvalidIP = 0x20000000; + static const CLR_UINT32 c_UNUSED_40000000 = 0x40000000; + static const CLR_UINT32 c_HasBreakpoint = 0x80000000; + + static const CLR_UINT32 c_ProcessSynchronize = c_NeedToSynchronize | c_PendingSynchronize | + c_NeedToSynchronizeGlobally | c_PendingSynchronizeGlobally ; + + //--// + + /////////////////////////////////////////////////////////////////////////////////////////// + // + // These fields have to be aligned + // + CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_evalStack; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_arguments; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_locals; // EVENT HEAP - NO RELOCATION - + CLR_PMETADATA m_IP; // ANY HEAP - DO RELOCATION - + // + /////////////////////////////////////////////////////////////////////////////////////////// + + CLR_RT_SubThread* m_owningSubThread; // EVENT HEAP - NO RELOCATION - + CLR_UINT32 m_flags; + + CLR_RT_MethodDef_Instance m_call; + + CLR_RT_MethodHandler m_nativeMethod; + CLR_PMETADATA m_IPstart; // ANY HEAP - DO RELOCATION - + + CLR_RT_HeapBlock* m_evalStackPos; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_evalStackEnd; // EVENT HEAP - NO RELOCATION - + + union + { + CLR_UINT32 m_customState; + void* m_customPointer; + }; + + + #ifndef CLR_NO_IL_INLINE + CLR_RT_InlineBuffer* m_inlineFrame; + #endif + + #if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_UINT32 m_depth; + #endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + #if defined(NANOCLR_PROFILE_NEW_CALLS) + CLR_PROF_CounterCallChain m_callchain; + #endif + + #if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; + #endif + + #if defined(ENABLE_NATIVE_PROFILER) + bool m_fNativeProfiled; + #endif + + CLR_RT_HeapBlock m_extension[ 1 ]; + + //////////////////////////////////////// + + static HRESULT Push( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_INT32 extraBlocks ); + + void Pop(); + + #ifndef CLR_NO_IL_INLINE + bool PushInline( CLR_PMETADATA& ip, CLR_RT_Assembly*& assm, CLR_RT_HeapBlock*& evalPos, CLR_RT_MethodDef_Instance& calleeInst, CLR_RT_HeapBlock* pThis); + void PopInline ( ); + + void RestoreFromInlineStack(); + void RestoreStack(CLR_RT_InlineFrame& frame); + void SaveStack(CLR_RT_InlineFrame& frame); + #endif + + + #if defined(NANOCLR_APPDOMAINS) + static HRESULT PushAppDomainTransition( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_RT_HeapBlock* pThis, CLR_RT_HeapBlock* pArgs ); + HRESULT PopAppDomainTransition( ); + #endif + + HRESULT FixCall(); + HRESULT MakeCall ( CLR_RT_MethodDef_Instance md, CLR_RT_HeapBlock* blkThis, CLR_RT_HeapBlock* blkArgs, int nArgs ); + + HRESULT HandleSynchronized( bool fAcquire, bool fGlobal ); + + void SetResult ( CLR_INT32 val, CLR_DataType dataType ); + void SetResult_I1 ( CLR_UINT8 val ); + void SetResult_I2 ( CLR_INT16 val ); + void SetResult_I4 ( CLR_INT32 val ); + void SetResult_I8 ( CLR_INT64& val ); + void SetResult_U1 ( CLR_INT8 val ); + void SetResult_U2 ( CLR_UINT16 val ); + void SetResult_U4 ( CLR_UINT32 val ); + void SetResult_U8 ( CLR_UINT64& val ); + + #if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + void SetResult_R4 ( float val ); + void SetResult_R8 ( double val ); + #else + void SetResult_R4 ( CLR_INT32 val ); + void SetResult_R8 ( CLR_INT64 val ); + #endif + + void SetResult_Boolean( bool val ); + void SetResult_Object ( CLR_RT_HeapBlock* val ); + HRESULT SetResult_String ( const char* val ); + + HRESULT SetupTimeoutFromTicks( CLR_RT_HeapBlock& input, CLR_INT64*& output ); + + void ConvertResultToBoolean(); + void NegateResult (); + + HRESULT NotImplementedStub(); + + void Relocate(); + + //////////////////////////////////////// + + CLR_RT_HeapBlock& ThisRef() const { return m_arguments[ 0 ]; } + CLR_RT_HeapBlock* This() const { return ThisRef().Dereference(); } + + CLR_RT_HeapBlock& Arg0() const { return m_arguments[ 0 ]; } + CLR_RT_HeapBlock& Arg1() const { return m_arguments[ 1 ]; } + CLR_RT_HeapBlock& Arg2() const { return m_arguments[ 2 ]; } + CLR_RT_HeapBlock& Arg3() const { return m_arguments[ 3 ]; } + CLR_RT_HeapBlock& Arg4() const { return m_arguments[ 4 ]; } + CLR_RT_HeapBlock& Arg5() const { return m_arguments[ 5 ]; } + CLR_RT_HeapBlock& Arg6() const { return m_arguments[ 6 ]; } + CLR_RT_HeapBlock& Arg7() const { return m_arguments[ 7 ]; } + + CLR_RT_HeapBlock& ArgN( CLR_INT32 n ) const { return m_arguments[ n ]; } + + CLR_RT_HeapBlock& TopValue () { return m_evalStackPos[ -1 ]; } + CLR_RT_HeapBlock& PushValue () { _ASSERTE(m_evalStackPos < m_evalStackEnd); return * m_evalStackPos++; } + CLR_RT_HeapBlock& PopValue () { _ASSERTE(m_evalStackPos > m_evalStack ); return *--m_evalStackPos; } + void ResetStack () { m_evalStackPos = m_evalStack ; } + int TopValuePosition () { return (int)(m_evalStackPos - m_evalStack); } + + CLR_RT_MethodDef_Instance& MethodCall() { return m_call; } + + CLR_RT_HeapBlock& PushValueAndClear() + { + CLR_RT_HeapBlock& val = PushValue(); + + val.SetObjectReference( NULL ); + + return val; + } + + CLR_RT_HeapBlock& PushValueAndAssign( const CLR_RT_HeapBlock& value ) + { + CLR_RT_HeapBlock& top = PushValue(); + + top.Assign( value ); + + return top; + } + + + inline void PushValueI4( CLR_INT32 val ) { SetResult_I4( val ); } + + //--// + + CLR_RT_StackFrame* Caller() { return (CLR_RT_StackFrame*)Prev(); } + CLR_RT_StackFrame* Callee() { return (CLR_RT_StackFrame*)Next(); } + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_StackFrame); +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +// +// This CT_ASSERT macro generates a compiler error in case these fields get out of alignment. +// +// The use of offsetof below throwns an "invalid offset warning" because CLR_RT_StackFrame is not POD type +// C+17 is the first standard that allow this, so until we are using it we have to disable it to keep GCC happy + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_owningThread) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_evalStack ) ) +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_evalStack ) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_arguments ) ) +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_arguments ) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_locals ) ) +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_locals ) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_IP ) ) + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_ProtectFromGC +{ + static const CLR_UINT32 c_Generic = 0x00000001; + static const CLR_UINT32 c_HeapBlock = 0x00000002; + static const CLR_UINT32 c_ResetKeepAlive = 0x00000004; + + typedef void (*Callback)( void* state ); + + static CLR_RT_ProtectFromGC* s_first; + + CLR_RT_ProtectFromGC* m_next; + void** m_data; + Callback m_fpn; + CLR_UINT32 m_flags; + + CLR_RT_ProtectFromGC ( CLR_RT_HeapBlock& ref ) { Initialize( ref ); } + CLR_RT_ProtectFromGC ( void** data, Callback fpn ) { Initialize( data, fpn ); } + ~CLR_RT_ProtectFromGC( ) { Cleanup ( ); } + + static void InvokeAll(); + +private: + void Initialize( CLR_RT_HeapBlock& ref ); + void Initialize( void** data, Callback fpn ); + void Cleanup ( ); + + void Invoke(); +}; + +//////////////////////////////////////// + +#if defined(NANOCLR_TRACE_EARLYCOLLECTION) + +struct CLR_RT_AssertEarlyCollection +{ + static CLR_RT_AssertEarlyCollection* s_first; + + CLR_RT_AssertEarlyCollection* m_next; + CLR_RT_HeapBlock* m_ptr; + + CLR_RT_AssertEarlyCollection( CLR_RT_HeapBlock* ptr ); + ~CLR_RT_AssertEarlyCollection(); + + void Cancel(); + + static void CheckAll( CLR_RT_HeapBlock* ptr ); +}; + +#define NANOCLR_FAULT_ON_EARLY_COLLECTION(ptr) CLR_RT_AssertEarlyCollection aec##ptr( ptr ) +#define NANOCLR_CANCEL_EARLY_COLLECTION(ptr) aec##ptr.Cancel() +#define NANOCLR_CHECK_EARLY_COLLECTION(ptr) CLR_RT_AssertEarlyCollection::CheckAll( ptr ) + +#else + +#define NANOCLR_FAULT_ON_EARLY_COLLECTION(ptr) +#define NANOCLR_CANCEL_EARLY_COLLECTION(ptr) +#define NANOCLR_CHECK_EARLY_COLLECTION(ptr) + +#endif + +//////////////////////////////////////// + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_GarbageCollector +{ + typedef bool (*MarkSingleFtn )( CLR_RT_HeapBlock** ptr ); + typedef bool (*MarkMultipleFtn)( CLR_RT_HeapBlock* lstExt, CLR_UINT32 numExt ); + typedef bool (*RelocateFtn )( void** ref ); + + struct MarkStackElement + { + CLR_RT_HeapBlock* ptr; + CLR_UINT32 num; + #if defined(NANOCLR_VALIDATE_APPDOMAIN_ISOLATION) + CLR_RT_AppDomain* appDomain; + #endif + }; + + struct MarkStack : CLR_RT_HeapBlock_Node + { + MarkStackElement* m_last; + MarkStackElement* m_top; + + void Initialize( MarkStackElement* ptr, size_t num ); + }; + + struct RelocationRegion + { + CLR_UINT8* m_start; + CLR_UINT8* m_end; + CLR_UINT8* m_destination; + CLR_UINT32 m_offset; + }; + + //--// + + static const int c_minimumSpaceForGC = 128; + static const int c_minimumSpaceForCompact = 128; + static const CLR_UINT32 c_pressureThreshold = 10; + static const CLR_UINT32 c_memoryThreshold = HEAP_SIZE_THRESHOLD; + static const CLR_UINT32 c_memoryThreshold2 = HEAP_SIZE_THRESHOLD_UPPER; + + static const CLR_UINT32 c_StartGraphEvent = 0x00000001; + static const CLR_UINT32 c_StopGraphEvent = 0x00000002; + static const CLR_UINT32 c_DumpGraphHeapEvent = 0x00000004; + static const CLR_UINT32 c_DumpPerfCountersEvent = 0x00000008; + + CLR_UINT32 m_numberOfGarbageCollections; + CLR_UINT32 m_numberOfCompactions; + + CLR_RT_DblLinkedList m_weakDelegates_Reachable; // list of CLR_RT_HeapBlock_Delegate_List + + + CLR_UINT32 m_totalBytes; + CLR_UINT32 m_freeBytes; + CLR_UINT32 m_pressureCounter; + + CLR_RT_DblLinkedList* m_markStackList; + MarkStack* m_markStack; + + RelocationRegion* m_relocBlocks; + size_t m_relocTotal; + size_t m_relocCount; + CLR_UINT8* m_relocMinimum; + CLR_UINT8* m_relocMaximum; + #if NANOCLR_VALIDATE_HEAP > NANOCLR_VALIDATE_HEAP_0_None + RelocateFtn m_relocWorker; + #endif + + MarkSingleFtn m_funcSingleBlock; + MarkMultipleFtn m_funcMultipleBlocks; + + bool m_fOutOfStackSpaceForGC; + + #if defined(_WIN32) + CLR_UINT32 m_events; + #endif + + //--// + + CLR_UINT32 ExecuteGarbageCollection(); + CLR_UINT32 ExecuteCompaction (); + + void Mark (); + void MarkWeak (); + void Sweep (); + void CheckMemoryPressure(); + + #if defined(NANOCLR_APPDOMAINS) + void AppDomain_Mark(); + #endif + + void Assembly_Mark(); + + void Thread_Mark( CLR_RT_DblLinkedList& threads ); + void Thread_Mark( CLR_RT_Thread* thread ); + + void Heap_Compact (); + CLR_UINT32 Heap_ComputeAliveVsDeadRatio(); + + void RecoverEventsFromGC(); + + void Heap_Relocate_Prepare ( RelocationRegion* blocks, size_t total ); + void Heap_Relocate_AddBlock( CLR_UINT8* dst, CLR_UINT8* src, CLR_UINT32 length ); + void Heap_Relocate ( ); + + //--// + + static void Heap_Relocate( CLR_RT_HeapBlock* lst, CLR_UINT32 len ); + static void Heap_Relocate( void** ref ); + + //--// + + #if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_3_Compaction + + static bool Relocation_JustCheck( void** ref ); + + void ValidatePointers() { Heap_Relocate_Pass( Relocation_JustCheck ); } + + static void ValidateCluster ( CLR_RT_HeapCluster* hc ); + static void ValidateHeap ( CLR_RT_DblLinkedList& lst ); + static void ValidateBlockNotInFreeList( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ); + static bool IsBlockInFreeList ( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst, bool fExact ); + static bool IsBlockInHeap ( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ); + + #else + + void ValidatePointers() {} + + static void ValidateCluster ( CLR_RT_HeapCluster* hc ) {} + static void ValidateHeap ( CLR_RT_DblLinkedList& lst ) {} + static void ValidateBlockNotInFreeList( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ) {} + + #endif + + #if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_4_CompactionPlus + + struct RelocationRecord + { + void** oldRef; + CLR_UINT32* oldPtr; + + void** newRef; + CLR_UINT32* newPtr; + + CLR_UINT32 data; + }; + + typedef std::list Rel_List; + typedef Rel_List::iterator Rel_List_Iter; + + typedef std::map< void**, RelocationRecord* > Rel_Map; + typedef Rel_Map::iterator Rel_Map_Iter; + + static Rel_List s_lstRecords; + static Rel_Map s_mapOldToRecord; + static Rel_Map s_mapNewToRecord; + + void Relocation_UpdatePointer(void** ref); + + static bool TestPointers_PopulateOld_Worker( void** ref ); + static bool TestPointers_PopulateNew_Worker( void** ref ); + + void TestPointers_PopulateOld(); + void TestPointers_Remap (); + void TestPointers_PopulateNew(); + + #else + + void TestPointers_PopulateOld() {} + void TestPointers_Remap () {} + void TestPointers_PopulateNew() {} + + #endif + + //--// + + #if defined(NANOCLR_GC_VERBOSE) + + void GC_Stats( int& resNumberObjects, int& resSizeObjects, int& resNumberEvents, int& resSizeEvents ); + + void DumpThreads ( ); + + #else + + void GC_Stats( int& resNumberObjects, int& resSizeObjects, int& resNumberEvents, int& resSizeEvents ) + { + resNumberObjects = 0; + resSizeObjects = 0; + resNumberEvents = 0; + resSizeEvents = 0; + } + + void DumpThreads ( ) {} + + #endif + + //--// + + bool CheckSingleBlock( CLR_RT_HeapBlock** ptr ) { return m_funcSingleBlock( ( CLR_RT_HeapBlock* *)ptr ); } + bool CheckSingleBlock( CLR_RT_HeapBlock_Array** ptr ) { return m_funcSingleBlock( (CLR_RT_HeapBlock* *)ptr ); } + bool CheckSingleBlock( CLR_RT_HeapBlock_Delegate** ptr ) { return m_funcSingleBlock( (CLR_RT_HeapBlock* *)ptr ); } + + bool CheckSingleBlock_Force( CLR_RT_HeapBlock* ptr ) { return ptr ? m_funcMultipleBlocks( ptr, 1 ) : true; } + bool CheckMultipleBlocks ( CLR_RT_HeapBlock* lst, CLR_UINT32 num ) { return lst ? m_funcMultipleBlocks( lst, num ) : true; } + + //--// + + static bool ComputeReachabilityGraphForSingleBlock ( CLR_RT_HeapBlock** ptr ); + static bool ComputeReachabilityGraphForMultipleBlocks( CLR_RT_HeapBlock* lst, CLR_UINT32 num ); + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_GarbageCollector); + + //--// + + private: + + void Heap_Relocate_Pass( RelocateFtn ftn ); + + void MarkSlow(); +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +extern CLR_RT_GarbageCollector g_CLR_RT_GarbageCollector; + +//--// + +struct CLR_RT_SubThread : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + static const int MODE_IncludeSelf = 0x00000001; + static const int MODE_CheckLocks = 0x00000002; + + static const int STATUS_Triggered = 0x00000001; + + CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + CLR_RT_StackFrame* m_owningStackFrame; + CLR_UINT32 m_lockRequestsCount; + + int m_priority; + CLR_INT64 m_timeConstraint; + CLR_UINT32 m_status; + + //--// + + static HRESULT CreateInstance ( CLR_RT_Thread* th, CLR_RT_StackFrame* stack , int priority, CLR_RT_SubThread*& sth ); + static void DestroyInstance( CLR_RT_Thread* th, CLR_RT_SubThread* sthBase, int flags ); + + bool ChangeLockRequestCount( int diff ); + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_SubThread); +}; + +//--// + +struct CLR_RT_ExceptionHandler +{ + union { + CLR_RT_TypeDef_Index m_typeFilter; + CLR_PMETADATA m_userFilterStart; + }; + CLR_PMETADATA m_tryStart; + CLR_PMETADATA m_tryEnd; + CLR_PMETADATA m_handlerStart; + CLR_PMETADATA m_handlerEnd; + + CLR_UINT16 m_ehType; + //--// + + bool ConvertFromEH( const CLR_RT_MethodDef_Instance& owner, CLR_PMETADATA ipStart, const CLR_RECORD_EH* ehPtr ); + + bool IsCatch() const { return m_ehType == CLR_RECORD_EH::EH_Catch ; } + bool IsCatchAll() const { return m_ehType == CLR_RECORD_EH::EH_CatchAll ; } + bool IsFilter() const { return m_ehType == CLR_RECORD_EH::EH_Filter ; } + bool IsFinally() const { return m_ehType == CLR_RECORD_EH::EH_Finally ; } + +}; + + +// +// Directly from the .NET enumerator. +// +struct ThreadPriority +{ + /*========================================================================= + ** Constants for thread priorities. + =========================================================================*/ + static const int Lowest = 0; + static const int BelowNormal = 1; + static const int Normal = 2; + static const int AboveNormal = 3; + static const int Highest = 4; + // One more priority for internal creation of managed code threads. + // We do not expose this priority to C# applications. + static const int System_Highest = 5; +}; + +struct CLR_RT_Thread : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + typedef void (*ThreadTerminationCallback)( void* arg ); + + struct UnwindStack + { + CLR_RT_StackFrame* m_stack; + CLR_RT_HeapBlock* m_exception; + CLR_PMETADATA m_ip; + + CLR_PMETADATA m_currentBlockStart; + CLR_PMETADATA m_currentBlockEnd; + CLR_PMETADATA m_handlerBlockStart; + CLR_PMETADATA m_handlerBlockEnd; + + CLR_RT_StackFrame* m_handlerStack; + CLR_UINT8 m_flags; + + static const CLR_UINT8 p_Phase_Mask = 0x07; + static const CLR_UINT8 p_1_SearchingForHandler_0 = 0x01; + static const CLR_UINT8 p_1_SearchingForHandler_1_SentFirstChance = 0x02; + static const CLR_UINT8 p_1_SearchingForHandler_2_SentUsersChance = 0x03; + static const CLR_UINT8 p_2_RunningFinallys_0 = 0x04; + static const CLR_UINT8 p_2_RunningFinallys_1_SentUnwindBegin = 0x05; + static const CLR_UINT8 p_3_RunningHandler = 0x06; + static const CLR_UINT8 p_4_NormalCleanup = 0x07; + + static const CLR_UINT8 c_MagicCatchForInline = 0x20; + static const CLR_UINT8 c_MagicCatchForInteceptedException = 0x40; + static const CLR_UINT8 c_ContinueExceptionHandler = 0x80; + + CLR_UINT8 inline GetPhase() { return m_flags & p_Phase_Mask; } + void inline SetPhase(CLR_UINT8 phase) + { + _ASSERTE((phase & ~p_Phase_Mask) == 0); + m_flags = (m_flags & ~p_Phase_Mask) | phase; + } + + }; + + static const CLR_UINT32 TH_S_Ready = 0x00000000; + static const CLR_UINT32 TH_S_Waiting = 0x00000001; + static const CLR_UINT32 TH_S_Terminated = 0x00000002; + static const CLR_UINT32 TH_S_Unstarted = 0x00000003; + + static const CLR_UINT32 TH_F_Suspended = 0x00000001; + static const CLR_UINT32 TH_F_Aborted = 0x00000002; + static const CLR_UINT32 TH_F_System = 0x00000004; + static const CLR_UINT32 TH_F_ContainsDoomedAppDomain = 0x00000008; + + static const CLR_INT32 TH_WAIT_RESULT_INIT = -1; + static const CLR_INT32 TH_WAIT_RESULT_HANDLE_0 = 0; + static const CLR_INT32 TH_WAIT_RESULT_TIMEOUT = 0x102; //WaitHandle.WaitTimeout + static const CLR_INT32 TH_WAIT_RESULT_HANDLE_ALL = 0x103; + + static const CLR_UINT32 c_TimeQuantum_Milliseconds = 20; + static const int c_MaxStackUnwindDepth = 6; + + int m_pid; + CLR_UINT32 m_status; + CLR_UINT32 m_flags; + int m_executionCounter; + volatile bool m_timeQuantumExpired; + + CLR_RT_HeapBlock_Delegate* m_dlg; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock m_currentException; // OBJECT HEAP - DO RELOCATION - + UnwindStack m_nestedExceptions[ c_MaxStackUnwindDepth ]; + int m_nestedExceptionsPos; + + //--// + + // + // For example, timers are implemented in terms of Threads. If not NULL, this is a worker thread for a timer. + // + ThreadTerminationCallback m_terminationCallback; + void* m_terminationParameter; // EVENT HEAP - NO RELOCATION - + + CLR_UINT32 m_waitForEvents; + CLR_INT64 m_waitForEvents_Timeout; + CLR_INT64 m_waitForEvents_IdleTimeWorkItem; + + CLR_RT_DblLinkedList m_locks; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Lock + CLR_UINT32 m_lockRequestsCount; + + CLR_RT_HeapBlock_WaitForObject* m_waitForObject; // EVENT HEAP - NO RELOCATION, but the objects they point to do + CLR_INT32 m_waitForObject_Result; + + CLR_RT_DblLinkedList m_stackFrames; // EVENT HEAP - NO RELOCATION - list of CLR_RT_StackFrame + + CLR_RT_DblLinkedList m_subThreads; // EVENT HEAP - NO RELOCATION - list of CLR_RT_SubThread + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + int m_scratchPad; + bool m_fHasJMCStepper; + + CLR_RT_Thread* m_realThread; // Normally, this points to the CLR_RT_Thread object that contains it. + // However, if this thread was spawned on behalf of the debugger to evaluate + // a property or function call, it points to the object coresponding to the + // thread that is currently selected in the debugger. +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(ENABLE_NATIVE_PROFILER) + bool m_fNativeProfiled; +#endif + + //--// + + static HRESULT CreateInstance( int pid, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ); + static HRESULT CreateInstance( int pid, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ); + HRESULT PushThreadProcDelegate( CLR_RT_HeapBlock_Delegate* pDelegate ); + + void DestroyInstance(); + + HRESULT Execute (); + + HRESULT Suspend (); + HRESULT Resume (); + HRESULT Terminate(); + HRESULT Abort (); + + void Restart( bool fDeleteEvent ); + + void Passivate(); + + bool CouldBeActivated(); + + void RecoverFromGC(); + + void Relocate(); + + UnwindStack* PushEH ( ); + void PopEH_Inner( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + bool FindEhBlock( CLR_RT_StackFrame* stack, CLR_PMETADATA from, CLR_PMETADATA to, CLR_RT_ExceptionHandler& eh, bool onlyFinallys ); + + + HRESULT ProcessException ( ); + HRESULT ProcessException_EndFilter ( ); + HRESULT ProcessException_EndFinally ( ); + HRESULT ProcessException_Phase1 ( ); + HRESULT ProcessException_Phase2 ( ); + void ProcessException_FilterPseudoFrameCopyVars(CLR_RT_StackFrame* to, CLR_RT_StackFrame* from); + + static void ProtectFromGCCallback( void* state ); + + static HRESULT Execute_DelegateInvoke( CLR_RT_StackFrame& stack ); + static HRESULT Execute_IL ( CLR_RT_StackFrame& stack ); + + //--// + + CLR_RT_StackFrame* FirstFrame () const { return (CLR_RT_StackFrame*)m_stackFrames.FirstNode(); } + CLR_RT_StackFrame* CurrentFrame() const { return (CLR_RT_StackFrame*)m_stackFrames.LastNode (); } + + CLR_RT_SubThread* CurrentSubThread() const { return (CLR_RT_SubThread*)m_subThreads.LastNode(); } + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* CurrentAppDomain() const { CLR_RT_StackFrame* stack = CurrentFrame(); return stack->Prev() ? stack->m_appDomain : NULL; } +#endif + + // Just return priority, no way to set it through this function. + int GetThreadPriority() const { return CurrentSubThread()->m_priority; } + // Here we set it. This function is called if managed code changes thread priority. + void SetThreadPriority( int threadPri ) { CurrentSubThread()->m_priority = threadPri; } + + int GetExecutionCounter() const { return CurrentSubThread()->m_priority + m_executionCounter; } + + // QuantumDebit is update for execution counter for each quantum: + // System_Highest - 1 + // Highest - 2 + // Above Normal - 4 + // Normal - 8 + // Below Normal - 16 + // Lowest - 32 + int GetQuantumDebit() const { return 1 << ( ThreadPriority::System_Highest - GetThreadPriority() ); } + + // If thread was sleeping and get too far behind on updating of m_executionCounter + // Then we make m_executionCounter 4 quantums above m_GlobalExecutionCounter; + void BringExecCounterToDate( int iGlobalExecutionCounter, int iDebitForEachRun ); + + void PopEH( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) { if(m_nestedExceptionsPos) PopEH_Inner( stack, ip ); } + +#if defined(NANOCLR_TRACE_CALLS) + void DumpStack(); +#else + void DumpStack() {} +#endif + + bool IsFinalizerThread(); + bool ReleaseWhenDeadEx(); + void OnThreadTerminated(); + bool CanThreadBeReused(); + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_Thread); + + //--// + +private: + + HRESULT Execute_Inner(); +}; + +//////////////////////////////////////////////////////////////////////////////// + +extern size_t LinkArraySize (); +extern size_t LinkMRUArraySize(); +extern size_t PayloadArraySize(); +extern size_t InterruptRecords(); +#ifndef CLR_NO_IL_INLINE +extern size_t InlineBufferCount(); +#endif + + +extern CLR_UINT32 g_scratchVirtualMethodTableLink []; +extern CLR_UINT32 g_scratchVirtualMethodTableLinkMRU []; +extern CLR_UINT32 g_scratchVirtualMethodPayload []; +extern CLR_UINT32 g_scratchInterruptDispatchingStorage[]; +#ifndef CLR_NO_IL_INLINE +extern CLR_UINT32 g_scratchInlineBuffer []; +#endif + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_EventCache +{ + struct BoundedList + { + CLR_RT_DblLinkedList m_blocks; + }; + +#if defined(NANOCLR_USE_AVLTREE_FOR_METHODLOOKUP) + + struct Payload + { + // + // The first two fields compose the key, the last field is the value. + // + CLR_RT_MethodDef_Index m_mdVirtual; // The definition of the virtual method. + CLR_RT_TypeDef_Index m_cls; // The class of the instance we need to resolve. + CLR_RT_MethodDef_Index m_md; // The actual implementation of the virtual method. + + //--// + + int Compare( Payload& right ) + { + if(m_mdVirtual.m_data == right.m_mdVirtual.m_data) + { + if(m_cls.m_data == right.m_cls.m_data) return 0; + + return m_cls.m_data < right.m_cls.m_data ? -1 : 1; + } + + return m_mdVirtual.m_data < right.m_mdVirtual.m_data ? -1 : 1; + } + }; + + struct LookupEntry : public CLR_RT_AVLTree::Entry + { + Payload m_payload; + + //--// + + static int Callback_Compare( void* state, CLR_RT_AVLTree::Entry* left, CLR_RT_AVLTree::Entry* right ); + }; + + struct VirtualMethodTable + { + CLR_RT_AVLTree m_tree; + LookupEntry* m_entries; + + CLR_RT_DblLinkedList m_list_freeItems; // list of CLR_RT_EventCache::LookupEntry + CLR_RT_DblLinkedList m_list_inUse; // list of CLR_RT_EventCache::LookupEntry + + //--// + + void Initialize(); + + bool FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ); + + //--// + + static CLR_RT_AVLTree::Entry* Callback_NewNode ( void* state, CLR_RT_AVLTree::Entry* payload ); + static void Callback_FreeNode( void* state, CLR_RT_AVLTree::Entry* node ); + static void Callback_Reassign( void* state, CLR_RT_AVLTree::Entry* from, CLR_RT_AVLTree::Entry* to ); + + //--// + +#if defined(_WIN32) + void DumpTree ( ); + bool ConsistencyCheck( ); + bool ConsistencyCheck( LookupEntry* node, int& depth ); +#else + void DumpTree () { } + bool ConsistencyCheck() { return true; } +#endif + }; + +#else + + struct Link + { + CLR_UINT16 m_next; + CLR_UINT16 m_prev; + }; + + struct Payload + { + struct Key + { + CLR_RT_MethodDef_Index m_mdVirtual; // The definition of the virtual method. + CLR_RT_TypeDef_Index m_cls; // The class of the instance we need to resolve. + }; + + Key m_key; + CLR_RT_MethodDef_Index m_md; // The actual implementation of the virtual method. + }; + + struct VirtualMethodTable + { + Link* m_entries; + Link* m_entriesMRU; + Payload* m_payloads; + + //--// + + void Initialize(); + + bool FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ); + + private: + + CLR_UINT32 GetNewEntry() { return m_entriesMRU[ LinkMRUArraySize() - 1 ].m_prev; } + + static void MoveEntryToTop( Link* entries, CLR_UINT32 slot, CLR_UINT32 idx ); + }; +#endif + + //--// + + static const CLR_UINT16 c_maxFastLists = 40; + + // the scratch array is used to avoid bringing in arm ABI methods (for semihosting) + // struct arrays require initialization with the v3.0 compiler and this is done with ABI methods, + // unless of course you provide a work around lik this ;-) + unsigned int m_scratch[ (sizeof(BoundedList) * c_maxFastLists + 3) / sizeof(unsigned int) ]; + BoundedList* m_events; + + VirtualMethodTable m_lookup_VirtualMethod; +#ifndef CLR_NO_IL_INLINE + CLR_RT_InlineBuffer* m_inlineBufferStart; +#endif + + //--// + + void EventCache_Initialize(); + CLR_UINT32 EventCache_Cleanup (); + + void Append_Node ( CLR_RT_HeapBlock* node ); + CLR_RT_HeapBlock* Extract_Node_Slow ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ); + CLR_RT_HeapBlock* Extract_Node_Fast ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ); + CLR_RT_HeapBlock* Extract_Node_Bytes( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 bytes ); + CLR_RT_HeapBlock* Extract_Node ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ); + + bool FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ); + +#ifndef CLR_NO_IL_INLINE + bool GetInlineFrameBuffer(CLR_RT_InlineBuffer** ppBuffer); + bool FreeInlineBuffer(CLR_RT_InlineBuffer* pBuffer); +#endif + + //--// + +#define EVENTCACHE_EXTRACT_NODE_AS_BYTES(ev,cls,type,flags,size) (cls*)((ev).Extract_Node_Bytes( type, flags, size )) +#define EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type,flags,size) (cls*)((ev).Extract_Node( type, flags, size )) +#define EVENTCACHE_EXTRACT_NODE(ev,cls,type) EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type, 0,CONVERTFROMSIZETOHEAPBLOCKS(sizeof(cls))) +#define EVENTCACHE_EXTRACT_NODE_NOALLOC(ev,cls,type) EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type,CLR_RT_HeapBlock::HB_NoGcOnFailure ,CONVERTFROMSIZETOHEAPBLOCKS(sizeof(cls))) +#define EVENTCACHE_EXTRACT_NODE_INITTOZERO(ev,cls,type) EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type,CLR_RT_HeapBlock::HB_InitializeToZero,CONVERTFROMSIZETOHEAPBLOCKS(sizeof(cls))) + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_EventCache); +}; + +extern CLR_RT_EventCache g_CLR_RT_EventCache; + +////////////////////////////////////////////////////////////////////////////////////// +// keep under control the size of the Link and Payload, since we will use externally +// defined arrays to handle those data structures in the Virtual Method cache + +#if defined(NANOCLR_USE_AVLTREE_FOR_METHODLOOKUP) +CT_ASSERT( sizeof(CLR_RT_EventCache::LookupEntry) == 12 ) +#else +CT_ASSERT( sizeof(CLR_RT_EventCache::Link) == 4 ) +CT_ASSERT( sizeof(CLR_RT_EventCache::Payload) == 12 ) +#endif + +////////////////////////////////////////////////////////////////////////////////////// + +//--// + +#include +#include +//#include + +//--// + +#if defined(NANOCLR_TRACE_STACK) + +// +// If this is set, no memory allocation should be allowed, it could lead to a GC while in an inconsistent state!! +// +extern bool g_CLR_RT_fBadStack; + +#endif + +//--// + +struct CLR_RT_ExecutionEngine +{ + static const CLR_UINT32 c_Event_SerialPortIn = 0x00000002; + static const CLR_UINT32 c_Event_SerialPortOut = 0x00000004; + static const CLR_UINT32 c_Event_EndPoint = 0x00000008; + static const CLR_UINT32 c_Event_StorageIo = 0x00000020; + static const CLR_UINT32 c_Event_I2cMaster = 0x00000080; + static const CLR_UINT32 c_Event_SpiMaster = 0x00000100; + static const CLR_UINT32 c_Event_OneWireMaster = 0x00000200; + static const CLR_UINT32 c_Event_AppDomain = 0x02000000; + static const CLR_UINT32 c_Event_Socket = 0x20000000; + static const CLR_UINT32 c_Event_IdleCPU = 0x40000000; + static const CLR_UINT32 c_Event_LowMemory = 0x80000000; // Wait for a low-memory condition. + + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const CLR_UINT32 c_Compile_CPP = 0x00000001; + static const CLR_UINT32 c_Compile_ARM = 0x00000002; + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_HeapState_Normal = 0x00000000; + static const int c_HeapState_UnderGC = 0x00000001; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // NEED TO KEEP THESE IN SYNC WITH Enum 'Commands.Debugging_Execution_ChangeConditions...' on debugger library code // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_fDebugger_StateInitialize = 0x00000000; + static const int c_fDebugger_StateResolutionFailed = 0x00000001; + static const int c_fDebugger_StateProgramRunning = 0x00000400; + static const int c_fDebugger_StateProgramExited = 0x00000800; + static const int c_fDebugger_StateMask = c_fDebugger_StateProgramRunning + c_fDebugger_StateProgramExited; + // + static const int c_fDebugger_BreakpointsDisabled = 0x00001000; + // + static const int c_fDebugger_Quiet = 0x00010000; // Do not spew debug text to the debugger + static const int c_fDebugger_ExitPending = 0x00020000; + // + static const int c_fDebugger_PauseTimers = 0x04000000; // Threads associated with timers are created in "suspended" mode. + static const int c_fDebugger_NoCompaction = 0x08000000; // Don't perform compaction during execution. + // + static const int c_fDebugger_SourceLevelDebugging = 0x10000000; + static const int c_fDebugger_RebootPending = 0x20000000; + static const int c_fDebugger_Enabled = 0x40000000; + static const int c_fDebugger_Stopped = 0x80000000; + + volatile int m_iDebugger_Conditions; + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_fExecution_GC_Pending = 0x00000001; //Not currently used + static const int c_fExecution_Compaction_Pending = 0x00000002; +#if defined(NANOCLR_APPDOMAINS) + static const int c_fExecution_UnloadingAppDomain = 0x00000004; +#endif + + int m_iExecution_Conditions; + + int m_iReboot_Options; + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_fProfiling_Enabled = 0x00000001; + static const int c_fProfiling_Allocations = 0x00000002; + static const int c_fProfiling_Calls = 0x00000004; + static const int c_fProfiling_CLRTypes = 0x00000008; //Don't dump out certain types, like ASSEMBLY, or THREAD, or BINARY_BLOB, etc. + int m_iProfiling_Conditions; + + enum + { EXECUTION_COUNTER_MAXIMUM = 0x70000000, // Threshold value when we increase all execution counters to avoid overflow + EXECUTION_COUNTER_ADJUSTMENT = 0x60000000 // The update ( increase ) value for all executioin counters after threshold is reached. + }; + //////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + static const int c_MaxBreakpointsActive = 5; + + size_t m_breakpointsNum; + CLR_DBG_Commands::Debugging_Execution_BreakpointDef* m_breakpoints; + CLR_DBG_Commands::Debugging_Execution_BreakpointDef m_breakpointsActive[ c_MaxBreakpointsActive ]; + size_t m_breakpointsActiveNum; +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if !defined(BUILD_RTM) || defined(_WIN32) + bool m_fPerformGarbageCollection; //Should the EE do a GC every context switch + bool m_fPerformHeapCompaction; //Should the EE do a Compaction following every GC +#endif + +#if defined(NANOCLR_APPDOMAINS) + static const int c_AppDomainId_Invalid = 0; + + CLR_RT_DblLinkedList m_appDomains; + CLR_RT_AppDomain* m_appDomainCurrent; + int m_appDomainIdNext; + + CLR_RT_AppDomain* SetCurrentAppDomain( CLR_RT_AppDomain* appDomain ); + CLR_RT_AppDomain* GetCurrentAppDomain( ); + + HRESULT UnloadAppDomain ( CLR_RT_AppDomain* appDomain, CLR_RT_Thread* th ); + void PrepareThreadsForAppDomainUnload( CLR_RT_AppDomain* appDomain, CLR_RT_DblLinkedList& threads ); + + void TryToUnloadAppDomains_Helper_Threads ( CLR_RT_DblLinkedList& threads ); + void TryToUnloadAppDomains_Helper_Finalizers( CLR_RT_DblLinkedList& finalizers, bool fAlive ); + bool TryToUnloadAppDomains ( ); +#endif //NANOCLR_APPDOMAINS + +#define CLR_EE_DBG_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions & CLR_RT_ExecutionEngine::c_fDebugger_##Cond) != 0) +#define CLR_EE_DBG_IS_NOT( Cond ) ((g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions & CLR_RT_ExecutionEngine::c_fDebugger_##Cond) == 0) +#define CLR_EE_DBG_SET( Cond ) g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions |= CLR_RT_ExecutionEngine::c_fDebugger_##Cond +#define CLR_EE_DBG_CLR( Cond ) g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions &= ~CLR_RT_ExecutionEngine::c_fDebugger_##Cond +#define CLR_EE_DBG_SET_MASK( Cond, Mask ) CLR_EE_DBG_CLR( Mask ); CLR_EE_DBG_SET( Cond ); +#define CLR_EE_DBG_RESTORE( Cond, f ) ((f) ? CLR_EE_DBG_SET( Cond ) : CLR_EE_DBG_CLR( Cond ) ) +#define CLR_EE_DBG_IS_MASK( Cond, Mask ) ((g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions & CLR_RT_ExecutionEngine::c_fDebugger_##Mask) == CLR_RT_ExecutionEngine::c_fDebugger_##Cond) + +#define CLR_EE_PRF_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions & CLR_RT_ExecutionEngine::c_fProfiling_##Cond) != 0) +#define CLR_EE_PRF_IS_NOT( Cond ) ((g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions & CLR_RT_ExecutionEngine::c_fProfiling_##Cond) == 0) + +#define CLR_EE_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iExecution_Conditions & CLR_RT_ExecutionEngine::c_fExecution_##Cond) != 0) +#define CLR_EE_IS_NOT( Cond ) ((g_CLR_RT_ExecutionEngine.m_iExecution_Conditions & CLR_RT_ExecutionEngine::c_fExecution_##Cond) == 0) +#define CLR_EE_SET( Cond ) g_CLR_RT_ExecutionEngine.m_iExecution_Conditions |= CLR_RT_ExecutionEngine::c_fExecution_##Cond +#define CLR_EE_CLR( Cond ) g_CLR_RT_ExecutionEngine.m_iExecution_Conditions &= ~CLR_RT_ExecutionEngine::c_fExecution_##Cond + +#define CLR_EE_REBOOT_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iReboot_Options & CLR_DBG_Commands::Monitor_Reboot::c_##Cond) == CLR_DBG_Commands::Monitor_Reboot::c_##Cond) +#define CLR_EE_REBOOT_CLR g_CLR_RT_ExecutionEngine.m_iReboot_Options = CLR_DBG_Commands::Monitor_Reboot::c_ClrOnly + +#define CLR_EE_DBG_EVENT_SEND( cmd, size, payload, flags ) ((g_CLR_DBG_Debugger->m_messaging != NULL) ? g_CLR_DBG_Debugger->m_messaging->SendEvent( cmd, size, (unsigned char*)payload, flags ) : false) + +#define CLR_EE_DBG_EVENT_BROADCAST( cmd, size, payload, flags ) CLR_EE_DBG_EVENT_SEND( cmd, size, payload, flags ) + + //////////////////////////////////////////////////////////////////////////////////////////////// + + // + // Used to subtract system time (GC, compaction, other) from ExecutionConstraint checks. + // + struct ExecutionConstraintCompensation + { + CLR_INT32 m_recursion; + CLR_INT32 m_start; + CLR_INT32 m_cumulative; + + void Suspend() + { + if(m_recursion++ == 0) + { + m_start = HAL_Time_CurrentSysTicks(); + } + } + + void Resume() + { + if(m_recursion) + { + if(--m_recursion == 0) + { + m_cumulative += (HAL_Time_CurrentSysTicks() - m_start); + } + } + } + + CLR_INT64 Adjust( CLR_INT64 time ) const + { + // FIXME: evaluate if the caller code can be adjusted to use SysTicks instead of 100ns ticks + return time + ::HAL_Time_SysTicksToTime( m_cumulative ); + } + }; + + static ExecutionConstraintCompensation s_compensation; + + //--// + + CLR_INT64 m_maximumTimeToActive; + + //--// + + CLR_INT64 m_startTime; + CLR_INT64 m_currentNextActivityTime; + bool m_timerCache; + CLR_UINT64 m_timerCacheNextTimeout; + + CLR_RT_DblLinkedList m_heap; // list of CLR_RT_HeapCluster + CLR_RT_HeapCluster* m_lastHcUsed; + int m_heapState; + + CLR_RT_DblLinkedList m_weakReferences; // OBJECT HEAP - DO RELOCATION - list of CLR_RT_HeapBlock_WeakReference + + CLR_RT_DblLinkedList m_timers; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Timer + CLR_UINT32 m_raisedEvents; + + CLR_RT_DblLinkedList m_threadsReady; // EVENT HEAP - NO RELOCATION - list of CLR_RT_Thread + CLR_RT_DblLinkedList m_threadsWaiting; // EVENT HEAP - NO RELOCATION - list of CLR_RT_Thread + CLR_RT_DblLinkedList m_threadsZombie; // EVENT HEAP - NO RELOCATION - list of CLR_RT_Thread + int m_lastPid; + CLR_RT_Thread* m_currentThread; + + CLR_RT_DblLinkedList m_finalizersAlive; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Finalizer + CLR_RT_DblLinkedList m_finalizersPending; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Finalizer + CLR_RT_Thread* m_finalizerThread; // EVENT HEAP - NO RELOCATION - + CLR_RT_Thread* m_cctorThread; // EVENT HEAP - NO RELOCATION - + +#if !defined(NANOCLR_APPDOMAINS) + CLR_RT_HeapBlock* m_globalLock; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock* m_outOfMemoryException; // OBJECT HEAP - DO RELOCATION - +#endif + + CLR_RT_HeapBlock* m_currentUICulture; // OBJECT HEAP - DO RELOCATION - + + //--// + + CLR_RT_Thread* m_interruptThread; // EVENT HEAP - NO RELOCATION + CLR_RT_Thread* m_timerThread; // EVENT HEAP - NO RELOCATION + + //--// + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_HeapBlock_Array* m_scratchPadArray; // OBJECT HEAP - DO RELOCATION - +#endif + + bool m_fShuttingDown; + + //--// + + static HRESULT CreateInstance(); + + HRESULT ExecutionEngine_Initialize(); + + static HRESULT DeleteInstance(); + + void ExecutionEngine_Cleanup(); + + HRESULT StartHardware(); + + static void Reboot( bool fHard ); + + void JoinAllThreadsAndExecuteFinalizer(); + + void LoadDownloadedAssemblies(); + + static void ExecutionConstraint_Suspend(); + static void ExecutionConstraint_Resume (); + + CLR_UINT32 PerformGarbageCollection(); + void PerformHeapCompaction (); + + void Relocate(); + + HRESULT ScheduleThreads( int maxContextSwitch ); + + CLR_UINT32 WaitForActivity( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeout_ms ); + CLR_UINT32 WaitForActivity( ); + + HRESULT Execute ( wchar_t* entryPointArgs, int maxContextSwitch ); + + HRESULT WaitForDebugger(); + + static CLR_RT_HeapBlock* AccessStaticField( const CLR_RT_FieldDef_Index& fd ); + + void ProcessTimeEvent( CLR_UINT32 event ); + + static void InvalidateTimerCache(); + + static CLR_INT64 GetUptime(); + + CLR_RT_HeapBlock* ExtractHeapBlocksForArray( CLR_RT_TypeDef_Instance& inst, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ); + CLR_RT_HeapBlock* ExtractHeapBlocksForClassOrValueTypes( CLR_UINT32 dataType, CLR_UINT32 flags, const CLR_RT_TypeDef_Index& cls, CLR_UINT32 length ); + CLR_RT_HeapBlock* ExtractHeapBytesForObjects ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + CLR_RT_HeapBlock* ExtractHeapBlocksForObjects ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + CLR_RT_HeapBlock_Node* ExtractHeapBlocksForEvents ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + + HRESULT NewThread ( CLR_RT_Thread*& th, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_INT32 id, CLR_UINT32 flags = 0 ); + void PutInProperList( CLR_RT_Thread* th ); + CLR_INT32 GetNextThreadId( ); + + HRESULT InitializeReference( CLR_RT_HeapBlock& ref, CLR_RT_SignatureParser& parser ); + HRESULT InitializeReference( CLR_RT_HeapBlock& ref, const CLR_RECORD_FIELDDEF* target, CLR_RT_Assembly* assm ); + + HRESULT InitializeLocals( CLR_RT_HeapBlock* locals, CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ); + + HRESULT NewObjectFromIndex( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Index& cls ); + HRESULT NewObject ( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Instance& inst ); + HRESULT NewObject ( CLR_RT_HeapBlock& reference, CLR_UINT32 token, CLR_RT_Assembly* assm ); + + HRESULT CloneObject ( CLR_RT_HeapBlock& reference , const CLR_RT_HeapBlock& source ); + HRESULT CopyValueType( CLR_RT_HeapBlock* destination, const CLR_RT_HeapBlock* source ); + + HRESULT NewArrayList ( CLR_RT_HeapBlock& ref, int size, CLR_RT_HeapBlock_Array*& array ); + + + HRESULT FindFieldDef( CLR_RT_TypeDef_Instance& inst , const char* szText , CLR_RT_FieldDef_Index& res ); + HRESULT FindFieldDef( CLR_RT_HeapBlock& reference, const char* szText , CLR_RT_FieldDef_Index& res ); + HRESULT FindField ( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_HeapBlock*& field ); + HRESULT SetField ( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_HeapBlock& value ); + HRESULT GetField ( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_HeapBlock& value ); + + + HRESULT LockObject ( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ); + HRESULT UnlockObject ( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth ); + void DeleteLockRequests( CLR_RT_Thread* thTarget , CLR_RT_SubThread* sthTarget ); + + HRESULT Sleep( CLR_RT_Thread* caller, const CLR_INT64& timeExpire ); + + HRESULT WaitEvents ( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_UINT32 events, bool& fSuccess ); + void SignalEvents( CLR_RT_DblLinkedList& threads, CLR_UINT32 events ); + void SignalEvents( CLR_UINT32 events ); + + + HRESULT InitTimeout( CLR_INT64& timeExpire, const CLR_INT64& timeout ); + HRESULT InitTimeout( CLR_INT64& timeExpire, CLR_INT32 timeout ); + + static bool IsInstanceOf( CLR_RT_TypeDescriptor& desc, CLR_RT_TypeDescriptor& descTarget ); + static bool IsInstanceOf( const CLR_RT_TypeDef_Index& cls , const CLR_RT_TypeDef_Index& clsTarget ); + static bool IsInstanceOf( CLR_RT_HeapBlock& obj , const CLR_RT_TypeDef_Index& clsTarget ); + static bool IsInstanceOf( CLR_RT_HeapBlock& obj , CLR_RT_Assembly* assm, CLR_UINT32 token ); + + static HRESULT CastToType( CLR_RT_HeapBlock& ref, CLR_UINT32 tk, CLR_RT_Assembly* assm, bool fUpdate ); + + void DebuggerLoop(); + +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + void SetDebuggingInfoBreakpoints( bool fSet ); + void InstallBreakpoints ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef* data, size_t num ); + void StopOnBreakpoint ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def , CLR_RT_Thread* th ); + void StopOnBreakpoint ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def , CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + void Breakpoint_System_Event ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def , CLR_UINT16 event, CLR_RT_Thread* th, CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + bool DequeueActiveBreakpoint ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def ); + + void Breakpoint_Assemblies_Loaded(); + + void Breakpoint_Threads_Prepare ( CLR_RT_DblLinkedList& threads ); + void Breakpoint_Thread_Terminated( CLR_RT_Thread* th ); + void Breakpoint_Thread_Created ( CLR_RT_Thread* th ); + + void Breakpoint_StackFrame_Break ( CLR_RT_StackFrame* stack ); + void Breakpoint_StackFrame_Push ( CLR_RT_StackFrame* stack, CLR_UINT32 reason ); + void Breakpoint_StackFrame_Pop ( CLR_RT_StackFrame* stack, bool stepEH ); + void Breakpoint_StackFrame_Step ( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + void Breakpoint_StackFrame_Hard ( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + + void Breakpoint_Exception ( CLR_RT_StackFrame* stack, CLR_UINT32 reason, CLR_PMETADATA ip ); + void Breakpoint_Exception_Intercepted( CLR_RT_StackFrame* stack ); + void Breakpoint_Exception_Uncaught ( CLR_RT_Thread* th ); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + //--// + + bool IsTimeExpired( const CLR_INT64& timeExpire, CLR_INT64& timeoutMin ); + + bool IsThereEnoughIdleTime( CLR_UINT32 expectedMsec ); + + void SpawnTimer(); + void SpawnFinalizer(); + void SpawnStaticConstructor( CLR_RT_Thread *&pCctorThread ); +#if defined(NANOCLR_APPDOMAINS) + bool SpawnStaticConstructorHelper( CLR_RT_AppDomain* appDomain, CLR_RT_AppDomainAssembly* appDomainAssembly, const CLR_RT_MethodDef_Index& idx ); +#else + bool SpawnStaticConstructorHelper( CLR_RT_Assembly* assembly, const CLR_RT_MethodDef_Index& idx ); +#endif + static void FinalizerTerminationCallback( void* arg ); + static void StaticConstructorTerminationCallback( void* arg ); + bool EnsureSystemThread( CLR_RT_Thread*& thread, int priority ); + + CLR_INT64 ProcessTimer(); + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_ExecutionEngine); + + //--// + +private: + + HRESULT AllocateHeaps(); + + void DeleteLockRequests( CLR_RT_Thread* thTarget, CLR_RT_SubThread* sthTarget, CLR_RT_DblLinkedList& threads ); + + CLR_RT_HeapBlock* ExtractHeapBlocks ( CLR_RT_DblLinkedList& heap, CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + + CLR_RT_HeapBlock_Lock* FindLockObject( CLR_RT_DblLinkedList& threads, CLR_RT_HeapBlock& object ); + CLR_RT_HeapBlock_Lock* FindLockObject( CLR_RT_HeapBlock& object ); + + void CheckTimers ( CLR_INT64& timeoutMin ); + void CheckThreads ( CLR_INT64& timeoutMin, CLR_RT_DblLinkedList& threads ); + + void ProcessHardware(); + + + void ReleaseAllThreads( CLR_RT_DblLinkedList& threads ); + void AbortAllThreads ( CLR_RT_DblLinkedList& threads ); + + void InsertThreadRoundRobin( CLR_RT_DblLinkedList& threads, CLR_RT_Thread* th ); + + CLR_UINT32 WaitSystemEvents( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeExpire ); + +#if defined(_WIN32) + HRESULT CreateEntryPointArgs( CLR_RT_HeapBlock& args, wchar_t* szCommandLineArgs ); +#endif + + // The lowest value for execution counter in threads. + int m_GlobalExecutionCounter; + + // Increase the value of m_executionCounter for all threads by iUpdateValue. + // This ensures that counter does not underflow. + void AdjustExecutionCounter( CLR_RT_DblLinkedList &threadList, int iUpdateValue ); +public : + + // This function updates execution counter in pThread and makes it last to execute. + // It is used to Thread.Sleep(0) imlementation. The thread is still ready, but is last to execute. + void UpdateToLowestExecutionCounter( CLR_RT_Thread *pThread ) const; + + void RetrieveCurrentMethod( CLR_UINT32& assmIdx, CLR_UINT32& methodIdx ); +}; + +extern CLR_RT_ExecutionEngine g_CLR_RT_ExecutionEngine; +extern CLR_UINT32 g_buildCRC; + +//--// + +// +// CT_ASSERT macro generates a compiler error in case the size of any structure changes. +// +CT_ASSERT( sizeof(CLR_RT_HeapBlock) == 12 ) +CT_ASSERT( sizeof(CLR_RT_HeapBlock_Raw) == sizeof(CLR_RT_HeapBlock) ) + +#if defined(NANOCLR_TRACE_MEMORY_STATS) +#define NANOCLR_TRACE_MEMORY_STATS_EXTRA_SIZE 4 +#else +#define NANOCLR_TRACE_MEMORY_STATS_EXTRA_SIZE 0 +#endif + +#if defined(__GNUC__) // Gcc compiler uses 8 bytes for a function pointer + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 20 + NANOCLR_TRACE_MEMORY_STATS_EXTRA_SIZE ) + +#elif defined(PLATFORM_WINDOWS_EMULATOR) || defined(NANOCLR_TRACE_MEMORY_STATS) + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 16 + 4 ) + +#else + +! ERROR + +#endif + +//--// + +#if defined(_MSC_VER) +#pragma pack(pop, NANOCLR_RUNTIME_H) +#endif + +#endif // _NANOCLR_RUNTIME_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h new file mode 100644 index 00000000..374c811e --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__HeapBlock.h @@ -0,0 +1,2443 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_RUNTIME__HEAPBLOCK_H_ +#define _NANOCLR_RUNTIME__HEAPBLOCK_H_ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define CLR_RT_HEAPBLOCK_RAW_ID( dataType, flags, size ) ( (dataType & 0x000000FF) | ((flags & 0x000000FF) << 8) | ((size & 0x0000FFFF) << 16)) +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED( dataType, num ) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.s4 = (CLR_INT32)num; } +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_SIGNED( dataType, num ) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.s8 = num; } + +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.u4 = (CLR_UINT32)num; } +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_UNSIGNED(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.u8 = num; } + +#define CLR_RT_HEAPBLOCK_ASSIGN_FLOAT32(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.r4 = num; } +#define CLR_RT_HEAPBLOCK_ASSIGN_FLOAT64(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.r8 = num; } + +//////////////////////////////////////////////////////////// + +#define CLR_RT_HEAPBLOCK_RELOCATE(ptr) \ +{ \ + CLR_DataType dt = ptr->DataType(); \ + \ + if(dt > DATATYPE_LAST_NONPOINTER && dt < DATATYPE_FIRST_INVALID) \ + { \ + CLR_RT_HeapBlockRelocate rel = c_CLR_RT_DataTypeLookup[ dt ].m_relocate; \ + if(rel) \ + { \ + (ptr->*rel)(); \ + } \ + } \ +} + + +//////////////////////////////////////////////////////////// + +// +// This is used in memory move operations. +// +struct CLR_RT_HeapBlock_Raw +{ + CLR_UINT32 data[ 3 ]; +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_HeapBlock +{ + friend struct CLR_RT_HeapBlock_Node; + friend struct CLR_RT_DblLinkedList; + + friend struct MethodCompiler; + //--// + +#if defined(NANOCLR_EMULATED_FLOATINGPOINT) +/*********************************************************/ +// Keep in Sync with nanoHAL.h +//#define HAL_FLOAT_SHIFT 10 +//#define HAL_FLOAT_PRECISION 1000 +//#define HAL_DOUBLE_SHIFT 16 +//#define HAL_DOUBLE_PRECISION 10000 +/*********************************************************/ + + static const int HB_FloatShift = 10; + static const int HB_DoubleShift = 16; + + static const CLR_INT32 HB_FloatUnit = (1 << HB_FloatShift ); + static const CLR_INT64 HB_DoubleUnit = (ULONGLONGCONSTANT(1) << HB_DoubleShift); + + static const CLR_INT32 HB_FloatMask = ((1 << HB_FloatShift) - 1); + static const CLR_INT64 HB_DoubleMask = ((ULONGLONGCONSTANT(1) << HB_DoubleShift) - 1); + +#endif + + + + static const CLR_UINT32 HB_Alive = 0x01; + static const CLR_UINT32 HB_KeepAlive = 0x02; + static const CLR_UINT32 HB_Event = 0x04; + static const CLR_UINT32 HB_Pinned = 0x08; + static const CLR_UINT32 HB_Boxed = 0x10; + static const CLR_UINT32 HB_Unused20 = 0x20; + //If more bits are needed, HB_Signaled and HB_SignalAutoReset can be freed for use with a little work. + //It is not necessary that any heapblock can be waited upon. Currently, only Threads (Thread.Join), + //ManualResetEvent, and AutoResetEvent are waitable objects. + static const CLR_UINT32 HB_Signaled = 0x40; + static const CLR_UINT32 HB_SignalAutoReset = 0x80; + + static const CLR_UINT32 HB_Unmovable = HB_Pinned | HB_Event; + + // + // These are special flags used to control allocation. + // + static const CLR_UINT32 HB_InitializeToZero = 0x00100; + static const CLR_UINT32 HB_NoGcOnFailure = 0x00200; + static const CLR_UINT32 HB_SpecialGCAllocation = 0x00400; + static const CLR_UINT32 HB_CompactOnFailure = 0x00800; + + static const CLR_UINT32 HB_NoGcOnFailedAllocation = HB_SpecialGCAllocation | HB_NoGcOnFailure; + static const CLR_UINT32 HB_MaxSize = 0x0000FFFF; + + static const CLR_UINT32 HB_Object_Fields_Offset = 1; + + //--// + +private: + + union CLR_RT_HeapBlock_Id + { + struct Type + { + CLR_UINT8 dataType; // CLR_DataType + CLR_UINT8 flags; // HB_* + CLR_UINT16 size; + } type; + + CLR_UINT32 raw; + } m_id; + + union CLR_RT_HeapBlock_AtomicData + { + struct NodeLink + { + CLR_RT_HeapBlock_Node* nextBlock; + CLR_RT_HeapBlock_Node* prevBlock; + } nodeLink; + + union Numeric + { + CLR_UINT8 u1; + CLR_UINT16 u2; + CLR_UINT32 u4; + + struct U8 + { + CLR_UINT32 LL; + CLR_UINT32 HH; + + operator CLR_UINT64() const + { + return ((CLR_UINT64)HH << 32 | (CLR_UINT64)LL ); + } + + U8& operator=( const CLR_UINT64 num ) + { + LL = (CLR_UINT32)((ULONGLONGCONSTANT(0x00000000FFFFFFFF) & num) ); + HH = (CLR_UINT32)((ULONGLONGCONSTANT(0xFFFFFFFF00000000) & num) >> 32); + return *this; + } + U8& operator+=( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value += (CLR_UINT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + U8& operator-=( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value -= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + + U8 operator*( const U8& num) + { + CLR_UINT64 value = (CLR_UINT64)*this; + U8 ret_value; + value *= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + U8 operator/( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; + U8 ret_value; + value /= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + U8 operator~( ) + { + U8 ret_value; + ret_value.LL = ~LL; + ret_value.HH = ~HH; + return ret_value; + } + + + U8& operator%=( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value %= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + U8& operator&=( const U8& num ) + { + LL &= num.LL; + HH &= num.HH; + return *this; + } + + U8& operator|=( const U8& num ) + { + LL |= num.LL; + HH |= num.HH; + return *this; + } + + U8& operator^=( const U8& num ) + { + LL ^= num.LL; + HH ^= num.HH; + return *this; + } + + U8& operator>>=( const CLR_UINT32 num ) + { + + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value >>= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + U8& operator<<=( const CLR_UINT32 num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value <<= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + bool operator<( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value < (CLR_UINT64)num ); + } + + bool operator>( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value > (CLR_UINT64)num ); + } + + bool operator==( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value ==(CLR_UINT64)num ); + } + + bool operator==( const CLR_UINT64 num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value == num ); + } + + } u8; + // + CLR_INT8 s1; + CLR_INT16 s2; + CLR_INT32 s4; + + struct S8 + { + CLR_UINT32 LL; + CLR_UINT32 HH; + + operator CLR_INT64() const + { + return (((CLR_UINT64)HH) << 32 | (CLR_UINT64)LL); + } + + S8& operator=( const CLR_INT64 num ) + { + LL = (CLR_UINT32) (( ULONGLONGCONSTANT(0x00000000FFFFFFFF) & num) ); + HH = (CLR_UINT32) (( ULONGLONGCONSTANT(0xFFFFFFFF00000000) & num) >> 32 ); + return *this; + } + + S8& operator+=( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value += (CLR_INT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8& operator-=( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value -= (CLR_INT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8 operator*( const S8& num) + { + CLR_INT64 value = (CLR_INT64)*this; + S8 ret_value; + value *= (CLR_INT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + S8 operator/( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; + S8 ret_value; + value /= (CLR_INT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + S8 operator~() + { + S8 ret_value; + ret_value.LL = ~LL; + ret_value.HH = ~HH; + return ret_value; + } + + + + S8& operator%=( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value %= (CLR_INT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8& operator&=( const S8& num ) + { + LL &= num.LL; + HH &= num.HH; + return *this; + } + + S8& operator|=( const S8& num ) + { + LL |= num.LL; + HH |= num.HH; + return *this; + } + + S8& operator^=( const S8& num ) + { + LL ^= num.LL; + HH ^= num.HH; + return *this; + } + + S8& operator>>=( const CLR_UINT32 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value >>= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8& operator<<=( const CLR_UINT32 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value <<= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + bool operator<( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value < (CLR_INT64)num ); + } + + bool operator>( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value > (CLR_INT64)num ); + } + + bool operator==( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == (CLR_INT64)num ); + } + + + bool operator==( const CLR_INT64 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == num ); + } + + } s8; + // + + #if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + + float r4; + + struct R8 + { + CLR_UINT32 LL; + CLR_UINT32 HH; + + operator double() const + { + double ret_val; + + #if defined(__GNUC__) + /// + /// UNDONE: FIXME: This code fixes an optimization problem with the gcc compiler. + /// When the optimization level is greater than zero, the gcc compiler + /// code will not work with the unsigned int* conversion, it requires you + /// to copy byte by byte. + /// + CLR_UINT8* tmp = (CLR_UINT8*)&ret_val; + CLR_UINT8* src = (CLR_UINT8*)&LL; + uint32_t i; + + for(i=0; i( const R8& num ) + { + double value = (double)*this; // uses conversion + return ( value > (double)num ); + } + + bool operator==( const R8& num ) + { + double value = (double)*this; // uses conversion + return ( value == (double)num ); + } + + bool operator==( const double num ) + { + double value = (double)*this; // uses conversion + return ( value == num ); + } + + } r8; + + #else + /// not using floating point lib, emulated one + + struct R4 { + + CLR_INT32 LL; + + operator CLR_INT32 () const + { + return LL; + } + + R4& operator=( const CLR_INT32 num ) + { + LL = num; + return *this; + } + R4& operator+=( const R4& num ) + { + LL += num.LL; + return *this; + } + + R4& operator-=( const R4& num ) + { + LL -= num.LL; + return *this; + } + + + R4& operator%=( const R4& num ) + { + LL %= num.LL; + return *this; + } + + + R4 operator*( const R4& num ) + { + R4 ret_value; + ret_value.LL = (CLR_INT32)(((CLR_INT64)LL * (CLR_INT64)num.LL) >> HB_FloatShift ); + return ret_value; + } + + R4 operator/( const R4& num ) + { + R4 ret_value; + ret_value.LL = (CLR_INT32)((((CLR_INT64)LL) << HB_FloatShift) / (CLR_INT64)num.LL); + return ret_value; + } + + } r4; + + struct R8 + { + CLR_UINT32 LL; + CLR_UINT32 HH; + + operator CLR_INT64() const + { + return ((CLR_INT64)HH << 32 | (CLR_INT64)LL ); + } + + R8& operator=( const CLR_INT64 num ) + { + LL = (CLR_UINT32) (( ULONGLONGCONSTANT(0x00000000FFFFFFFF) & num) ); + HH = (CLR_UINT32) (( ULONGLONGCONSTANT(0xFFFFFFFF00000000) & num) >> 32 ); + return *this; + } + + R8& operator+=( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value += (CLR_INT64)num; + *this = value; + return *this; + } + + R8& operator-=( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value -= (CLR_INT64)num; + *this = value; + return *this; + } + + R8 operator*( const R8& num) + { + CLR_UINT64 op1 = (CLR_INT64) *this; + CLR_UINT64 op2 = (CLR_INT64) num; + CLR_UINT64 res = 0; + R8 ret_value; + + bool fNegate = false; + + if((CLR_INT64)op1 < (CLR_INT64)res) + { + op1 = -(CLR_INT64)op1; + fNegate = !fNegate; + } + + if((CLR_INT64)op2 < (CLR_INT64)res) + { + op2 = -(CLR_INT64)op2; + fNegate = !fNegate; + } + + CLR_UINT64 v; + + #define ACCUMULATE(res,op,part) v = op1 * (CLR_UINT16)(op2 >> (16 * part)); res += (16 * part - HB_DoubleShift >= 0) ? (v << (16 * part - HB_DoubleShift)) : (v >> (HB_DoubleShift - 16 * part)) + + ACCUMULATE(res,+=,0); + ACCUMULATE(res,+=,1); + ACCUMULATE(res,+=,2); + ACCUMULATE(res,+=,3); + + #undef ACCUMULATE + + ret_value = (CLR_INT64)res; + + if(fNegate && (CLR_INT64)ret_value != 0) + { + ret_value = -(CLR_INT64)ret_value; + } + + return ret_value; + } + + R8 operator/( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; + R8 ret_value; + + value = (value / num) << HB_DoubleShift; + + ret_value = value; + + return ret_value; + } + + bool operator==( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == (CLR_INT64)num ); + } + + + bool operator==( const CLR_INT64 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == num ); + } + R8& operator%=( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + + value = (CLR_INT64)((value % (CLR_INT64)num)) ; // uses conversion and then built-in type double + *this = value; // uses assignment operator (operator=) + + return *this; + } + + } r8; + + #endif + } numeric; + + // The macro CT_ASSERT is used to validate that members of Numeric union start at zero offset in union. + // This presumption is used in CRL_RT_Interop code. + // This macro does not add any code or data member, it is pure compiler time validation. + // This is not a valid check for Big Endian. + // Addr: 0011223344556677 Number: 0xAABBCCDD + // MemBE: AABBCCDD + // MemLE: DDCCBBAA + // So for LE DD,Addr 00 is the low byte. + // For BE it is certainly not true, hence this check will not work. Will Interop? FIXME GJS - verify interop + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s1 ) == 0, s1 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s2 ) == 0, s2 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s4 ) == 0, s4 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u1 ) == 0, u1 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u2 ) == 0, u2 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u4 ) == 0, u4 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, r4 ) == 0, r4 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s8 ) == 0, s8 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u8 ) == 0, u8 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, r8 ) == 0, r8 ) + + struct String + { + const char* m_text; +#if !defined(NANOCLR_NO_ASSEMBLY_STRINGS) + CLR_RT_Assembly* m_assm; +#endif + } string; + + //--// + + struct ObjectReference + { + CLR_RT_HeapBlock* ptr; + } objectReference; + + struct ArrayReference + { + CLR_RT_HeapBlock_Array* array; + CLR_UINT32 index; + } arrayReference; + + struct ObjectHeader + { + CLR_RT_TypeDef_Index cls; + CLR_RT_HeapBlock_Lock* lock; + } objectHeader; + +#if defined(NANOCLR_APPDOMAINS) + struct TransparentProxy + { + CLR_RT_HeapBlock* ptr; //points to a DATATYPE_CLASS derived from MBRO + CLR_RT_AppDomain* appDomain; //EVENT HEAP -- NO RELOCATION + } transparentProxy; +#endif + + //--// + + CLR_RT_ReflectionDef_Index reflection; + + //--// + + struct BinaryBlob + { + CLR_RT_MarkingHandler m_mark; + CLR_RT_RelocationHandler m_relocate; + } binaryBlob; + + } m_data; + +public: + + //--// + + void InitializeToZero(); + + //--// + + CLR_DataType DataType () const { return (CLR_DataType)m_id.type.dataType; } + CLR_UINT8 DataFlags() const { return m_id.type.flags ; } + CLR_UINT16 DataSize () const { return m_id.type.size ; } + + // Returns number of bytes actually used in CLR_RT_HeapBlock_AtomicData + CLR_UINT32 GetAtomicDataUsedBytes() const; + + void SetDataId ( CLR_UINT32 id ) { m_id.raw = id; } + void ChangeDataType ( CLR_UINT32 dataType ) { m_id.type.dataType = dataType; } + void ChangeDataFlags( CLR_UINT32 flags ) { m_id.type.flags = flags; } + + void ClearData() + { + m_data.nodeLink.nextBlock = NULL; + m_data.nodeLink.prevBlock = NULL; + } + + void SetFlags ( CLR_UINT8 flags ) { m_id.type.flags |= flags ; } + void ResetFlags( CLR_UINT8 flags ) { m_id.type.flags &= ~flags ; } + bool IsFlagSet ( CLR_UINT8 flags ) const { return (m_id.type.flags & flags) != 0; } + + //--// + +#if defined(NANOCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + + void Debug_ClearBlock ( int data ); + void Debug_CheckPointer( ) const; + static void Debug_CheckPointer( void* ptr ); + +#else + + void Debug_ClearBlock ( int data ) {} + void Debug_CheckPointer( ) const {} + static void Debug_CheckPointer( void* ptr ) {} + +#endif + + //--// + + bool IsAlive () const { return IsFlagSet ( HB_Alive ); } + bool IsEvent () const { return IsFlagSet ( HB_Event ); } + bool IsForcedAlive () const { return IsFlagSet ( HB_KeepAlive ); } + + bool IsPinned () const { return IsFlagSet ( HB_Pinned ); } + void Pin () { SetFlags ( HB_Pinned ); } + void Unpin () { ResetFlags( HB_Pinned ); } + + void MarkDead () { ResetFlags( HB_Alive ); } + void MarkAlive () { SetFlags ( HB_Alive ); } + + void MarkForcedAlive () { SetFlags ( HB_KeepAlive ); } + void UnmarkForcedAlive() { ResetFlags( HB_KeepAlive ); } + + bool IsBoxed () const { return IsFlagSet ( HB_Boxed ); } + void Box () { SetFlags ( HB_Boxed ); } + void Unbox () { ResetFlags( HB_Boxed ); } + + //--// + + void SetBoolean( bool val ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED( DATATYPE_BOOLEAN, val ? 1 : 0 ); } + void SetInteger( const CLR_INT32 num, CLR_UINT8 dataType ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED( dataType , num ); } + + void SetInteger( const CLR_INT8 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED (DATATYPE_I1, num); } + void SetInteger( const CLR_INT16 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED (DATATYPE_I2, num); } + void SetInteger( const CLR_INT32 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED (DATATYPE_I4, num); } + void SetInteger( const CLR_INT64& num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_SIGNED (DATATYPE_I8, num); } + void SetInteger( const CLR_UINT8 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(DATATYPE_U1, num); } + void SetInteger( const CLR_UINT16 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(DATATYPE_U2, num); } + void SetInteger( const CLR_UINT32 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(DATATYPE_U4, num); } + void SetInteger( const CLR_UINT64& num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_UNSIGNED(DATATYPE_U8, num); } + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + void SetFloat ( const float num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT32 (DATATYPE_R4, num); } + void SetDouble ( const double num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT64 (DATATYPE_R8, num); } + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + + void SetFloatFromBits ( const CLR_UINT32 num ) { SetFloat ( *(const float *)&num ); } + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + void SetDoubleFromBits( const CLR_UINT64& num ) { SetDouble( *(const double*)&num ); } +#else + void SetFloat ( const CLR_INT32 num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT32 (DATATYPE_R4, num); } + void SetDouble ( const CLR_INT64& num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT64 (DATATYPE_R8, num); } + HRESULT SetFloatIEEE754 ( const CLR_UINT32 num ); + HRESULT SetDoubleIEEE754( const CLR_UINT64& num ); +#endif + + + void SetObjectReference( const CLR_RT_HeapBlock* ptr ) + { + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_OBJECT, 0, 1); + m_data.objectReference.ptr = (CLR_RT_HeapBlock*)ptr; + } + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* TransparentProxyAppDomain () const { return m_data.transparentProxy.appDomain; } + CLR_RT_HeapBlock* TransparentProxyDereference() const { return Dereference() ; } + + void SetTransparentProxyReference( CLR_RT_AppDomain* appDomain, CLR_RT_HeapBlock* ptr ); + HRESULT TransparentProxyValidate() const; + + bool IsTransparentProxy() const { return IsAReferenceOfThisType( DATATYPE_TRANSPARENT_PROXY ); } +#endif + + void SetReference( CLR_RT_HeapBlock& dst ) + { + CLR_RT_HeapBlock* obj; + + // + // ValueTypes are implemented as pointers to objects, + // so getting a reference to a ValueType has to be treated like getting a reference to object, not to its holder! + // + if(dst.IsAValueType()) + { + obj = dst.Dereference(); + } + else + { + obj = &dst; + } + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_BYREF, 0, 1); + m_data.objectReference.ptr = obj; + } + + bool IsAReferenceOfThisType( CLR_DataType dataType ) const + { + if(DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* obj = Dereference(); + + if(obj && obj->DataType() == dataType) return true; + } + + return false; + } + + bool IsAValueType() const + { + if(DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* obj = Dereference(); + + if(obj && obj->DataType() == DATATYPE_VALUETYPE && obj->IsBoxed() == false) return true; + } + + return false; + } + + bool SameHeader( const CLR_RT_HeapBlock& right ) const + { + return this->m_data.numeric.u8 == right.m_data.numeric.u8; + } + + //--// + + CLR_RT_HeapBlock_Array* RecoverArrayHeader() const + { + return (DataType() == DATATYPE_ARRAY_BYREF) ? m_data.arrayReference.array : NULL; + } + + //--// + + const char* RecoverString() const + { + if(DataType() == DATATYPE_OBJECT) + { + const CLR_RT_HeapBlock* ptr = m_data.objectReference.ptr; + + if(ptr) + { + return ptr->StringText(); + } + } + + return NULL; + } + + //--// + const CLR_RT_HeapBlock_AtomicData& DataByRefConst() const { return m_data; } + + CLR_RT_HeapBlock_AtomicData::Numeric& NumericByRef () { return m_data.numeric; } + const CLR_RT_HeapBlock_AtomicData::Numeric& NumericByRefConst() const { return m_data.numeric; } + + //--// + + const char* StringText() const { return m_data.string.m_text; } + +#if defined(NANOCLR_NO_ASSEMBLY_STRINGS) + void SetStringText( const char* szText ) + { + m_data.string.m_text = szText; + } +#else + void SetStringText( const char* szText, CLR_RT_Assembly* assm ) + { + m_data.string.m_text = szText; + m_data.string.m_assm = assm; + } + + CLR_RT_Assembly* StringAssembly() const { return m_data.string.m_assm; } +#endif + + //--// + + const CLR_RT_TypeDef_Index& ObjectCls ( ) const { return m_data.objectHeader.cls ; } + CLR_RT_HeapBlock_Lock* ObjectLock ( ) const { return m_data.objectHeader.lock ; } + void SetObjectLock( CLR_RT_HeapBlock_Lock* lock ) { m_data.objectHeader.lock = lock; } + + HRESULT SetObjectCls( const CLR_RT_TypeDef_Index& cls ); + + //--// + + const CLR_RT_ReflectionDef_Index& ReflectionDataConst() const { return m_data.reflection; } + CLR_RT_ReflectionDef_Index& ReflectionData () { return m_data.reflection; } + + //--// + + CLR_RT_HeapBlock_Array* Array () const { return m_data.arrayReference.array ; } + CLR_UINT32 ArrayIndex () const { return m_data.arrayReference.index ; } + void ArrayIndexIncrement() { m_data.arrayReference.index++; } + + //--// + + CLR_RT_MarkingHandler BinaryBlobMarkingHandler () const { return m_data.binaryBlob.m_mark ; } + CLR_RT_RelocationHandler BinaryBlobRelocationHandler() const { return m_data.binaryBlob.m_relocate; } + + void SetBinaryBlobHandlers( CLR_RT_MarkingHandler mark, CLR_RT_RelocationHandler relocate ) + { + m_data.binaryBlob.m_mark = mark ; + m_data.binaryBlob.m_relocate = relocate; + } + + //--// + //--// + + CLR_RT_HeapBlock* Dereference() const { return m_data.objectReference.ptr; } + + CLR_RT_HeapBlock_WeakReference* DereferenceWeakReference() const { return (CLR_RT_HeapBlock_WeakReference*)Dereference(); } + CLR_RT_HeapBlock_String * DereferenceString () const { return (CLR_RT_HeapBlock_String *)Dereference(); } + CLR_RT_HeapBlock_Array * DereferenceArray () const { return (CLR_RT_HeapBlock_Array *)Dereference(); } + CLR_RT_HeapBlock_Delegate * DereferenceDelegate () const { return (CLR_RT_HeapBlock_Delegate *)Dereference(); } + CLR_RT_HeapBlock_Delegate_List* DereferenceDelegateList () const { return (CLR_RT_HeapBlock_Delegate_List*)Dereference(); } + CLR_RT_HeapBlock_BinaryBlob * DereferenceBinaryBlob () const { return (CLR_RT_HeapBlock_BinaryBlob *)Dereference(); } + + //--// + + void AssignId( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + m_id = value.m_id; + } + + void AssignData( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + m_data = value.m_data; + } + + void Assign( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + value.Debug_CheckPointer(); + + CLR_RT_HeapBlock_Raw* src = (CLR_RT_HeapBlock_Raw*) this; + CLR_RT_HeapBlock_Raw* dst = (CLR_RT_HeapBlock_Raw*)&value; + + *src = *dst; + } + + void AssignAndPreserveType( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + this->m_data = value.m_data; + + if(this->DataType() > DATATYPE_LAST_PRIMITIVE_TO_PRESERVE) this->m_id = value.m_id; + } + + void AssignPreserveTypeCheckPinned( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + + { // If local variable does not have pinned type - move source data into it + if (!IsPinned()) + { + AssignAndPreserveType( value ); + } + else // IsPinned() is true; + { AssignAndPinReferencedObject( value ); + } + } + } + + // This function is called for assigning to "pinned" reference variables. + // Since it is rare case, the code is not inlined to save code size. + void AssignAndPinReferencedObject( const CLR_RT_HeapBlock& value ); + + HRESULT Convert( CLR_DataType et, bool fOverflow, bool fUnsigned ) + { + // + // For V1, we don't throw on overflow. + // + return Convert_Internal( et ); + } + + bool InitObject(); + + //--// + + static CLR_INT32 Compare_Unsigned_Values( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right ) { return Compare_Values( left, right, false ); } + static CLR_INT32 Compare_Signed_Values ( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right ) { return Compare_Values( left, right, true ); } + + //--// + + + HRESULT SetReflection( const CLR_RT_ReflectionDef_Index& reflex ); + HRESULT SetReflection( const CLR_RT_Assembly_Index& assm ); + HRESULT SetReflection( const CLR_RT_TypeSpec_Index& sig ); + HRESULT SetReflection( const CLR_RT_TypeDef_Index& cls ); + HRESULT SetReflection( const CLR_RT_FieldDef_Index& fd ); + HRESULT SetReflection( const CLR_RT_MethodDef_Index& md ); + + + HRESULT InitializeArrayReference ( CLR_RT_HeapBlock& ref , int index ); + void InitializeArrayReferenceDirect( CLR_RT_HeapBlock_Array& array, int index ); + void FixArrayReferenceForValueTypes( ); + + HRESULT LoadFromReference ( CLR_RT_HeapBlock& ref ); + HRESULT StoreToReference ( CLR_RT_HeapBlock& ref, int size ); + HRESULT Reassign ( const CLR_RT_HeapBlock& value ); + HRESULT PerformBoxingIfNeeded( ); + HRESULT PerformBoxing ( const CLR_RT_TypeDef_Instance& cls ); + HRESULT PerformUnboxing ( const CLR_RT_TypeDef_Instance& cls ); + CLR_RT_HeapBlock* FixBoxingReference ( ); + HRESULT EnsureObjectReference( CLR_RT_HeapBlock*& obj ); + + //--// + + bool IsZero () const; + void Promote(); + + static CLR_UINT32 GetHashCode ( CLR_RT_HeapBlock* ptr, bool fRecurse, CLR_UINT32 crc ); + static bool ObjectsEqual ( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSameReference ); + + static CLR_INT32 Compare_Values( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSigned ); + + HRESULT Convert_Internal( CLR_DataType et ); + HRESULT NumericAdd ( const CLR_RT_HeapBlock& right ); + HRESULT NumericSub ( const CLR_RT_HeapBlock& right ); + HRESULT NumericMul ( const CLR_RT_HeapBlock& right ); + HRESULT NumericDiv ( const CLR_RT_HeapBlock& right ); + HRESULT NumericDivUn ( const CLR_RT_HeapBlock& right ); + HRESULT NumericRem ( const CLR_RT_HeapBlock& right ); + HRESULT NumericRemUn ( const CLR_RT_HeapBlock& right ); + HRESULT NumericShl ( const CLR_RT_HeapBlock& right ); + HRESULT NumericShr ( const CLR_RT_HeapBlock& right ); + HRESULT NumericShrUn ( const CLR_RT_HeapBlock& right ); + HRESULT NumericNeg ( ); + + CLR_RT_HeapBlock* ExtractValueBlock( int offset ); + void ReadValue ( CLR_INT64& val, int offset ); + void WriteValue ( const CLR_INT64& val, int offset ); + + void Relocate__HeapBlock(); + void Relocate_String (); + void Relocate_Obj (); + void Relocate_Cls (); + void Relocate_Ref (); + void Relocate_ArrayRef (); + +#if defined(NANOCLR_APPDOMAINS) + void Relocate_TransparentProxy(); +#endif + +private: + CLR_RT_HeapBlock& operator=( const CLR_RT_HeapBlock& ); + + +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +//--// + +#define NANOCLR_FOREACH_NODE(cls,ptr,lst) \ + { \ + cls* ptr; \ + cls* ptr##Next; \ + \ + for(ptr = (cls*)(lst).FirstNode(); (ptr##Next = (cls*)ptr->Next()) != NULL; ptr = ptr##Next) \ + { NANOCLR_FAULT_ON_EARLY_COLLECTION( ptr##Next ); + +#define NANOCLR_FOREACH_NODE__NODECL(cls,ptr,lst) \ + { \ + cls* ptr##Next; \ + \ + for(ptr = (cls*)(lst).FirstNode(); (ptr##Next = (cls*)ptr->Next()) != NULL; ptr = ptr##Next) \ + { NANOCLR_FAULT_ON_EARLY_COLLECTION( ptr##Next ); + +#define NANOCLR_FOREACH_NODE__DIRECT(cls,ptr,startNode) \ + { \ + cls* ptr; \ + cls* ptr##Next; \ + \ + for(ptr = (cls*)(startNode); (ptr##Next = (cls*)ptr->Next()) != NULL; ptr = ptr##Next) \ + { NANOCLR_FAULT_ON_EARLY_COLLECTION( ptr##Next ); + +#define NANOCLR_FOREACH_NODE_PREPARE_RELOAD(ptr) \ + NANOCLR_CANCEL_EARLY_COLLECTION(ptr##Next) + +#define NANOCLR_FOREACH_NODE_RELOAD(cls,ptr) \ + ptr##Next = (cls*)ptr->Next() + +#define NANOCLR_FOREACH_NODE_RESTART(cls,ptr,lst) \ + ptr##Next = (cls*)(lst).FirstNode(); continue + +#define NANOCLR_FOREACH_NODE_END() \ + } \ + } + + +#define NANOCLR_FOREACH_NODE_BACKWARD(cls,ptr,lst) \ + { \ + cls* ptr; \ + cls* ptr##Prev; \ + \ + for(ptr = (cls*)(lst).LastNode(); (ptr##Prev = (cls*)ptr->Prev()) != NULL; ptr = ptr##Prev) \ + { NANOCLR_FAULT_ON_EARLY_COLLECTION( ptr##Prev ); + +#define NANOCLR_FOREACH_NODE_BACKWARD__NODECL(cls,ptr,lst) \ + { \ + cls* ptr##Prev; \ + \ + for(ptr = (cls*)(lst).LastNode(); (ptr##Prev = (cls*)ptr->Prev()) != NULL; ptr = ptr##Prev) \ + { NANOCLR_FAULT_ON_EARLY_COLLECTION( ptr##Prev ); + +#define NANOCLR_FOREACH_NODE_BACKWARD__DIRECT(cls,ptr,startNode) \ + { \ + cls* ptr; \ + cls* ptr##Prev; \ + \ + for(ptr = (cls*)(startNode); (ptr##Prev = (cls*)ptr->Prev()) != NULL; ptr = ptr##Prev) \ + { NANOCLR_FAULT_ON_EARLY_COLLECTION( ptr##Prev ); + +#define NANOCLR_FOREACH_NODE_BACKWARD_RESTART(cls,ptr,lst) \ + ptr##Prev = (cls*)(lst).LastNode(); continue + +#define NANOCLR_FOREACH_NODE_BACKWARD_PREPARE_RELOAD(ptr) \ + NANOCLR_CANCEL_EARLY_COLLECTION(ptr##Prev) + +#define NANOCLR_FOREACH_NODE_BACKWARD_RELOAD(cls,ptr) \ + ptr##Prev = (cls*)ptr->Prev() + +#define NANOCLR_FOREACH_NODE_BACKWARD_END() \ + } \ + } + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_HeapBlock_Node : public CLR_RT_HeapBlock +{ + friend struct CLR_RT_DblLinkedList; + + void GenericNode_Initialize() + { + ClearData(); + } + + CLR_RT_HeapBlock_Node* Next () const { return m_data.nodeLink.nextBlock; } + CLR_RT_HeapBlock_Node* Prev () const { return m_data.nodeLink.prevBlock; } + + void SetNext( CLR_RT_HeapBlock_Node* next ) { m_data.nodeLink.nextBlock = next; } + void SetPrev( CLR_RT_HeapBlock_Node* prev ) { m_data.nodeLink.prevBlock = prev; } + + // + // The ARM compiler cannot inline these methods, + // it keeps injecting a call to a 4 instruction-long function (arg!!). + // + // So we'll have to use the explicit check... + // + //bool IsValidForward () const { return Next() != NULL; } + //bool IsValidBackward() const { return Prev() != NULL; } + + //--// + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink + void ConsistencyCheck_Nodes( CLR_RT_HeapBlock_Node* prev, CLR_RT_HeapBlock_Node* next ) + { + if( prev && next) return; + if(!prev && !next) return; + + CLR_Debug::Printf( "Bad node!!\r\n" ); + + NANOCLR_DEBUG_STOP(); + } + +#else + + void ConsistencyCheck_Nodes( CLR_RT_HeapBlock_Node* prev, CLR_RT_HeapBlock_Node* next ) {} + +#endif + + void RemoveFromList() + { + CLR_RT_HeapBlock_Node* prev = m_data.nodeLink.prevBlock; + CLR_RT_HeapBlock_Node* next = m_data.nodeLink.nextBlock; + + ConsistencyCheck_Nodes( prev, next ); + + if(prev) prev->m_data.nodeLink.nextBlock = next; + if(next) next->m_data.nodeLink.prevBlock = prev; + } + + void Unlink() + { + CLR_RT_HeapBlock_Node* prev = m_data.nodeLink.prevBlock; + CLR_RT_HeapBlock_Node* next = m_data.nodeLink.nextBlock; + + ConsistencyCheck_Nodes( prev, next ); + + if(prev) prev->m_data.nodeLink.nextBlock = next; + if(next) next->m_data.nodeLink.prevBlock = prev; + + m_data.nodeLink.prevBlock = NULL; + m_data.nodeLink.nextBlock = NULL; + } + + //--// + + void Relocate(); +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +struct CLR_RT_DblLinkedList +{ +private: + // + // Logically, a list starts with a CLR_RT_HeapBlock_Node with only the Next() set and ends with a node with only Prev() set. + // This can be collapsed to have the two nodes overlap. + // + CLR_RT_HeapBlock_Node* m_first; // ANY HEAP - DO RELOCATION - + CLR_RT_HeapBlock_Node* m_null; + CLR_RT_HeapBlock_Node* m_last; // ANY HEAP - DO RELOCATION - + + //--// + +public: + void DblLinkedList_Initialize (); + void DblLinkedList_PushToCache(); + void DblLinkedList_Release (); + + int NumOfNodes (); + + void Relocate (); + + //--// + + CLR_RT_HeapBlock_Node* FirstNode () const { return m_first ; } + CLR_RT_HeapBlock_Node* LastNode () const { return m_last ; } + bool IsEmpty () const { return m_first == Tail(); } + + CLR_RT_HeapBlock_Node* FirstValidNode() const { CLR_RT_HeapBlock_Node* res = m_first; return res->Next() ? res : NULL; } + CLR_RT_HeapBlock_Node* LastValidNode () const { CLR_RT_HeapBlock_Node* res = m_last ; return res->Prev() ? res : NULL; } + + // Check that node pNode is not "dummy" tail or head node. + static bool IsValidListNode( CLR_RT_HeapBlock_Node* pNode ) + { + return pNode->m_data.nodeLink.nextBlock != NULL && pNode->m_data.nodeLink.prevBlock != NULL; + } + + CLR_RT_HeapBlock_Node* Head() const { return (CLR_RT_HeapBlock_Node*)((size_t)&m_first - offsetof(CLR_RT_HeapBlock, m_data.nodeLink.nextBlock)); } + CLR_RT_HeapBlock_Node* Tail() const { return (CLR_RT_HeapBlock_Node*)((size_t)&m_last - offsetof(CLR_RT_HeapBlock, m_data.nodeLink.prevBlock)); } + +#if NANOCLR_VALIDATE_HEAP >= NANOCLR_VALIDATE_HEAP_2_DblLinkedList + void ValidateList(); +#else + void ValidateList() {}; +#endif + + //--// + +private: + void Insert( CLR_RT_HeapBlock_Node* prev, CLR_RT_HeapBlock_Node* next, CLR_RT_HeapBlock_Node* node ) + { + node->m_data.nodeLink.nextBlock = next; + node->m_data.nodeLink.prevBlock = prev; + + next->m_data.nodeLink.prevBlock = node; + prev->m_data.nodeLink.nextBlock = node; + } + +public: + void InsertBeforeNode( CLR_RT_HeapBlock_Node* node, CLR_RT_HeapBlock_Node* nodeNew ) + { + ValidateList(); + + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node->Prev(), node, nodeNew ); + } + } + + void InsertAfterNode( CLR_RT_HeapBlock_Node* node, CLR_RT_HeapBlock_Node* nodeNew ) + { + ValidateList(); + + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node, node->Next(), nodeNew ); + } + } + + void LinkAtFront( CLR_RT_HeapBlock_Node* node ) + { + InsertAfterNode( Head(), node ); + } + + void LinkAtBack( CLR_RT_HeapBlock_Node* node ) + { + InsertBeforeNode( Tail(), node ); + } + + CLR_RT_HeapBlock_Node* ExtractFirstNode() + { + ValidateList(); + + CLR_RT_HeapBlock_Node* node = FirstValidNode(); + + if(node) node->Unlink(); + + return node; + } + + CLR_RT_HeapBlock_Node* ExtractLastNode() + { + ValidateList(); + + CLR_RT_HeapBlock_Node* node = LastValidNode(); + + if(node) node->Unlink(); + + return node; + } + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_DblLinkedList); +}; + + +struct CLR_RT_AVLTree +{ + struct Owner; + + enum Skew + { + SKEW_LEFT = -1, + SKEW_NONE = 0, + SKEW_RIGHT = 1, + }; + + enum Result + { + RES_OK = 0, + RES_BALANCE = 1, + RES_NOTFOUND = 2, + RES_DUPLICATE = 3, + RES_ERROR = 4, + }; + + struct Entry : public CLR_RT_HeapBlock_Node + { + Entry* m_left; + Entry* m_right; + Skew m_skew; + }; + + typedef int (*ComparerFtn)( void* state, Entry* left, Entry* right ); + typedef Entry* (*NewNodeFtn )( void* state, Entry* payload ); + typedef void (*FreeNodeFtn)( void* state, Entry* node ); + typedef void (*ReassignFtn)( void* state, Entry* from, Entry* to ); + + struct OwnerInfo + { + ComparerFtn m_ftn_compare; + NewNodeFtn m_ftn_newNode; + FreeNodeFtn m_ftn_freeNode; + ReassignFtn m_ftn_reassignNode; + void* m_state; + }; + + //--// + + Entry* m_root; + OwnerInfo m_owner; + + //--// + + void Initialize(); + + Result Insert( Entry* newDatum ); + Result Remove( Entry* oldDatum ); + Entry* Find ( Entry* srcDatum ); + +private: + static void RotateLeft ( Entry*& n ); + static void RotateRight ( Entry*& n ); + + static Result LeftGrown ( Entry*& n ); + static Result RightGrown ( Entry*& n ); + + static Result LeftShrunk ( Entry*& n ); + static Result RightShrunk ( Entry*& n ); + + bool FindHighest ( Entry*& n, Entry* target, Result& res ); + bool FindLowest ( Entry*& n, Entry* target, Result& res ); + + Result Insert( Entry*& n, Entry* newDatum ); + Result Remove( Entry*& n, Entry* oldDatum ); +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_HeapBlock_String : public CLR_RT_HeapBlock +{ + static CLR_RT_HeapBlock_String* CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, const char* szText ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, const char* szText, CLR_UINT32 length ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 token , CLR_RT_Assembly* assm ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, const char* szText, CLR_RT_Assembly* assm ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT16* szText, CLR_UINT32 length ); + + static CLR_RT_HeapBlock_String* GetStringEmpty(); +}; + +struct CLR_RT_HeapBlock_Array : public CLR_RT_HeapBlock +{ + CLR_UINT32 m_numOfElements; + CLR_UINT8 m_typeOfElement; + CLR_UINT8 m_sizeOfElement; + CLR_UINT8 m_fReference; + CLR_UINT8 m_pad; + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_TypeDef_Index& cls ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, CLR_RT_Assembly* assm , CLR_UINT32 tk ); + + CLR_UINT8* GetFirstElement() { return ((CLR_UINT8*)&this[ 1 ]); } + + CLR_UINT8* GetElement( CLR_UINT32 index ) { return GetFirstElement() + m_sizeOfElement * index; } + + CLR_UINT16* GetFirstElementUInt16() { return ((CLR_UINT16*)&this[ 1 ]); } + + CLR_UINT16* GetElementUInt16( CLR_UINT32 index ) { return GetFirstElementUInt16() + m_sizeOfElement * index; } + + HRESULT ClearElements( int index, int length ); + + //--// + + void Relocate(); + + //--// + + static bool CheckRange( int index, int length, int numOfElements ); + + static HRESULT IndexOf( CLR_RT_HeapBlock_Array* array, CLR_RT_HeapBlock& match, int start, int stop, bool fForward, int& index ); + static HRESULT Copy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length ); +}; + +struct CLR_RT_HeapBlock_Delegate : public CLR_RT_HeapBlock_Node // OBJECT HEAP - DO RELOCATION - +{ + CLR_RT_TypeDef_Index m_cls; + CLR_RT_MethodDef_Index m_ftn; +#if defined(NANOCLR_DELEGATE_PRESERVE_STACK) + CLR_UINT32 m_numOfStackFrames; +#endif + CLR_RT_HeapBlock m_object; // ANY HEAP - DO RELOCATION - + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; +#endif + + //--// + + const CLR_RT_MethodDef_Index& DelegateFtn () const { return m_ftn ; } +#if defined(NANOCLR_DELEGATE_PRESERVE_STACK) + CLR_UINT32 DelegateNumOfStackFrames() const { return m_numOfStackFrames ; } + CLR_RT_MethodDef_Index* GetStackFrames() { return (CLR_RT_MethodDef_Index*)&this[ 1 ]; } +#endif + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, const CLR_RT_MethodDef_Index& ftn, CLR_RT_StackFrame* call ); + + void Relocate(); +}; + +struct CLR_RT_HeapBlock_Delegate_List : public CLR_RT_HeapBlock_Node // OBJECT HEAP - DO RELOCATION - +{ + static const CLR_UINT32 c_Weak = 0x00000001; + + CLR_RT_TypeDef_Index m_cls; + CLR_UINT32 m_length; + CLR_UINT32 m_flags; + + CLR_RT_HeapBlock* GetDelegates() { return &this[ 1 ]; } // ANY HEAP - DO RELOCATION - + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_Delegate_List*& list, CLR_UINT32 length ); + + static HRESULT Combine( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateNew, bool fWeak ); + static HRESULT Remove ( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateOld ); + + void Relocate(); + +private: + + static HRESULT Change( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateTarget, bool fCombine, bool fWeak ); + + CLR_RT_HeapBlock* CopyAndCompress( CLR_RT_HeapBlock* src, CLR_RT_HeapBlock* dst, CLR_UINT32 num ); +}; + +//--// + +struct CLR_RT_HeapBlock_BinaryBlob : public CLR_RT_HeapBlock +{ + friend struct CLR_RT_Memory; + + //--// + + CLR_RT_Assembly* m_assembly; + + void* GetData( ) { return (void*)&this[ 1 ] ; } + static CLR_RT_HeapBlock_BinaryBlob* GetBlob( void* data ) { return (CLR_RT_HeapBlock_BinaryBlob*)data - 1; } + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, CLR_RT_MarkingHandler mark, CLR_RT_RelocationHandler relocate, CLR_UINT32 flags ); + + void Release( bool fEvent ); + + void Relocate(); + +private: + static CLR_RT_HeapBlock_BinaryBlob* Allocate( CLR_UINT32 length, CLR_UINT32 flags ); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_ObjectToEvent_Destination : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_DblLinkedList m_references; // EVENT HEAP - NO RELOCATION - list of CLR_RT_ObjectToEvent_Source + + //--// + + void Initialize (); + void CheckAll (); + void SignalAll (); + void DetachAll (); + bool IsReadyForRelease(); + bool ReleaseWhenDead (); +}; + +struct CLR_RT_ObjectToEvent_Source : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_ObjectToEvent_Destination* m_eventPtr; // EVENT HEAP - NO RELOCATION - Pointer to the event referenced. + + CLR_RT_HeapBlock* m_objectPtr; // OBJECT HEAP - DO RELOCATION - Pointer to the object to keep alive. + CLR_RT_HeapBlock* m_referencePtr; // OBJECT HEAP - DO RELOCATION - Pointer to the HeapBlock referencing this structure. + + //--// + + static HRESULT CreateInstance ( CLR_RT_ObjectToEvent_Destination* event, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock& reference ); + static CLR_RT_ObjectToEvent_Source* ExtractInstance( CLR_RT_HeapBlock& reference ); + + void EnsureObjectIsAlive(); + void Detach (); + + void Relocate (); +}; + +//////////////////////////////////////// + +struct CLR_RT_HeapBlock_Button : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + int m_key; + bool m_fPressed; +}; + +//--// + +struct CLR_RT_HeapBlock_Lock : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + struct Owner : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + CLR_RT_SubThread* m_owningSubThread; // EVENT HEAP - NO RELOCATION - + CLR_UINT32 m_recursion; + }; + + CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + + CLR_RT_HeapBlock m_resource; // OBJECT HEAP - DO RELOCATION - + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; // EVENT HEAP - NO RELOCATION - +#endif + + CLR_RT_DblLinkedList m_owners; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Lock::Owner + CLR_RT_DblLinkedList m_requests; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_LockRequest + + //--// + + static HRESULT CreateInstance ( CLR_RT_HeapBlock_Lock*& lock, CLR_RT_Thread* th, CLR_RT_HeapBlock& resource ); + static HRESULT IncrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ); + static HRESULT DecrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth ); + + void DestroyOwner( CLR_RT_SubThread* sth ); + void ChangeOwner ( ); + + void Relocate (); + void Relocate_Owner(); +}; + +struct CLR_RT_HeapBlock_LockRequest : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_SubThread* m_subthreadWaiting; // EVENT HEAP - NO RELOCATION - + CLR_INT64 m_timeExpire; + bool m_fForce; + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ); +}; + +struct CLR_RT_HeapBlock_Timer : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + static const CLR_UINT32 c_NoFixedChange = 0x00000000; + static const CLR_UINT32 c_SecondChange = 0x00000001; + static const CLR_UINT32 c_MinuteChange = 0x00000002; + static const CLR_UINT32 c_HourChange = 0x00000003; + static const CLR_UINT32 c_DayChange = 0x00000004; + static const CLR_UINT32 c_TimeZoneChange = 0x00000005; + static const CLR_UINT32 c_SetTimeChange = 0x00000006; + static const CLR_UINT32 c_AnyChange = 0x0000000F; + + static const CLR_UINT32 c_Triggered = 0x00000010; + static const CLR_UINT32 c_Executing = 0x00000020; + + static const CLR_UINT32 c_ACTION_Create = 0x00010000; + static const CLR_UINT32 c_ACTION_Change = 0x00020000; + static const CLR_UINT32 c_ACTION_Destroy = 0x00040000; + static const CLR_UINT32 c_UNUSED_00080000 = 0x00080000; + + static const CLR_UINT32 c_INPUT_Int32 = 0x00100000; + static const CLR_UINT32 c_INPUT_TimeSpan = 0x00200000; + + static const CLR_UINT32 c_UNUSED_10000000 = 0x10000000; + static const CLR_UINT32 c_Recurring = 0x40000000; + static const CLR_UINT32 c_EnabledTimer = 0x80000000; + + //--// + + static const CLR_INT32 c_TickPerMillisecond = 10000; + //--// + + CLR_UINT32 m_flags; + CLR_INT64 m_timeExpire; + CLR_INT64 m_timeFrequency; + CLR_INT64 m_timeLastExpiration; + CLR_INT64 m_ticksLastExpiration; + + //--// + + static HRESULT CreateInstance ( CLR_UINT32 flags, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& tmRef ); + static HRESULT ExtractInstance( CLR_RT_HeapBlock& ref , CLR_RT_HeapBlock_Timer*& timer ); + static HRESULT ConfigureObject( CLR_RT_StackFrame& stack, CLR_UINT32 flags ); + static bool CheckDisposed ( CLR_RT_StackFrame& stack ); + + void AdjustNextFixedExpire( const SYSTEMTIME& systemTime, bool fNext ); + + void Trigger (); + void Reschedule (); + void RecoverFromGC(); + void SpawnTimer ( CLR_RT_Thread* thread ); + + static void ThreadTerminationCallback( void* param ); +}; + +struct CLR_RT_HeapBlock_EndPoint : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + struct Port + { + CLR_UINT32 m_type; + CLR_UINT32 m_id; + + bool Compare( const Port& port ); + }; + + struct Address + { + CLR_UINT32 m_seq; + Port m_from; + Port m_to; + }; + + + struct Message : public CLR_RT_HeapBlock_Node + { + CLR_UINT32 m_cmd; + Address m_addr; + + CLR_UINT32 m_found; + CLR_UINT32 m_length; + + CLR_UINT8 m_data[ 1 ]; + }; + + Port m_addr; + CLR_RT_DblLinkedList m_messages; + CLR_UINT32 m_seq; + + //--// + + static CLR_RT_DblLinkedList m_endPoints; + + static void HandlerMethod_Initialize (); + static void HandlerMethod_RecoverFromGC(); + static void HandlerMethod_CleanUp (); + + static CLR_RT_HeapBlock_EndPoint* FindEndPoint( const CLR_RT_HeapBlock_EndPoint::Port& port ); + + static HRESULT CreateInstance ( const CLR_RT_HeapBlock_EndPoint::Port& port, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& epRef ); + static HRESULT ExtractInstance( CLR_RT_HeapBlock& ref , CLR_RT_HeapBlock_EndPoint*& endPoint ); + + bool ReleaseWhenDeadEx(); + void RecoverFromGC (); + + Message* FindMessage( CLR_UINT32 cmd, const CLR_UINT32* seq ); +}; + +//--// + +struct CLR_RT_HeapBlock_WaitForObject : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_INT64 m_timeExpire; + CLR_UINT32 m_cObjects; + bool m_fWaitAll; + + CLR_RT_HeapBlock* GetWaitForObjects() { return &this[ 1 ]; } // EVENT HEAP - DO RELOCATION - + + //--// + + static HRESULT WaitForSignal ( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock& object ); + static HRESULT WaitForSignal ( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ); + static void SignalObject ( CLR_RT_HeapBlock& object ); + + void Relocate(); + +private: + static bool TryWaitForSignal ( CLR_RT_Thread* caller, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ); + static void TryWaitForSignal ( CLR_RT_Thread* caller ); + static HRESULT CreateInstance ( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ); +}; + +//--// + +struct CLR_RT_HeapBlock_Finalizer : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_HeapBlock* m_object; // OBJECT HEAP - DO RELOCATION - + CLR_RT_MethodDef_Index m_md; + +#if defined(NANOCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; +#endif + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock* object, const CLR_RT_TypeDef_Instance& inst ); + + void Relocate(); + + static void SuppressFinalize( CLR_RT_HeapBlock* object ); + +private: + static void RemoveInstance( CLR_RT_HeapBlock* object, CLR_RT_DblLinkedList& lst ); +}; + +//--// + +struct CLR_RT_HeapBlock_MemoryStream : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + struct Buffer : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + static const int c_NumOfBlocks = 32; + static const int c_PayloadSize = c_NumOfBlocks * sizeof(CLR_RT_HeapBlock) - sizeof(CLR_UINT8*) - sizeof(int); + + CLR_UINT8* m_data; + int m_length; + CLR_UINT8 m_payload[ c_PayloadSize ]; + }; + + //--// + + CLR_RT_DblLinkedList m_buffers; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_MemoryStream::Buffer + + Buffer* m_current; + int m_pos; + CLR_UINT32 m_avail; + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_MemoryStream*& stream, CLR_UINT8* buf, int len ); + static void DeleteInstance( CLR_RT_HeapBlock_MemoryStream*& stream ); + + void Release(); + + void Rewind(); + void Reset(); + + HRESULT ToArray ( CLR_RT_HeapBlock& ref ); + + int BitsAvailable(); + int BitsWritten (); + + HRESULT ReadBits ( CLR_UINT32& val, CLR_UINT32 bits ); + HRESULT WriteBits ( CLR_UINT32 val, CLR_UINT32 bits ); + + HRESULT ReadBits ( CLR_UINT64& val, CLR_UINT32 bits ); + HRESULT WriteBits ( CLR_UINT64 val, CLR_UINT32 bits ); + + HRESULT ReadArray ( CLR_UINT8* buf, CLR_UINT32 bytes ); + HRESULT WriteArray( const CLR_UINT8* buf, CLR_UINT32 bytes ); + +private: + + HRESULT Initialize( CLR_UINT8* buf, CLR_UINT32 len ); + + Buffer* NewBuffer(); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_HeapBlock_WeakReference_Identity +{ + CLR_UINT32 m_crc; + CLR_UINT32 m_flags; + CLR_UINT32 m_length; + + CLR_UINT32 m_selectorHash; + CLR_UINT32 m_id; + CLR_INT32 m_priority; + + CLR_UINT32 ComputeCRC( const CLR_UINT8* ptr, CLR_UINT32 len ) const; +}; + +struct CLR_RT_HeapBlock_WeakReference : public CLR_RT_HeapBlock_Node // OBJECT HEAP - DO RELOCATION - +{ + static const CLR_UINT32 WR_SurviveBoot = 0x00000001; + static const CLR_UINT32 WR_SurvivePowerdown = 0x00000002; + static const CLR_UINT32 WR_ArrayOfBytes = 0x00000004; + static const CLR_UINT32 WR_Unused_00000008 = 0x00000008; + static const CLR_UINT32 WR_Unused_00000010 = 0x00000010; + static const CLR_UINT32 WR_Unused_00000020 = 0x00000020; + static const CLR_UINT32 WR_Unused_00000040 = 0x00000040; + static const CLR_UINT32 WR_Unused_00000080 = 0x00000080; + static const CLR_UINT32 WR_Unused_00000100 = 0x00000100; + static const CLR_UINT32 WR_Unused_00000200 = 0x00000200; + static const CLR_UINT32 WR_Unused_00000400 = 0x00000400; + static const CLR_UINT32 WR_Unused_00000800 = 0x00000800; + static const CLR_UINT32 WR_Unused_00001000 = 0x00001000; + static const CLR_UINT32 WR_Unused_00002000 = 0x00002000; + static const CLR_UINT32 WR_Unused_00004000 = 0x00004000; + static const CLR_UINT32 WR_Unused_00008000 = 0x00008000; + static const CLR_UINT32 WR_Unused_00010000 = 0x00010000; + static const CLR_UINT32 WR_Unused_00020000 = 0x00020000; + static const CLR_UINT32 WR_Unused_00040000 = 0x00040000; + static const CLR_UINT32 WR_Unused_00080000 = 0x00080000; + static const CLR_UINT32 WR_Unused_00100000 = 0x00100000; + static const CLR_UINT32 WR_Unused_00200000 = 0x00200000; + static const CLR_UINT32 WR_Unused_00400000 = 0x00400000; + static const CLR_UINT32 WR_Unused_00800000 = 0x00800000; + static const CLR_UINT32 WR_Unused_01000000 = 0x01000000; + static const CLR_UINT32 WR_Unused_02000000 = 0x02000000; + static const CLR_UINT32 WR_Unused_04000000 = 0x04000000; + static const CLR_UINT32 WR_Unused_08000000 = 0x08000000; + static const CLR_UINT32 WR_Unused_10000000 = 0x10000000; + static const CLR_UINT32 WR_Persisted = 0x20000000; + static const CLR_UINT32 WR_Restored = 0x40000000; + + //--// + + CLR_RT_HeapBlock_WeakReference_Identity m_identity; + + CLR_RT_HeapBlock* m_targetDirect; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock_Array* m_targetSerialized; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock_Array* m_targetCopied; // OBJECT HEAP - NO RELOCATION - + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_WeakReference*& weakref ); + + static void RecoverObjects ( CLR_RT_DblLinkedList& lstHeap ); + static bool PrepareForRecovery( CLR_RT_HeapBlock_Node* ptr, CLR_RT_HeapBlock_Node* end, CLR_UINT32 blockSize ); + + HRESULT SetTarget( CLR_RT_HeapBlock& targetReference ); + HRESULT GetTarget( CLR_RT_HeapBlock& targetReference ); + + void InsertInPriorityOrder(); + + void Relocate(); +}; + +//--// + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +struct CLR_RT_Persistence_Manager +{ + static const CLR_UINT32 c_Erased = 0xFFFFFFFF; + + struct ObjectHeader + { + static const CLR_UINT32 c_Version = 0x504F5631; // POV1 = Persisted Object V1 + + static const CLR_UINT32 c_InUseBlock = 0xFFFFFFFF; + static const CLR_UINT32 c_DeletedBlock = 0x00000000; + + CLR_UINT32 m_signature; + CLR_UINT32 m_status; + + CLR_UINT32 m_crcIdentity; + CLR_RT_HeapBlock_WeakReference_Identity m_identity; + + CLR_RT_HeapBlock_Array m_object; + + //--// + + static ObjectHeader* Find( FLASH_WORD* start, FLASH_WORD* end ); + + bool Initialize( CLR_RT_HeapBlock_WeakReference* ref ); + + bool HasGoodSignature() const { return m_signature == c_Version ; } + bool IsInUse () const { return m_status == c_InUseBlock; } + + bool IsGood( bool fIncludeData ) const; + + void Delete(); + + CLR_UINT32 Length( ) const; + static CLR_UINT32 Length( const CLR_RT_HeapBlock_WeakReference* ref ); + static CLR_UINT32 Length( CLR_UINT32 data ); + + ObjectHeader* Next() const; + + private: + CLR_UINT32 ComputeCRC() const; + + //--// + }; + + struct BankHeader + { + static const CLR_UINT32 c_Version = 0x50535631; // PSV1 = Persisted Storage V1 + + static const CLR_UINT32 c_InUseBank = 0xFFFFFFFF; + static const CLR_UINT32 c_DeletedBank = 0x00000000; + + CLR_UINT32 m_signature; + CLR_UINT32 m_status; + + CLR_UINT32 m_sequenceNumber; + + //--// + + static BankHeader* Find( FLASH_WORD* start, FLASH_WORD* end ); + + void Initialize(); + + bool HasGoodSignature() const { return m_signature == c_Version; } + bool IsInUse () const { return m_status == c_InUseBank; } + + bool IsGood() const; + + void Delete(); + + ObjectHeader* FirstObjectHeader() const { return (ObjectHeader*)&this[ 1 ]; } + }; + + struct Bank + { + static const CLR_UINT32 c_SafetyMargin = 10; + + static const FLASH_WORD c_Erased = 0xFFFFFFFF; + static const FLASH_WORD c_Invalidated = 0x00000000; + + //--// + + CLR_UINT32 m_totalBytes; + CLR_UINT32 m_totalSafeBytes; + + BlockStorageStream m_stream; + + BankHeader* m_bankHeader; + + FLASH_WORD* m_start; + FLASH_WORD* m_end; + + FLASH_WORD* m_current; + + //--// + + bool IsGood() const; + + bool Initialize( unsigned int kind ); + + bool Erase ( int& sectorIndex ); + void EraseAll( ); + + bool Format ( ); + bool SetSequence( CLR_UINT32 sequenceNumber ); + + void Switch( Bank& other ); + + CLR_RT_Persistence_Manager::ObjectHeader* RecoverHeader( CLR_RT_HeapBlock_WeakReference* ref ); + bool WriteHeader ( CLR_RT_HeapBlock_WeakReference* ref, ObjectHeader*& pOH, FLASH_WORD*& pData ); + + //--// + + BankHeader* GetBankHeader() const { return m_bankHeader; } + + //--// + + void ReloadNonXIPBufferData(); + + bool WriteNonXIPData(FLASH_WORD* dst, CLR_UINT32 length); + + static bool FindBankWriteNonXIPData(FLASH_WORD* dst, CLR_UINT32 length); + //--// + + static bool CanWrite ( FLASH_WORD* dst, CLR_UINT32 length ); + static bool Write ( FLASH_WORD* dst, const FLASH_WORD* src , CLR_UINT32 length ); + static void Invalidate( FLASH_WORD* dst, FLASH_WORD match, CLR_UINT32 length ); + + static FLASH_WORD* IncrementPointer( FLASH_WORD* ptr, CLR_UINT32 length ) + { + return (FLASH_WORD*)((CLR_UINT8*)ptr + length); + } + static FLASH_WORD* DecrementPointer( FLASH_WORD* ptr, CLR_UINT32 length ) { return (FLASH_WORD*)((CLR_UINT8*)ptr - length); } + }; + + //--// + + static const CLR_UINT32 STATE_FlushNextObject = 0; + static const CLR_UINT32 STATE_Idle = 1; + static const CLR_UINT32 STATE_Erase = 2; + static const CLR_UINT32 STATE_EraseSector = 3; + static const CLR_UINT32 STATE_CopyToOtherBank = 4; + static const CLR_UINT32 STATE_CopyBackToRam = 5; + static const CLR_UINT32 STATE_SwitchBank = 6; + + static const CLR_UINT32 c_MaxWriteBurst = 128; + + //--// + + HAL_COMPLETION m_completion; + + unsigned int m_margin_BurstWrite; + unsigned int m_margin_BlockErase; + + Bank m_bankA; + Bank m_bankB; + + CLR_UINT32 m_state; + + CLR_RT_HeapBlock_WeakReference* m_pending_object; + ObjectHeader* m_pending_header; + CLR_UINT32 m_pending_size; + FLASH_WORD* m_pending_src; + FLASH_WORD* m_pending_dst; + + int m_eraseIndex; + + //--// + + void Initialize(); + void Uninitialize(); + void EraseAll (); + + void InvalidateEntry( CLR_RT_HeapBlock_WeakReference* weak ); + + void Relocate(); + + ObjectHeader* RecoverHeader( CLR_RT_HeapBlock_WeakReference* ref ); + + static void Callback( void* arg ); + + #if !defined(BUILD_RTM) + void GenerateStatistics( CLR_UINT32& totalSize, CLR_UINT32& inUse ); + #endif + + void Flush(); + + //--// + + #undef DECL_POSTFIX + #if defined(NANOCLR_TRACE_PERSISTENCE) + #define DECL_POSTFIX + #else + #define DECL_POSTFIX {} + #endif + + static void Trace_Emit( char* szText ) DECL_POSTFIX; + + static void Trace_Printf( const char* format, ... ) DECL_POSTFIX; + + static void Trace_DumpIdentity( char*& szBuffer, size_t& iBuffer, CLR_RT_HeapBlock_WeakReference_Identity* identity ) DECL_POSTFIX; + + static void Trace_DumpState( const char* szText, FLASH_WORD* dst, ObjectHeader* oh, CLR_RT_HeapBlock_WeakReference* wr ) DECL_POSTFIX; + + //--// + + private: + + bool AdvanceState( bool force ); + + void EnqueueNextCallback(); +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +extern CLR_RT_Persistence_Manager g_CLR_RT_Persistence_Manager; + +//--// + + +struct CLR_RT_ApplicationInterrupt; + +//--// + +//struct GPIO_PortParams +//{ +// GPIO_INT_EDGE m_interruptMode; +// GPIO_RESISTOR m_resistorMode; +// bool m_glitchFilterEnable; +// bool m_initialState; +// bool m_initialDirectionOutput; +// +// //--// +// +// static const CLR_UINT8 c_Input = 0x01; // GPIO_ATTRIBUTE_INPUT +// static const CLR_UINT8 c_Output = 0x02; // GPIO_ATTRIBUTE_OUTPUT +// static const CLR_UINT8 c_AlternateA = 0x04; // GPIO_ATTRIBUTE_ALTERNATE_A +// static const CLR_UINT8 c_AlternateB = 0x08; // GPIO_ATTRIBUTE_ALTERNATE_B +// +// static const CLR_UINT8 c_InterruptDisabled = 0x10; +// static const CLR_UINT8 c_Disposed = 0x20; +//}; + + +struct CLR_RT_HeapBlock_NativeEventDispatcher : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + static void HandlerMethod_Initialize (); + static void HandlerMethod_RecoverFromGC (); + static void HandlerMethod_CleanUp (); + + static CLR_RT_DblLinkedList eventList; + + + struct InterruptPortInterrupt + { + CLR_INT64 time; + CLR_RT_HeapBlock_NativeEventDispatcher* context; + CLR_UINT32 data1; + CLR_UINT32 data2; + CLR_UINT32 data3; + }; + + // Pointer to Hardware driver methods + CLR_RT_DriverInterruptMethods *driverMethods; + //--// + // Pointer to custom data used by device drivers. + void *pDrvCustomData; + + + + //--// + + static HRESULT CreateInstance ( CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& portRef ); + static HRESULT ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_NativeEventDispatcher*& port ); + + HRESULT StartDispatch ( CLR_RT_ApplicationInterrupt* interrupt, CLR_RT_Thread* th ); + HRESULT RecoverManagedObject( CLR_RT_HeapBlock*& port ); + + static void ThreadTerminationCallback( void* arg ); + void SaveToHALQueue( uint32_t data1, uint32_t data2 ); + void RemoveFromHALQueue(); + + void RecoverFromGC (); + bool ReleaseWhenDeadEx(); +}; + +//--// + +struct CLR_RT_ApplicationInterrupt : public CLR_RT_HeapBlock_Node +{ + CLR_RT_HeapBlock_NativeEventDispatcher ::InterruptPortInterrupt m_interruptPortInterrupt; +}; + +//--// + +#define Library_corlib_native_System_Collections_ArrayList__FIELD___items 1 +#define Library_corlib_native_System_Collections_ArrayList__FIELD___size 2 + +struct CLR_RT_HeapBlock_ArrayList : public CLR_RT_HeapBlock +{ +public: + HRESULT GetItem( CLR_INT32 index, CLR_RT_HeapBlock*& value ); + HRESULT SetItem( CLR_INT32 index, CLR_RT_HeapBlock* value ); + + HRESULT Add( CLR_RT_HeapBlock* value, CLR_INT32& index ); + HRESULT Clear(); + HRESULT Insert( CLR_INT32 index, CLR_RT_HeapBlock* value ); + HRESULT RemoveAt( CLR_INT32 index ); + HRESULT SetCapacity( CLR_UINT32 newCapacity ); + + //--// + + __inline CLR_INT32 GetSize() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___size ].NumericByRef().s4; } + +private: + + // Keep in-sync with _defaultCapacity in System.Collections.ArrayList class in ArrayList.cs + static const CLR_INT32 c_DefaultCapacity = 4; + + HRESULT EnsureCapacity( CLR_INT32 min, CLR_INT32 currentCapacity ); + + __inline CLR_RT_HeapBlock_Array* GetItems() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___items ].DereferenceArray(); } + + __inline void SetItems( CLR_RT_HeapBlock_Array* items ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___items ].SetObjectReference( items ); } + __inline void SetSize ( CLR_INT32 size ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___size ].SetInteger ( size ); } +}; + +#if (NANOCLR_SYSTEM_COLLECTIONS == TRUE) + +#define Library_nf_system_collections_System_Collections_Queue__FIELD___array 1 +#define Library_nf_system_collections_System_Collections_Queue__FIELD___head 2 +#define Library_nf_system_collections_System_Collections_Queue__FIELD___tail 3 +#define Library_nf_system_collections_System_Collections_Queue__FIELD___size 4 + +struct CLR_RT_HeapBlock_Queue : public CLR_RT_HeapBlock +{ +public: + HRESULT Dequeue( CLR_RT_HeapBlock*& value ); + HRESULT Enqueue( CLR_RT_HeapBlock* value ); + + HRESULT Peek( CLR_RT_HeapBlock*& value ); + HRESULT Clear(); + + HRESULT CopyTo( CLR_RT_HeapBlock_Array* toArray, CLR_INT32 index ); + + //--// + + __inline CLR_INT32 GetSize() { return ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___size ].NumericByRef().s4; } + +private: + + // Keep in-sync with _defaultCapacity in System.Collections.Queue class in Queue.cs + static const CLR_INT32 c_DefaultCapacity = 4; + + static HRESULT ObjArrayMemcpy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length ); + + __inline CLR_RT_HeapBlock_Array* GetArray() { return ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___array ].DereferenceArray(); } + __inline CLR_INT32 Head () { return ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___head ].NumericByRef().s4; } + __inline CLR_INT32 GetTail () { return ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___tail ].NumericByRef().s4; } + + __inline void SetArray( CLR_RT_HeapBlock_Array* array ) { ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___array ].SetObjectReference( array ); } + __inline void SetHead ( CLR_INT32 head ) { ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___head ].SetInteger ( head ); } + __inline void SetTail ( CLR_INT32 tail ) { ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___tail ].SetInteger ( tail ); } + __inline void SetSize ( CLR_INT32 size ) { ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Queue__FIELD___size ].SetInteger ( size ); } +}; + + +#define Library_nf_system_collections_System_Collections_Stack__FIELD___array 1 +#define Library_nf_system_collections_System_Collections_Stack__FIELD___size 2 + +struct CLR_RT_HeapBlock_Stack : public CLR_RT_HeapBlock +{ +public: + HRESULT Pop( CLR_RT_HeapBlock*& value ); + HRESULT Push( CLR_RT_HeapBlock* value ); + + HRESULT Peek( CLR_RT_HeapBlock*& value ); + HRESULT Clear(); + + //--// + + __inline CLR_INT32 GetSize() { return ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Stack__FIELD___size ].NumericByRef().s4; } + +protected: + + // Keep in-sync with _defaultCapacity in System.Collections.Stack class in Stack.cs + static const CLR_INT32 c_DefaultCapacity = 4; + + __inline CLR_RT_HeapBlock_Array* GetArray() { return ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Stack__FIELD___array ].DereferenceArray(); } + + __inline void SetArray( CLR_RT_HeapBlock_Array* array ) { ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Stack__FIELD___array ].SetObjectReference( array ); } + __inline void SetSize ( CLR_INT32 size ) { ((CLR_RT_HeapBlock*)this)[ Library_nf_system_collections_System_Collections_Stack__FIELD___size ].SetInteger ( size ); } +}; + +#endif // (NANOCLR_SYSTEM_COLLECTIONS == TRUE) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _NANOCLR_RUNTIME__HEAPBLOCK_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__Serialization.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__Serialization.h new file mode 100644 index 00000000..32fd47d5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Runtime__Serialization.h @@ -0,0 +1,285 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_RUNTIME__SERIALIZATION_H_ +#define _NANOCLR_RUNTIME__SERIALIZATION_H_ + +struct CLR_RT_BinaryFormatter : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + ////////////////////////////////////////////////////////////////// + // + // Keep in sync with definitions in Reflection.cs!!!! + // Keep in sync with definitions in Reflection.cs!!!! + // Keep in sync with definitions in Reflection.cs!!!! + // + static const int TE_L1 = 2; + static const CLR_UINT32 TE_L1_Null = 0x00000000; + static const CLR_UINT32 TE_L1_Duplicate = 0x00000001; // N bits for the duplicate id. + static const CLR_UINT32 TE_L1_Reference = 0x00000002; // 32 bits for the type. + static const CLR_UINT32 TE_L1_Other = 0x00000003; + + static const int TE_L2 = 2; + static const CLR_UINT32 TE_L2_Primitive = 0x00000000; // 4 bits for the type. + static const CLR_UINT32 TE_L2_Array = 0x00000001; + static const CLR_UINT32 TE_L2_ArrayList = 0x00000002; + static const CLR_UINT32 TE_L2_Other = 0x00000003; + + static const int TE_L3 = 4; + static const CLR_UINT32 TE_L3_Type = 0x00000000; // 32 bits for the type. + static const CLR_UINT32 TE_L3_Reflection = 0x00000001; // CLR_RT_ReflectionDef_Index. Valid in marshaling only. + static const CLR_UINT32 TE_L3_MBRO = 0x00000002; // 32 bits for the pointer to the MBRO class, 32 bits for the pointer to the AppDomain + + static const int TE_ElementType = 4; + static const int TE_ArrayDepth = 4; + + static const CLR_UINT32 c_Flags_None = 0x00000000; + static const CLR_UINT32 c_Flags_Marshal = 0x00000001; + + // + //--// + // + enum SerializationFlags + { + SF_Encrypted = 0x00000001, + SF_Compressed = 0x00000002, // Value uses range compression (max 2^30 values). + SF_Optional = 0x00000004, // If the value cannot be deserialized, skip it. + + SF_PointerNeverNull = 0x00000010, + SF_ElementsNeverNull = 0x00000020, + + SF_FixedType = 0x00000100, + }; + // + struct SerializationHintsAttribute + { + SerializationFlags m_flags; + + int m_arraySize; // -1 == extend to the end of the stream. + + int m_bitPacked; // In bits. + CLR_INT64 m_rangeBias; + CLR_UINT64 m_scale; // For time, it's in ticks. + }; + // + ////////////////////////////////////////////////////////////////// + + struct TypeHandler + { + // + // Type of signatures: + // + // 1) NULL + // + // Invalid for NeverNull + // + // 2) DUPLICATE + // + // Invalid for Sealed/FixedType + NeverNull + // + // 3) PRIMITIVE + // + // optional for FixedType + // PRIMITIVE optional for FixedType + NeverNull + // + // 4) REFERENCE + // + // optional for Sealed/FixedType + // REFERENCE optional for Sealed/FixedType + NeverNull + // + // 5) ARRAYLIST + // + // optional for FixedSize + // ARRAYLIST optional for FixedType + NeverNull + // + // 6) ARRAY + // + // optional for FixedSize + // optional for FixedType + // ARRAY optional for FixedType + NeverNull + // + // 7) REFLECTION + // + // only valid for marshaling + // + // 8) MBRO + // pointer to the DATATYPE_CLASS of the MarshalByRefObject on the object heap + // It is the responsibility of the caller (CLR_RT_AppDomain::MarshalObject) to ensure that + // this pointer is kept alive, and not moved during the marshaling process + // pointer to the AppDomain that this MBRO object lives in. + // It is the responsiblity of the caller (CLR_RT_AppDomain::MarshalObject) to ensure that + // the AppDomain does not get unloaded during the marshaling process. + // + + // Always match type if FixedTyped is specified. + // + static const int c_Signature_Header = 0x01; + static const int c_Signature_Type = 0x02; + static const int c_Signature_Length = 0x04; + + static const int c_Action_None = 0; + static const int c_Action_ObjectData = 1; + static const int c_Action_ObjectFields = 2; + static const int c_Action_ObjectElements = 3; + + //--// + + CLR_RT_HeapBlock* m_value; + SerializationHintsAttribute m_hints; + CLR_RT_TypeDescriptor* m_type; + + CLR_RT_TypeDescriptor* m_typeExpected; + CLR_RT_TypeDescriptor* m_typeForced; + + CLR_RT_BinaryFormatter* m_bf; + + CLR_RT_HeapBlock m_value_tmp; + CLR_RT_TypeDescriptor m_type_tmp; + CLR_RT_TypeDescriptor m_typeExpected_tmp; + CLR_RT_TypeDescriptor m_typeForced_tmp; + +#if defined(NANOCLR_APPDOMAINS) + bool m_fIsMarshalByRefObject; +#endif + + //--// + + HRESULT TypeHandler_Initialize( CLR_RT_BinaryFormatter* bf, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* expected ); + + HRESULT SetValue( CLR_RT_HeapBlock* v ); + + //--// + + int SignatureRequirements(); + + bool CompareTypes( CLR_RT_TypeDescriptor* left, CLR_RT_TypeDescriptor* right ); + + static CLR_DataType GetDataType ( CLR_RT_TypeDescriptor* type ); + static CLR_UINT32 GetSizeOfType( CLR_RT_TypeDescriptor* type ); + static bool GetSignOfType( CLR_RT_TypeDescriptor* type ); + + static CLR_RT_HeapBlock* FixDereference( CLR_RT_HeapBlock* v ); + static CLR_RT_HeapBlock* FixNull ( CLR_RT_HeapBlock* v ); + + //--// + + HRESULT EmitSignature ( int& res ); + HRESULT EmitSignature_Inner( int mask, CLR_RT_TypeDescriptor* type, CLR_RT_HeapBlock* value ); + HRESULT ReadSignature ( int& res ); + HRESULT EmitValue ( int& res ); + HRESULT ReadValue ( int& res ); + + HRESULT TrackObject ( int& res ); + }; + + struct State : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + CLR_RT_BinaryFormatter* m_parent; + + bool m_value_NeedProcessing; + TypeHandler m_value; + + bool m_fields_NeedProcessing; + CLR_RT_TypeDef_Instance m_fields_CurrentClass; + int m_fields_CurrentField; + CLR_RT_HeapBlock* m_fields_Pointer; + + bool m_array_NeedProcessing; + CLR_RT_TypeDescriptor* m_array_ExpectedType; + CLR_RT_TypeDescriptor m_array_ExpectedType_Tmp; + CLR_RT_HeapBlock_Array* m_array; + int m_array_CurrentPos; + int m_array_LastPos; + + //--// + + static HRESULT CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_HeapBlock* type ); + static HRESULT CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* type ); + + void DestroyInstance(); + + HRESULT FindHints( SerializationHintsAttribute& hints, const CLR_RT_TypeDef_Instance& cls ); + HRESULT FindHints( SerializationHintsAttribute& hints, const CLR_RT_FieldDef_Instance& fld ); + + //--// + + HRESULT AssignAndFixBoxing( CLR_RT_HeapBlock& dst ); + + HRESULT GetValue (); + HRESULT SetValueAndDestroyInstance(); + + //--// + + HRESULT Advance (); + HRESULT AdvanceToTheNextField (); + HRESULT AdvanceToTheNextElement(); + }; + + + struct DuplicateTracker : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + CLR_RT_HeapBlock* m_ptr; + CLR_UINT32 m_idx; + }; + + //--// + + CLR_RT_HeapBlock_MemoryStream* m_stream; + CLR_UINT32 m_idx; + CLR_UINT32 m_lastTypeRead; + CLR_RT_DblLinkedList m_duplicates; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::DuplicateTracker + CLR_RT_DblLinkedList m_states; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::State + + bool m_fDeserialize; + CLR_RT_HeapBlock m_value; + CLR_RT_TypeDescriptor m_value_desc; + + CLR_UINT32 m_flags; + + //--// + + static bool SerializationEnabled(); + + static HRESULT CreateInstance( CLR_UINT8* buf, int len, CLR_RT_BinaryFormatter*& res ); + + void DestroyInstance(); + HRESULT Advance (); + + static HRESULT Serialize ( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object , CLR_RT_HeapBlock* cls , CLR_UINT32 flags ); + static HRESULT Deserialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object , CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ); + static HRESULT Deserialize( CLR_RT_HeapBlock& refData, CLR_UINT8* data, CLR_UINT32 size, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ); + + HRESULT TrackDuplicate ( CLR_RT_HeapBlock* object ); + CLR_UINT32 SearchDuplicate( CLR_RT_HeapBlock* object ); + CLR_RT_HeapBlock* GetDuplicate ( CLR_UINT32 idx ); + + //--// + + int BitsAvailable ( ); + + HRESULT ReadBits ( CLR_UINT32& val, int bits ); + HRESULT WriteBits ( CLR_UINT32 val, int bits ); + + HRESULT ReadBits ( CLR_UINT64& val, int bits ); + HRESULT WriteBits ( CLR_UINT64 val, int bits ); + + HRESULT ReadArray ( CLR_UINT8* buf, int bytes ); + HRESULT WriteArray ( const CLR_UINT8* buf, int bytes ); + + HRESULT ReadCompressedUnsigned ( CLR_UINT32& val ); + HRESULT WriteCompressedUnsigned( CLR_UINT32 val ); + + HRESULT ReadType ( CLR_RT_ReflectionDef_Index& val ); + HRESULT WriteType ( const CLR_RT_ReflectionDef_Index& val ); + HRESULT WriteType ( CLR_UINT32 val ); + + //--// + +private: + + static void PrepareForGC( void* data ); +}; + +#endif // _NANOCLR_RUNTIME__SERIALIZATION_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Types.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Types.h new file mode 100644 index 00000000..bae4648d --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Types.h @@ -0,0 +1,1148 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_TYPES_H_ +#define _NANOCLR_TYPES_H_ + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#define FAULT_ON_NULL_HR(ptr,hr) if(!(ptr) ) NANOCLR_SET_AND_LEAVE((hr) ) +#define CHECK_ALLOCATION(ptr) if(!(ptr) ) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY) +#define CHECK_SIZE_RANGE(len) if( len > CLR_RT_HeapBlock::HB_MaxSize) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE ) + +#define FIMPLIES(x,y) ((!(x)) || (y)) +#define FINRANGE(val,lo,hi) (((val) >= (lo)) && ((val) <= (hi))) + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#define NANOCLR_INTEROP_STUB_RETURN(stack) return stack.NotImplementedStub() +#define NANOCLR_SYSTEM_STUB_RETURN() return S_OK +#define NANOCLR_FEATURE_STUB_RETURN() return CLR_E_NOTIMPL + +////////////////////////////////////////////////// + +#define NANOCLR_PARAMCHECK_BEGIN() \ +{ \ + HRESULT hrInner = S_OK; + +#define NANOCLR_PARAMCHECK_POINTER(ptr) \ + { \ + if(ptr == NULL) \ + { \ + hrInner = CLR_E_NULL_REFERENCE; \ + } \ + } + +#define NANOCLR_PARAMCHECK_POINTER_AND_SET(ptr,val) \ + { \ + if(ptr == NULL) \ + { \ + hrInner = CLR_E_NULL_REFERENCE; \ + } \ + else \ + { \ + *ptr = val; \ + } \ + } + +#define NANOCLR_PARAMCHECK_NOTNULL(ptr) \ + { \ + if(ptr == NULL) \ + { \ + hrInner = CLR_E_INVALID_PARAMETER; \ + } \ + } + +#define NANOCLR_PARAMCHECK_STRING_NOT_EMPTY(ptr) \ + { \ + if(ptr == NULL || ptr[ 0 ] == 0) \ + { \ + hrInner = CLR_E_INVALID_PARAMETER; \ + } \ + } + +#define NANOCLR_PARAMCHECK_END() \ + { NANOCLR_CHECK_HRESULT(hrInner); } \ +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_MSC_VER) +#pragma pack(push, NANOCLR_TYPES_H, 4) +#endif + +enum CLR_OPCODE +{ +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) c, +#include "opcode.def" +#undef OPDEF +CEE_COUNT, /* number of instructions and macros pre-defined */ +}; + +#if defined (__GNUC__) +#define __int64 long long +#endif + +typedef unsigned char CLR_UINT8; +typedef unsigned short CLR_UINT16; +typedef unsigned int CLR_UINT32; +typedef unsigned __int64 CLR_UINT64; +typedef signed char CLR_INT8; +typedef signed short CLR_INT16; +typedef signed int CLR_INT32; +typedef signed __int64 CLR_INT64; + +typedef CLR_UINT16 CLR_OFFSET; +typedef CLR_UINT32 CLR_OFFSET_LONG; +typedef CLR_UINT16 CLR_IDX; +typedef CLR_UINT16 CLR_STRING; +typedef CLR_UINT16 CLR_SIG; +typedef const CLR_UINT8* CLR_PMETADATA; + + +//--// +//may need to change later +typedef CLR_INT64 CLR_INT64_TEMP_CAST; +typedef CLR_UINT64 CLR_UINT64_TEMP_CAST; + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) +typedef double CLR_DOUBLE_TEMP_CAST; +#else +typedef CLR_INT64 CLR_DOUBLE_TEMP_CAST; +#endif + +#define CLR_SIG_INVALID 0xFFFF + +enum CLR_LOGICAL_OPCODE +{ + LO_Not = 0x00, + LO_And = 0x01, + LO_Or = 0x02, + LO_Xor = 0x03, + LO_Shl = 0x04, + LO_Shr = 0x05, + + LO_Neg = 0x06, + LO_Add = 0x07, + LO_Sub = 0x08, + LO_Mul = 0x09, + LO_Div = 0x0A, + LO_Rem = 0x0B, + + LO_Box = 0x0C, + LO_Unbox = 0x0D, + + LO_Branch = 0x0E, + LO_Set = 0x0F, + LO_Switch = 0x10, + + LO_LoadFunction = 0x11, + LO_LoadVirtFunction = 0x12, + + LO_Call = 0x13, + LO_CallVirt = 0x14, + LO_Ret = 0x15, + + LO_NewObject = 0x16, + LO_CastClass = 0x17, + LO_IsInst = 0x18, + + LO_Dup = 0x19, + LO_Pop = 0x1A, + + LO_Throw = 0x1B, + LO_Rethrow = 0x1C, + LO_Leave = 0x1D, + LO_EndFinally = 0x1E, + + LO_Convert = 0x1F, + + LO_StoreArgument = 0x20, + LO_LoadArgument = 0x21, + LO_LoadArgumentAddress = 0x22, + + LO_StoreLocal = 0x23, + LO_LoadLocal = 0x24, + LO_LoadLocalAddress = 0x25, + + LO_LoadConstant_I4 = 0x26, + LO_LoadConstant_I8 = 0x27, + LO_LoadConstant_R4 = 0x28, + LO_LoadConstant_R8 = 0x29, + + LO_LoadNull = 0x2A, + LO_LoadString = 0x2B, + LO_LoadToken = 0x2C, + + LO_NewArray = 0x2D, + LO_LoadLength = 0x2E, + + LO_StoreElement = 0x2F, + LO_LoadElement = 0x30, + LO_LoadElementAddress = 0x31, + + LO_StoreField = 0x32, + LO_LoadField = 0x33, + LO_LoadFieldAddress = 0x34, + + LO_StoreStaticField = 0x35, + LO_LoadStaticField = 0x36, + LO_LoadStaticFieldAddress = 0x37, + + LO_StoreIndirect = 0x38, + LO_LoadIndirect = 0x39, + + LO_InitObject = 0x3A, + LO_LoadObject = 0x3B, + LO_CopyObject = 0x3C, + LO_StoreObject = 0x3D, + + LO_Nop = 0x3E, + + LO_EndFilter = 0x3F, + + LO_Unsupported = 0x40, + + LO_FIRST = LO_Not, + LO_LAST = LO_EndFilter, +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +static const CLR_IDX CLR_EmptyIndex = 0xFFFF; +static const CLR_UINT32 CLR_EmptyToken = 0xFFFFFFFF; +static const size_t CLR_MaxStreamSize_AssemblyRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_TypeRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_FieldRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_MethodRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_TypeDef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_FieldDef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_MethodDef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_Attributes = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_TypeSpec = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_Resources = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_ResourcesData = 0xFFFFFFFF; +static const size_t CLR_MaxStreamSize_Strings = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_Signatures = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_ByteCode = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_ResourcesFiles = 0x0000FFFF; + +enum CLR_OpcodeParam +{ + CLR_OpcodeParam_Field = 0, + CLR_OpcodeParam_Method = 1, + CLR_OpcodeParam_Type = 2, + CLR_OpcodeParam_String = 3, + CLR_OpcodeParam_Tok = 4, + CLR_OpcodeParam_Sig = 5, + CLR_OpcodeParam_BrTarget = 6, + CLR_OpcodeParam_ShortBrTarget = 7, + CLR_OpcodeParam_I = 8, + CLR_OpcodeParam_I8 = 9, + CLR_OpcodeParam_None = 10, + CLR_OpcodeParam_R = 11, + CLR_OpcodeParam_Switch = 12, + CLR_OpcodeParam_Var = 13, + CLR_OpcodeParam_ShortI = 14, + CLR_OpcodeParam_ShortR = 15, + CLR_OpcodeParam_ShortVar = 16, +}; + +#define CanCompressOpParamToken(opParam) (opParam >= CLR_OpcodeParam_Field && opParam <= CLR_OpcodeParam_String) +#define IsOpParamToken(opParam) (opParam >= CLR_OpcodeParam_Field && opParam <= CLR_OpcodeParam_Sig) + +//--// + +enum CLR_FlowControl +{ + CLR_FlowControl_NEXT = 0, + CLR_FlowControl_CALL = 1, + CLR_FlowControl_RETURN = 2, + CLR_FlowControl_BRANCH = 3, + CLR_FlowControl_COND_BRANCH = 4, + CLR_FlowControl_THROW = 5, + CLR_FlowControl_BREAK = 6, + CLR_FlowControl_META = 7, +}; + +//--// + +#define c_CLR_StringTable_Version 1 + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +enum CLR_TABLESENUM +{ + TBL_AssemblyRef = 0x00000000, + TBL_TypeRef = 0x00000001, + TBL_FieldRef = 0x00000002, + TBL_MethodRef = 0x00000003, + TBL_TypeDef = 0x00000004, + TBL_FieldDef = 0x00000005, + TBL_MethodDef = 0x00000006, + TBL_Attributes = 0x00000007, + TBL_TypeSpec = 0x00000008, + TBL_Resources = 0x00000009, + TBL_ResourcesData = 0x0000000A, + TBL_Strings = 0x0000000B, + TBL_Signatures = 0x0000000C, + TBL_ByteCode = 0x0000000D, + TBL_ResourcesFiles = 0x0000000E, + TBL_EndOfAssembly = 0x0000000F, + TBL_Max = 0x00000010, +}; + +enum CLR_CorCallingConvention +{ + ///////////////////////////////////////////////////////////////////////////////////////////// + // + // This is based on CorCallingConvention. + // + PIMAGE_CEE_CS_CALLCONV_DEFAULT = 0x0, + + PIMAGE_CEE_CS_CALLCONV_VARARG = 0x5, + PIMAGE_CEE_CS_CALLCONV_FIELD = 0x6, + PIMAGE_CEE_CS_CALLCONV_LOCAL_SIG = 0x7, + PIMAGE_CEE_CS_CALLCONV_PROPERTY = 0x8, + PIMAGE_CEE_CS_CALLCONV_UNMGD = 0x9, + PIMAGE_CEE_CS_CALLCONV_GENERICINST = 0xa, // generic method instantiation + PIMAGE_CEE_CS_CALLCONV_NATIVEVARARG = 0xb, // used ONLY for 64bit vararg PInvoke calls + PIMAGE_CEE_CS_CALLCONV_MAX = 0xc, // first invalid calling convention + + // The high bits of the calling convention convey additional info + PIMAGE_CEE_CS_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits + PIMAGE_CEE_CS_CALLCONV_HASTHIS = 0x20, // Top bit indicates a 'this' parameter + PIMAGE_CEE_CS_CALLCONV_EXPLICITTHIS = 0x40, // This parameter is explicitly in the signature + PIMAGE_CEE_CS_CALLCONV_GENERIC = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) + // + // End of overlap with CorCallingConvention. + // + ///////////////////////////////////////////////////////////////////////////////////////////// +}; + +enum CLR_DataType // KEEP IN SYNC WITH Microsoft.SPOT.DataType!! +{ + DATATYPE_VOID , // 0 bytes + + DATATYPE_BOOLEAN , // 1 byte + DATATYPE_I1 , // 1 byte + DATATYPE_U1 , // 1 byte + + DATATYPE_CHAR , // 2 bytes + DATATYPE_I2 , // 2 bytes + DATATYPE_U2 , // 2 bytes + + DATATYPE_I4 , // 4 bytes + DATATYPE_U4 , // 4 bytes + DATATYPE_R4 , // 4 bytes + + DATATYPE_I8 , // 8 bytes + DATATYPE_U8 , // 8 bytes + DATATYPE_R8 , // 8 bytes + DATATYPE_DATETIME , // 8 bytes // Shortcut for System.DateTime + DATATYPE_TIMESPAN , // 8 bytes // Shortcut for System.TimeSpan + DATATYPE_STRING , + + DATATYPE_LAST_NONPOINTER = DATATYPE_TIMESPAN, // This is the last type that doesn't need to be relocated. + DATATYPE_LAST_PRIMITIVE_TO_PRESERVE = DATATYPE_R8 , // All the above types don't need fix-up on assignment. +#if defined(NANOCLR_NO_ASSEMBLY_STRINGS) + DATATYPE_LAST_PRIMITIVE_TO_MARSHAL = DATATYPE_STRING, // All the above types can be marshaled by assignment. +#else + DATATYPE_LAST_PRIMITIVE_TO_MARSHAL = DATATYPE_TIMESPAN, // All the above types can be marshaled by assignment. +#endif + DATATYPE_LAST_PRIMITIVE = DATATYPE_STRING , // All the above types don't need fix-up on assignment. + + DATATYPE_OBJECT , // Shortcut for System.Object + DATATYPE_CLASS , // CLASS + DATATYPE_VALUETYPE , // VALUETYPE + DATATYPE_SZARRAY , // Shortcut for single dimension zero lower bound array SZARRAY + DATATYPE_BYREF , // BYREF + + //////////////////////////////////////// + + DATATYPE_FREEBLOCK , + DATATYPE_CACHEDBLOCK , + DATATYPE_ASSEMBLY , + DATATYPE_WEAKCLASS , + DATATYPE_REFLECTION , + DATATYPE_ARRAY_BYREF , + DATATYPE_DELEGATE_HEAD , + DATATYPE_DELEGATELIST_HEAD , + DATATYPE_OBJECT_TO_EVENT , + DATATYPE_BINARY_BLOB_HEAD , + + DATATYPE_THREAD , + DATATYPE_SUBTHREAD , + DATATYPE_STACK_FRAME , + DATATYPE_TIMER_HEAD , + DATATYPE_LOCK_HEAD , + DATATYPE_LOCK_OWNER_HEAD , + DATATYPE_LOCK_REQUEST_HEAD , + DATATYPE_WAIT_FOR_OBJECT_HEAD , + DATATYPE_FINALIZER_HEAD , + DATATYPE_MEMORY_STREAM_HEAD , // SubDataType? + DATATYPE_MEMORY_STREAM_DATA , // SubDataType? + + DATATYPE_SERIALIZER_HEAD , // SubDataType? + DATATYPE_SERIALIZER_DUPLICATE , // SubDataType? + DATATYPE_SERIALIZER_STATE , // SubDataType? + + DATATYPE_ENDPOINT_HEAD , + + //These constants are shared by Debugger.dll, and cannot be conditionally compiled away. + //This adds a couple extra bytes to the lookup table. But frankly, the lookup table should probably + //be shrunk to begin with. Most of the datatypes are used just to tag memory. + //For those datatypes, perhaps we should use a subDataType instead (probably what the comments above are about). + + DATATYPE_RADIO_LAST = DATATYPE_ENDPOINT_HEAD + 3, + + DATATYPE_IO_PORT , + DATATYPE_IO_PORT_LAST = DATATYPE_RADIO_LAST + 1, + + DATATYPE_VTU_PORT_LAST = DATATYPE_IO_PORT_LAST + 1, + +#if defined(NANOCLR_APPDOMAINS) + DATATYPE_APPDOMAIN_HEAD , + DATATYPE_TRANSPARENT_PROXY , + DATATYPE_APPDOMAIN_ASSEMBLY , +#endif + DATATYPE_APPDOMAIN_LAST = DATATYPE_VTU_PORT_LAST + 3, + + DATATYPE_FIRST_INVALID , + + // Type modifies. This is exact copy of VALUES ELEMENT_TYPE_* from CorHdr.h + // + + DATATYPE_TYPE_MODIFIER = 0x40, + DATATYPE_TYPE_SENTINEL = 0x01 | DATATYPE_TYPE_MODIFIER, // sentinel for varargs + DATATYPE_TYPE_PINNED = 0x05 | DATATYPE_TYPE_MODIFIER, + DATATYPE_TYPE_R4_HFA = 0x06 | DATATYPE_TYPE_MODIFIER, // used only internally for R4 HFA types + DATATYPE_TYPE_R8_HFA = 0x07 | DATATYPE_TYPE_MODIFIER, // used only internally for R8 HFA types +}; + +enum CLR_ReflectionType +{ + REFLECTION_INVALID = 0x00, + REFLECTION_ASSEMBLY = 0x01, + REFLECTION_TYPE = 0x02, + REFLECTION_TYPE_DELAYED = 0x03, + REFLECTION_CONSTRUCTOR = 0x04, + REFLECTION_METHOD = 0x05, + REFLECTION_FIELD = 0x06, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +inline CLR_UINT32 CLR_DataFromTk( CLR_UINT32 tk ) { return tk & 0x00FFFFFF; } +inline CLR_TABLESENUM CLR_TypeFromTk( CLR_UINT32 tk ) { return (CLR_TABLESENUM)(tk >> 24); } +inline CLR_UINT32 CLR_TkFromType( CLR_TABLESENUM tbl, CLR_UINT32 data ) { return ((((CLR_UINT32)tbl) << 24) & 0xFF000000) | (data & 0x00FFFFFF); } +#if 0 +// Used on LE host to target BE +inline CLR_UINT32 CLR_TkFromType( CLR_TABLESENUM tbl, CLR_UINT32 data ) { return ( ((CLR_UINT32)(tbl) & 0xFF) | (data & 0xFFFFFF00)); } +inline CLR_UINT32 CLR_DataFromTk( CLR_UINT32 tk ) { return tk & 0xFFFFFF00; } +inline CLR_TABLESENUM CLR_TypeFromTk( CLR_UINT32 tk ) { return (CLR_TABLESENUM)(tk&0xFF); } +#endif +//--// + +inline CLR_UINT32 CLR_UncompressStringToken( CLR_UINT32 tk ) +{ + return CLR_TkFromType( TBL_Strings, tk ); +} + +inline CLR_UINT32 CLR_UncompressTypeToken( CLR_UINT32 tk ) +{ + static const CLR_TABLESENUM c_lookup[3] = { TBL_TypeDef, TBL_TypeRef, TBL_TypeSpec }; + return CLR_TkFromType( c_lookup[(tk >> 14) & 3], 0x3fff & tk ); +} + +inline CLR_UINT32 CLR_UncompressFieldToken( CLR_UINT32 tk ) +{ + static const CLR_TABLESENUM c_lookup[2] = { TBL_FieldDef, TBL_FieldRef }; + return CLR_TkFromType( c_lookup[(tk >> 15) & 1], 0x7fff & tk ); +} + +inline CLR_UINT32 CLR_UncompressMethodToken( CLR_UINT32 tk ) +{ + static const CLR_TABLESENUM c_lookup[ 2 ] = { TBL_MethodDef, TBL_MethodRef }; + return CLR_TkFromType( c_lookup[ (tk >> 15) & 1 ], 0x7fff & tk ); +} + +#if defined(_WIN32) + + CLR_UINT32 CLR_ReadTokenCompressed( CLR_PMETADATA& ip, CLR_OPCODE opcode ); + +#endif + +//--// + +HRESULT CLR_CompressTokenHelper( const CLR_TABLESENUM *tables, CLR_UINT16 cTables, CLR_UINT32& tk); + +inline HRESULT CLR_CompressStringToken( CLR_UINT32& tk) +{ + static const CLR_TABLESENUM c_lookup[ 1 ] = { TBL_Strings }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +inline HRESULT CLR_CompressTypeToken( CLR_UINT32& tk ) +{ + static const CLR_TABLESENUM c_lookup[ 3 ] = { TBL_TypeDef, TBL_TypeRef, TBL_TypeSpec }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +inline HRESULT CLR_CompressFieldToken( CLR_UINT32& tk ) +{ + static const CLR_TABLESENUM c_lookup[ 2 ] = { TBL_FieldDef, TBL_FieldRef }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +inline HRESULT CLR_CompressMethodToken( CLR_UINT32& tk ) +{ + static const CLR_TABLESENUM c_lookup[ 2 ] = { TBL_MethodDef, TBL_MethodRef }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +//--// + +inline bool CLR_CompressData( CLR_UINT32 val, CLR_UINT8*& p ) +{ + CLR_UINT8* ptr = p; + + if(val <= 0x7F) + { + *ptr++ = (CLR_UINT8)(val); + } + else if(val <= 0x3FFF) + { + *ptr++ = (CLR_UINT8)((val >> 8) | 0x80); + *ptr++ = (CLR_UINT8)((val ) ); + } + else if(val <= 0x1FFFFFFF) + { + *ptr++ = (CLR_UINT8)((val >> 24) | 0xC0); + *ptr++ = (CLR_UINT8)((val >> 16) ); + *ptr++ = (CLR_UINT8)((val >> 8) ); + *ptr++ = (CLR_UINT8)((val ) ); + } + else + { + return false; + } + + p = ptr; + + return true; +} + +inline CLR_UINT32 CLR_UncompressData( const CLR_UINT8*& p ) +{ + CLR_PMETADATA ptr = p; + CLR_UINT32 val = *ptr++; + // Handle smallest data inline. + if((val & 0x80) == 0x00) // 0??? ???? + { + } + else if((val & 0xC0) == 0x80) // 10?? ???? + { + val = (val & 0x3F) << 8; + val |= (CLR_UINT32)*ptr++ ; + } + else // 110? ???? + { + val = (val & 0x1F) << 24; + val |= (CLR_UINT32)*ptr++ << 16; + val |= (CLR_UINT32)*ptr++ << 8; + val |= (CLR_UINT32)*ptr++ << 0; + } +#if 0 + // Handle smallest data inline. + if((val & 0x80) == 0x00) // 0??? ???? + { + } + else if((val & 0xC0) == 0x80) // 10?? ???? + { + val = (val & 0x3F); + val |= ((CLR_UINT32)*ptr++ <<8); + } + else // 110? ???? + { + val = (val & 0x1F) ; + val |= (CLR_UINT32)*ptr++ << 8; + val |= (CLR_UINT32)*ptr++ << 16; + val |= (CLR_UINT32)*ptr++ << 24; + } + +#endif + + p = ptr; + + return val; +} + +inline CLR_DataType CLR_UncompressElementType( const CLR_UINT8*& p ) +{ + return (CLR_DataType)*p++; +} + +inline CLR_UINT32 CLR_TkFromStream( const CLR_UINT8*& p ) +{ + static const CLR_TABLESENUM c_lookup[ 4 ] = { TBL_TypeDef, TBL_TypeRef, TBL_TypeSpec, TBL_Max }; + + CLR_UINT32 data = CLR_UncompressData( p ); + + return CLR_TkFromType( c_lookup[ data & 3 ], data >> 2 ); +} + +//--//--//--// + +#if defined(__GNUC__) + +#define NANOCLR_READ_UNALIGNED_UINT8(arg,ip) arg = *(const CLR_UINT8 *)ip; ip += sizeof(CLR_UINT8 ) +template __inline void NANOCLR_READ_UNALIGNED_UINT16(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT16)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT16)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); +} +template __inline void NANOCLR_READ_UNALIGNED_UINT32(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT32)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); +} +template __inline void NANOCLR_READ_UNALIGNED_UINT64(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT64)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 32; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 40; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 48; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 56; ip += sizeof(CLR_UINT8); +} + +#define NANOCLR_READ_UNALIGNED_INT8(arg,ip) arg = *(const CLR_INT8 * )ip; ip += sizeof(CLR_INT8 ) +template __inline void NANOCLR_READ_UNALIGNED_INT16(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT16)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT16)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg = (CLR_INT16)arg; +} +template __inline void NANOCLR_READ_UNALIGNED_INT32(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT32)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); + arg = (CLR_INT32)arg; +} +template __inline void NANOCLR_READ_UNALIGNED_INT64(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT64)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 32; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 40; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 48; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 56; ip += sizeof(CLR_UINT8); + arg = (CLR_INT64)arg; +} + + +#elif defined(_MSC_VER) + +#define NANOCLR_READ_UNALIGNED_UINT8(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT8 *)ip; ip += sizeof(CLR_UINT8 ) +#define NANOCLR_READ_UNALIGNED_UINT16(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT16*)ip; ip += sizeof(CLR_UINT16) +#define NANOCLR_READ_UNALIGNED_UINT32(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT32*)ip; ip += sizeof(CLR_UINT32) +#define NANOCLR_READ_UNALIGNED_UINT64(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT64*)ip; ip += sizeof(CLR_UINT64) + +#define NANOCLR_READ_UNALIGNED_INT8(arg,ip) arg = *(__declspec(align(1)) const CLR_INT8 * )ip; ip += sizeof(CLR_INT8 ) +#define NANOCLR_READ_UNALIGNED_INT16(arg,ip) arg = *(__declspec(align(1)) const CLR_INT16* )ip; ip += sizeof(CLR_INT16 ) +#define NANOCLR_READ_UNALIGNED_INT32(arg,ip) arg = *(__declspec(align(1)) const CLR_INT32* )ip; ip += sizeof(CLR_INT32 ) +#define NANOCLR_READ_UNALIGNED_INT64(arg,ip) arg = *(__declspec(align(1)) const CLR_INT64* )ip; ip += sizeof(CLR_INT64 ) + +//--// + +#define NANOCLR_WRITE_UNALIGNED_UINT8(ip,arg) *(__declspec(align(1)) CLR_UINT8 *)ip = arg; ip += sizeof(CLR_UINT8 ) +#define NANOCLR_WRITE_UNALIGNED_UINT16(ip,arg) *(__declspec(align(1)) CLR_UINT16*)ip = arg; ip += sizeof(CLR_UINT16) +#define NANOCLR_WRITE_UNALIGNED_UINT32(ip,arg) *(__declspec(align(1)) CLR_UINT32*)ip = arg; ip += sizeof(CLR_UINT32) +#define NANOCLR_WRITE_UNALIGNED_UINT64(ip,arg) *(__declspec(align(1)) CLR_UINT64*)ip = arg; ip += sizeof(CLR_UINT64) + +#define NANOCLR_WRITE_UNALIGNED_INT8(ip,arg) *(__declspec(align(1)) CLR_INT8 * )ip = arg; ip += sizeof(CLR_INT8 ) +#define NANOCLR_WRITE_UNALIGNED_INT16(ip,arg) *(__declspec(align(1)) CLR_INT16* )ip = arg; ip += sizeof(CLR_INT16 ) +#define NANOCLR_WRITE_UNALIGNED_INT32(ip,arg) *(__declspec(align(1)) CLR_INT32* )ip = arg; ip += sizeof(CLR_INT32 ) +#define NANOCLR_WRITE_UNALIGNED_INT64(ip,arg) *(__declspec(align(1)) CLR_INT64* )ip = arg; ip += sizeof(CLR_INT64 ) + +#else // TODO: __packed is compiler specific... Which compiler is this for? + +#define NANOCLR_READ_UNALIGNED_UINT8(arg,ip) arg = *(__packed CLR_UINT8 *)ip; ip += sizeof(CLR_UINT8 ) +#define NANOCLR_READ_UNALIGNED_UINT16(arg,ip) arg = *(__packed CLR_UINT16*)ip; ip += sizeof(CLR_UINT16) +#define NANOCLR_READ_UNALIGNED_UINT32(arg,ip) arg = *(__packed CLR_UINT32*)ip; ip += sizeof(CLR_UINT32) +#define NANOCLR_READ_UNALIGNED_UINT64(arg,ip) arg = *(__packed CLR_UINT64*)ip; ip += sizeof(CLR_UINT64) +#define NANOCLR_READ_UNALIGNED_INT8(arg,ip) arg = *(__packed CLR_INT8 * )ip; ip += sizeof(CLR_INT8 ) +#define NANOCLR_READ_UNALIGNED_INT16(arg,ip) arg = *(__packed CLR_INT16* )ip; ip += sizeof(CLR_INT16 ) +#define NANOCLR_READ_UNALIGNED_INT32(arg,ip) arg = *(__packed CLR_INT32* )ip; ip += sizeof(CLR_INT32 ) +#define NANOCLR_READ_UNALIGNED_INT64(arg,ip) arg = *(__packed CLR_INT64* )ip; ip += sizeof(CLR_INT64 ) + +//--// + +#define NANOCLR_WRITE_UNALIGNED_UINT8(ip,arg) *(__packed CLR_UINT8 *)ip = arg; ip += sizeof(CLR_UINT8 ) +#define NANOCLR_WRITE_UNALIGNED_UINT16(ip,arg) *(__packed CLR_UINT16*)ip = arg; ip += sizeof(CLR_UINT16) +#define NANOCLR_WRITE_UNALIGNED_UINT32(ip,arg) *(__packed CLR_UINT32*)ip = arg; ip += sizeof(CLR_UINT32) +#define NANOCLR_WRITE_UNALIGNED_UINT64(ip,arg) *(__packed CLR_UINT64*)ip = arg; ip += sizeof(CLR_UINT64) + +#define NANOCLR_WRITE_UNALIGNED_INT8(ip,arg) *(__packed CLR_INT8 * )ip = arg; ip += sizeof(CLR_INT8 ) +#define NANOCLR_WRITE_UNALIGNED_INT16(ip,arg) *(__packed CLR_INT16* )ip = arg; ip += sizeof(CLR_INT16 ) +#define NANOCLR_WRITE_UNALIGNED_INT32(ip,arg) *(__packed CLR_INT32* )ip = arg; ip += sizeof(CLR_INT32 ) +#define NANOCLR_WRITE_UNALIGNED_INT64(ip,arg) *(__packed CLR_INT64* )ip = arg; ip += sizeof(CLR_INT64 ) + +#endif + +//--// +#define NANOCLR_READ_UNALIGNED_OPCODE(op,ip) op = CLR_OPCODE(*ip++); if(op == CEE_PREFIX1) { opcode = CLR_OPCODE(*ip++ + 256); } + +#define NANOCLR_READ_UNALIGNED_COMPRESSED_FIELDTOKEN(arg,ip) NANOCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressFieldToken ( arg ) +#define NANOCLR_READ_UNALIGNED_COMPRESSED_METHODTOKEN(arg,ip) NANOCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressMethodToken( arg ) +#define NANOCLR_READ_UNALIGNED_COMPRESSED_TYPETOKEN(arg,ip) NANOCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressTypeToken ( arg ) +#define NANOCLR_READ_UNALIGNED_COMPRESSED_STRINGTOKEN(arg,ip) NANOCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressStringToken( arg ) + + +//--// + +inline CLR_OPCODE CLR_ReadNextOpcode( CLR_PMETADATA& ip ) +{ + CLR_PMETADATA ptr = ip; + CLR_OPCODE opcode = CLR_OPCODE(*ptr++); + + if(opcode == CEE_PREFIX1) + { + opcode = CLR_OPCODE(*ptr++ + 256); + } + + ip = ptr; + + return opcode; +} + +inline CLR_OPCODE CLR_ReadNextOpcodeCompressed( CLR_PMETADATA& ip ) +{ + CLR_PMETADATA ptr = ip; + CLR_OPCODE opcode = CLR_OPCODE(*ptr++); + + if(opcode == CEE_PREFIX1) + { + opcode = CLR_OPCODE(*ptr++ + 256); + } + + ip = ptr; + + return opcode; +} + +//--// + +#define FETCH_ARG_UINT8(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_UINT8 ( arg, ip ) +#define FETCH_ARG_UINT16(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_UINT16( arg, ip ) +#define FETCH_ARG_UINT32(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_UINT32( arg, ip ) +#define FETCH_ARG_UINT64(arg,ip) CLR_UINT64 arg; NANOCLR_READ_UNALIGNED_UINT64( arg, ip ) + +#define FETCH_ARG_INT8(arg,ip) CLR_INT32 arg; NANOCLR_READ_UNALIGNED_INT8 ( arg, ip ) +#define FETCH_ARG_INT16(arg,ip) CLR_INT32 arg; NANOCLR_READ_UNALIGNED_INT16( arg, ip ) +#define FETCH_ARG_INT32(arg,ip) CLR_INT32 arg; NANOCLR_READ_UNALIGNED_INT32( arg, ip ) +#define FETCH_ARG_INT64(arg,ip) CLR_INT64 arg; NANOCLR_READ_UNALIGNED_INT64( arg, ip ) + +#define FETCH_ARG_COMPRESSED_STRINGTOKEN(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_COMPRESSED_STRINGTOKEN( arg, ip ) +#define FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_COMPRESSED_FIELDTOKEN ( arg, ip ) +#define FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_COMPRESSED_TYPETOKEN ( arg, ip ) +#define FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_COMPRESSED_METHODTOKEN( arg, ip ) +#define FETCH_ARG_TOKEN(arg,ip) CLR_UINT32 arg; NANOCLR_READ_UNALIGNED_UINT32 ( arg, ip ) + +//--// + +#if defined(_WIN32) + + CLR_PMETADATA CLR_SkipBodyOfOpcode ( CLR_PMETADATA ip, CLR_OPCODE opcode ); + CLR_PMETADATA CLR_SkipBodyOfOpcodeCompressed( CLR_PMETADATA ip, CLR_OPCODE opcode ); + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + extern bool CLR_SafeSprintfV( char*& szBuffer, size_t& iBuffer, const char* format, va_list arg ); + extern bool CLR_SafeSprintf ( char*& szBuffer, size_t& iBuffer, const char* format, ... ); + +#if !defined(BUILD_RTM) + +#define NANOCLR_DEBUG_STOP() _ASSERTE(false) + +#else + +#define NANOCLR_DEBUG_STOP() CPU_Reset() + +#endif + +//--// + +struct CLR_Debug +{ + static int PrintfV( const char *format, va_list arg ); + static int Printf ( const char *format, ... ); + static void Emit ( const char *text, int len ); + static void Flush ( ); + + //--// + + typedef int (*OutputHandler)( const char *format, ... ); + +#if defined(_WIN32) + static void RedirectToString( std::string* str ); + static void SaveMessage (std::string str ); +#endif +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RECORD_VERSION +{ + CLR_UINT16 iMajorVersion; + CLR_UINT16 iMinorVersion; + CLR_UINT16 iBuildNumber; + CLR_UINT16 iRevisionNumber; +}; + +struct CLR_RECORD_ASSEMBLY +{ + static const CLR_UINT32 c_Flags_NeedReboot = 0x00000001; + static const CLR_UINT32 c_Flags_Patch = 0x00000002; + + CLR_UINT8 marker[ 8 ]; + // + CLR_UINT32 headerCRC; + CLR_UINT32 assemblyCRC; + CLR_UINT32 flags; + // + CLR_UINT32 nativeMethodsChecksum; + CLR_UINT32 patchEntryOffset; + // + CLR_RECORD_VERSION version; + // + CLR_STRING assemblyName; // TBL_Strings + CLR_UINT16 stringTableVersion; + // + CLR_OFFSET_LONG startOfTables[ TBL_Max ]; + CLR_UINT32 numOfPatchedMethods; + // + //For every table, a number of bytes that were padded to the end of the table + //to align to unsigned long. Each table starts at a unsigned long boundary, and ends + //at a unsigned long boundary. Some of these tables will, by construction, have + //no padding, and all will have values in the range [0-3]. This isn't the most + //compact form to hold this information, but it only costs 16 bytes/assembly. + //Trying to only align some of the tables is just much more hassle than it's worth. + //And, of course, this field also has to be unsigned long-aligned. + CLR_UINT8 paddingOfTables[ ((TBL_Max-1)+3)/4*4 ]; + //--// + + bool GoodHeader () const; + bool GoodAssembly() const; + +#if defined(_WIN32) + void ComputeCRC(); +#endif + + CLR_OFFSET_LONG SizeOfTable( CLR_TABLESENUM tbl ) const { return startOfTables[ tbl+1 ] - startOfTables[ tbl ] - paddingOfTables[ tbl ]; } + + CLR_OFFSET_LONG TotalSize() const { return startOfTables[ TBL_EndOfAssembly ]; } + + //--// + + static CLR_UINT32 ComputeAssemblyHash( const char* name, const CLR_RECORD_VERSION& ver ); +}; + +struct CLR_RECORD_ASSEMBLYREF +{ + CLR_STRING name; // TBL_Strings + CLR_UINT16 pad; + // + CLR_RECORD_VERSION version; +}; + +struct CLR_RECORD_TYPEREF +{ + CLR_STRING name; // TBL_Strings + CLR_STRING nameSpace; // TBL_Strings + // + CLR_IDX scope; // TBL_AssemblyRef | TBL_TypeRef // 0x8000 + CLR_UINT16 pad; +}; + +struct CLR_RECORD_FIELDREF +{ + CLR_STRING name; // TBL_Strings + CLR_IDX container; // TBL_TypeRef + // + CLR_SIG sig; // TBL_Signatures + CLR_UINT16 pad; +}; + +struct CLR_RECORD_METHODREF +{ + CLR_STRING name; // TBL_Strings + CLR_IDX container; // TBL_TypeRef + // + CLR_SIG sig; // TBL_Signatures + CLR_UINT16 pad; +}; + +struct CLR_RECORD_TYPEDEF +{ + static const CLR_UINT16 TD_Scope_Mask = 0x0007; + static const CLR_UINT16 TD_Scope_NotPublic = 0x0000; // Class is not public scope. + static const CLR_UINT16 TD_Scope_Public = 0x0001; // Class is public scope. + static const CLR_UINT16 TD_Scope_NestedPublic = 0x0002; // Class is nested with public visibility. + static const CLR_UINT16 TD_Scope_NestedPrivate = 0x0003; // Class is nested with private visibility. + static const CLR_UINT16 TD_Scope_NestedFamily = 0x0004; // Class is nested with family visibility. + static const CLR_UINT16 TD_Scope_NestedAssembly = 0x0005; // Class is nested with assembly visibility. + static const CLR_UINT16 TD_Scope_NestedFamANDAssem = 0x0006; // Class is nested with family and assembly visibility. + static const CLR_UINT16 TD_Scope_NestedFamORAssem = 0x0007; // Class is nested with family or assembly visibility. + + static const CLR_UINT16 TD_Serializable = 0x0008; + + static const CLR_UINT16 TD_Semantics_Mask = 0x0030; + static const CLR_UINT16 TD_Semantics_Class = 0x0000; + static const CLR_UINT16 TD_Semantics_ValueType = 0x0010; + static const CLR_UINT16 TD_Semantics_Interface = 0x0020; + static const CLR_UINT16 TD_Semantics_Enum = 0x0030; + + static const CLR_UINT16 TD_Abstract = 0x0040; + static const CLR_UINT16 TD_Sealed = 0x0080; + + static const CLR_UINT16 TD_SpecialName = 0x0100; + static const CLR_UINT16 TD_Delegate = 0x0200; + static const CLR_UINT16 TD_MulticastDelegate = 0x0400; + + static const CLR_UINT16 TD_Patched = 0x0800; + + static const CLR_UINT16 TD_BeforeFieldInit = 0x1000; + static const CLR_UINT16 TD_HasSecurity = 0x2000; + static const CLR_UINT16 TD_HasFinalizer = 0x4000; + static const CLR_UINT16 TD_HasAttributes = 0x8000; + + + CLR_STRING name; // TBL_Strings + CLR_STRING nameSpace; // TBL_Strings + // + CLR_IDX extends; // TBL_TypeDef | TBL_TypeRef // 0x8000 + CLR_IDX enclosingType; // TBL_TypeDef + // + CLR_SIG interfaces; // TBL_Signatures + CLR_IDX methods_First; // TBL_MethodDef + // + CLR_UINT8 vMethods_Num; + CLR_UINT8 iMethods_Num; + CLR_UINT8 sMethods_Num; + CLR_UINT8 dataType; + // + CLR_IDX sFields_First; // TBL_FieldDef + CLR_IDX iFields_First; // TBL_FieldDef + // + CLR_UINT8 sFields_Num; + CLR_UINT8 iFields_Num; + CLR_UINT16 flags; + + //--// + + bool IsEnum () const { return (flags & (TD_Semantics_Mask )) == TD_Semantics_Enum; } + bool IsDelegate() const { return (flags & (TD_Delegate | TD_MulticastDelegate)) != 0 ; } +}; + +struct CLR_RECORD_FIELDDEF +{ + static const CLR_UINT16 FD_Scope_Mask = 0x0007; + static const CLR_UINT16 FD_Scope_PrivateScope = 0x0000; // Member not referenceable. + static const CLR_UINT16 FD_Scope_Private = 0x0001; // Accessible only by the parent type. + static const CLR_UINT16 FD_Scope_FamANDAssem = 0x0002; // Accessible by sub-types only in this Assembly. + static const CLR_UINT16 FD_Scope_Assembly = 0x0003; // Accessibly by anyone in the Assembly. + static const CLR_UINT16 FD_Scope_Family = 0x0004; // Accessible only by type and sub-types. + static const CLR_UINT16 FD_Scope_FamORAssem = 0x0005; // Accessibly by sub-types anywhere, plus anyone in assembly. + static const CLR_UINT16 FD_Scope_Public = 0x0006; // Accessibly by anyone who has visibility to this scope. + + static const CLR_UINT16 FD_NotSerialized = 0x0008; // Field does not have to be serialized when type is remoted. + + static const CLR_UINT16 FD_Static = 0x0010; // Defined on type, else per instance. + static const CLR_UINT16 FD_InitOnly = 0x0020; // Field may only be initialized, not written to after init. + static const CLR_UINT16 FD_Literal = 0x0040; // Value is compile time constant. + + static const CLR_UINT16 FD_SpecialName = 0x0100; // field is special. Name describes how. + static const CLR_UINT16 FD_HasDefault = 0x0200; // Field has default. + static const CLR_UINT16 FD_HasFieldRVA = 0x0400; // Field has RVA. + + static const CLR_UINT16 FD_NoReflection = 0x0800; // field does not allow reflection + + static const CLR_UINT16 FD_HasAttributes = 0x8000; + + + CLR_STRING name; // TBL_Strings + CLR_SIG sig; // TBL_Signatures + // + CLR_SIG defaultValue; // TBL_Signatures + CLR_UINT16 flags; +}; + +struct CLR_RECORD_METHODDEF +{ + static const CLR_UINT32 MD_Scope_Mask = 0x00000007; + static const CLR_UINT32 MD_Scope_PrivateScope = 0x00000000; // Member not referenceable. + static const CLR_UINT32 MD_Scope_Private = 0x00000001; // Accessible only by the parent type. + static const CLR_UINT32 MD_Scope_FamANDAssem = 0x00000002; // Accessible by sub-types only in this Assembly. + static const CLR_UINT32 MD_Scope_Assem = 0x00000003; // Accessibly by anyone in the Assembly. + static const CLR_UINT32 MD_Scope_Family = 0x00000004; // Accessible only by type and sub-types. + static const CLR_UINT32 MD_Scope_FamORAssem = 0x00000005; // Accessibly by sub-types anywhere, plus anyone in assembly. + static const CLR_UINT32 MD_Scope_Public = 0x00000006; // Accessibly by anyone who has visibility to this scope. + + static const CLR_UINT32 MD_Static = 0x00000010; // Defined on type, else per instance. + static const CLR_UINT32 MD_Final = 0x00000020; // Method may not be overridden. + static const CLR_UINT32 MD_Virtual = 0x00000040; // Method virtual. + static const CLR_UINT32 MD_HideBySig = 0x00000080; // Method hides by name+sig, else just by name. + + static const CLR_UINT32 MD_VtableLayoutMask = 0x00000100; + static const CLR_UINT32 MD_ReuseSlot = 0x00000000; // The default. + static const CLR_UINT32 MD_NewSlot = 0x00000100; // Method always gets a new slot in the vtable. + static const CLR_UINT32 MD_Abstract = 0x00000200; // Method does not provide an implementation. + static const CLR_UINT32 MD_SpecialName = 0x00000400; // Method is special. Name describes how. + static const CLR_UINT32 MD_NativeProfiled = 0x00000800; + + static const CLR_UINT32 MD_Constructor = 0x00001000; + static const CLR_UINT32 MD_StaticConstructor = 0x00002000; + static const CLR_UINT32 MD_Finalizer = 0x00004000; + + static const CLR_UINT32 MD_DelegateConstructor = 0x00010000; + static const CLR_UINT32 MD_DelegateInvoke = 0x00020000; + static const CLR_UINT32 MD_DelegateBeginInvoke = 0x00040000; + static const CLR_UINT32 MD_DelegateEndInvoke = 0x00080000; + + static const CLR_UINT32 MD_Synchronized = 0x01000000; + static const CLR_UINT32 MD_GloballySynchronized = 0x02000000; + static const CLR_UINT32 MD_Patched = 0x04000000; + static const CLR_UINT32 MD_EntryPoint = 0x08000000; + static const CLR_UINT32 MD_RequireSecObject = 0x10000000; // Method calls another method containing security code. + static const CLR_UINT32 MD_HasSecurity = 0x20000000; // Method has security associate with it. + static const CLR_UINT32 MD_HasExceptionHandlers = 0x40000000; + static const CLR_UINT32 MD_HasAttributes = 0x80000000; + + + CLR_STRING name; // TBL_Strings + CLR_OFFSET RVA; + // + CLR_UINT32 flags; + // + CLR_UINT8 retVal; + CLR_UINT8 numArgs; + CLR_UINT8 numLocals; + CLR_UINT8 lengthEvalStack; + // + CLR_SIG locals; // TBL_Signatures + CLR_SIG sig; // TBL_Signatures +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif +// pragma required here because compiler is not too happy with the cast to CLR_UINT32* from a CLR_UINT16 variable + +struct CLR_RECORD_ATTRIBUTE +{ + CLR_UINT16 ownerType; // one of TBL_TypeDef, TBL_MethodDef, or TBL_FieldDef. + CLR_UINT16 ownerIdx; // TBL_TypeDef | TBL_MethodDef | TBL_FielfDef + CLR_UINT16 constructor; + CLR_SIG data; // TBL_Signatures + + CLR_UINT32 Key() const { return *(CLR_UINT32*)&ownerType; } +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +struct CLR_RECORD_TYPESPEC +{ + CLR_SIG sig; // TBL_Signatures + CLR_UINT16 pad; +}; + +struct CLR_RECORD_EH +{ + static const CLR_UINT16 EH_Catch = 0x0000; + static const CLR_UINT16 EH_CatchAll = 0x0001; + static const CLR_UINT16 EH_Finally = 0x0002; + static const CLR_UINT16 EH_Filter = 0x0003; + + //--// + + CLR_UINT16 mode; + union { + CLR_IDX classToken; // TBL_TypeDef | TBL_TypeRef + CLR_OFFSET filterStart; + }; + CLR_OFFSET tryStart; + CLR_OFFSET tryEnd; + CLR_OFFSET handlerStart; + CLR_OFFSET handlerEnd; + + //--// + + static CLR_PMETADATA ExtractEhFromByteCode( CLR_PMETADATA ipEnd, const CLR_RECORD_EH*& ptrEh, CLR_UINT32& numEh ); + + CLR_UINT32 GetToken() const; +}; + +CT_ASSERT_UNIQUE_NAME( sizeof(CLR_RECORD_EH) == 12, CLR_RECORD_EH ) + +struct CLR_RECORD_RESOURCE_FILE +{ + static const CLR_UINT32 CURRENT_VERSION = 2; + + CLR_UINT32 version; + CLR_UINT32 sizeOfHeader; + CLR_UINT32 sizeOfResourceHeader; + CLR_UINT32 numberOfResources; + CLR_STRING name; // TBL_Strings + CLR_UINT16 pad; + CLR_UINT32 offset; // TBL_Resource +}; + +struct CLR_RECORD_RESOURCE +{ + static const CLR_UINT8 RESOURCE_Invalid = 0x00; + static const CLR_UINT8 RESOURCE_Bitmap = 0x01; + static const CLR_UINT8 RESOURCE_Font = 0x02; + static const CLR_UINT8 RESOURCE_String = 0x03; + static const CLR_UINT8 RESOURCE_Binary = 0x04; + + static const CLR_UINT8 FLAGS_PaddingMask = 0x03; + static const CLR_INT16 SENTINEL_ID = 0x7FFF; + + // + // Sorted on id + // + CLR_INT16 id; + CLR_UINT8 kind; + CLR_UINT8 flags; + CLR_UINT32 offset; +}; + +#if defined(_MSC_VER) +#pragma pack(pop, NANOCLR_TYPES_H) +#endif + +#endif // _NANOCLR_TYPES_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Win32.h b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Win32.h new file mode 100644 index 00000000..b4fae5be --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoCLR_Win32.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOCLR_WIN32_H_ +#define _NANOCLR_WIN32_H_ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void HAL_Windows_FastSleep( signed __int64 ticks ); + +bool HAL_Windows_IsShutdownPending(); + +void HAL_Windows_AcquireGlobalLock(); +void HAL_Windows_ReleaseGlobalLock(); +bool HAL_Windows_HasGlobalLock(); + +unsigned __int64 HAL_Windows_GetPerformanceTicks(); + +void HAL_Windows_Debug_Print( char* szText ); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class HAL_Mutex +{ + CRITICAL_SECTION m_data; + +public: + HAL_Mutex(); + ~HAL_Mutex(); + + //--// + + void Lock (); + void Unlock(); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _NANOCLR_WIN32_H_ + diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoPackStruct.h b/source/native/nf-interpreter/src/CLR/Include/nanoPackStruct.h new file mode 100644 index 00000000..c275b407 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoPackStruct.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#ifndef _NANO_PACKSTRUCT_H_ +#define _NANO_PACKSTRUCT_H_ 1 + +// definition of PACK attribute for structs +#if defined(_MSC_VER) +// VC++ doesn't support this attribute the same way so it's definition ends up being an empty one +// for VC++ the equivalent is #pragma pack +#define __nfpack + +#elif defined(__GNUC__) +#define __nfpack __attribute__((__packed__)) + +#else +#error "Unknow platform. Please add definition for attribute to tell compiler to pack the struct." +#endif + +#endif // _NANO_PACKSTRUCT_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoSupport.h b/source/native/nf-interpreter/src/CLR/Include/nanoSupport.h new file mode 100644 index 00000000..f7b46d0d --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoSupport.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _SUPPORT_NANOSUPPORT_H_ +#define _SUPPORT_NANOSUPPORT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +unsigned int SUPPORT_ComputeCRC(const void* rgBlock, int nLength, unsigned int crc); + +#if defined(__cplusplus) +} +#endif + +#endif // _SUPPORT_NANOSUPPORT_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/nanoWeak.h b/source/native/nf-interpreter/src/CLR/Include/nanoWeak.h new file mode 100644 index 00000000..a4cd9cac --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nanoWeak.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANO_WEAK_H_ +#define _NANO_WEAK_H_ 1 + +// definition of WEAK attribute for stub functions +#if defined(_MSC_VER) +// because VC++ doesn't support this attribute it's definition end up being an empty one +#define __nfweak + +#elif defined(__GNUC__) +#define __nfweak __attribute__((weak)) + +#else +#error "Unknow platform. Please add definition for weak attribute." +#endif + +#endif // _NANO_WEAK_H_ diff --git a/source/native/nf-interpreter/src/CLR/Include/nf_errors_exceptions.h b/source/native/nf-interpreter/src/CLR/Include/nf_errors_exceptions.h new file mode 100644 index 00000000..5d7bd40c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/nf_errors_exceptions.h @@ -0,0 +1,171 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef __NF_ERRORS_H__ +#define __NF_ERRORS_H__ + +#if !defined(WIN32) && !defined(_WIN32) + +typedef int HRESULT; + +// +// Severity values +// + +#define SEVERITY_SUCCESS 0 +#define SEVERITY_ERROR 1 + + +// +// Generic test for success on any status value (non-negative numbers +// indicate success). +// + +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) + +// +// and the inverse +// + +#define FAILED(Status) ((HRESULT)(Status)<0) + + +// +// Success codes +// +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) + + +// +// Return the code +// + +#define HRESULT_CODE(hr) ((hr) & 0xFFFF) + +// +// Return the facility +// + +#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) + +// +// Return the severity +// + +#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) + +// +// Create an HRESULT value from component pieces +// + +#define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + +#endif // !defined(WIN32) && !defined(_WIN32) + +//--// + +// +// These are denormalized HRESULTs, only the 8 most significant bits are set, to allow use of MOV ,# by the compiler. +// + +#define CLR_E_UNKNOWN_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0100, 0x0000 ) +#define CLR_E_UNSUPPORTED_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0200, 0x0000 ) + +#define CLR_E_STACK_OVERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1100, 0x0000 ) +#define CLR_E_STACK_UNDERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1200, 0x0000 ) + +#define CLR_E_ENTRY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x1500, 0x0000 ) +#define CLR_E_ASSM_WRONG_CHECKSUM MAKE_HRESULT( SEVERITY_ERROR , 0x1600, 0x0000 ) +#define CLR_E_ASSM_PATCHING_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x1700, 0x0000 ) +#define CLR_E_SHUTTING_DOWN MAKE_HRESULT( SEVERITY_ERROR , 0x1800, 0x0000 ) +#define CLR_E_OBJECT_DISPOSED MAKE_HRESULT( SEVERITY_ERROR , 0x1900, 0x0000 ) +#define CLR_E_WATCHDOG_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x1A00, 0x0000 ) + +#define CLR_E_NULL_REFERENCE MAKE_HRESULT( SEVERITY_ERROR , 0x2100, 0x0000 ) +#define CLR_E_WRONG_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x2200, 0x0000 ) +#define CLR_E_TYPE_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x2300, 0x0000 ) +#define CLR_E_INVALID_CAST MAKE_HRESULT( SEVERITY_ERROR , 0x2400, 0x0000 ) +#define CLR_E_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2500, 0x0000 ) + +#define CLR_E_SERIALIZATION_VIOLATION MAKE_HRESULT( SEVERITY_ERROR , 0x2700, 0x0000 ) +#define CLR_E_SERIALIZATION_BADSTREAM MAKE_HRESULT( SEVERITY_ERROR , 0x2800, 0x0000 ) +#define CLR_E_INDEX_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2900, 0x0000 ) + +#define CLR_E_DIVIDE_BY_ZERO MAKE_HRESULT( SEVERITY_ERROR , 0x3100, 0x0000 ) + +#define CLR_E_BUSY MAKE_HRESULT( SEVERITY_ERROR , 0x3300, 0x0000 ) + +#define CLR_E_PROCESS_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4100, 0x0000 ) + +#define CLR_E_THREAD_WAITING MAKE_HRESULT( SEVERITY_ERROR , 0x4200, 0x0000 ) + +#define CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4400, 0x0000 ) + +#define CLR_E_APPDOMAIN_EXITED MAKE_HRESULT( SEVERITY_ERROR , 0x4800, 0x0000 ) +#define CLR_E_APPDOMAIN_MARSHAL_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4900, 0x0000 ) +#define CLR_E_NOTIMPL MAKE_HRESULT( SEVERITY_ERROR , 0x4a00, 0x0000 ) + +#define CLR_E_UNKNOWN_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x4d00, 0x0000 ) +#define CLR_E_ARGUMENT_NULL MAKE_HRESULT( SEVERITY_ERROR , 0x4e00, 0x0000 ) +#define CLR_E_IO MAKE_HRESULT( SEVERITY_ERROR , 0x4f00, 0x0000 ) + +#define CLR_E_ENTRYPOINT_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x5000, 0x0000 ) +#define CLR_E_DRIVER_NOT_REGISTERED MAKE_HRESULT( SEVERITY_ERROR , 0x5100, 0x0000 ) + + +// +// Gp IO error codes +// +#define CLR_E_PIN_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x5400, 0x0000 ) +#define CLR_E_PIN_DEAD MAKE_HRESULT( SEVERITY_ERROR , 0x5500, 0x0000 ) +#define CLR_E_INVALID_OPERATION MAKE_HRESULT( SEVERITY_ERROR , 0x5600, 0x0000 ) +#define CLR_E_WRONG_INTERRUPT_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x5700, 0x0000 ) +#define CLR_E_NO_INTERRUPT MAKE_HRESULT( SEVERITY_ERROR , 0x5800, 0x0000 ) +#define CLR_E_DISPATCHER_ACTIVE MAKE_HRESULT( SEVERITY_ERROR , 0x5900, 0x0000 ) + +// +// IO error codes +// (Keep in-sync with IOExceptionErrorCode enum in IOException.cs) +// +#define CLR_E_FILE_IO MAKE_HRESULT( SEVERITY_ERROR , 0x6000, 0x0000 ) +#define CLR_E_INVALID_DRIVER MAKE_HRESULT( SEVERITY_ERROR , 0x6100, 0x0000 ) +#define CLR_E_FILE_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6200, 0x0000 ) +#define CLR_E_DIRECTORY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6300, 0x0000 ) +#define CLR_E_VOLUME_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6400, 0x0000 ) +#define CLR_E_PATH_TOO_LONG MAKE_HRESULT( SEVERITY_ERROR , 0x6500, 0x0000 ) +#define CLR_E_DIRECTORY_NOT_EMPTY MAKE_HRESULT( SEVERITY_ERROR , 0x6600, 0x0000 ) +#define CLR_E_UNAUTHORIZED_ACCESS MAKE_HRESULT( SEVERITY_ERROR , 0x6700, 0x0000 ) +#define CLR_E_PATH_ALREADY_EXISTS MAKE_HRESULT( SEVERITY_ERROR , 0x6800, 0x0000 ) +#define CLR_E_TOO_MANY_OPEN_HANDLES MAKE_HRESULT( SEVERITY_ERROR , 0x6900, 0x0000 ) + +// +// General error codes +// + +#define CLR_E_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x7500, 0x0000 ) +#define CLR_E_BUFFER_TOO_SMALL MAKE_HRESULT( SEVERITY_ERROR , 0x7600, 0x0000 ) +#define CLR_E_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7700, 0x0000 ) +#define CLR_E_HMAC_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7701, 0x0000 ) +#define CLR_E_RESCHEDULE MAKE_HRESULT( SEVERITY_ERROR , 0x7800, 0x0000 ) + +#define CLR_E_OUT_OF_MEMORY MAKE_HRESULT( SEVERITY_ERROR , 0x7A00, 0x0000 ) +#define CLR_E_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_ERROR , 0x7B00, 0x0000 ) + +#define CLR_E_INVALID_PARAMETER MAKE_HRESULT( SEVERITY_ERROR , 0x7D00, 0x0000 ) +#define CLR_E_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x7E00, 0x0000 ) +#define CLR_E_FAIL MAKE_HRESULT( SEVERITY_ERROR , 0x7F00, 0x0000 ) + +//--// + +#define CLR_S_THREAD_EXITED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0100, 0x0000 ) +#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0200, 0x0000 ) +#define CLR_S_NO_READY_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0300, 0x0000 ) +#define CLR_S_NO_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0400, 0x0000 ) +#define CLR_S_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_SUCCESS, 0x0500, 0x0000 ) + + +#endif // __NF_ERRORS_H__ + diff --git a/source/native/nf-interpreter/src/CLR/Include/opcode.def b/source/native/nf-interpreter/src/CLR/Include/opcode.def new file mode 100644 index 00000000..9f909fc3 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/opcode.def @@ -0,0 +1,359 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +/***************************************************************************** + ** ** + ** Opcode.def - COM+ Intrinsic Opcodes and Macros. ** + ** ** + ** This is the master table from which all opcode lists ** + ** are derived. New instructions must be added to this ** + ** table and generators run to produce the lookup tables ** + ** used by the interpreter loop. ** + ** ** + ** Stack Behaviour is describing the number of 4 byte ** + ** slots pushed and Poped. ** + ** ** + *****************************************************************************/ + + +#ifndef __OPCODE_DEF_ +#define __OPCODE_DEF_ + +#define MOOT 0x00 // Marks unused second byte when encoding single +#define STP1 0xFE // Prefix code 1 for Standard Map +#define REFPRE 0xFF // Prefix for Reference Code Encoding +#define RESERVED_PREFIX_START 0xF7 + +#endif + +// If the first byte of the standard encoding is 0xFF, then +// the second byte can be used as 1 byte encoding. Otherwise l b b +// the encoding is two bytes. e y y +// n t t +// g e e +// (unused) t +// Canonical Name String Name Stack Behaviour Operand Params Opcode Kind h 1 2 Control Flow +// ------------------------------------------------------------------------------------------------------------------------------------------------------- +OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) +OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) +OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) +OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) +OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) +OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) +OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) +OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) +OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) +OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) +OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) +OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) +OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) +OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) +OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) +OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) +OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) +OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) +OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) +OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) +OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) +OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) +OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) +OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) +OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) +OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) +OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) +OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) +OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) +OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) +OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) +OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) +OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) +OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) +OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) +OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) +OPDEF(CEE_UNUSED49, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x24, NEXT) +OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) +OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) +OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) +OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) +OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) +OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) +OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) +OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) +OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) +OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) +OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) +OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) +OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) +OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) +OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) +OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) +OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) +OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) +OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) +OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) +OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) +OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) +OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) +OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) +OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) +OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) +OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) +OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) +OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) +OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) +OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) +OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) +OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) +OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) +OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) +OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) +OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) +OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) +OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) +OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) +OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) +OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) +OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) +OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) +OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) +OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) +OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) +OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) +OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) +OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) +OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) +OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) +OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) +OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) +OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) +OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) +OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) +OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) +OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) +OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) +OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) +OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) +OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) +OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) +OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) +OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) +OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) +OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) +OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) +OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) +OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) +OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) +OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) +OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) +OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) +OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) +OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) +OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) +OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) +OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) +OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) +OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) +OPDEF(CEE_UNUSED58, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x77, NEXT) +OPDEF(CEE_UNUSED1, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x78, NEXT) +OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) +OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) +OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) +OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) +OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) +OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) +OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) +OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) +OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) +OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) +OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) +OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) +OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) +OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) +OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) +OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) +OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) +OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) +OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) +OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) +OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) +OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) +OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) +OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) +OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) +OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) +OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) +OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) +OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) +OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) +OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) +OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) +OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) +OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) +OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) +OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) +OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) +OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) +OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) +OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) +OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) +OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) +OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) +OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) +OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) +OPDEF(CEE_UNUSED5, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA6, NEXT) +OPDEF(CEE_UNUSED6, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA7, NEXT) +OPDEF(CEE_UNUSED7, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA8, NEXT) +OPDEF(CEE_UNUSED8, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA9, NEXT) +OPDEF(CEE_UNUSED9, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAA, NEXT) +OPDEF(CEE_UNUSED10, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAB, NEXT) +OPDEF(CEE_UNUSED11, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAC, NEXT) +OPDEF(CEE_UNUSED12, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAD, NEXT) +OPDEF(CEE_UNUSED13, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAE, NEXT) +OPDEF(CEE_UNUSED14, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAF, NEXT) +OPDEF(CEE_UNUSED15, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB0, NEXT) +OPDEF(CEE_UNUSED16, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB1, NEXT) +OPDEF(CEE_UNUSED17, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB2, NEXT) +OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) +OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) +OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) +OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) +OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) +OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) +OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) +OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) +OPDEF(CEE_UNUSED50, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBB, NEXT) +OPDEF(CEE_UNUSED18, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBC, NEXT) +OPDEF(CEE_UNUSED19, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBD, NEXT) +OPDEF(CEE_UNUSED20, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBE, NEXT) +OPDEF(CEE_UNUSED21, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBF, NEXT) +OPDEF(CEE_UNUSED22, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC0, NEXT) +OPDEF(CEE_UNUSED23, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC1, NEXT) +OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) +OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) +OPDEF(CEE_UNUSED24, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC4, NEXT) +OPDEF(CEE_UNUSED25, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC5, NEXT) +OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) +OPDEF(CEE_UNUSED59, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC7, NEXT) +OPDEF(CEE_UNUSED60, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC8, NEXT) +OPDEF(CEE_UNUSED61, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC9, NEXT) +OPDEF(CEE_UNUSED62, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCA, NEXT) +OPDEF(CEE_UNUSED63, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCB, NEXT) +OPDEF(CEE_UNUSED64, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCC, NEXT) +OPDEF(CEE_UNUSED65, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCD, NEXT) +OPDEF(CEE_UNUSED66, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCE, NEXT) +OPDEF(CEE_UNUSED67, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCF, NEXT) +OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) +OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) +OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) +OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) +OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) +OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) +OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) +OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) +OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) +OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) +OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) +OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) +OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) +OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) +OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) +OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) +OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) +OPDEF(CEE_UNUSED26, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE1, NEXT) +OPDEF(CEE_UNUSED27, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE2, NEXT) +OPDEF(CEE_UNUSED28, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE3, NEXT) +OPDEF(CEE_UNUSED29, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE4, NEXT) +OPDEF(CEE_UNUSED30, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE5, NEXT) +OPDEF(CEE_UNUSED31, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE6, NEXT) +OPDEF(CEE_UNUSED32, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE7, NEXT) +OPDEF(CEE_UNUSED33, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE8, NEXT) +OPDEF(CEE_UNUSED34, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE9, NEXT) +OPDEF(CEE_UNUSED35, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEA, NEXT) +OPDEF(CEE_UNUSED36, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEB, NEXT) +OPDEF(CEE_UNUSED37, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEC, NEXT) +OPDEF(CEE_UNUSED38, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xED, NEXT) +OPDEF(CEE_UNUSED39, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEE, NEXT) +OPDEF(CEE_UNUSED40, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEF, NEXT) +OPDEF(CEE_UNUSED41, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF0, NEXT) +OPDEF(CEE_UNUSED42, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF1, NEXT) +OPDEF(CEE_UNUSED43, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF2, NEXT) +OPDEF(CEE_UNUSED44, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF3, NEXT) +OPDEF(CEE_UNUSED45, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF4, NEXT) +OPDEF(CEE_UNUSED46, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF5, NEXT) +OPDEF(CEE_UNUSED47, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF6, NEXT) +OPDEF(CEE_UNUSED48, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF7, NEXT) +OPDEF(CEE_PREFIX7, "prefix7", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF8, META) +OPDEF(CEE_PREFIX6, "prefix6", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF9, META) +OPDEF(CEE_PREFIX5, "prefix5", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFA, META) +OPDEF(CEE_PREFIX4, "prefix4", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFB, META) +OPDEF(CEE_PREFIX3, "prefix3", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFC, META) +OPDEF(CEE_PREFIX2, "prefix2", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFD, META) +OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) +OPDEF(CEE_PREFIXREF, "prefixref", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFF, META) + +OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) +OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) +OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) +OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) +OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) +OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) +OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) +OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) +OPDEF(CEE_UNUSED56, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x08, NEXT) +OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) +OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) +OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) +OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) +OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) +OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) +OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) +OPDEF(CEE_UNUSED57, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x10, NEXT) +OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) +OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) +OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) +OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) +OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) +OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) +OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) +OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) +OPDEF(CEE_UNUSED69, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x19, NEXT) +OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) +OPDEF(CEE_UNUSED51, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1B, NEXT) +OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) +OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) +OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) +OPDEF(CEE_UNUSED53, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1F, NEXT) +OPDEF(CEE_UNUSED54, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x20, NEXT) +OPDEF(CEE_UNUSED55, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x21, NEXT) +OPDEF(CEE_UNUSED70, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x22, NEXT) + +// These are not real opcodes, but they are handy internally in the EE + +OPDEF(CEE_ILLEGAL, "illegal", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) +OPDEF(CEE_MACRO_END, "endmac", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) + +#ifndef OPALIAS +#define _OPALIAS_DEFINED_ +#define OPALIAS(canonicalName, stringName, realOpcode) +#endif + +OPALIAS(CEE_BRNULL, "brnull", CEE_BRFALSE) +OPALIAS(CEE_BRNULL_S, "brnull.s", CEE_BRFALSE_S) +OPALIAS(CEE_BRZERO, "brzero", CEE_BRFALSE) +OPALIAS(CEE_BRZERO_S, "brzero.s", CEE_BRFALSE_S) +OPALIAS(CEE_BRINST, "brinst", CEE_BRTRUE) +OPALIAS(CEE_BRINST_S, "brinst.s", CEE_BRTRUE_S) +OPALIAS(CEE_LDIND_U8, "ldind.u8", CEE_LDIND_I8) +OPALIAS(CEE_LDELEM_U8, "ldelem.u8", CEE_LDELEM_I8) +OPALIAS(CEE_LDELEM_ANY, "ldelem.any", CEE_LDELEM) +OPALIAS(CEE_STELEM_ANY, "stelem.any", CEE_STELEM) +OPALIAS(CEE_LDC_I4_M1x, "ldc.i4.M1", CEE_LDC_I4_M1) +OPALIAS(CEE_ENDFAULT, "endfault", CEE_ENDFINALLY) + +#ifdef _OPALIAS_DEFINED_ +#undef OPALIAS +#undef _OPALIAS_DEFINED_ +#endif + diff --git a/source/native/nf-interpreter/src/CLR/Include/stdafx.h b/source/native/nf-interpreter/src/CLR/Include/stdafx.h new file mode 100644 index 00000000..d680969b --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Include/stdafx.h @@ -0,0 +1,11 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +//////////////////////////////////////////////////////////////////////////// +// This is header file is empty on purpose. // +// It has to exist here in order to keep Visual Studio C++ compiler happy // +// to use pre-processed headers for WIN32 projects // +//////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj new file mode 100644 index 00000000..5349bd2f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + {2337c4a4-3ab4-4014-9c29-9ebe32f4510e} + false + false + + + + {131001E3-0201-451F-A87B-951D1C5C3EEE} + Win32Proj + Messaging + 10.0.17763.0 + Messaging + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj.filters new file mode 100644 index 00000000..2056f148 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging-vs2019.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging.cpp b/source/native/nf-interpreter/src/CLR/Messaging/Messaging.cpp new file mode 100644 index 00000000..e870e3dd --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging.cpp @@ -0,0 +1,416 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include +#include +#include +#include + +// the Arm 3.0 compiler drags in a bunch of ABI methods (for initialization) if struct arrays are not initialized +CLR_UINT32 g_scratchMessaging[ sizeof(CLR_Messaging) ]; +CLR_Messaging *g_CLR_Messaging; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//--// + +static const CLR_Messaging_CommandHandlerLookup c_Messaging_Lookup_Request[] = +{ + { CLR_Messaging::Messaging_Query, CLR_Messaging_Commands::c_Messaging_Query }, + { CLR_Messaging::Messaging_Send, CLR_Messaging_Commands::c_Messaging_Send }, + { CLR_Messaging::Messaging_Reply, CLR_Messaging_Commands::c_Messaging_Reply }, +}; + +static const CLR_Messaging_CommandHandlerLookup c_Messaging_Lookup_Reply[] = +{ + { CLR_Messaging::Messaging_Query, CLR_Messaging_Commands::c_Messaging_Query }, + { CLR_Messaging::Messaging_Send, CLR_Messaging_Commands::c_Messaging_Send }, + { CLR_Messaging::Messaging_Reply, CLR_Messaging_Commands::c_Messaging_Reply }, +}; + + +//--// + +bool CLR_Messaging::AllocateAndQueueMessage( CLR_UINT32 cmd, unsigned int length, unsigned char* data, CLR_RT_HeapBlock_EndPoint::Port port, CLR_RT_HeapBlock_EndPoint::Address addr, CLR_UINT32 found ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + CLR_RT_HeapBlock_EndPoint::Message* rpc; + CLR_RT_HeapBlock_EndPoint* ep; + + if((ep = CLR_RT_HeapBlock_EndPoint::FindEndPoint( port )) == NULL) return false; + + { + CLR_RT_ProtectFromGC gc( *ep ); + + if((rpc = (CLR_RT_HeapBlock_EndPoint::Message*)CLR_RT_Memory::Allocate( sizeof(*rpc) + length, CLR_RT_HeapBlock::HB_CompactOnFailure )) == NULL) return false; + + rpc->ClearData(); + + rpc->m_cmd = cmd;; + rpc->m_addr = addr; + rpc->m_length = length; + rpc->m_found = found; + + if(data) memcpy( rpc->m_data, data, length ); + + ep->m_messages.LinkAtBack( rpc ); + + g_CLR_RT_ExecutionEngine.SignalEvents( CLR_RT_ExecutionEngine::c_Event_EndPoint ); + } + + return true; +} + + +bool CLR_Messaging::Messaging_Query( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + CLR_Messaging_Commands::Messaging_Query* cmd = (CLR_Messaging_Commands::Messaging_Query*)msg->m_payload; + CLR_Messaging_Commands::Messaging_Query::Reply res; + CLR_RT_HeapBlock_EndPoint* ep = CLR_RT_HeapBlock_EndPoint::FindEndPoint( cmd->m_addr.m_to ); + + res.m_found = (ep != NULL); + res.m_addr = cmd->m_addr; + + WP_ReplyToCommand(msg, true, false, &res, sizeof(res)); + + return true; +} + +bool CLR_Messaging::Messaging_Query__Reply( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + + CLR_Messaging_Commands::Messaging_Query::Reply* cmd = (CLR_Messaging_Commands::Messaging_Query::Reply*)msg->m_payload; + + g_CLR_Messaging->AllocateAndQueueMessage( CLR_Messaging_Commands::c_Messaging_Query, 0, NULL, cmd->m_addr.m_from, cmd->m_addr, cmd->m_found ); + + return true; +} + +//--// + +bool CLR_Messaging::Messaging_Send( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + CLR_Messaging_Commands::Messaging_Send* cmd = (CLR_Messaging_Commands::Messaging_Send*)msg->m_payload; + CLR_Messaging_Commands::Messaging_Send::Reply res; + CLR_UINT32 len; + bool fRes; + + len = msg->m_header.m_size - sizeof(cmd->m_addr); + + fRes = g_CLR_Messaging->AllocateAndQueueMessage( CLR_Messaging_Commands::c_Messaging_Send, len, cmd->m_data, cmd->m_addr.m_to, cmd->m_addr, false ); + + res.m_found = true; + res.m_addr = cmd->m_addr; + + WP_ReplyToCommand( msg, fRes, false, &res, sizeof(res) ); + + return true; +} + +bool CLR_Messaging::Messaging_Send__Reply( WP_Message* msg ) +{ + (void)msg; + + NATIVE_PROFILE_CLR_MESSAGING(); + // + // retransmission support is currently not implemented + // + + return true; +} + +//--// + +bool CLR_Messaging::Messaging_Reply( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + CLR_Messaging_Commands::Messaging_Reply* cmd = (CLR_Messaging_Commands::Messaging_Reply*)msg->m_payload; + CLR_Messaging_Commands::Messaging_Reply::Reply res; + bool fRes; + CLR_UINT32 len; + + len = msg->m_header.m_size - sizeof(cmd->m_addr); + fRes = g_CLR_Messaging->AllocateAndQueueMessage( CLR_Messaging_Commands::c_Messaging_Reply, len, cmd->m_data, cmd->m_addr.m_from, cmd->m_addr, false ); + + res.m_found = true; + res.m_addr = cmd->m_addr; + + WP_ReplyToCommand( msg, fRes, false, &res, sizeof(res) ); + + return true; +} + +bool CLR_Messaging::Messaging_Reply__Reply( WP_Message* msg ) +{ + (void)msg; + + NATIVE_PROFILE_CLR_MESSAGING(); + // + // retransmission support is currently not implemented + // + + return true; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +//--// + +bool CLR_Messaging::App_ProcessHeader( void* state, WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + CLR_Messaging* pThis = (CLR_Messaging*)state; + + Watchdog_Reset(); + + if( !pThis->ProcessHeader( msg ) ) + { + TRACE0("ProcessHeader() indicated invalid header!\n"); + return false; + } + + if(msg->m_header.m_size) + { + void* ptr = CLR_RT_Memory::Allocate( msg->m_header.m_size, CLR_RT_HeapBlock::HB_CompactOnFailure ); + + if(ptr == NULL) + { + TRACE0("Failed to allocate 0x%08X bytes for message payload!\n"); + return false; + } + + msg->m_payload = (unsigned char*)ptr; + } + + return true; +} + +bool CLR_Messaging::App_ProcessPayload( void* state, WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + CLR_Messaging* pThis = (CLR_Messaging*)state; + + Watchdog_Reset(); + + if(pThis->ProcessPayload( msg ) == false) + { + return false; + } + + return true; +} + +bool CLR_Messaging::App_Release( void* state, WP_Message* msg ) +{ + (void)state; + + NATIVE_PROFILE_CLR_MESSAGING(); + if(msg->m_payload != NULL) + { + CLR_RT_Memory::Release( msg->m_payload ); + + msg->m_payload = NULL; + } + + return true; +} + +//--// + + + + + + + + + + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_Messaging::CreateInstance() +{ + NATIVE_PROFILE_CLR_MESSAGING(); + NANOCLR_HEADER(); + + g_CLR_Messaging = (CLR_Messaging*)&g_scratchMessaging[ 0 ]; + + CLR_RT_Memory::ZeroFill( g_CLR_Messaging, sizeof(CLR_Messaging) ); + + g_CLR_Messaging->Initialize( + NULL, + 0, + NULL, + 0 + ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +void CLR_Messaging::Initialize( + const CLR_Messaging_CommandHandlerLookup* requestLookup, + const CLR_UINT32 requestLookupCount, + const CLR_Messaging_CommandHandlerLookup* replyLookup, + const CLR_UINT32 replyLookupCount + ) +{ + if(m_fInitialized) return; + + m_Lookup_Requests[ 0 ].table = c_Messaging_Lookup_Request; + m_Lookup_Requests[ 0 ].size = ARRAYSIZE(c_Messaging_Lookup_Request); + + m_Lookup_Replies[ 0 ].table = c_Messaging_Lookup_Reply; + m_Lookup_Replies[ 0 ].size = ARRAYSIZE(c_Messaging_Lookup_Reply); + + m_port = HalSystemConfig.DebuggerPort; + + m_Lookup_Requests[ 1 ].table = requestLookup; + m_Lookup_Requests[ 1 ].size = requestLookupCount; + + m_Lookup_Replies[ 1 ].table = replyLookup; + m_Lookup_Replies[ 1 ].size = replyLookupCount; + + m_fDebuggerInitialized = (DebuggerPort_Initialize( HalSystemConfig.DebuggerPort ) != false); + + m_fInitialized = true; + +} + +HRESULT CLR_Messaging::DeleteInstance() +{ + NATIVE_PROFILE_CLR_MESSAGING(); + NANOCLR_HEADER(); + + g_CLR_Messaging->Cleanup(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_Messaging::Cleanup() +{ + NATIVE_PROFILE_CLR_MESSAGING(); + + if(!m_fInitialized) return; + + // Some devices cannot reset the USB controller so we need to allow them to skip uninitialization + // of the debug transport + if(!g_fDoNotUninitializeDebuggerPort) + { + DebuggerPort_Uninitialize( m_port ); + } + + m_fDebuggerInitialized = false; + + m_fInitialized = false; +} + +//--// + + + + + + + + + + +bool CLR_Messaging::ProcessHeader( WP_Message* msg ) +{ + (void)msg; + + NATIVE_PROFILE_CLR_MESSAGING(); + TRACE("MSG: 0x%08X\n", msg->m_header.m_cmd ); + return true; +} + +bool CLR_Messaging::ProcessPayload( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + if(msg->m_header.m_flags & WP_Flags_c_NACK) + { + // + // Bad packet... + // + return true; + } + + //--// + + const CLR_Messaging_CommandHandlerLookups* tables; + int tableCount = 0; + + if(msg->m_header.m_flags & WP_Flags_c_Reply) + { + tables = m_Lookup_Replies; + tableCount = ARRAYSIZE(m_Lookup_Replies); + } + else + { + tables = m_Lookup_Requests; + tableCount = ARRAYSIZE(m_Lookup_Requests); + } + + while(tableCount-- > 0) + { + size_t num = tables->size; + const CLR_Messaging_CommandHandlerLookup* cmd = tables->table; + + while(num-- > 0 && cmd != NULL) + { + if(cmd->cmd == msg->m_header.m_cmd) + { + WP_ReplyToCommand(msg, (*(cmd->hnd))( msg ), false, NULL, 0); + return true; + } + + cmd++; + } + tables++; + } + + WP_ReplyToCommand(msg, false, false, NULL, 0); + + return true; +} + +// wrapper function for CLR_Messaging::ProcessPayload( +extern "C" int CLR_Messaging_ProcessPayload(WP_Message* msg) +{ + bool retValue = g_CLR_DBG_Debugger->m_messaging->ProcessPayload(msg); + return retValue; +} + +//--// + +bool CLR_Messaging::SendEvent( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + WP_PrepareAndSendProtocolMessage(cmd, payloadSize, payload, flags); + + // FIXME: returning true to keep compatibility with previous code base + // improve this in a future revision + return true; +} + +void CLR_Messaging::BroadcastEvent( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + WP_PrepareAndSendProtocolMessage(cmd, payloadSize, payload, flags); +} + +//--// diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj b/source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj new file mode 100644 index 00000000..b39a55b6 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + {2337c4a4-3ab4-4014-9c29-9ebe32f4510e} + false + false + + + + {131001E3-0201-451F-A87B-951D1C5C3EEE} + Win32Proj + Messaging + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\CorLib;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj.filters new file mode 100644 index 00000000..2056f148 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.cpp b/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.cpp new file mode 100644 index 00000000..3d93cbfe --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +__nfweak CLR_Messaging *g_CLR_Messaging; + +__nfweak CLR_UINT32 g_scratchMessaging[sizeof(CLR_Messaging) ]; + +__nfweak HRESULT CLR_Messaging::CreateInstance() +{ + NATIVE_PROFILE_CLR_MESSAGING(); + g_CLR_Messaging = (CLR_Messaging*)&g_scratchMessaging[0]; + NANOCLR_SYSTEM_STUB_RETURN(); +} + +__nfweak HRESULT CLR_Messaging::DeleteInstance() +{ + NATIVE_PROFILE_CLR_MESSAGING(); + NANOCLR_SYSTEM_STUB_RETURN(); +} + +__nfweak bool CLR_Messaging::SendEvent( unsigned int cmd, unsigned int payloadSize, unsigned char* payload, unsigned int flags ) +{ + (void)cmd; + (void)payloadSize; + (void)payload; + (void)flags; + + NATIVE_PROFILE_CLR_MESSAGING(); + return true; +} + +__nfweak void CLR_Messaging::Initialize(const CLR_Messaging_CommandHandlerLookup* requestLookup, const CLR_UINT32 requestLookupCount, const CLR_Messaging_CommandHandlerLookup* replyLookup, const CLR_UINT32 replyLookupCount ) +{ + (void)requestLookup; + (void)requestLookupCount; + (void)replyLookup; + (void)replyLookupCount; + + NATIVE_PROFILE_CLR_MESSAGING(); +} + +__nfweak void CLR_Messaging::Cleanup() +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj b/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj new file mode 100644 index 00000000..49e8e57d --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25} + Win32Proj + Messaging_stub + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj.filters new file mode 100644 index 00000000..ca8c8999 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Messaging/Messaging_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Startup/CLRStartup.cpp b/source/native/nf-interpreter/src/CLR/Startup/CLRStartup.cpp new file mode 100644 index 00000000..37ecaa8f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Startup/CLRStartup.cpp @@ -0,0 +1,459 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "CLRStartup.h" +#include +#include +#include +#include +#include + +void ClrExit() +{ + NATIVE_PROFILE_CLR_STARTUP(); + CLR_EE_DBG_SET(ExitPending); +} + +void ClrReboot() +{ + NATIVE_PROFILE_CLR_STARTUP(); + CLR_EE_REBOOT_CLR; + CLR_EE_DBG_SET(RebootPending); +} + +// the CLR Startup code on Windows version is different +#ifndef WIN32 + +struct Settings +{ + CLR_SETTINGS m_clrOptions; + bool m_fInitialized; + + //--// + + HRESULT Initialize(CLR_SETTINGS params) + { + NANOCLR_HEADER(); + + m_clrOptions = params; + + NANOCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CreateInstance()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Created EE.\r\n" ); +#endif + +#if !defined(BUILD_RTM) + if(params.WaitForDebugger) + { + CLR_EE_DBG_SET( Stopped ); + } +#endif + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.StartHardware()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Started Hardware.\r\n" ); +#endif + + m_fInitialized = true; + + NANOCLR_NOCLEANUP(); + } + + HRESULT LoadAssembly( const CLR_RECORD_ASSEMBLY* header, CLR_RT_Assembly*& assm ) + { + NANOCLR_HEADER(); + + const CLR_RT_NativeAssemblyData *pNativeAssmData; + + NANOCLR_CHECK_HRESULT(CLR_RT_Assembly::CreateInstance( header, assm )); + + // Get handlers for native functions in assembly + pNativeAssmData = GetAssemblyNativeData( assm->m_szName ); + + // If pNativeAssmData not NULL- means this assembly has native calls and there is pointer to table with native calls. + if ( pNativeAssmData != NULL ) + { + // First verify that check sum in assembly object matches hardcoded check sum. + if ( assm->m_header->nativeMethodsChecksum != pNativeAssmData->m_checkSum ) + { + CLR_Debug::Printf("\r\n\r\n***********************************************************************\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* ERROR!!!! Firmware version does not match managed code version!!!! *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* Invalid native checksum: %s 0x%08X!=0x%08X *\r\n", + assm->m_szName, + assm->m_header->nativeMethodsChecksum, + pNativeAssmData->m_checkSum + ); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("***********************************************************************\r\n"); + + NANOCLR_SET_AND_LEAVE(CLR_E_ASSM_WRONG_CHECKSUM); + } + + // Assembly has valid pointer to table with native methods. Save it. + assm->m_nativeCode = (const CLR_RT_MethodHandler *)pNativeAssmData->m_pNativeMethods; + } + g_CLR_RT_TypeSystem.Link( assm ); + NANOCLR_NOCLEANUP(); + } + + + HRESULT Load() + { + NANOCLR_HEADER(); + + // clear flag (in case EE wasn't restarted) + CLR_EE_DBG_CLR(StateResolutionFailed); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Create TS.\r\n" ); +#endif + //NANOCLR_CHECK_HRESULT(LoadKnownAssemblies( (char*)&__deployment_start__, (char*)&__deployment_end__ )); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Loading Deployment Assemblies.\r\n" ); +#endif + + NANOCLR_CHECK_HRESULT(LoadDeploymentAssemblies()); + + //--// + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolving.\r\n" ); +#endif + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll()); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.PrepareForExecution()); + +#if defined(NANOCLR_PROFILE_HANDLER) + CLR_PROF_Handler::Calibrate(); +#endif + + NANOCLR_CLEANUP(); + +#if !defined(BUILD_RTM) + if(FAILED(hr)) + { + CLR_Debug::Printf( "Error: %08x\r\n", hr ); + + if(hr == CLR_E_TYPE_UNAVAILABLE) + { + // exception occurred during type resolution + CLR_EE_DBG_SET(StateResolutionFailed); + } + } +#endif + + NANOCLR_CLEANUP_END(); + } + + HRESULT LoadKnownAssemblies( char* start, char* end ) + { + //--// + NANOCLR_HEADER(); + char *assStart = start; + char *assEnd = end; + const CLR_RECORD_ASSEMBLY* header; + +#if !defined(BUILD_RTM) + CLR_Debug::Printf(" Loading start at %x, end %x\r\n", (unsigned int)assStart, (unsigned int)assEnd); +#endif + + g_buildCRC = SUPPORT_ComputeCRC( assStart, (unsigned int)assEnd -(unsigned int) assStart, 0 ); + + + header = (const CLR_RECORD_ASSEMBLY*)assStart; + + while((char*)header + sizeof(CLR_RECORD_ASSEMBLY) < assEnd && header->GoodAssembly()) + { + CLR_RT_Assembly* assm; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + NANOCLR_CHECK_HRESULT(LoadAssembly( header, assm )); + + header = (const CLR_RECORD_ASSEMBLY*)ROUNDTOMULTIPLE((size_t)header + header->TotalSize(), CLR_UINT32); + } + + NANOCLR_NOCLEANUP(); + } + + + HRESULT ContiguousBlockAssemblies(BlockStorageStream stream) + { + NANOCLR_HEADER(); + + const CLR_RECORD_ASSEMBLY* header; + unsigned char* assembliesBuffer; + uint32_t headerInBytes = sizeof(CLR_RECORD_ASSEMBLY); + unsigned char* headerBuffer = NULL; + + // for the context it's being used (read the assemblies) + // XIP and memory mapped block regions are equivalent so they can be ORed + bool isXIP = (stream.Flags & BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP) || + (stream.Flags & BLOCKSTORAGESTREAM_c_BlockStorageStream__MemoryMapped); + + if(!isXIP) + { + headerBuffer = (unsigned char*)platform_malloc(headerInBytes); + + if (headerBuffer == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear the buffer + memset(headerBuffer, 0, headerInBytes); + } + + while(stream.CurrentIndex < stream.Length) + { + // check if there is enough stream length to continue + if((stream.Length - stream.CurrentIndex ) < headerInBytes) + { + // not enough stream to read, leave now + break; + } + + if(!BlockStorageStream_Read(&stream, &headerBuffer, headerInBytes )) + { + // failed to read + break; + } + + header = (const CLR_RECORD_ASSEMBLY*)headerBuffer; + + // check header first before read + if(!header->GoodHeader()) + { + // check failed, try to continue to the next + continue; + } + + unsigned int assemblySizeInByte = ROUNDTOMULTIPLE(header->TotalSize(), CLR_UINT32); + + if(!isXIP) + { + // setup buffer for assembly + ///////////////////////////////////////////////////////////////////////////////////// + // because we need to map to the functions, the assembly needs to remain on memory // + // so platform_free can't be called for this // + ///////////////////////////////////////////////////////////////////////////////////// + assembliesBuffer = (unsigned char*)platform_malloc(assemblySizeInByte); + + if (assembliesBuffer == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear the buffer + memset(assembliesBuffer, 0, assemblySizeInByte); + } + + // advance stream beyond header + BlockStorageStream_Seek(&stream, -headerInBytes, BlockStorageStream_SeekCurrent); + + // read the assembly + if(!BlockStorageStream_Read(&stream, &assembliesBuffer, assemblySizeInByte)) + { + // something wrong with the read, can't continue + break; + } + + header = (const CLR_RECORD_ASSEMBLY*)assembliesBuffer; + + if(!header->GoodAssembly()) + { + // check failed, try to continue to the next + + if(!isXIP && assembliesBuffer != NULL) + { + // release the assembliesBuffer + platform_free(assembliesBuffer); + } + + continue; + } + + // we have good Assembly + CLR_RT_Assembly* assm; + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Attaching deployed file.\r\n" ); +#endif + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + if (FAILED(LoadAssembly(header, assm))) + { + // load failed, try to continue to the next + + if(!isXIP && assembliesBuffer != NULL) + { + // release the assembliesBuffer which has being used and leave + platform_free(assembliesBuffer); + } + + continue; + } + + // load successfull, mark as deployed + assm->m_flags |= CLR_RT_Assembly::Deployed; + } + + if(!isXIP && headerBuffer != NULL) + { + // release the headerbuffer which has being used and leave + platform_free(headerBuffer); + } + + NANOCLR_NOCLEANUP(); + } + + HRESULT LoadDeploymentAssemblies() + { + NANOCLR_HEADER(); + + // perform initialization of BlockStorageStream structure + BlockStorageStream stream; + memset(&stream, 0, sizeof(BlockStorageStream)); + + // init the stream for deployment storage + if (!BlockStorageStream_Initialize(&stream, BlockUsage_DEPLOYMENT)) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "ERROR: failed to initialize DEPLOYMENT storage\r\n" ); +#endif + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + NANOCLR_CHECK_HRESULT(ContiguousBlockAssemblies(stream)); + + NANOCLR_NOCLEANUP(); + } + + void Cleanup() + { + CLR_RT_ExecutionEngine::DeleteInstance(); + + memset( &g_CLR_RT_ExecutionEngine, 0, sizeof(g_CLR_RT_ExecutionEngine)); + memset( &g_CLR_RT_WellKnownTypes, 0, sizeof(g_CLR_RT_WellKnownTypes)); + memset( &g_CLR_RT_WellKnownMethods, 0, sizeof(g_CLR_RT_WellKnownMethods)); + memset( &g_CLR_RT_TypeSystem, 0, sizeof(g_CLR_RT_TypeSystem)); + memset( &g_CLR_RT_EventCache, 0, sizeof(g_CLR_RT_EventCache)); + memset( &g_CLR_RT_GarbageCollector, 0, sizeof(g_CLR_RT_GarbageCollector)); + memset( &g_CLR_HW_Hardware, 0, sizeof(g_CLR_HW_Hardware)); + + m_fInitialized = false; + } + + Settings() + { + m_fInitialized = false; + } + +}; + + +static Settings s_ClrSettings; + +void ClrStartup(CLR_SETTINGS params) +{ + NATIVE_PROFILE_CLR_STARTUP(); + Settings settings; + ASSERT(sizeof(CLR_RT_HeapBlock_Raw) == sizeof(CLR_RT_HeapBlock)); + bool softReboot; + + do + { + softReboot = false; + + CLR_RT_Assembly::InitString(); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "\r\nnanoCLR (Build %d.%d.%d.%d)\r\n\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION ); + CLR_Debug::Printf( "\r\n%s\r\n\r\n", OEMSYSTEMINFOSTRING ); +#endif + + CLR_RT_Memory::Reset(); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Starting...\r\n" ); +#endif + + + HRESULT hr; + + if(SUCCEEDED(hr = s_ClrSettings.Initialize(params))) + { + if(SUCCEEDED(hr = s_ClrSettings.Load())) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Ready.\r\n" ); +#endif + + (void)g_CLR_RT_ExecutionEngine.Execute( NULL, params.MaxContextSwitches ); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Done.\r\n" ); +#endif + } + } + + // process setting of power mode, if reboot was requested along with a power mode "higher" then PowerLevel__Active + if(CLR_EE_REBOOT_IS( ClrOnly ) && g_CLR_HW_Hardware.m_powerLevel > PowerLevel__Active) + { + CPU_SetPowerMode(g_CLR_HW_Hardware.m_powerLevel); + } + + if( CLR_EE_DBG_IS_NOT( RebootPending )) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET_MASK(StateProgramExited, StateMask); + CLR_EE_DBG_EVENT_BROADCAST(CLR_DBG_Commands::c_Monitor_ProgramExit, 0, NULL, WP_Flags_c_NonCritical); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if !defined(BUILD_RTM) + if(params.EnterDebuggerLoopAfterExit) + { + CLR_DBG_Debugger::Debugger_WaitForCommands(); + } +#endif + } + + // DO NOT USE 'ELSE IF' here because the state can change in Debugger_WaitForCommands() call + + if( CLR_EE_DBG_IS( RebootPending )) + { + if(CLR_EE_REBOOT_IS( ClrOnly )) + { + softReboot = true; + + params.WaitForDebugger = CLR_EE_REBOOT_IS(WaitForDebugger); + + s_ClrSettings.Cleanup(); + + nanoHAL_Uninitialize(); + + //re-init the hal for the reboot (initially it is called in bootentry) + nanoHAL_Initialize(); + } + else + { + CPU_Reset(); + } + } + + } while( softReboot ); + + #if !defined(BUILD_RTM) + CLR_Debug::Printf( "Exiting.\r\n" ); + #endif + + CPU_Reset(); +} + +#endif // WIN32 diff --git a/source/native/nf-interpreter/src/CLR/Startup/CLRStartup.h b/source/native/nf-interpreter/src/CLR/Startup/CLRStartup.h new file mode 100644 index 00000000..68b0212c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Startup/CLRStartup.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef __CLRSTARTUP_H__ +#define __CLRSTARTUP_H__ + +///////////////////////////////////////////////////////////////////////////// + +#include +#include +//#include +//#include +//#include +#include +// +//#include +// +//#include +//#include +//#include +//#include +//#include +//#include + +#endif // __CLRSTARTUP_H__ + diff --git a/source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj b/source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj new file mode 100644 index 00000000..0f3388cb --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + {89cf8bdb-9c8a-4d18-bc3e-4312c5bd34b1} + false + false + false + + + + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6} + Win32Proj + StartUp + 10.0.17763.0 + Startup + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj.filters b/source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj.filters new file mode 100644 index 00000000..3c321f80 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/Startup/Startup.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.cpp b/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.cpp new file mode 100644 index 00000000..78101de5 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.cpp @@ -0,0 +1,70 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_native_system_math.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + Library_nf_native_system_math_System_Math::Abs___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Abs___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Acos___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Acos___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Asin___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Asin___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Atan___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Atan___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Atan2___STATIC__R8__R8__R8, + Library_nf_native_system_math_System_Math::Atan2___STATIC__R4__R4__R4, + Library_nf_native_system_math_System_Math::Ceiling___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Ceiling___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Cos___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Cos___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Cosh___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Cosh___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::IEEERemainder___STATIC__R8__R8__R8, + Library_nf_native_system_math_System_Math::IEEERemainder___STATIC__R4__R4__R4, + Library_nf_native_system_math_System_Math::Exp___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Exp___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Floor___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Floor___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Log___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Log___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Log10___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Log10___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Max___STATIC__R8__R8__R8, + Library_nf_native_system_math_System_Math::Max___STATIC__R4__R4__R4, + Library_nf_native_system_math_System_Math::Min___STATIC__R8__R8__R8, + Library_nf_native_system_math_System_Math::Min___STATIC__R4__R4__R4, + Library_nf_native_system_math_System_Math::Pow___STATIC__R8__R8__R8, + Library_nf_native_system_math_System_Math::Pow___STATIC__R4__R4__R4, + Library_nf_native_system_math_System_Math::Round___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Round___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Sign___STATIC__I4__R8, + Library_nf_native_system_math_System_Math::Sign___STATIC__I4__R4, + Library_nf_native_system_math_System_Math::Sin___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Sin___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Sinh___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Sinh___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Sqrt___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Sqrt___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Tan___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Tan___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Tanh___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Tanh___STATIC__R4__R4, + Library_nf_native_system_math_System_Math::Truncate___STATIC__R8__R8, + Library_nf_native_system_math_System_Math::Truncate___STATIC__R4__R4, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Math = +{ + "System.Math", + 0xC5A2A195, + method_lookup, + { 100, 0, 4, 3 } +}; diff --git a/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.h b/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.h new file mode 100644 index 00000000..9d91affa --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math.h @@ -0,0 +1,70 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_NATIVE_SYSTEM_MATH_H_ +#define _NF_NATIVE_SYSTEM_MATH_H_ + +#include +#include +// #include + +struct Library_nf_native_system_math_System_Math +{ + NANOCLR_NATIVE_DECLARE(Abs___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Abs___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Acos___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Acos___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Asin___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Asin___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Atan___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Atan___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Atan2___STATIC__R8__R8__R8); + NANOCLR_NATIVE_DECLARE(Atan2___STATIC__R4__R4__R4); + NANOCLR_NATIVE_DECLARE(Ceiling___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Ceiling___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Cos___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Cos___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Cosh___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Cosh___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(IEEERemainder___STATIC__R8__R8__R8); + NANOCLR_NATIVE_DECLARE(IEEERemainder___STATIC__R4__R4__R4); + NANOCLR_NATIVE_DECLARE(Exp___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Exp___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Floor___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Floor___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Log___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Log___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Log10___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Log10___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Max___STATIC__R8__R8__R8); + NANOCLR_NATIVE_DECLARE(Max___STATIC__R4__R4__R4); + NANOCLR_NATIVE_DECLARE(Min___STATIC__R8__R8__R8); + NANOCLR_NATIVE_DECLARE(Min___STATIC__R4__R4__R4); + NANOCLR_NATIVE_DECLARE(Pow___STATIC__R8__R8__R8); + NANOCLR_NATIVE_DECLARE(Pow___STATIC__R4__R4__R4); + NANOCLR_NATIVE_DECLARE(Round___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Round___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Sign___STATIC__I4__R8); + NANOCLR_NATIVE_DECLARE(Sign___STATIC__I4__R4); + NANOCLR_NATIVE_DECLARE(Sin___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Sin___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Sinh___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Sinh___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Sqrt___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Sqrt___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Tan___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Tan___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Tanh___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Tanh___STATIC__R4__R4); + NANOCLR_NATIVE_DECLARE(Truncate___STATIC__R8__R8); + NANOCLR_NATIVE_DECLARE(Truncate___STATIC__R4__R4); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Math; + +#endif //_NF_NATIVE_SYSTEM_MATH_H_ diff --git a/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math_System_Math.cpp b/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math_System_Math.cpp new file mode 100644 index 00000000..7b42b113 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/System.Math/nf_native_system_math_System_Math.cpp @@ -0,0 +1,1481 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_native_system_math.h" + +#if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + #include "nanoPAL_NativeDouble.h" + + HRESULT Library_nf_native_system_math_System_Math::Max___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float x = stack.Arg0().NumericByRefConst().r4; + float y = stack.Arg1().NumericByRefConst().r4; + float res = x >= y ? x : y; + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Max___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double x = stack.Arg0().NumericByRefConst().r8; + double y = stack.Arg1().NumericByRefConst().r8; + double res = x >= y ? x : y; + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Min___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float x = stack.Arg0().NumericByRefConst().r4; + float y = stack.Arg1().NumericByRefConst().r4; + float res = x <= y ? x : y; + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Min___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double x = stack.Arg0().NumericByRefConst().r8; + double y = stack.Arg1().NumericByRefConst().r8; + double res = x <= y ? x : y; + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Abs___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = fabs( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Abs___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = fabsf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Acos___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = acos( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Acos___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = acosf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Asin___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = asin( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Asin___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = asinf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Atan___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = atan( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Atan___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = atanf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Atan2___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double x = stack.Arg0().NumericByRefConst().r8; + double y = stack.Arg1().NumericByRefConst().r8; + double res = atan2( x, y ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Atan2___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float x = stack.Arg0().NumericByRefConst().r4; + float y = stack.Arg1().NumericByRefConst().r4; + float res = atan2f( x, y ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Ceiling___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = ceil( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Ceiling___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = ceilf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Cos___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = cos( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Cos___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = cosf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Cosh___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = cosh( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Cosh___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = coshf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::IEEERemainder___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double x = stack.Arg0().NumericByRefConst().r8; + double y = stack.Arg1().NumericByRefConst().r8; + double res = remainder(x, y); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::IEEERemainder___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float x = stack.Arg0().NumericByRefConst().r4; + float y = stack.Arg1().NumericByRefConst().r4; + float res = remainderf(x, y); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Exp___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = exp( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL();; + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Exp___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = expf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL();; + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Floor___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = floor( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Floor___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = floorf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Log___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = log( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Log___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = logf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Log10___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = log10( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Log10___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = log10f( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Pow___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (DP_FLOATINGPOINT == TRUE) + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double x = stack.Arg0().NumericByRefConst().r8; + double y = stack.Arg1().NumericByRefConst().r8; + + double res = pow( x, y ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #else + return stack.NotImplementedStub(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Pow___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float x = stack.Arg0().NumericByRefConst().r4; + float y = stack.Arg1().NumericByRefConst().r4; + + float res = powf( x, y ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Round___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double hi = d + 0.5; + double res = floor( hi ); + + //If the number was in the middle of two integers, we need to round to the even one. + if(res==hi) + { + if(fmod( res, 2.0 ) != 0) + { + //Rounding up made the number odd so we should round down. + res -= 1.0; + } + } + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Round___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float hi = d + 0.5; + float res = floorf( hi ); + + //If the number was in the middle of two integers, we need to round to the even one. + if(res==hi) + { + if(fmodf( res, 2.0 ) != 0) + { + //Rounding up made the number odd so we should round down. + res -= 1.0; + } + } + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sign___STATIC__I4__R8( CLR_RT_StackFrame& stack ) + { + #if (DP_FLOATINGPOINT == TRUE) + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + int32_t res; + if (d < 0) res = -1; + else if (d > 0) res = +1; + else res = 0; + + stack.SetResult_I4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #else + return stack.NotImplementedStub(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Sign___STATIC__I4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + int32_t res; + if (d < 0) res = -1; + else if (d > 0) res = +1; + else res = 0; + + stack.SetResult_I4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sin___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = sin( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Sin___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = sinf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Sinh___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = sinh( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Sinh___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = sinhf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Sqrt___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = sqrt( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Sqrt___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = sqrtf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Tan___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = tan( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Tan___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = tanf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Tanh___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + + #if (DP_FLOATINGPOINT == TRUE) + + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = tanh( d ); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Tanh___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + #if (NANOCLR_LIGHT_MATH == TRUE) + return stack.NotImplementedStub(); + #else + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = tanhf( d ); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Truncate___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + #if (DP_FLOATINGPOINT == TRUE) + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + double d = stack.Arg0().NumericByRefConst().r8; + double res = 0.0; + modf(d, &res); + + stack.SetResult_R8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + return stack.NotImplementedStub(); + #endif + } + + HRESULT Library_nf_native_system_math_System_Math::Truncate___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + float d = stack.Arg0().NumericByRefConst().r4; + float res = 0.0; + modff(d, &res); + + stack.SetResult_R4( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + +#else + + /// No floating point + HRESULT Library_nf_native_system_math_System_Math::Max___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Max___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Min___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Min___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Abs___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Abs___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Acos___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Acos___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Asin___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Asin___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Atan___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Atan___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Atan2___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Atan2___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Ceiling___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64 d = stack.Arg0().NumericByRefConst().r8; + + CLR_INT64 res = (CLR_INT64)(d + (CLR_INT64)CLR_RT_HeapBlock::HB_DoubleMask) & (~CLR_RT_HeapBlock::HB_DoubleMask); + + stack.SetResult_I8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Ceiling___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Cos___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Cos___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Cosh___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Cosh___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::IEEERemainder___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::IEEERemainder___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Exp___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Exp___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Floor___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64 d = stack.Arg0().NumericByRefConst().r8; + CLR_INT64 res = (CLR_INT64)( d & (~CLR_RT_HeapBlock::HB_DoubleMask) ); + stack.SetResult_I8( res ); + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Floor___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Log___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Log___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Log10___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Log10___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Pow___STATIC__R8__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Pow___STATIC__R4__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Round___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_INT64 d = stack.Arg0().NumericByRefConst().r8; + + //for negative number we have to be banker's round, if -0.5, round to 0, but 0.5 to 0 + if (d <0) d =d + 1; + CLR_INT64 res = (CLR_INT64)(d + (CLR_INT64)(CLR_RT_HeapBlock::HB_DoubleMask>>1) ) & (~CLR_RT_HeapBlock::HB_DoubleMask); + + stack.SetResult_I8( res ); + + + NANOCLR_NOCLEANUP_NOLABEL(); + } + + HRESULT Library_nf_native_system_math_System_Math::Round___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sign___STATIC__I4__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sign___STATIC__I4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sin___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sin___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sinh___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sinh___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sqrt___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Sqrt___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Tan___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Tan___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Tanh___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Tanh___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Truncate___STATIC__R8__R8( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + + HRESULT Library_nf_native_system_math_System_Math::Truncate___STATIC__R4__R4( CLR_RT_StackFrame& stack ) + { + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); + } + +#endif // NANOCLR_EMULATED_FLOATINGPOINT diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj new file mode 100644 index 00000000..afefd6ed --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E} + Win32Proj + WireProtocol + 10.0.17763.0 + WireProtocol + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(SolutionDir)$(Configuration)\ + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj.filters b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj.filters new file mode 100644 index 00000000..a163610f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol-vs2019.vcxproj.filters @@ -0,0 +1,34 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj new file mode 100644 index 00000000..5b9a87b2 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj @@ -0,0 +1,160 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E} + Win32Proj + WireProtocol + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\targets\os\win32\Include;..\Include;..\..\HAL\Include;..\..\PAL\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj.filters b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj.filters new file mode 100644 index 00000000..a163610f --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol.vcxproj.filters @@ -0,0 +1,34 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_App_Interface.c b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_App_Interface.c new file mode 100644 index 00000000..00f04a07 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_App_Interface.c @@ -0,0 +1,33 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "WireProtocol_App_Interface.h" + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +// The functions below are the ones that need to be ported to client applications, +// tipically nanoBooter and CLR debugger +// +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +// provided as weak to be replaced by actual implementation in the client application +__nfweak int WP_App_ProcessHeader(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation in the client application +__nfweak int WP_App_ProcessPayload(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_HAL_Interface.c b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_HAL_Interface.c new file mode 100644 index 00000000..f27f0035 --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_HAL_Interface.c @@ -0,0 +1,40 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "WireProtocol_HAL_Interface.h" + +///////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////// +// The functions below are the ones that need to be ported to new channels/HALs when required +// +// Please check the reference implementation provided for ChibiOS in: +// RTOS\ChibiOS\WireProtocol_HAL_Interface.c +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +// provided as weak to be replaced by actual implementation by HAL interface +__nfweak int WP_ReceiveBytes(uint8_t* ptr, unsigned short* size) +{ + (void)(ptr); + (void)(size); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by HAL interface +__nfweak int WP_TransmitMessage(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by HAL interface +__nfweak void WP_CheckAvailableIncomingData() +{ +} diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_Message.c b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_Message.c new file mode 100644 index 00000000..0e024e0c --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_Message.c @@ -0,0 +1,395 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include "WireProtocol_Message.h" + +uint8_t receptionBuffer[sizeof(WP_Packet) + WP_PACKET_SIZE]; +static uint16_t lastOutboundMessage; +static uint8_t* marker; + +// timeout to receive WP payload before bailing out +// 5 secs (100 nsecs units) +static const uint64_t c_PayloadTimeout = 50000000; + +extern void debug_printf( const char* format, ... ); +extern uint64_t HAL_Time_SysTicksToTime_C(unsigned int sysTicks); + +////////////////////////////////////////// +// helper functions + +void WP_ReplyToCommand(WP_Message* message, int fSuccess, int fCritical, void* ptr, int size) +{ + WP_Message msgReply; + uint32_t flags = 0; + + // + // Make sure we reply only once! + // + if(message->m_header.m_flags & WP_Flags_c_NonCritical) return; + message->m_header.m_flags |= WP_Flags_c_NonCritical; + + // + // No caching in the request, no caching in the reply... + // + if(message->m_header.m_flags & WP_Flags_c_NoCaching) flags |= WP_Flags_c_NoCaching; + + if(fSuccess ) flags |= WP_Flags_c_ACK; + else flags |= WP_Flags_c_NACK; + if(!fCritical) flags |= WP_Flags_c_NonCritical; + + if(fSuccess == false) + { + ptr = NULL; + size = 0; + } + + WP_Message_Initialize(&msgReply); + + WP_Message_PrepareReply(&msgReply, &message->m_header, flags, size, (uint8_t*)ptr ); + + WP_TransmitMessage(&msgReply); +} + +void WP_Message_Initialize(WP_Message* message) +{ + memset(&message->m_header, 0, sizeof(message->m_header)); + message->m_payload = NULL; + message->m_pos = NULL; + message->m_size = 0; + message->m_payloadTicks = 0; + message->m_rxState = ReceiveState_Idle; +} + +void WP_Message_PrepareReception(WP_Message* message) +{ + message->m_rxState = ReceiveState_Initialize; +} + +void WP_Message_PrepareRequest(WP_Message* message, uint32_t cmd, uint32_t flags, uint32_t payloadSize, uint8_t* payload) +{ + memcpy(&message->m_header.m_signature, marker ? marker : (uint8_t*)MARKER_PACKET_V1, sizeof(message->m_header.m_signature)); + +#if defined(WP_IMPLEMENTS_CRC32) + message->m_header.m_crcData = SUPPORT_ComputeCRC(payload, payloadSize, 0); +#else + message->m_header.m_crcData = 0; +#endif + message->m_header.m_cmd = cmd; + message->m_header.m_seq = lastOutboundMessage++; + message->m_header.m_seqReply = 0; + message->m_header.m_flags = flags; + message->m_header.m_size = payloadSize; + message->m_payload = payload; + + // + // The CRC for the header is computed setting the CRC field to zero and then running the CRC algorithm. + // + message->m_header.m_crcHeader = 0; +#if defined(WP_IMPLEMENTS_CRC32) + message->m_header.m_crcHeader = SUPPORT_ComputeCRC((uint8_t*)&message->m_header, sizeof(message->m_header), 0); +#endif +} + + +void WP_Message_PrepareReply(WP_Message* message, const WP_Packet* req, uint32_t flags, uint32_t payloadSize, uint8_t* payload) +{ + memcpy(&message->m_header.m_signature, marker ? marker : (uint8_t*)MARKER_PACKET_V1, sizeof(message->m_header.m_signature)); + +#if defined(WP_IMPLEMENTS_CRC32) + message->m_header.m_crcData = SUPPORT_ComputeCRC(payload, payloadSize, 0); +#else + message->m_header.m_crcData = 0; +#endif + message->m_header.m_cmd = req->m_cmd; + message->m_header.m_seq = lastOutboundMessage++; + message->m_header.m_seqReply = req->m_seq; + message->m_header.m_flags = flags | WP_Flags_c_Reply; + message->m_header.m_size = payloadSize; + message->m_payload = payload; + + // + // The CRC for the header is computed setting the CRC field to zero and then running the CRC algorithm. + // + message->m_header.m_crcHeader = 0; +#if defined(WP_IMPLEMENTS_CRC32) + message->m_header.m_crcHeader = SUPPORT_ComputeCRC((uint8_t*)&message->m_header, sizeof(message->m_header), 0); +#endif +} + +void WP_Message_SetPayload(WP_Message* message, uint8_t* payload) +{ + message->m_payload = payload; +} + +void WP_Message_Release(WP_Message* message) +{ + if(message->m_payload) + { + message->m_payload = NULL; + } +} + +int WP_Message_VerifyHeader(WP_Message* message) +{ + message->m_header.m_crcHeader = 0; + +#if defined(WP_IMPLEMENTS_CRC32) + + uint32_t crc = message->m_header.m_crcHeader; + + uint32_t computedCrc = SUPPORT_ComputeCRC((uint8_t*)&message->m_header, sizeof(message->m_header), 0); + message->m_header.m_crcHeader = crc; + + if(computedCrc != crc) + { + TRACE( TRACE_ERRORS, "Header CRC check failed: computed: 0x%08X; got: 0x%08X\n", computedCrc, message->m_header.m_crcHeader ); + return false; + } + +#endif + + return true; +} + +int WP_Message_VerifyPayload(WP_Message* message) +{ + if(message->m_payload == NULL && message->m_header.m_size) + { + return false; + } + +#if defined(WP_IMPLEMENTS_CRC32) + + uint32_t computedCrc = SUPPORT_ComputeCRC(message->m_payload, message->m_header.m_size, 0); + if(computedCrc != message->m_header.m_crcData) + { + TRACE( TRACE_ERRORS, "Payload CRC check failed: computed: 0x%08X; got: 0x%08X\n", computedCrc, message->m_header.m_crcData ); + return false; + } + +#endif + + return true; +} + +void WP_Message_ReplyBadPacket(uint32_t flags) +{ + WP_Message message; + WP_Message_Initialize(&message); + WP_Message_PrepareRequest(&message, 0, WP_Flags_c_NonCritical | WP_Flags_c_NACK | flags, 0, NULL); + + WP_TransmitMessage(&message); +} + +int WP_Message_Process(WP_Message* message) +{ + uint8_t* buf = (uint8_t*)&message->m_header; + uint16_t len; + + while(true) + { + switch(message->m_rxState) + { + case ReceiveState_Idle: + TRACE0( TRACE_STATE, "RxState==IDLE\n"); + return true; + + case ReceiveState_Initialize: + TRACE0( TRACE_STATE, "RxState==INIT\n"); + WP_Message_Release(message); + + message->m_rxState = ReceiveState_WaitingForHeader; + message->m_pos = (uint8_t*)&message->m_header; + message->m_size = sizeof(message->m_header); + break; + + case ReceiveState_WaitingForHeader: + TRACE0( TRACE_STATE, "RxState==WaitForHeader\n"); + if(WP_ReceiveBytes(message->m_pos, &message->m_size) == false) + { + // didn't receive the expected amount of bytes, returning false + TRACE0( TRACE_NODATA, "ReceiveBytes returned false - bailing out\n"); + return false; + } + + // Synch to the start of a message. + while(true) + { + len = sizeof(message->m_header) - message->m_size; + if(len <= 0) + { + break; + } + + size_t lenCmp = min(len, sizeof(message->m_header.m_signature)); + + if(memcmp(&message->m_header, MARKER_DEBUGGER_V1, lenCmp) == 0) + { + break; + } + if(memcmp(&message->m_header, MARKER_PACKET_V1, lenCmp) == 0) + { + break; + } + + memmove(&buf[0], &buf[1], len-1); + + message->m_pos--; + message->m_size++; + } + + if(len >= sizeof(message->m_header.m_signature)) + { + message->m_rxState = ReceiveState_ReadingHeader; + } + break; + + case ReceiveState_ReadingHeader: + TRACE0( TRACE_STATE, "RxState==ReadingHeader\n"); + if(WP_ReceiveBytes(message->m_pos, &message->m_size) == false) + { + // didn't receive the expected amount of bytes, returning false + TRACE0( TRACE_NODATA, "ReceiveBytes returned false - bailing out\n"); + return false; + } + + if(message->m_size == 0) + { + message->m_rxState = ReceiveState_CompleteHeader; + } + break; + + case ReceiveState_CompleteHeader: + { + TRACE0( TRACE_STATE, "RxState=CompleteHeader\n"); + bool fBadPacket = true; + + if(WP_Message_VerifyHeader(message)) + { + TRACE( TRACE_HEADERS, "RXMSG: 0x%08X, 0x%08X, 0x%08X\n", message->m_header.m_cmd, message->m_header.m_flags, message->m_header.m_size ); + + if(WP_App_ProcessHeader(message)) + { + fBadPacket = false; + + if(message->m_header.m_size) + { + if(message->m_payload == NULL) // Bad, no buffer... + { + message->m_rxState = ReceiveState_Initialize; + } + else + { + message->m_payloadTicks = HAL_Time_CurrentSysTicks(); + message->m_rxState = ReceiveState_ReadingPayload; + message->m_pos = message->m_payload; + message->m_size = message->m_header.m_size; + } + } + else + { + message->m_rxState = ReceiveState_CompletePayload; + } + } + } + + if(fBadPacket) + { + if((message->m_header.m_flags & WP_Flags_c_NonCritical) == 0) + { + WP_Message_ReplyBadPacket(WP_Flags_c_BadHeader); + } + + message->m_rxState = ReceiveState_Initialize; + } + } + break; + + case ReceiveState_ReadingPayload: + { + TRACE( TRACE_STATE, "RxState=ReadingPayload. Expecting %d bytes.\n", message->m_size); + + uint64_t curTicks = HAL_Time_CurrentSysTicks(); + + // If the time between consecutive payload bytes exceeds the timeout threshold then assume that + // the rest of the payload is not coming. Reinitialize to synch on the next header. + + if(HAL_Time_SysTicksToTime_C( curTicks - message->m_payloadTicks ) < c_PayloadTimeout) + { + message->m_payloadTicks = curTicks; + + if(WP_ReceiveBytes(message->m_pos, &message->m_size) == false) + { + // didn't receive the expected amount of bytes, returning false + TRACE0( TRACE_NODATA, "ReceiveBytes returned false - bailing out\n"); + return false; + } + + if(message->m_size == 0) + { + message->m_rxState = ReceiveState_CompletePayload; + } + } + else + { + TRACE0( TRACE_ERRORS, "RxError: Payload InterCharacterTimeout exceeded\n"); + message->m_rxState = ReceiveState_Initialize; + } + } + break; + + case ReceiveState_CompletePayload: + TRACE0( TRACE_STATE, "RxState=CompletePayload\n"); + if(WP_Message_VerifyPayload(message) == true) + { + WP_App_ProcessPayload(message); + } + else + { + WP_Message_ReplyBadPacket(WP_Flags_c_BadPayload); + } + + message->m_rxState = ReceiveState_Initialize; + break; + + default: + // unknow state + TRACE0( TRACE_ERRORS, "RxState=UNKNOWN!!\n"); + return false; + } + } +} + +void WP_SendProtocolMessage(WP_Message *message) +{ + TRACE( TRACE_HEADERS, "TXMSG: 0x%08X, 0x%08X, 0x%08X\n", message->m_header.m_cmd, message->m_header.m_flags, message->m_header.m_size ); + WP_TransmitMessage(message); +} + +void WP_PrepareAndSendProtocolMessage(uint32_t cmd, uint32_t payloadSize, uint8_t* payload, uint32_t flags) +{ + WP_Message message; + WP_Message_Initialize(&message); + WP_Message_PrepareRequest(&message, cmd, flags, payloadSize, payload); + + TRACE( TRACE_HEADERS, "TXMSG: 0x%08X, 0x%08X, 0x%08X\n", message.m_header.m_cmd, message.m_header.m_flags, message.m_header.m_size ); + WP_TransmitMessage(&message); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// weak implementations of the functions (to be replaced with _strong_ implementations if and when required) // + +__nfweak void debug_printf( const char* format, ... ) +{ + (void)format; + + return; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_MonitorCommands.c b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_MonitorCommands.c new file mode 100644 index 00000000..040c554a --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/WireProtocol_MonitorCommands.c @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "WireProtocol_MonitorCommands.h" + +//////////////////////////////////////////////////// + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_Ping(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_OemInfo(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_ReadMemory(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_WriteMemory(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_Reboot(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_EraseMemory(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_QueryConfiguration(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_UpdateConfiguration(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_CheckMemory(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_MemoryMap(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} + +// provided as weak to be replaced by actual implementation by application +__nfweak int Monitor_FlashSectorMap(WP_Message* message) +{ + (void)(message); + + // default to false + return false; +} diff --git a/source/native/nf-interpreter/src/CLR/WireProtocol/targetHAL_time.cpp b/source/native/nf-interpreter/src/CLR/WireProtocol/targetHAL_time.cpp new file mode 100644 index 00000000..d3c5a5ac --- /dev/null +++ b/source/native/nf-interpreter/src/CLR/WireProtocol/targetHAL_time.cpp @@ -0,0 +1,22 @@ + +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +extern "C" { + + uint64_t HAL_Time_SysTicksToTime_C(unsigned int sysTicks) + { + return 0; + } + + unsigned int HAL_Time_CurrentSysTicks() + { + // TODO need to check if using the Win32 100ns ticks works + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->CurrentTicks(); + } +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_lwipopts_sntp.h b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_lwipopts_sntp.h new file mode 100644 index 00000000..55d0603c --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_lwipopts_sntp.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// lwIP options related with SNTP + +#ifndef __NF_LWIPOPTS_SNTP_H__ +#define __NF_LWIPOPTS_SNTP_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void SetSystemTimeFromUnixEpoch(uint32_t seconds); + +#ifdef __cplusplus +} +#endif + +// SNTP servers can be IP or full address and are resolved at +#define SNTP_SERVER_DNS 1 + +// use two servers +#define SNTP_MAX_SERVERS 2 + +// call to set the system time with seconds (Unix Epoch time) +#define SNTP_SET_SYSTEM_TIME SetSystemTimeFromUnixEpoch + +// need to declare this here to keep compiler happy +__nfweak char* ctime (const time_t * timer); + +#endif // __NF_LWIPOPTS_SNTP_H__ diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.cpp new file mode 100644 index 00000000..2156bf7e --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.cpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_networking_sntp.h" + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::Start___STATIC__VOID, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::Stop___STATIC__VOID, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::UpdateNow___STATIC__VOID, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::get_IsStarted___STATIC__BOOLEAN, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::get_Server1___STATIC__STRING, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::set_Server1___STATIC__VOID__STRING, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::get_Server2___STATIC__STRING, + Library_nf_networking_sntp_nanoFramework_Networking_Sntp::set_Server2___STATIC__VOID__STRING, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Networking_Sntp = +{ + "nanoFramework.Networking.Sntp", + 0xB617FDFB, + method_lookup, + { 100, 0, 4, 3 } +}; diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.h b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.h new file mode 100644 index 00000000..d6313818 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _NF_NETWORKING_SNTP_H_ +#define _NF_NETWORKING_SNTP_H_ + +#include +#include +#include +#include + +extern "C" +{ +#ifdef CC32XX +#include +#else +#include +#endif +} + +struct Library_nf_networking_sntp_nanoFramework_Networking_Sntp +{ + NANOCLR_NATIVE_DECLARE(Start___STATIC__VOID); + NANOCLR_NATIVE_DECLARE(Stop___STATIC__VOID); + NANOCLR_NATIVE_DECLARE(UpdateNow___STATIC__VOID); + NANOCLR_NATIVE_DECLARE(get_IsStarted___STATIC__BOOLEAN); + NANOCLR_NATIVE_DECLARE(get_Server1___STATIC__STRING); + NANOCLR_NATIVE_DECLARE(set_Server1___STATIC__VOID__STRING); + NANOCLR_NATIVE_DECLARE(get_Server2___STATIC__STRING); + NANOCLR_NATIVE_DECLARE(set_Server2___STATIC__VOID__STRING); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Networking_Sntp; + +#endif //_NF_NETWORKING_SNTP_H_ diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp_nanoFramework_Networking_Sntp.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp_nanoFramework_Networking_Sntp.cpp new file mode 100644 index 00000000..4064338f --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/Networking.Sntp/nf_networking_sntp_nanoFramework_Networking_Sntp.cpp @@ -0,0 +1,113 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "nf_networking_sntp.h" + + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::Start___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + sntp_init(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::Stop___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + sntp_stop(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::UpdateNow___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // this is just a stop and start of the SNTP client + sntp_stop(); + sntp_init(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::get_IsStarted___STATIC__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + stack.SetResult_Boolean(sntp_enabled()); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::get_Server1___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + stack.SetResult_String(sntp_getservername(0)); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::set_Server1___STATIC__VOID__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get server name as string + char* serverName = (char*)stack.Arg0().RecoverString(); FAULT_ON_NULL(serverName); + + sntp_setservername(0, serverName); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::get_Server2___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + stack.SetResult_String(sntp_getservername(1)); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_networking_sntp_nanoFramework_Networking_Sntp::set_Server2___STATIC__VOID__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get server name as string + char* serverName = (char*)stack.Arg0().RecoverString(); FAULT_ON_NULL(serverName); + + sntp_setservername(1, serverName); + } + NANOCLR_NOCLEANUP(); +} + +// need this declared as "C" because we are calling it from lwIP +extern "C" +{ +void SetSystemTimeFromUnixEpoch(uint32_t seconds) +{ + HAL_Time_SetUtcTime(((uint64_t)seconds * TIME_CONVERSION__TO_SECONDS) + TIME_UNIX_EPOCH_AS_TICKS); +} +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.cpp new file mode 100644 index 00000000..c9c94b58 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.cpp @@ -0,0 +1,305 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_net_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration::GetWireless82011ConfigurationCount___STATIC__I4, + Library_sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration::GetWireless82011Configuration___STATIC__SystemNetNetworkInformationWireless80211Configuration__I4, + Library_sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration::UpdateConfiguration___STATIC__VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::GetWirelessAPConfigurationCount___STATIC__I4, + Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::GetWirelessAPConfiguration___STATIC__SystemNetNetworkInformationWirelessAPConfiguration__I4, + Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::UpdateConfiguration___STATIC__VOID, + Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::NativeGetConnectedClients___STATIC__SZARRAY_SystemNetNetworkInformationWirelessAPStation__I4, + Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::NativeDeauthStation___STATIC__STRING__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::InitializeNetworkInterfaceSettings___VOID, + Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::UpdateConfiguration___VOID__I4, + NULL, + Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::GetNetworkInterfaceCount___STATIC__I4, + Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::GetNetworkInterface___STATIC__SystemNetNetworkInformationNetworkInterface__U4, + Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::IPAddressFromString___STATIC__U4__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_net_native_System_Net_Security_CertificateManager::AddCaCertificateBundle___STATIC__BOOLEAN__SZARRAY_U1, + Library_sys_net_native_System_Net_Security_SslNative::SecureServerInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate, + Library_sys_net_native_System_Net_Security_SslNative::SecureClientInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate, + Library_sys_net_native_System_Net_Security_SslNative::SecureAccept___STATIC__VOID__I4__OBJECT, + Library_sys_net_native_System_Net_Security_SslNative::SecureConnect___STATIC__VOID__I4__STRING__OBJECT, + Library_sys_net_native_System_Net_Security_SslNative::SecureRead___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4, + Library_sys_net_native_System_Net_Security_SslNative::SecureWrite___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4, + Library_sys_net_native_System_Net_Security_SslNative::SecureCloseSocket___STATIC__I4__OBJECT, + Library_sys_net_native_System_Net_Security_SslNative::ExitSecureContext___STATIC__I4__I4, + Library_sys_net_native_System_Net_Security_SslNative::DataAvailable___STATIC__I4__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_net_native_System_Net_Sockets_NativeSocket::socket___STATIC__I4__I4__I4__I4, + Library_sys_net_native_System_Net_Sockets_NativeSocket::bind___STATIC__VOID__OBJECT__SystemNetEndPoint, + Library_sys_net_native_System_Net_Sockets_NativeSocket::connect___STATIC__VOID__OBJECT__SystemNetEndPoint__BOOLEAN, + Library_sys_net_native_System_Net_Sockets_NativeSocket::send___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4, + Library_sys_net_native_System_Net_Sockets_NativeSocket::recv___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4, + Library_sys_net_native_System_Net_Sockets_NativeSocket::close___STATIC__I4__OBJECT, + Library_sys_net_native_System_Net_Sockets_NativeSocket::listen___STATIC__VOID__OBJECT__I4, + Library_sys_net_native_System_Net_Sockets_NativeSocket::accept___STATIC__I4__OBJECT, + Library_sys_net_native_System_Net_Sockets_NativeSocket::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1, + Library_sys_net_native_System_Net_Sockets_NativeSocket::shutdown___STATIC__VOID__OBJECT__I4__BYREF_I4, + Library_sys_net_native_System_Net_Sockets_NativeSocket::sendto___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__SystemNetEndPoint, + Library_sys_net_native_System_Net_Sockets_NativeSocket::recvfrom___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__BYREF_SystemNetEndPoint, + Library_sys_net_native_System_Net_Sockets_NativeSocket::getpeername___STATIC__VOID__OBJECT__BYREF_SystemNetEndPoint, + Library_sys_net_native_System_Net_Sockets_NativeSocket::getsockname___STATIC__VOID__OBJECT__BYREF_SystemNetEndPoint, + Library_sys_net_native_System_Net_Sockets_NativeSocket::getsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1, + Library_sys_net_native_System_Net_Sockets_NativeSocket::setsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1, + Library_sys_net_native_System_Net_Sockets_NativeSocket::poll___STATIC__BOOLEAN__OBJECT__I4__I4, + Library_sys_net_native_System_Net_Sockets_NativeSocket::ioctl___STATIC__VOID__OBJECT__U4__BYREF_U4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::ParseCertificate___STATIC__VOID__SZARRAY_U1__STRING__BYREF_STRING__BYREF_STRING__BYREF_mscorlibSystemDateTime__BYREF_mscorlibSystemDateTime, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2::DecodePrivateKeyNative___STATIC__VOID__SZARRAY_U1__STRING, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Net = +{ + "System.Net", + 0x0B718489, + method_lookup, + { 100, 1, 3, 0 } +}; diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.h b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.h new file mode 100644 index 00000000..8c013b80 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native.h @@ -0,0 +1,336 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _SYS_NET_NATIVE_H_ +#define _SYS_NET_NATIVE_H_ + +#include +#include +#include +#include +#include + +struct Library_sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration +{ + static const int FIELD___configurationIndex = 1; + static const int FIELD___id = 2; + static const int FIELD___authentication = 3; + static const int FIELD___encryption = 4; + static const int FIELD___radio = 5; + static const int FIELD___password = 6; + static const int FIELD___ssid = 7; + static const int FIELD___options = 8; + + NANOCLR_NATIVE_DECLARE(GetWireless82011ConfigurationCount___STATIC__I4); + NANOCLR_NATIVE_DECLARE(GetWireless82011Configuration___STATIC__SystemNetNetworkInformationWireless80211Configuration__I4); + NANOCLR_NATIVE_DECLARE(UpdateConfiguration___STATIC__VOID); + + //--// + +}; + +struct Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration +{ + static const int FIELD___apConfigurationIndex = 1; + static const int FIELD___apId = 2; + static const int FIELD___apAuthentication = 3; + static const int FIELD___apEncryption = 4; + static const int FIELD___apRadio = 5; + static const int FIELD___apPassword = 6; + static const int FIELD___apSsid = 7; + static const int FIELD___options = 8; + static const int FIELD___apChannel = 9; + static const int FIELD___apMaxConnections = 10; + + NANOCLR_NATIVE_DECLARE(GetWirelessAPConfigurationCount___STATIC__I4); + NANOCLR_NATIVE_DECLARE(GetWirelessAPConfiguration___STATIC__SystemNetNetworkInformationWirelessAPConfiguration__I4); + NANOCLR_NATIVE_DECLARE(UpdateConfiguration___STATIC__VOID); + NANOCLR_NATIVE_DECLARE(NativeGetConnectedClients___STATIC__SZARRAY_SystemNetNetworkInformationWirelessAPStation__I4); + NANOCLR_NATIVE_DECLARE(NativeDeauthStation___STATIC__STRING__I4); + + //--// + +}; + +struct Library_sys_net_native_System_Net_NetworkInformation_NetworkChange +{ + static const int FIELD_STATIC__NetworkAddressChanged = 0; + static const int FIELD_STATIC__NetworkAvailabilityChanged = 1; + static const int FIELD_STATIC__NetworkAPStationChanged = 2; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_NetworkInformation_NetworkChange__NetworkEvent +{ + static const int FIELD__EventType = 3; + static const int FIELD__Flags = 4; + static const int FIELD__Index = 5; + static const int FIELD__Data = 6; + static const int FIELD__Time = 7; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_IPAddress +{ + static const int FIELD_STATIC__Any = 3; + static const int FIELD_STATIC__Loopback = 4; + + static const int FIELD___address = 1; + static const int FIELD___family = 2; + static const int FIELD___numbers = 3; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_IPEndPoint +{ + static const int FIELD___address = 1; + static const int FIELD___port = 2; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_IPHostEntry +{ + static const int FIELD__hostName = 1; + static const int FIELD__addressList = 2; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_NetworkInformation_NetworkAPStationEventArgs +{ + static const int FIELD___stationIndex = 1; + static const int FIELD___isConnected = 2; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_NetworkInformation_NetworkAvailabilityEventArgs +{ + static const int FIELD___isAvailable = 1; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface +{ + static const int FIELD___interfaceIndex = 1; + static const int FIELD___macAddress = 2; + static const int FIELD___startupAddressMode = 3; + static const int FIELD___specificConfigId = 4; + static const int FIELD___automaticDns = 5; + static const int FIELD___ipv4Address = 6; + static const int FIELD___ipv4NetMask = 7; + static const int FIELD___ipv4GatewayAddress = 8; + static const int FIELD___ipv4dnsAddress1 = 9; + static const int FIELD___ipv4dnsAddress2 = 10; + static const int FIELD___ipv6Address = 11; + static const int FIELD___ipv6NetMask = 12; + static const int FIELD___ipv6GatewayAddress = 13; + static const int FIELD___ipv6dnsAddress1 = 14; + static const int FIELD___ipv6dnsAddress2 = 15; + static const int FIELD___networkInterfaceType = 16; + + NANOCLR_NATIVE_DECLARE(InitializeNetworkInterfaceSettings___VOID); + NANOCLR_NATIVE_DECLARE(UpdateConfiguration___VOID__I4); + NANOCLR_NATIVE_DECLARE(GetNetworkInterfaceCount___STATIC__I4); + NANOCLR_NATIVE_DECLARE(GetNetworkInterface___STATIC__SystemNetNetworkInformationNetworkInterface__U4); + NANOCLR_NATIVE_DECLARE(IPAddressFromString___STATIC__U4__STRING); + + //--// + +}; + +struct Library_sys_net_native_System_Net_NetworkInformation_WirelessAPStation +{ + static const int FIELD___macAddress = 1; + static const int FIELD___rssi = 2; + static const int FIELD___phyModes = 3; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_Security_CertificateManager +{ + NANOCLR_NATIVE_DECLARE(AddCaCertificateBundle___STATIC__BOOLEAN__SZARRAY_U1); + + //--// + +}; + +struct Library_sys_net_native_System_Net_Security_SslNative +{ + NANOCLR_NATIVE_DECLARE(SecureServerInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate); + NANOCLR_NATIVE_DECLARE(SecureClientInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate); + NANOCLR_NATIVE_DECLARE(SecureAccept___STATIC__VOID__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(SecureConnect___STATIC__VOID__I4__STRING__OBJECT); + NANOCLR_NATIVE_DECLARE(SecureRead___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(SecureWrite___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(SecureCloseSocket___STATIC__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(ExitSecureContext___STATIC__I4__I4); + NANOCLR_NATIVE_DECLARE(DataAvailable___STATIC__I4__OBJECT); + + //--// + + static HRESULT ReadWriteHelper( CLR_RT_StackFrame& stack, bool isWrite ); + static HRESULT InitHelper ( CLR_RT_StackFrame& stack, bool isServer ); + static HRESULT ThrowOnError ( CLR_RT_StackFrame& stack, int err ); + static void ThrowError ( CLR_RT_StackFrame& stack, int errorCode ); + +}; + +struct Library_sys_net_native_System_Net_Sockets_NetworkStream +{ + static const int FIELD___socket = 1; + static const int FIELD___socketType = 2; + static const int FIELD___remoteEndPoint = 3; + static const int FIELD___ownsSocket = 4; + static const int FIELD___disposed = 5; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_Security_SslStream +{ + static const int FIELD___sslVerification = 6; + static const int FIELD___sslContext = 7; + static const int FIELD___isServer = 8; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_SocketAddress +{ + static const int FIELD__m_Buffer = 1; + static const int FIELD___address = 2; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_Sockets_NativeSocket +{ + NANOCLR_NATIVE_DECLARE(socket___STATIC__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(bind___STATIC__VOID__OBJECT__SystemNetEndPoint); + NANOCLR_NATIVE_DECLARE(connect___STATIC__VOID__OBJECT__SystemNetEndPoint__BOOLEAN); + NANOCLR_NATIVE_DECLARE(send___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(recv___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(close___STATIC__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(listen___STATIC__VOID__OBJECT__I4); + NANOCLR_NATIVE_DECLARE(accept___STATIC__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(shutdown___STATIC__VOID__OBJECT__I4__BYREF_I4); + NANOCLR_NATIVE_DECLARE(sendto___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__SystemNetEndPoint); + NANOCLR_NATIVE_DECLARE(recvfrom___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__BYREF_SystemNetEndPoint); + NANOCLR_NATIVE_DECLARE(getpeername___STATIC__VOID__OBJECT__BYREF_SystemNetEndPoint); + NANOCLR_NATIVE_DECLARE(getsockname___STATIC__VOID__OBJECT__BYREF_SystemNetEndPoint); + NANOCLR_NATIVE_DECLARE(getsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(setsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(poll___STATIC__BOOLEAN__OBJECT__I4__I4); + NANOCLR_NATIVE_DECLARE(ioctl___STATIC__VOID__OBJECT__U4__BYREF_U4); + + //--// + static HRESULT MarshalSockAddress( struct SOCK_sockaddr* addrDst, CLR_UINT32& addrLenDst, const CLR_RT_HeapBlock& blkEndPointAddress ); + static HRESULT MarshalSockAddress( CLR_RT_HeapBlock& blkDst, const struct SOCK_sockaddr* addrSrc, CLR_UINT32 addrLenSrc ); + static HRESULT SendRecvHelper( CLR_RT_StackFrame& stack, bool fSend, bool fAddress ); + static HRESULT SockOptHelper( CLR_RT_StackFrame& stack, bool fGet ); + static HRESULT SockNameHelper( CLR_RT_StackFrame& stack, bool fPeer ); + static HRESULT BindConnectHelper( CLR_RT_StackFrame& stack, bool fBind ); + static HRESULT ThrowOnError( CLR_RT_StackFrame& stack, CLR_INT32 err ); + static void ThrowError( CLR_RT_StackFrame& stack, CLR_INT32 errorCode ); + + static CLR_INT32 Helper__SelectSocket( CLR_INT32 socket, CLR_INT32 mode ); + + /* WARNING!!! + * The value of this constant is the offset for the m_Handle field in the System.Net.Sockets.Socket class. + * It is defined here to avoid a circular reference issue. + */ + static const int FIELD__m_Handle = 1; + + static const int DISPOSED_HANDLE = -1; +}; + +struct Library_sys_net_native_System_Net_Sockets_Socket +{ + static const int FIELD__m_Handle = 1; + static const int FIELD__m_fBlocking = 2; + static const int FIELD__m_localEndPoint = 3; + static const int FIELD__m_recvTimeout = 4; + static const int FIELD__m_sendTimeout = 5; + static const int FIELD___socketType = 6; + static const int FIELD___nonBlockingConnectInProgress = 7; + static const int FIELD___nonBlockingConnectRightEndPoint = 8; + static const int FIELD___rightEndPoint = 9; + + + //--// + +}; + +struct Library_sys_net_native_System_Net_Sockets_SocketException +{ + static const int FIELD___errorCode = 5; + + + //--// + +}; + +struct Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate +{ + static const int FIELD___certificate = 1; + static const int FIELD___password = 2; + static const int FIELD___issuer = 3; + static const int FIELD___subject = 4; + static const int FIELD___effectiveDate = 5; + static const int FIELD___expirationDate = 6; + static const int FIELD___handle = 7; + static const int FIELD___sessionHandle = 8; + + NANOCLR_NATIVE_DECLARE(ParseCertificate___STATIC__VOID__SZARRAY_U1__STRING__BYREF_STRING__BYREF_STRING__BYREF_mscorlibSystemDateTime__BYREF_mscorlibSystemDateTime); + + //--// + +}; + +struct Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2 +{ + static const int FIELD___privateKey = 9; + + NANOCLR_NATIVE_DECLARE(DecodePrivateKeyNative___STATIC__VOID__SZARRAY_U1__STRING); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Net; + +#endif //_SYS_NET_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_NetworkInterface.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_NetworkInterface.cpp new file mode 100644 index 00000000..f77c5689 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_NetworkInterface.cpp @@ -0,0 +1,277 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_net_native.h" + +void Network_PostEvent( unsigned int eventType, unsigned int flags, unsigned int index) +{ + PostManagedEvent( EVENT_NETWORK, eventType, flags, index ); +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::InitializeNetworkInterfaceSettings___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + HAL_Configuration_NetworkInterface config; + CLR_RT_HeapBlock* pConfig = stack.Arg0().Dereference(); _ASSERTE(pConfig != NULL); + + CLR_UINT32 interfaceIndex = pConfig[ FIELD___interfaceIndex ].NumericByRefConst().u4; + + NANOCLR_CLEAR(config); + + // load network interface configuration from storage + if(!ConfigurationManager_GetConfigurationBlock((void*)&config, DeviceConfigurationOption_Network, interfaceIndex)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + _ASSERTE(config.StartupAddressMode > 0); + + // now load adapter configuration on top of the stored config + NANOCLR_CHECK_HRESULT(SOCK_CONFIGURATION_LoadAdapterConfiguration(&config, interfaceIndex)); + + pConfig[ FIELD___ipv4Address ].SetInteger( (CLR_UINT32)config.IPv4Address); + pConfig[ FIELD___ipv4GatewayAddress ].SetInteger( (CLR_UINT32)config.IPv4GatewayAddress); + pConfig[ FIELD___ipv4NetMask ].SetInteger( (CLR_UINT32)config.IPv4NetMask); + pConfig[ FIELD___ipv4dnsAddress1 ].SetInteger( (CLR_UINT32)config.IPv4DNSAddress1); + pConfig[ FIELD___ipv4dnsAddress2 ].SetInteger( (CLR_UINT32)config.IPv4DNSAddress2); + + // FIXME IPV6 + // pConfig[ FIELD___ipv6Address ].SetInteger( (CLR_UINT32)config.IPv6Address); + // pConfig[ FIELD___ipv6GatewayAddress ].SetInteger( (CLR_UINT32)config.IPv6GatewayAddress); + // pConfig[ FIELD___ipv6NetMask ].SetInteger( (CLR_UINT32)config.IPv6NetMask); + // pConfig[ FIELD___ipv6dnsAddress1 ].SetInteger( (CLR_UINT32)config.IPv6DNSAddress1); + // pConfig[ FIELD___ipv6dnsAddress2 ].SetInteger( (CLR_UINT32)config.IPv6DNSAddress2); + + pConfig[ FIELD___automaticDns ].SetInteger( (CLR_UINT32)config.AutomaticDNS); + pConfig[ FIELD___networkInterfaceType ].SetInteger( (CLR_UINT32)config.InterfaceType); + pConfig[ FIELD___specificConfigId ].SetInteger( (CLR_UINT32)config.SpecificConfigId); + pConfig[ FIELD___startupAddressMode ].SetInteger( (CLR_UINT32)config.StartupAddressMode); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( pConfig[ FIELD___macAddress ], NETIF_MAX_HWADDR_LEN, g_CLR_RT_WellKnownTypes.m_UInt8)); + memcpy(pConfig[ FIELD___macAddress ].DereferenceArray()->GetFirstElement(), config.MacAddress, NETIF_MAX_HWADDR_LEN); + + NANOCLR_NOCLEANUP(); +} + +inline bool operator!=(const HAL_Configuration_NetworkInterface &lhs, const HAL_Configuration_NetworkInterface &rhs) { + if (lhs.IPv4Address != rhs.IPv4Address) { + return true; + } + + if (lhs.IPv4GatewayAddress != rhs.IPv4GatewayAddress) { + return true; + } + + if (lhs.IPv4NetMask != rhs.IPv4NetMask) { + return true; + } + + if (lhs.IPv4DNSAddress1 != rhs.IPv4DNSAddress1) { + return true; + } + + if (lhs.IPv4DNSAddress2 != rhs.IPv4DNSAddress2) { + return true; + } + + if (lhs.AutomaticDNS != rhs.AutomaticDNS) { + return true; + } + + if (lhs.InterfaceType != rhs.InterfaceType) { + return true; + } + + if (lhs.SpecificConfigId != rhs.SpecificConfigId) { + return true; + } + + if (lhs.StartupAddressMode != rhs.StartupAddressMode) { + return true; + } + + if (memcmp(lhs.MacAddress, rhs.MacAddress, sizeof(rhs.MacAddress))) { + return true; + } + + if (memcmp(lhs.IPv6Address, rhs.IPv6Address, sizeof(rhs.IPv6Address))) { + return true; + } + + if (memcmp(lhs.IPv6NetMask, rhs.IPv6NetMask, sizeof(rhs.IPv6NetMask))) { + return true; + } + + if (memcmp(lhs.IPv6GatewayAddress, rhs.IPv6GatewayAddress, sizeof(rhs.IPv6GatewayAddress))) { + return true; + } + + if (memcmp(lhs.IPv6DNSAddress1, rhs.IPv6DNSAddress1, sizeof(rhs.IPv6DNSAddress1))) { + return true; + } + + if (memcmp(lhs.IPv6DNSAddress2, rhs.IPv6DNSAddress2, sizeof(rhs.IPv6DNSAddress2))) { + return true; + } + + return false; +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::UpdateConfiguration___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + HAL_Configuration_NetworkInterface config, storageConfig; + bool configChanged; + CLR_RT_HeapBlock* pConfig = stack.Arg0().Dereference(); _ASSERTE(pConfig != NULL); + CLR_UINT32 interfaceIndex = pConfig[ FIELD___interfaceIndex ].NumericByRefConst().u4; + CLR_UINT32 updateFlags = stack.Arg1().NumericByRef().u4; + CLR_RT_HeapBlock_Array* pMACAddress = pConfig[ FIELD___macAddress ].DereferenceArray(); + + NANOCLR_CLEAR(config); + NANOCLR_CLEAR(storageConfig); + + config.IPv4Address = pConfig[ FIELD___ipv4Address ].NumericByRef().u4; + config.IPv4GatewayAddress = pConfig[ FIELD___ipv4GatewayAddress ].NumericByRef().u4; + config.IPv4NetMask = pConfig[ FIELD___ipv4NetMask ].NumericByRef().u4; + config.IPv4DNSAddress1 = pConfig[ FIELD___ipv4dnsAddress1 ].NumericByRef().u4; + config.IPv4DNSAddress2 = pConfig[ FIELD___ipv4dnsAddress2 ].NumericByRef().u4; + + // FIXME IPV6 + // config.IPv6Address = pConfig[ FIELD___ipv6Address ].NumericByRef().u4; + // config.IPv6GatewayAddress = pConfig[ FIELD___ipv6GatewayAddress ].NumericByRef().u4; + // config.IPv6NetMask = pConfig[ FIELD___ipv6NetMask ].NumericByRef().u4; + // config.IPv6DNSAddress1 = pConfig[ FIELD___ipv6dnsAddress1 ].NumericByRef().u4; + // config.IPv6DNSAddress2 = pConfig[ FIELD___ipv6dnsAddress2 ].NumericByRef().u4; + + config.AutomaticDNS = pConfig[ FIELD___automaticDns ].NumericByRef().u4; + config.InterfaceType = (NetworkInterfaceType) pConfig[ FIELD___networkInterfaceType ].NumericByRef().u4; + config.SpecificConfigId = (CLR_UINT32) pConfig[ FIELD___specificConfigId ].NumericByRef().u4; + config.StartupAddressMode = (AddressMode) pConfig[ FIELD___startupAddressMode ].NumericByRef().u4; + + if(pMACAddress != NULL) + { + memcpy( &config.MacAddress, pMACAddress->GetFirstElement(), NETIF_MAX_HWADDR_LEN ); + } + + // load network interface configuration from storage + if(!ConfigurationManager_GetConfigurationBlock((void*)&storageConfig, DeviceConfigurationOption_Network, interfaceIndex)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + // save the configuration only if there has been a change + configChanged = (config != storageConfig); + + // store configuration, updating the configuration block + if(configChanged && ConfigurationManager_UpdateConfigurationBlock(&config, DeviceConfigurationOption_Network, interfaceIndex) != TRUE) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_CHECK_HRESULT(SOCK_CONFIGURATION_UpdateAdapterConfiguration(&config, interfaceIndex, updateFlags)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::GetNetworkInterfaceCount___STATIC__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + // grab the count right from the structure + stack.SetResult_I4( g_TargetConfiguration.NetworkInterfaceConfigs->Count ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::GetNetworkInterface___STATIC__SystemNetNetworkInformationNetworkInterface__U4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + HAL_Configuration_NetworkInterface config; + CLR_RT_HeapBlock* pConfig; + CLR_UINT32 interfaceIndex = stack.Arg0().NumericByRef().u4; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + NANOCLR_CLEAR(config); + + // load network interface configuration from storage + if(!ConfigurationManager_GetConfigurationBlock((void*)&config, DeviceConfigurationOption_Network, interfaceIndex)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + _ASSERTE(config.StartupAddressMode > 0); + + // now load adapter configuration on top of the stored config + NANOCLR_CHECK_HRESULT(SOCK_CONFIGURATION_LoadConfiguration(&config, interfaceIndex)); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( top, g_CLR_RT_WellKnownTypes.m_NetworkInterface )); + + pConfig = top.Dereference(); FAULT_ON_NULL(pConfig); + + pConfig[ FIELD___ipv4Address ].SetInteger( (CLR_UINT32)config.IPv4Address); + pConfig[ FIELD___ipv4GatewayAddress ].SetInteger( (CLR_UINT32)config.IPv4GatewayAddress); + pConfig[ FIELD___ipv4NetMask ].SetInteger( (CLR_UINT32)config.IPv4NetMask); + pConfig[ FIELD___ipv4dnsAddress1 ].SetInteger( (CLR_UINT32)config.IPv4DNSAddress1); + pConfig[ FIELD___ipv4dnsAddress2 ].SetInteger( (CLR_UINT32)config.IPv4DNSAddress2); + + // FIXME IPV6 + // pConfig[ FIELD___ipv6Address ].SetInteger( (CLR_UINT32)config.IPv6Address); + // pConfig[ FIELD___ipv6GatewayAddress ].SetInteger( (CLR_UINT32)config.IPv6GatewayAddress); + // pConfig[ FIELD___ipv6NetMask ].SetInteger( (CLR_UINT32)config.IPv6NetMask); + // pConfig[ FIELD___ipv6dnsAddress1 ].SetInteger( (CLR_UINT32)config.IPv6DNSAddress1); + // pConfig[ FIELD___ipv6dnsAddress2 ].SetInteger( (CLR_UINT32)config.IPv6DNSAddress2); + + pConfig[ FIELD___automaticDns ].SetInteger( (CLR_UINT32)config.AutomaticDNS); + pConfig[ FIELD___networkInterfaceType ].SetInteger( (CLR_UINT32)config.InterfaceType); + pConfig[ FIELD___specificConfigId ].SetInteger( (CLR_UINT32)config.SpecificConfigId); + pConfig[ FIELD___startupAddressMode ].SetInteger( (CLR_UINT32)config.StartupAddressMode); + pConfig[ FIELD___interfaceIndex ].SetInteger( (CLR_UINT32)interfaceIndex); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( pConfig[ FIELD___macAddress ], NETIF_MAX_HWADDR_LEN, g_CLR_RT_WellKnownTypes.m_UInt8 )); + memcpy( pConfig[ FIELD___macAddress ].DereferenceArray()->GetFirstElement(), config.MacAddress, NETIF_MAX_HWADDR_LEN ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::IPAddressFromString___STATIC__U4__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + LPCSTR szName = stack.Arg0().RecoverString(); + struct SOCK_addrinfo hints; + struct SOCK_addrinfo* addr = NULL; + struct SOCK_sockaddr_in* addr_in; + int ret; + + memset( &hints, 0, sizeof(hints) ); + + ret = SOCK_getaddrinfo( szName, NULL, &hints, &addr ); + + // getaddrinfo returns a winsock error code rather than SOCK_SOCKET_ERROR, so pass this on to the exception handling + if(ret != 0 || addr == NULL || addr->ai_family != SOCK_AF_INET) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + _ASSERTE(addr->ai_addr != NULL); + _ASSERTE(addr->ai_addrlen >= sizeof(SOCK_sockaddr_in)); + + addr_in = (struct SOCK_sockaddr_in*)addr->ai_addr; + + stack.PushValue().SetInteger( (CLR_UINT32)addr_in->sin_addr.S_un.S_addr ); + + NANOCLR_CLEANUP(); + + if( addr ) SOCK_freeaddrinfo( addr ); + + NANOCLR_CLEANUP_END(); +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration.cpp new file mode 100644 index 00000000..0935dbb7 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration.cpp @@ -0,0 +1,103 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_net_native.h" + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration::GetWireless82011ConfigurationCount___STATIC__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + // grab the count right from the structure + stack.SetResult_I4(g_TargetConfiguration.Wireless80211Configs->Count); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration::GetWireless82011Configuration___STATIC__SystemNetNetworkInformationWireless80211Configuration__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + HAL_Configuration_Wireless80211 config; + CLR_RT_HeapBlock* pConfig; + CLR_UINT32 configurationIndex = stack.Arg0().NumericByRef().u4; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + NANOCLR_CLEAR(config); + + // load wireless 802.11 configuration from the storage + if(!ConfigurationManager_GetConfigurationBlock((void*)&config, DeviceConfigurationOption_Wireless80211Network, configurationIndex)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + // create new object for configuration + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_Wireless80211Configuration)); + + // load from stack + pConfig = top.Dereference(); FAULT_ON_NULL(pConfig); + + // fill in fields from config struct + pConfig[FIELD___id].SetInteger((CLR_UINT32)config.Id); + pConfig[FIELD___authentication].SetInteger((CLR_UINT32)config.Authentication); + pConfig[FIELD___encryption].SetInteger((CLR_UINT32)config.Encryption); + pConfig[FIELD___radio].SetInteger((CLR_UINT32)config.Radio); + pConfig[FIELD___options].SetInteger((CLR_UINT8)config.Flags); + + // the following ones are strings so a simple assignment isn't enough, need to create a managed string instance and copy over + // make sure the terminators are there + config.Password[WIRELESS82011_CONFIG_MAX_PASSWORD_LEN - 1] = 0; + config.Ssid[WIRELESS82011_CONFIG_MAX_SSID_LEN - 1] = 0; + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(pConfig[FIELD___password], (const char*)config.Password)); + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(pConfig[FIELD___ssid], (const char*)config.Ssid)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_Wireless80211Configuration::UpdateConfiguration___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + HAL_Configuration_Wireless80211 config; + CLR_RT_HeapBlock* pConfig = stack.Arg0().Dereference(); _ASSERTE(pConfig != NULL); + + CLR_UINT32 configurationIndex = pConfig[FIELD___configurationIndex].NumericByRefConst().u4; + + CLR_RT_HeapBlock_String* hbPassword = NULL; + CLR_RT_HeapBlock_String* hbSsid = NULL; + CLR_UINT32 ssidLength; + CLR_UINT32 passwordLength; + + NANOCLR_CLEAR(config); + + config.Id = (CLR_UINT32)pConfig[FIELD___id].NumericByRef().u4; + config.Authentication = (AuthenticationType)pConfig[FIELD___authentication].NumericByRef().u4; + config.Encryption = (EncryptionType)pConfig[FIELD___encryption].NumericByRef().u4; + config.Radio = (RadioType)pConfig[FIELD___radio].NumericByRef().u4; + config.Flags = (uint8_t)pConfig[FIELD___options].NumericByRef().u1; + + // the following ones are strings + // make sure the terminators are there + hbPassword = pConfig[FIELD___password].DereferenceString(); FAULT_ON_NULL(hbPassword); + passwordLength = hal_strlen_s(hbPassword->StringText()); + if (passwordLength >= sizeof(config.Password)) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + hal_strncpy_s((char*)config.Password, WIRELESS82011_CONFIG_MAX_PASSWORD_LEN, hbPassword->StringText(), passwordLength); + + hbSsid = pConfig[FIELD___ssid].DereferenceString(); FAULT_ON_NULL(hbSsid); + ssidLength = hal_strlen_s(hbSsid->StringText()); + if (ssidLength >= sizeof(config.Ssid)) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + hal_strncpy_s((char*)config.Ssid, WIRELESS82011_CONFIG_MAX_SSID_LEN, hbSsid->StringText(), ssidLength); + + // store configuration + if(ConfigurationManager_UpdateConfigurationBlock(&config, DeviceConfigurationOption_Wireless80211Network, configurationIndex) != TRUE) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration.cpp new file mode 100644 index 00000000..97035bb9 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration.cpp @@ -0,0 +1,235 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_net_native.h" + + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::GetWirelessAPConfigurationCount___STATIC__I4( CLR_RT_StackFrame& stack ) +{ +#ifdef PLATFORM_ESP32 + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + // grab the count right from the structure + stack.SetResult_I4(g_TargetConfiguration.WirelessAPConfigs->Count); + + NANOCLR_NOCLEANUP_NOLABEL(); +#else + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +#endif +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::GetWirelessAPConfiguration___STATIC__SystemNetNetworkInformationWirelessAPConfiguration__I4( CLR_RT_StackFrame& stack ) +{ +#ifdef PLATFORM_ESP32 + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + HAL_Configuration_WirelessAP config; + CLR_RT_HeapBlock* pConfig; + CLR_UINT32 configurationIndex = stack.Arg0().NumericByRef().u4; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + NANOCLR_CLEAR(config); + + // load wireless AP configuration from the storage + if(!ConfigurationManager_GetConfigurationBlock((void*)&config, DeviceConfigurationOption_WirelessNetworkAP, configurationIndex)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + // create new object for configuration + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_WirelessAPConfiguration)); + + // load from stack + pConfig = top.Dereference(); FAULT_ON_NULL(pConfig); + + // fill in fields from config struct + pConfig[FIELD___apId].SetInteger((CLR_UINT32)config.Id); + pConfig[FIELD___apAuthentication].SetInteger((CLR_UINT32)config.Authentication); + pConfig[FIELD___apEncryption].SetInteger((CLR_UINT32)config.Encryption); + pConfig[FIELD___apRadio].SetInteger((CLR_UINT32)config.Radio); + pConfig[FIELD___options].SetInteger((CLR_UINT8)config.Flags); + pConfig[FIELD___apChannel].SetInteger((CLR_UINT8)config.Channel); + pConfig[FIELD___apMaxConnections].SetInteger((CLR_UINT8)config.MaxConnections); + + // the following ones are strings so a simple assignment isn't enough, need to create a managed string instance and copy over + // make sure the terminators are there + config.Password[WIRELESS82011_CONFIG_MAX_PASSWORD_LEN - 1] = 0; + config.Ssid[WIRELESS82011_CONFIG_MAX_SSID_LEN - 1] = 0; + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(pConfig[FIELD___apPassword], (const char*)config.Password)); + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(pConfig[FIELD___apSsid], (const char*)config.Ssid)); + + NANOCLR_NOCLEANUP(); +#else + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +#endif +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::UpdateConfiguration___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ +#ifdef PLATFORM_ESP32 + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + HAL_Configuration_WirelessAP config; + CLR_RT_HeapBlock* pConfig = stack.Arg0().Dereference(); _ASSERTE(pConfig != NULL); + + CLR_UINT32 configurationIndex = pConfig[FIELD___apConfigurationIndex].NumericByRefConst().u4; + + CLR_RT_HeapBlock_String* hbPassword = NULL; + CLR_RT_HeapBlock_String* hbSsid = NULL; + CLR_UINT32 ssidLength; + CLR_UINT32 passwordLength; + + NANOCLR_CLEAR(config); + + config.Id = (CLR_UINT32)pConfig[FIELD___apId].NumericByRef().u4; + config.Authentication = (AuthenticationType)pConfig[FIELD___apAuthentication].NumericByRef().u4; + config.Encryption = (EncryptionType)pConfig[FIELD___apEncryption].NumericByRef().u4; + config.Radio = (RadioType)pConfig[FIELD___apRadio].NumericByRef().u4; + config.Flags = (uint8_t)pConfig[FIELD___options].NumericByRef().u1; + config.Channel = (uint8_t)pConfig[FIELD___apChannel].NumericByRef().u1; + config.MaxConnections = (uint8_t)pConfig[FIELD___apMaxConnections].NumericByRef().u1; + + // the following ones are strings + // make sure the terminators are there + hbPassword = pConfig[FIELD___apPassword].DereferenceString(); FAULT_ON_NULL(hbPassword); + passwordLength = hal_strlen_s(hbPassword->StringText()); + if (passwordLength >= sizeof(config.Password)) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + hal_strncpy_s((char*)config.Password, WIRELESS82011_CONFIG_MAX_PASSWORD_LEN, hbPassword->StringText(), passwordLength); + + hbSsid = pConfig[FIELD___apSsid].DereferenceString(); FAULT_ON_NULL(hbSsid); + ssidLength = hal_strlen_s(hbSsid->StringText()); + if (ssidLength >= sizeof(config.Ssid)) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + hal_strncpy_s((char*)config.Ssid, WIRELESS82011_CONFIG_MAX_SSID_LEN, hbSsid->StringText(), ssidLength); + + // store configuration + if(ConfigurationManager_UpdateConfigurationBlock(&config, DeviceConfigurationOption_WirelessNetworkAP, configurationIndex) != TRUE) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_NOCLEANUP(); +#else + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +#endif +} + + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::NativeGetConnectedClients___STATIC__SZARRAY_SystemNetNetworkInformationWirelessAPStation__I4(CLR_RT_StackFrame& stack) +{ +#ifdef PLATFORM_ESP32 + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index apStationTypeDef; + CLR_RT_HeapBlock* apStation; + CLR_RT_HeapBlock* hbObj; + + uint16_t stationCount = 0; + + uint8_t mac[6]; + uint8_t rssi; + uint32_t phyModes = 0; + + CLR_RT_HeapBlock& top = stack.PushValue(); + + // Get index of station info required or if index == 0 then return all connected stations + uint16_t index = (uint16_t)stack.Arg0().NumericByRef().u4; + + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("WirelessAPStation", "System.Net.NetworkInformation", apStationTypeDef); + + // Count stations connected + for (int x = 0; x < Network_Interface_Max_Stations(); x++) + { + if (index != 0 && x != index) continue; + + if (Network_Interface_Get_Station(x, mac, &rssi, &phyModes)) + { + stationCount++; + } + } + + // Create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, stationCount, apStationTypeDef)); + + // get a pointer to the first object in the array (which is of type ) + apStation = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // Create Array + if (stationCount > 0) + { + for (int x = 0; x < Network_Interface_Max_Stations(); x++) + { + if (index != 0 && x != index) continue; + + if (Network_Interface_Get_Station(x, mac, &rssi, &phyModes)) + { + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*apStation, apStationTypeDef)); + + // dereference the object in order to reach its fields + hbObj = apStation->Dereference(); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(hbObj[Library_sys_net_native_System_Net_NetworkInformation_WirelessAPStation::FIELD___macAddress], 6, g_CLR_RT_WellKnownTypes.m_UInt8)); + memcpy(hbObj[Library_sys_net_native_System_Net_NetworkInformation_WirelessAPStation::FIELD___macAddress].DereferenceArray()->GetFirstElement(), mac, 6); + + + CLR_RT_HeapBlock& rssiFieldRef = hbObj[Library_sys_net_native_System_Net_NetworkInformation_WirelessAPStation::FIELD___rssi]; + CLR_INT8* pRes2 = (CLR_INT8*)&rssiFieldRef.NumericByRef().s1; + *pRes2 = rssi; + + CLR_RT_HeapBlock& phyModesFieldRef = hbObj[Library_sys_net_native_System_Net_NetworkInformation_WirelessAPStation::FIELD___phyModes]; + CLR_INT32* pRes3 = (CLR_INT32*)&phyModesFieldRef.NumericByRef().s4; + *pRes3 = phyModes; + + apStation++; + } + } + } + + NANOCLR_NOCLEANUP(); +#else + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +#endif +} + +HRESULT Library_sys_net_native_System_Net_NetworkInformation_WirelessAPConfiguration::NativeDeauthStation___STATIC__STRING__I4(CLR_RT_StackFrame& stack) +{ +#ifdef PLATFORM_ESP32 + NANOCLR_HEADER(); + + uint16_t index = (uint16_t)stack.Arg0().NumericByRef().u4; + + Network_Interface_Deauth_Station(index); + + NANOCLR_NOCLEANUP_NOLABEL(); +#else + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +#endif +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_CertificateManager.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_CertificateManager.cpp new file mode 100644 index 00000000..4946f4df --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_CertificateManager.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_net_native.h" + +HRESULT Library_sys_net_native_System_Net_Security_CertificateManager::AddCaCertificateBundle___STATIC__BOOLEAN__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* arrayCA = stack.Arg0().DereferenceArray(); + + CLR_UINT8* certificateBinary; + uint32_t certificateSize; + + // we only have one CA root bundle, so this is fixed to 0 + uint32_t configIndex = 0; + + // check for empty array + FAULT_ON_NULL(arrayCA); + + certificateSize = (int)arrayCA->m_numOfElements; + + // get a pointer to the the binary data for the certificate + certificateBinary = arrayCA->GetFirstElement(); + + if(g_TargetConfiguration.CertificateStore->Count == 0) + { + // not found, add the certificate bundle + if(ConfigurationManager_StoreConfigurationBlock(certificateBinary, DeviceConfigurationOption_X509CaRootBundle, configIndex, certificateSize, 0) != TRUE) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + else + { + // update the configuration block + if(ConfigurationManager_UpdateConfigurationBlock(certificateBinary, DeviceConfigurationOption_X509CaRootBundle, configIndex) != TRUE) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + // reach here, we should be OK + stack.SetResult_Boolean(TRUE); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_SslNative.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_SslNative.cpp new file mode 100644 index 00000000..d6ce05bc --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Security_SslNative.cpp @@ -0,0 +1,631 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "sys_net_native.h" + + +struct SSL_SeedConfig +{ + HAL_DRIVER_CONFIG_HEADER Header; + + //--// + + uint64_t SeedCounter; + uint8_t SslSeedKey[ 260 ]; + + //--// + static const char * GetDriverName() { return "SSL_SEED_KEY"; } +}; + +struct SSL_SeedDriver +{ + SSL_SeedConfig Config; + + bool Initialized; + HAL_COMPLETION m_completion; +}; + +static SSL_SeedDriver g_SSL_SeedData; + +// TODO - save seed value +static void UpdateSslSeedValue(void* arg) +{ + (void)arg; + + // if(!HAL_CONFIG_BLOCK::UpdateBlockWithName( g_SSL_SeedData.Config.GetDriverName(), &g_SSL_SeedData.Config, sizeof(g_SSL_SeedData.Config), TRUE )) + // { + // ASSERT(FALSE); + // CPU_Reset(); + // } +} + +// TODO generate ramdom seed for encryption +// Maybe move this to specicfic provider files + +static void GenerateNewSslSeed() +{ +// uint8_t signature[ 128 ]; +// uint8_t IVPtr[ BLOCK_SIZE ]; +// bool success; + +// uint64_t data[ 2 ] = { ++g_SSL_SeedData.Config.SeedCounter, HAL_Time_CurrentTicks() }; + +// memset( &IVPtr[ 0 ], 0, sizeof(IVPtr) ); + +// // Encrypts a buffer using a symmetric algorithm. +// // BOOL Crypto_Encrypt(BYTE *Key, BYTE *IV, DWORD cbIVSize, BYTE* pPlainText, DWORD cbPlainText, BYTE *pCypherText, DWORD cbCypherText); +// //success = Crypto_Encrypt( (BYTE*)&g_SSL_SeedData.Config.SslSeedKey[ 0 ], (uint8_t*)IVPtr, sizeof(IVPtr), (uint8_t*)&data, sizeof(data), signature, sizeof(signature) ) == CRYPTO_SUCCESS ? S_OK : CLR_E_FAIL; + +// // ASSERT(success); + +// ssl_rand_seed(signature, sizeof(signature)); + +// if(!g_SSL_SeedData.m_completion.IsLinked()) +// { +// g_SSL_SeedData.m_completion.EnqueueDelta( 5 * 1000000ul ); // 5 seconds +// } +} + +//--// + +void Time_GetDateTime(DATE_TIME_INFO* dt) +{ + NATIVE_PROFILE_CLR_NETWORK(); + SYSTEMTIME st; + + HAL_Time_ToSystemTime( HAL_Time_CurrentTime(), &st ); + +// TODO check if offset needed for security date time, maybe needed to certificate validation +// dt->tzOffset = Time_GetTimeZoneOffset() * 60; + dt->tzOffset = 0; + + dt->year = st.wYear; + dt->month = st.wMonth; + dt->day = st.wDay; + dt->hour = st.wHour; + dt->minute = st.wMinute; + dt->second = st.wSecond; + dt->msec = st.wMilliseconds; + + dt->dlsTime = 0; + } + +// Initalise SSL as a server +HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureServerInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return InitHelper( stack, true ); +} + +// Initalise SSL as a client +HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureClientInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return InitHelper( stack, false ); +} + +// +// Server - socket connected now accept connection by doing the server SSL handshake +// +HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureAccept___STATIC__VOID__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_INT32 sslContext = stack.Arg0().NumericByRef().s4; + CLR_RT_HeapBlock* socket = stack.Arg1().Dereference(); + CLR_INT32 timeout_ms = -1; // wait forever + CLR_RT_HeapBlock hbTimeout; + + int result = 0; + CLR_INT32 handle; + bool fRes = true; + CLR_INT64 *timeout; + + FAULT_ON_NULL(socket); + + handle = socket[ Library_sys_net_native_System_Net_Sockets_NativeSocket::FIELD__m_Handle ].NumericByRef().s4; + + /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see + * if our handle has been shutdown before continuing. */ + if (handle == Library_sys_net_native_System_Net_Sockets_NativeSocket::DISPOSED_HANDLE) + { + ThrowError(stack, CLR_E_OBJECT_DISPOSED); + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger( (CLR_INT64)timeout_ms * TIME_CONVERSION__TO_MILLISECONDS ); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + + // first make sure we have data to read or ability to write + while(true) + { + result = SSL_Accept( handle, sslContext ); + + if(result == SOCK_EWOULDBLOCK || result == SOCK_TRY_AGAIN) + { + // non-blocking - allow other threads to run while we wait for socket activity + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); + } + else + { + break; + } + } + + stack.PopValue(); // Timeout + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, result )); + + NANOCLR_NOCLEANUP(); +} + +// +// Client - Natve socket connected, now do client side SSL handshake +// +HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureConnect___STATIC__VOID__I4__STRING__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_INT32 sslContext = stack.Arg0().NumericByRef().s4; + CLR_RT_HeapBlock* hb = stack.Arg1().DereferenceString(); + CLR_RT_HeapBlock* socket = stack.Arg2().Dereference(); + CLR_RT_HeapBlock hbTimeout; + + int result; + const char * szName; + CLR_INT32 handle; + bool fRes = true; + CLR_INT64 * timeout; + + FAULT_ON_NULL(socket); + + handle = socket[ Library_sys_net_native_System_Net_Sockets_NativeSocket::FIELD__m_Handle ].NumericByRef().s4; + + /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see + * if our handle has been shutdown before continuing. */ + if (handle == Library_sys_net_native_System_Net_Sockets_NativeSocket::DISPOSED_HANDLE) + { + ThrowError( stack, CLR_E_OBJECT_DISPOSED ); + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + FAULT_ON_NULL_ARG(hb); + + szName = hb->StringText(); + + // Infinite Timeout + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger( (CLR_INT64)-1 ); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + while(true) + { + result = SSL_Connect( handle, szName, sslContext ); + + if(result == SOCK_EWOULDBLOCK || result == SOCK_TRY_AGAIN) + { + // non-blocking - allow other threads to run while we wait for socket activity + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); + + if(result < 0) break; + } + else + { + break; + } + } + + stack.PopValue(); // Timeout + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, result )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureRead___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return ReadWriteHelper( stack, false ); +} + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureWrite___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return ReadWriteHelper( stack, true ); +} + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureCloseSocket___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + int result; + CLR_INT32 handle; + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); FAULT_ON_NULL(socket); + + handle = socket[ Library_sys_net_native_System_Net_Sockets_NativeSocket::FIELD__m_Handle ].NumericByRef().s4; + + result = SSL_CloseSocket( handle ); + + stack.SetResult_I4( result ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::ExitSecureContext___STATIC__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_INT32 sslContext = stack.Arg0().NumericByRef().s4; + + int result = SSL_ExitContext( sslContext ) == TRUE ? 0 : -1; + + stack.SetResult_I4( result ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::DataAvailable___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + int result; + CLR_INT32 handle; + + FAULT_ON_NULL(socket); + + handle = socket[ Library_sys_net_native_System_Net_Sockets_NativeSocket::FIELD__m_Handle ].NumericByRef().s4; + + result = SSL_DataAvailable( handle ); + + // ThrowOnError expects anything other than 0 to be a failure - so return 0 if we don't have an error + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, result >= 0 ? 0 : result )); + + stack.SetResult_I4( result ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::ReadWriteHelper( CLR_RT_StackFrame& stack, bool isWrite ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_RT_HeapBlock_Array* arrData = stack.Arg1().DereferenceArray(); + CLR_INT32 offset = stack.Arg2().NumericByRef().s4; + CLR_INT32 count = stack.Arg3().NumericByRef().s4; + CLR_INT32 timeout_ms = stack.Arg4().NumericByRef().s4; + CLR_UINT8* buffer; + CLR_RT_HeapBlock hbTimeout; + + CLR_INT32 totReadWrite; + bool fRes = true; + CLR_INT64 *timeout; + int result = 0; + CLR_INT32 handle; + + if(count == 0) + { + stack.SetResult_I4( 0 ); + NANOCLR_SET_AND_LEAVE(S_OK); + } + + FAULT_ON_NULL(socket); + + handle = socket[ Library_sys_net_native_System_Net_Sockets_NativeSocket::FIELD__m_Handle ].NumericByRef().s4; + + // Check not Disposed + if (handle == Library_sys_net_native_System_Net_Sockets_NativeSocket::DISPOSED_HANDLE) + { + ThrowError( stack, CLR_E_OBJECT_DISPOSED ); + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + FAULT_ON_NULL(arrData); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger( (CLR_INT64)timeout_ms * TIME_CONVERSION__TO_MILLISECONDS ); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // + // Push "totReadWrite" onto the eval stack. + // + if(stack.m_customState == 1) + { + stack.PushValueI4( 0 ); + + stack.m_customState = 2; + } + + totReadWrite = stack.m_evalStack[ 1 ].NumericByRef().s4; + + buffer = arrData->GetElement( offset + totReadWrite ); + count -= totReadWrite; + + if((offset + count + totReadWrite) > (int)arrData->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); + + while(count > 0) + { + // first make sure we have data to read or ability to write + while(fRes) + { + if(!isWrite) + { + // check SSL_DataAvailable() in case SSL has already read and buffered socket data + result = SSL_DataAvailable(handle); + + if((result > 0) || ((result < 0) && (SOCK_getlasterror() != SOCK_EWOULDBLOCK))) + { + break; + } + } + + result = Library_sys_net_native_System_Net_Sockets_NativeSocket::Helper__SelectSocket( handle, isWrite ? 1 : 0 ); + + if((result > 0) || ((result < 0) && (SOCK_getlasterror() != SOCK_EWOULDBLOCK))) + { + break; + } + + // non-blocking - allow other threads to run while we wait for socket activity + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); + + // timeout expired + if(!fRes) + { + result = SOCK_SOCKET_ERROR; + + ThrowError(stack, SOCK_ETIMEDOUT); + + NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); + } + } + + // socket is in the excepted state, so let's bail out + if(SOCK_SOCKET_ERROR == result) + { + break; + } + + if(isWrite) + { + result = SSL_Write( handle, (const char*)buffer, count ); + } + else + { + result = SSL_Read( handle, (char*)buffer, count ); + + if(result == SSL_RESULT__WOULD_BLOCK) + { + continue; + } + } + + // ThrowOnError expects anything other than 0 to be a failure - so return 0 if we don't have an error + if(result <= 0) + { + break; + } + + buffer += result; + totReadWrite += result; + count -= result; + + + // read is non-blocking if we have any data + if(!isWrite && (totReadWrite > 0)) + { + break; + } + + stack.m_evalStack[ 1 ].NumericByRef().s4 = totReadWrite; + } + + stack.PopValue(); // totReadWrite + stack.PopValue(); // Timeout + + if(result < 0) + { + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, result )); + } + + stack.SetResult_I4( totReadWrite ); + + NANOCLR_NOCLEANUP(); + +} + + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::InitHelper( CLR_RT_StackFrame& stack, bool isServer ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index x509Certificate2TypeDef; + + CLR_INT32 sslContext = -1; + CLR_INT32 sslMode = stack.Arg0().NumericByRef().s4; + CLR_INT32 sslVerify = stack.Arg1().NumericByRef().s4; + CLR_RT_HeapBlock *hbCert = stack.Arg2().Dereference(); + CLR_RT_HeapBlock* caCert = stack.Arg3().Dereference(); + CLR_RT_HeapBlock_Array* arrCert = NULL; + CLR_RT_HeapBlock_Array* privateKey = NULL; + CLR_UINT8* sslCert = NULL; + int result; + bool isFirstCall = false; + const char * password = ""; + uint8_t* pk = NULL; + + if(!g_SSL_SeedData.Initialized) + { +// bool fOK = FALSE; + + isFirstCall = true; + +// FIXME +// #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) +// int i; + +// // TODO save seed data +// // if(!HAL_CONFIG_BLOCK::ApplyConfig( g_SSL_SeedData.Config.GetDriverName(), &g_SSL_SeedData.Config, sizeof(g_SSL_SeedData.Config) )) +// // { +// // return CLR_E_NOT_SUPPORTED; +// // } + +// // validate the security key (make sure it isn't all 0x00 or all 0xFF +// for(i=1; iPin(); + + // there is a client certificate, find if it's a X509Certificate2 + if(hbCert->ObjectCls().Type() == x509Certificate2TypeDef.Type()) + { + // get private key + privateKey = hbCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2::FIELD___privateKey ].DereferenceArray(); + pk = privateKey->GetFirstElement(); + } + + // get certificate + sslCert = arrCert->GetFirstElement(); + + // get password + CLR_RT_HeapBlock *hbPwd = hbCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___password ].Dereference();// FAULT_ON_NULL(hbPwd); + password = hbPwd->StringText(); + } + + if(isServer) + { + result = (SSL_ServerInit( sslMode, sslVerify, (const char*)sslCert, sslCert == NULL ? 0 : arrCert->m_numOfElements, pk, pk == NULL ? 0 : privateKey->m_numOfElements, password, hal_strlen_s(password), sslContext ) ? 0 : -1); + } + else + { + result = (SSL_ClientInit( sslMode, sslVerify, (const char*)sslCert, sslCert == NULL ? 0 : arrCert->m_numOfElements, pk, pk == NULL ? 0 : privateKey->m_numOfElements, password, hal_strlen_s(password), sslContext ) ? 0 : -1); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, result )); + + if(isFirstCall) + { + GenerateNewSslSeed(); + } + + if(caCert != NULL) + { + arrCert = caCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___certificate ].DereferenceArray(); //FAULT_ON_NULL(arrCert); + + // If arrCert == NULL then the certificate is an X509Certificate2 which uses a certificate handle + if(arrCert == NULL) + { + CLR_INT32 sessionCtx = 0; + + arrCert = caCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___handle ].DereferenceArray(); FAULT_ON_NULL(arrCert); + + sslCert = arrCert->GetFirstElement(); + + arrCert = caCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___sessionHandle ].DereferenceArray(); FAULT_ON_NULL(arrCert); + + sessionCtx = *(int32_t*)arrCert->GetFirstElement(); + + // pass the session handle down as the password paramter and the certificate handle as the data parameter + result = (SSL_AddCertificateAuthority( sslContext, (const char*)sslCert, arrCert->m_numOfElements, (LPCSTR)&sessionCtx ) ? 0 : -1); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, result )); + } + else + { + + arrCert->Pin(); + + sslCert = arrCert->GetFirstElement(); + + CLR_RT_HeapBlock *hbPwd = caCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___password ].Dereference(); FAULT_ON_NULL(hbPwd); + + LPCSTR szCAPwd = hbPwd->StringText(); + + result = (SSL_AddCertificateAuthority( sslContext, (const char*)sslCert, arrCert->m_numOfElements, szCAPwd ) ? 0 : -1); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, result )); + } + } + + stack.SetResult_I4( sslContext ); + + NANOCLR_CLEANUP(); + + if(FAILED(hr) && (sslContext != -1)) + { + SSL_ExitContext( sslContext ); + } + + NANOCLR_CLEANUP_END(); +} + +void Library_sys_net_native_System_Net_Security_SslNative::ThrowError( CLR_RT_StackFrame& stack, int errorCode ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + CLR_RT_HeapBlock& res = stack.m_owningThread->m_currentException; + + if((Library_corlib_native_System_Exception::CreateInstance( res, g_CLR_RT_WellKnownTypes.m_SocketException, CLR_E_FAIL, &stack )) == S_OK) + { + res.Dereference()[ Library_sys_net_native_System_Net_Sockets_SocketException::FIELD___errorCode ].SetInteger( errorCode ); + } +} + +HRESULT Library_sys_net_native_System_Net_Security_SslNative::ThrowOnError( CLR_RT_StackFrame& stack, int res ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + if(res != 0) + { + ThrowError( stack, res ); + + NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); + } + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Sockets_NativeSocket.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Sockets_NativeSocket.cpp new file mode 100644 index 00000000..08dab47c --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Net_Sockets_NativeSocket.cpp @@ -0,0 +1,876 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "sys_net_native.h" + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::socket___STATIC__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_INT32 family = stack.Arg0().NumericByRef().s4; + CLR_INT32 type = stack.Arg1().NumericByRef().s4; + CLR_INT32 protocol = stack.Arg2().NumericByRef().s4; + + CLR_INT32 nonBlocking = 1; + CLR_INT32 sock = SOCK_socket( family, type, protocol ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, sock )); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, SOCK_ioctl( sock, SOCK_FIONBIO, &nonBlocking ) )); + + stack.SetResult_I4( sock ); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::bind___STATIC__VOID__OBJECT__SystemNetEndPoint( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + return BindConnectHelper( stack, true ); + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::connect___STATIC__VOID__OBJECT__SystemNetEndPoint__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + return BindConnectHelper( stack, false ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::send___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SendRecvHelper( stack, true, false ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::recv___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SendRecvHelper( stack, false, false ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::close___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_INT32 handle, ret; + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); FAULT_ON_NULL(socket); + + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + ret = SOCK_close( handle ); + + //If a socket gets closed, we need to make sure to wake up any threads that are waiting on it. + Events_Set( SYSTEM_EVENT_FLAG_SOCKET ); + + stack.SetResult_I4( ret ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::listen___STATIC__VOID__OBJECT__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 backlog = stack.Arg1().NumericByRef().s4; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + ret = SOCK_listen( handle, backlog ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::accept___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 ret; + CLR_INT32 nonBlocking = 1; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + + /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see + * if our handle has been shutdown before continuing. */ + if (handle == DISPOSED_HANDLE) + { + ThrowError(stack, CLR_E_OBJECT_DISPOSED); + NANOCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION); + } + + ret = SOCK_accept( handle, NULL, NULL ); + + if(ret != SOCK_SOCKET_ERROR) + { + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, SOCK_ioctl( ret, SOCK_FIONBIO, &nonBlocking ) )); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + stack.SetResult_I4( ret ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + LPCSTR szName = stack.Arg0().RecoverString(); + struct SOCK_addrinfo hints; + struct SOCK_addrinfo* addr = NULL; + struct SOCK_addrinfo* addrT; + CLR_UINT32 cAddresses = 0; + CLR_RT_HeapBlock* pAddress; + CLR_INT32 timeout_ms = 30000; + CLR_RT_HeapBlock hbTimeout; + CLR_INT32 ret; + bool fRes = true; + CLR_INT64* timeout; + uint32_t socketError = SOCK_SOCKET_ERROR; + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger( (CLR_INT64)timeout_ms * TIME_CONVERSION__TO_MILLISECONDS ); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + do + { + memset( &hints, 0, sizeof(hints) ); + + ret = SOCK_getaddrinfo( szName, NULL, &hints, &addr ); + + if(ret == SOCK_SOCKET_ERROR) + { + // get last error from socket + socketError = SOCK_getlasterror(); + + if(socketError == SOCK_EWOULDBLOCK) + { + // non-blocking - allow other threads to run while we wait for handle activity + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); + } + else + { + break; + } + } + else + { + // return without error, clear socket error + socketError = 0; + + // done here + break; + } + } + while(fRes); + + // timeout expired + if(!fRes) + { + ret = SOCK_SOCKET_ERROR; + + ThrowError( stack, SOCK_ETIMEDOUT ); + + NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); + } + else + { + // error wasn't a timeout so use socket error + ret = socketError; + } + + // getaddrinfo returns a winsock error code rather than SOCK_SOCKET_ERROR, so pass this on to the exception handling + if(ret != 0) + { + ThrowError( stack, ret ); + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + { + CLR_RT_HeapBlock hbCanonicalName; + CLR_RT_HeapBlock hbAddresses; + + hbCanonicalName.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( hbCanonicalName ); + + hbAddresses.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc2( hbAddresses ); + + for(int pass = 0; pass < 2; pass++) + { + cAddresses = 0; + + for(addrT = addr; addrT != NULL; addrT = addrT->ai_next) + { + if(pass == 1) + { + if(addrT->ai_canonname && addrT->ai_canonname[ 0 ]) + { + //allocate return string + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbCanonicalName, addrT->ai_canonname )); + NANOCLR_CHECK_HRESULT(hbCanonicalName.StoreToReference( stack.Arg1(), 0 )); + } + + //allocate address and store into array + pAddress = (CLR_RT_HeapBlock*)hbAddresses.DereferenceArray()->GetElement( cAddresses ); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( *pAddress, (CLR_UINT32)addrT->ai_addrlen, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + //copy address. + memcpy( pAddress->DereferenceArray()->GetFirstElement(), addrT->ai_addr, addrT->ai_addrlen ); + } + + cAddresses++; + } + + if(pass == 0) + { + //allocate array of byte arrays + CLR_RT_ReflectionDef_Index idx; + + idx.m_kind = REFLECTION_TYPE; + idx.m_levels = 2; + idx.m_data.m_type.m_data = g_CLR_RT_WellKnownTypes.m_UInt8.m_data; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( hbAddresses, cAddresses, idx )); + + NANOCLR_CHECK_HRESULT(hbAddresses.StoreToReference( stack.Arg2(), 0 )); + } + } + } + + stack.PopValue(); // Timeout + + NANOCLR_CLEANUP(); + + if( addr ) SOCK_freeaddrinfo( addr ); + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::shutdown___STATIC__VOID__OBJECT__I4__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 how = stack.Arg1().NumericByRef().s4; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + ret = SOCK_shutdown( handle, how ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::sendto___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__SystemNetEndPoint( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SendRecvHelper( stack, true, true ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::recvfrom___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__BYREF_SystemNetEndPoint( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SendRecvHelper( stack, false, true ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::getpeername___STATIC__VOID__OBJECT__BYREF_SystemNetEndPoint( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SockNameHelper( stack, true ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::getsockname___STATIC__VOID__OBJECT__BYREF_SystemNetEndPoint( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SockNameHelper( stack, false ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::getsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SockOptHelper( stack, true ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::setsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + return SockOptHelper( stack, false ); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::poll___STATIC__BOOLEAN__OBJECT__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 mode = stack.Arg1().NumericByRef().s4; + CLR_INT32 timeout_us = stack.Arg2().NumericByRef().s4; + CLR_RT_HeapBlock hbTimeout; + + CLR_INT32 res = 0; + bool fRes = true; + + CLR_INT64* timeout; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see + * if our handle has been shutdown before continuing. */ + if (handle == DISPOSED_HANDLE) + { + ThrowError( stack, CLR_E_OBJECT_DISPOSED ); + NANOCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION); + } + + if(timeout_us < 0) + { + // Infinite Timeout + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger( (CLR_INT64)-1 ); + } + else + { + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger( (CLR_INT64)timeout_us * TIME_CONVERSION__TO_MILLISECONDS / 1000 ); + } + + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + while(fRes) + { + res = Helper__SelectSocket( handle, mode ); + + if(res != 0) break; + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); + } + + stack.PopValue(); //timer + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, res )); + + stack.SetResult_Boolean( res != 0 ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::ioctl___STATIC__VOID__OBJECT__U4__BYREF_U4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 cmd = stack.Arg1().NumericByRef().s4; + CLR_RT_HeapBlock blkArg; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + _SIDE_ASSERTE(SUCCEEDED(blkArg.LoadFromReference( stack.Arg2() ))); + + ret = SOCK_ioctl( handle, cmd, (CLR_INT32*)&blkArg.NumericByRef().s4 ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + _SIDE_ASSERTE(SUCCEEDED(blkArg.StoreToReference( stack.Arg2(), 0 ))); + + NANOCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::BindConnectHelper( CLR_RT_StackFrame& stack, bool fBind ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + + CLR_INT32 handle; + SOCK_sockaddr addr; + CLR_UINT32 addrLen = sizeof(addr); + CLR_INT32 ret; + bool fThrowOnWouldBlock = false; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, stack.Arg1() )); + + if(fBind) + { + ret = SOCK_bind( handle, &addr, addrLen ); + } + else + { + ret = SOCK_connect( handle, &addr, addrLen ); + + fThrowOnWouldBlock = (stack.Arg2().NumericByRefConst().s4 != 0); + + if(!fThrowOnWouldBlock && SOCK_getsocklasterror( handle ) == SOCK_EWOULDBLOCK) + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +CLR_INT32 Library_sys_net_native_System_Net_Sockets_NativeSocket::Helper__SelectSocket(CLR_INT32 handle, CLR_INT32 mode ) +{ + struct SOCK_timeval timeval; + SOCK_fd_set* readfds = NULL; + SOCK_fd_set* writefds = NULL; + SOCK_fd_set* exceptfds = NULL; + SOCK_fd_set fds; + SOCK_fd_set fdsExcept; + CLR_INT32 res = 0; + + switch(mode) + { + case 0: + readfds = &fds; + break; + case 1: + writefds = &fds; + break; + default: + _ASSERTE(FALSE); + // fall through + case 2: + exceptfds = &fds; + break; + } + + fds.fd_count = 1; + fds.fd_array[ 0 ] = handle; + + // This Poll method is a little handicapped in the sense that it only allows the caller to wait + // for a read, a write or an except. This causes a problem when there is a socket exception. The + // poll will continue to block forever because the select statement wasn't looking for exceptions + // Therefore, we will force the select call to look for the except case if it is not already doing it. + if(exceptfds == NULL) + { + fdsExcept.fd_count = 1; + fdsExcept.fd_array[ 0 ] = handle; + exceptfds = &fdsExcept; + } + + timeval.tv_sec = 0; + timeval.tv_usec = 0; + + res = SOCK_select( 1, readfds, writefds, exceptfds, &timeval ); + + // socket is in the exception state (only return error if caller was NOT looking for the excepted state) + if((mode != 2) && (fdsExcept.fd_count != 0)) + { + // For read mode ignore exception if we have data to read + if(!(mode == 0 && fds.fd_count != 0)) + { + return SOCK_SOCKET_ERROR; + } + } + + return res; +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::MarshalSockAddress( CLR_RT_HeapBlock& blkDst, const struct SOCK_sockaddr* addrSrc, CLR_UINT32 addrLenSrc ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + + NANOCLR_HEADER(); + + (void)addrLenSrc; + + SOCK_sockaddr_in* src = (SOCK_sockaddr_in*)addrSrc; + + CLR_RT_TypeDef_Index ipAddressTypeDef; + CLR_RT_TypeDef_Index ipEndPointTypeDef; + CLR_RT_HeapBlock* ipAddressHbObj; + CLR_RT_HeapBlock* ipEndPointHbObj; + + CLR_RT_HeapBlock ipAddress; ipAddress.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc1( ipAddress ); + + CLR_RT_HeapBlock ipEndPoint; ipEndPoint.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc2( ipEndPoint ); + + // find type definition, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "IPAddress", "System.Net", ipAddressTypeDef ); + + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(ipAddress, ipAddressTypeDef)); + + // find type definition, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "IPEndPoint", "System.Net", ipEndPointTypeDef ); + + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(ipEndPoint, ipEndPointTypeDef)); + + // dereference the objects in order to reach their fields + ipAddressHbObj = ipAddress.Dereference(); + ipEndPointHbObj = ipEndPoint.Dereference(); + + { + // get a reference to the managed fields and set them + + // IPAddress _address field + // CLR_INT64 fields need to be accessed by pointer + CLR_RT_HeapBlock& addressFieldRef = ipAddressHbObj[ Library_sys_net_native_System_Net_IPAddress::FIELD___address ]; + CLR_INT64* pRes = (CLR_INT64*)&addressFieldRef.NumericByRef().s8; + *pRes = src->sin_addr.S_un.S_addr; + + // IPAddress _family field + ipAddressHbObj[ Library_sys_net_native_System_Net_IPAddress::FIELD___family ].NumericByRef().s4 = src->sin_family; + + // IPEndPoint _port field + // take care of endianess swapping + ipEndPointHbObj[ Library_sys_net_native_System_Net_IPEndPoint::FIELD___port ].NumericByRef().s4 = SOCK_ntohs(src->sin_port); + + // set IPEndPoint address with IPAddress heap block object + ipEndPointHbObj[ Library_sys_net_native_System_Net_IPEndPoint::FIELD___address ].SetObjectReference( ipAddressHbObj ); + } + + _ASSERTE(blkDst.DataType() == DATATYPE_BYREF); + + // store the new IPEndPoint object to reference + NANOCLR_CHECK_HRESULT(ipEndPoint.StoreToReference( blkDst, 0 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::MarshalSockAddress( struct SOCK_sockaddr* addrDst, CLR_UINT32& addrLenDst, const CLR_RT_HeapBlock& blkEndPointAddress ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + SOCK_sockaddr_in* dst = (SOCK_sockaddr_in*)addrDst; + + CLR_RT_HeapBlock* endPointAddress; + CLR_RT_HeapBlock* remoteEndPointAddress; + int64_t address; + int32_t port; + + endPointAddress = blkEndPointAddress.Dereference(); + FAULT_ON_NULL(endPointAddress); + + // get a pointer to the managed field object instance for m_Address + remoteEndPointAddress = endPointAddress[ Library_sys_net_native_System_Net_IPEndPoint::FIELD___address ].Dereference(); + FAULT_ON_NULL(remoteEndPointAddress); + + // get value of m_Address field (type long) + address = (CLR_INT64)remoteEndPointAddress[ Library_sys_net_native_System_Net_IPAddress::FIELD___address ].NumericByRef().s8; + + // get value of m_Port field (type int) + port = endPointAddress[ Library_sys_net_native_System_Net_IPEndPoint::FIELD___port ].NumericByRef().s4; + + // clear struct + memset(dst, 0, sizeof(SOCK_sockaddr)); + + dst->sin_family = SOCK_AF_INET; + // need to convert port number to network order + dst->sin_port = SOCK_htons(port); + + //address already in network byte order + memcpy((int8_t*)&dst->sin_addr.S_un.S_addr, (int8_t*)&address, sizeof(address)); + + addrLenDst = sizeof(address); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::SendRecvHelper( CLR_RT_StackFrame& stack, bool fSend, bool fAddress ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_RT_HeapBlock_Array* arrData = stack.Arg1().DereferenceArray(); + CLR_UINT32 offset = stack.Arg2().NumericByRef().u4; + CLR_UINT32 count = stack.Arg3().NumericByRef().u4; + CLR_INT32 flags = stack.Arg4().NumericByRef().s4; + CLR_RT_HeapBlock hbTimeout; + + CLR_INT64* timeout; + CLR_UINT8* buf; + bool fRes = true; + CLR_INT32 totReadWrite; + CLR_INT32 ret = 0; + + FAULT_ON_NULL(socket); + FAULT_ON_NULL(arrData); + + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see + * if our handle has been shutdown before continuing. */ + if (handle == DISPOSED_HANDLE) + { + ThrowError( stack, CLR_E_OBJECT_DISPOSED ); + NANOCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION); + } + + if(offset + count > arrData->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); + + // Infinite Timeout + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger( (CLR_INT64)-1 ); + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // + // Push "totReadWrite" onto the eval stack. + // + if(stack.m_customState == 1) + { + stack.PushValueI4( 0 ); + + stack.m_customState = 2; + } + + totReadWrite = stack.m_evalStack[ 1 ].NumericByRef().s4; + + buf = arrData->GetElement( offset + totReadWrite ); + count -= totReadWrite; + + while(count > 0) + { + CLR_INT32 bytes = 0; + + // first make sure we have data to read or ability to write + while(fRes) + { + ret = Helper__SelectSocket( handle, fSend ? 1 : 0 ); + + if(ret != 0) break; + + // non-blocking - allow other threads to run while we wait for handle activity + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); + } + + // timeout expired + if(!fRes) + { + ret = SOCK_SOCKET_ERROR; + + ThrowError( stack, SOCK_ETIMEDOUT ); + + NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); + } + + // socket is in the excepted state, so let's bail out + if(SOCK_SOCKET_ERROR == ret) + { + break; + } + + if(fAddress) + { + struct SOCK_sockaddr addr; + CLR_UINT32 addrLen = sizeof(addr); + CLR_RT_HeapBlock& blkAddr = stack.Arg6(); + + if(fSend) + { + NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, blkAddr )); + + bytes = SOCK_sendto( handle, (const char*)buf, count, flags, &addr, addrLen ); + } + else + { + CLR_RT_HeapBlock* pBlkAddr = blkAddr.Dereference(); + + NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, *pBlkAddr )); + + bytes = SOCK_recvfrom( handle, (char*)buf, count, flags, &addr, (int*)&addrLen ); + + if(bytes != SOCK_SOCKET_ERROR) + { + NANOCLR_CHECK_HRESULT(MarshalSockAddress( blkAddr, &addr, addrLen )); + } + } + } + else + { + if(fSend) + { + bytes = SOCK_send( handle, (const char*)buf, count, flags ); + } + else + { + bytes = SOCK_recv( handle, (char*)buf, count, flags ); + } + } + + // send/recv/sendto/recvfrom failed + if(bytes == SOCK_SOCKET_ERROR) + { + CLR_INT32 err = SOCK_getlasterror(); + + if(err != SOCK_EWOULDBLOCK) + { + ret = SOCK_SOCKET_ERROR; + break; + } + + continue; + } + // zero recv bytes indicates the handle has been closed. + else if(!fSend && (bytes == 0)) + { + break; + } + + buf += bytes; + totReadWrite += bytes; + count -= bytes; + + stack.m_evalStack[ 1 ].NumericByRef().s4 = totReadWrite; + + // receive returns immediately after receiving bytes. + if(!fSend && (totReadWrite > 0)) + { + break; + } + + } + + stack.PopValue(); // totReadWrite + stack.PopValue(); // Timeout + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + stack.SetResult_I4( totReadWrite ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::SockOptHelper( CLR_RT_StackFrame& stack, bool fGet ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 level = stack.Arg1().NumericByRef().s4; + CLR_INT32 optname = stack.Arg2().NumericByRef().s4; + CLR_RT_HeapBlock_Array* arrOpt = stack.Arg3().DereferenceArray(); + char* optval; + CLR_INT32 optlen; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + FAULT_ON_NULL(arrOpt); + + optval = (char*)arrOpt->GetFirstElement(); + optlen = arrOpt->m_numOfElements; + + if(fGet) + { + ret = SOCK_getsockopt( handle, level, optname, optval, &optlen ); + _ASSERTE( optlen <= (CLR_INT32)arrOpt->m_numOfElements ); + } + else + { + ret = SOCK_setsockopt( handle, level, optname, optval, optlen ); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::SockNameHelper( CLR_RT_StackFrame& stack, bool fPeer ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 ret; + + struct SOCK_sockaddr addr; + CLR_INT32 addrLen = sizeof(addr); + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + if(fPeer) + { + ret = SOCK_getpeername( handle, &addr, &addrLen ); + } + else + { + ret = SOCK_getsockname( handle, &addr, &addrLen ); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_CHECK_HRESULT(MarshalSockAddress( stack.Arg1(), &addr, addrLen )); + + NANOCLR_NOCLEANUP(); +} + +void Library_sys_net_native_System_Net_Sockets_NativeSocket::ThrowError( CLR_RT_StackFrame& stack, CLR_INT32 errorCode ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + CLR_RT_HeapBlock& res = stack.m_owningThread->m_currentException; + + if((Library_corlib_native_System_Exception::CreateInstance( res, g_CLR_RT_WellKnownTypes.m_SocketException, CLR_E_FAIL, &stack )) == S_OK) + { + res.Dereference()[ Library_sys_net_native_System_Net_Sockets_SocketException::FIELD___errorCode ].SetInteger( errorCode ); + } +} + +HRESULT Library_sys_net_native_System_Net_Sockets_NativeSocket::ThrowOnError( CLR_RT_StackFrame& stack, CLR_INT32 res ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + if(res == SOCK_SOCKET_ERROR) + { + CLR_INT32 err = SOCK_getlasterror(); + + ThrowError( stack, err ); + + NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate.cpp new file mode 100644 index 00000000..f8800960 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate.cpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_net_native.h" + +HRESULT Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::ParseCertificate___STATIC__VOID__SZARRAY_U1__STRING__BYREF_STRING__BYREF_STRING__BYREF_mscorlibSystemDateTime__BYREF_mscorlibSystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* arrData = stack.Arg0().DereferenceArray(); + CLR_UINT8* certBytes; + CLR_RT_HeapBlock hbIssuer; + CLR_RT_HeapBlock hbSubject; + CLR_RT_ProtectFromGC gc1( hbIssuer ); + CLR_RT_ProtectFromGC gc2( hbSubject ); + X509CertData cert; + CLR_INT64* val; +// CLR_INT64 tzOffset; + SYSTEMTIME st; +// INT32 standardBias; + CLR_RT_HeapBlock* hbPwd = stack.Arg1().DereferenceString(); + LPCSTR szPwd; + + FAULT_ON_NULL_ARG(hbPwd); + + szPwd = hbPwd->StringText(); + + CLR_RT_Memory::ZeroFill( &cert, sizeof(cert) ); + + FAULT_ON_NULL(arrData); + + certBytes = arrData->GetFirstElement(); + + if(!SSL_ParseCertificate( (const char*)certBytes, arrData->m_numOfElements, szPwd, &cert )) + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbIssuer, cert.Issuer )); + NANOCLR_CHECK_HRESULT(hbIssuer.StoreToReference( stack.Arg2(), 0 )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbSubject, cert.Subject )); + NANOCLR_CHECK_HRESULT(hbSubject.StoreToReference( stack.Arg3(), 0 )); + + st.wYear = cert.EffectiveDate.year; + st.wMonth = cert.EffectiveDate.month; + st.wDay = cert.EffectiveDate.day; + st.wHour = cert.EffectiveDate.hour; + st.wMinute = cert.EffectiveDate.minute; + st.wSecond = cert.EffectiveDate.second; + st.wMilliseconds = cert.EffectiveDate.msec; + + // standardBias = Time_GetTimeZoneOffset(); + // standardBias *= TIME_CONVERSION__ONEMINUTE; + + val = Library_corlib_native_System_DateTime::GetValuePtr( stack.Arg4() ); + *val = HAL_Time_ConvertFromSystemTime(&st); + + // tzOffset = cert.EffectiveDate.tzOffset; + + // // adjust for timezone differences + // if(standardBias != tzOffset) + // { + // *val += tzOffset - standardBias; + // } + + st.wYear = cert.ExpirationDate.year; + st.wMonth = cert.ExpirationDate.month; + st.wDay = cert.ExpirationDate.day; + st.wHour = cert.ExpirationDate.hour; + st.wMinute = cert.ExpirationDate.minute; + st.wSecond = cert.ExpirationDate.second; + st.wMilliseconds = cert.ExpirationDate.msec; + + val = Library_corlib_native_System_DateTime::GetValuePtr( stack.ArgN( 5 ) ); + *val = HAL_Time_ConvertFromSystemTime(&st); + + // tzOffset = cert.ExpirationDate.tzOffset; + + // if(standardBias != tzOffset) + // { + // *val += tzOffset - standardBias; + // } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2.cpp b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2.cpp new file mode 100644 index 00000000..0ed9c8e4 --- /dev/null +++ b/source/native/nf-interpreter/src/DeviceInterfaces/System.Net/sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_net_native.h" + +HRESULT Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate2::DecodePrivateKeyNative___STATIC__VOID__SZARRAY_U1__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* keyData = stack.Arg0().DereferenceArray(); + CLR_UINT8* keyBuffer; + CLR_RT_HeapBlock* passwordHb = stack.Arg1().DereferenceString(); + const char* password; + + // get key buffer + keyBuffer = keyData->GetFirstElement(); + + // manage password + FAULT_ON_NULL_ARG(passwordHb); + password = passwordHb->StringText(); + + if(SSL_DecodePrivateKey( + (const unsigned char*)keyBuffer, + keyData->m_numOfElements, + (const unsigned char*)password, + hal_strlen_s(password)) < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL.h new file mode 100644 index 00000000..d006b2cc --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL.h @@ -0,0 +1,1805 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOHAL_H_ +#define _NANOHAL_H_ 1 + +#include +#include +#include +#include +#include +#include + +#if defined(PLATFORM_EMULATED_FLOATINGPOINT) +/***************************************************/ +// Keep in sync with the nanoCLR_Runtime__HeapBlock.h + +#define HAL_FLOAT_SHIFT 10 +#define HAL_FLOAT_PRECISION 1000 + +#define HAL_DOUBLE_SHIFT 16 +#define HAL_DOUBLE_PRECISION 10000 + +/************************************************/ +#else +#include +#endif + + + +#include +#include +#include +#include +#include + +//#if !defined(_WIN32) && !defined(FIQ_SAMPLING_PROFILER) && !defined(HAL_REDUCESIZE) && defined(PROFILE_BUILD) +//#define ENABLE_NATIVE_PROFILER +//#endif + +//#include "..\pal\Diagnostics\Native_Profiler.h" + +#define NATIVE_PROFILE_CLR_DEBUGGER() +#define NATIVE_PROFILE_CLR_UTF8_DECODER() +#define NATIVE_PROFILE_CLR_CORE() +#define NATIVE_PROFILE_CLR_MESSAGING() +#define NATIVE_PROFILE_CLR_SERIALIZATION() +#define NATIVE_PROFILE_CLR_NETWORK() +#define NATIVE_PROFILE_CLR_I2C() +#define NATIVE_PROFILE_CLR_DIAGNOSTICS() +#define NATIVE_PROFILE_CLR_HARDWARE() +#define NATIVE_PROFILE_CLR_GRAPHICS() +#define NATIVE_PROFILE_CLR_STARTUP() +#define NATIVE_PROFILE_CLR_HEAP_PERSISTENCE() +#define NATIVE_PROFILE_CLR_IOPORT() +#define NATIVE_PROFILE_CLR_IO() + + +#if defined(_MSC_VER) + +#define GNU_PACKED + + + + + +#elif defined(__GNUC__) + + +#define GNU_PACKED __attribute__((packed)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#else +!ERROR +#endif + +//--// + + + + + + + + + + + + + + +//--// + + + +//--// + + + + + + + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#define TRANSPORT_SHIFT 8 +#define TRANSPORT_MASK (0xFF << TRANSPORT_SHIFT) +#define PORT_NUMBER_MASK 0x00FF + +// Macro to extract the transport type from a COM_HANDLE +#define ExtractTransport(x) ((unsigned int)(x) & TRANSPORT_MASK) + +// Macro to extract well-known system event flag ids from a COM_HANDLE +#define ExtractEventFromTransport(x) (ExtractTransport(x) == USART_TRANSPORT ? SYSTEM_EVENT_FLAG_COM_IN: \ + ExtractTransport(x) == SOCKET_TRANSPORT ? SYSTEM_EVENT_FLAG_SOCKET: \ + ExtractTransport(x) == GENERIC_TRANSPORT ? SYSTEM_EVENT_FLAG_GENERIC_PORT: \ + ExtractTransport(x) == DEBUG_TRANSPORT ? SYSTEM_EVENT_FLAG_DEBUGGER_ACTIVITY: \ + ExtractTransport(x) == MESSAGING_TRANSPORT ? SYSTEM_EVENT_FLAG_MESSAGING_ACTIVITY: \ + 0) \ + +#define USART_TRANSPORT (1 << TRANSPORT_SHIFT) +//#define COM_NULL ((COM_HANDLE)(USART_TRANSPORT)) + +#define USB_TRANSPORT (2 << TRANSPORT_SHIFT) +//#define USB_CONTROLLER_SHIFT 5 +//#define USB_CONTROLLER_MASK 0xE0 +//#define USB_STREAM_MASK 0x00FF +//#define USB_STREAM_INDEX_MASK 0x001F + +#define SOCKET_TRANSPORT (3 << TRANSPORT_SHIFT) +#define COM_SOCKET_DBG ((COM_HANDLE)(SOCKET_TRANSPORT + 1)) + +#define DEBUG_TRANSPORT (4 << TRANSPORT_SHIFT) + + + + + + + +#define MESSAGING_TRANSPORT (7 << TRANSPORT_SHIFT) + +#define GENERIC_TRANSPORT (8 << TRANSPORT_SHIFT) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Creates a COM_HANDLE value for a platform specific port number +#define ConvertCOM_DebugHandle(x) ((COM_HANDLE)((x) + DEBUG_TRANSPORT + 1)) + +// Extracts a Socket transport port id from a SOCKET_TRASNPORT COM_HANDLE +#define ConvertCOM_SockPort(x) (((x) & PORT_NUMBER_MASK) - 1) + +typedef unsigned int FLASH_WORD; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +typedef void (*LOGGING_CALLBACK)(const char* text); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// //--// + +// //--// + + + + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//--// + + + + + + + + + + + + + + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +template class HAL_DblLinkedList; + +template class HAL_DblLinkedNode +{ + T* m_nextNode; + T* m_prevNode; + + friend class HAL_DblLinkedList; + +public: + void Initialize() + { + m_nextNode = NULL; + m_prevNode = NULL; + } + + T* Next() const { return m_nextNode; } + T* Prev() const { return m_prevNode; } + + void SetNext( T* next ) { m_nextNode = next; } + void SetPrev( T* prev ) { m_prevNode = prev; } + + bool IsLinked() const { return m_nextNode != NULL; } + + //--// + + void RemoveFromList() + { + T* next = m_nextNode; + T* prev = m_prevNode; + + if(prev) prev->m_nextNode = next; + if(next) next->m_prevNode = prev; + } + + void Unlink() + { + T* next = m_nextNode; + T* prev = m_prevNode; + + if(prev) prev->m_nextNode = next; + if(next) next->m_prevNode = prev; + + m_nextNode = NULL; + m_prevNode = NULL; + } +}; + +//--// + +// The use of offsetof below throwns an "invalid offset warning" because CLR_RT_StackFrame is not POD type +// C+17 is the first standard that allow this, so until we are using it we have to disable it to keep GCC happy + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + +template class HAL_DblLinkedList +{ + // + // Logically, a list starts with a HAL_DblLinkedNode with only the Next() set and ends with a node with only Prev() set. + // This can be collapsed to have the two nodes overlap. + // + T* m_first; + T* m_null; + T* m_last; + + //--// + +public: + void Initialize() + { + m_first = Tail(); + m_null = NULL; + m_last = Head(); + } + + int NumOfNodes() + { + T* ptr; + T* ptrNext; + int num = 0; + + for(ptr = FirstNode(); (ptrNext = ptr->Next()) != NULL; ptr = ptrNext) + { + num++; + } + + return num; + } + + //--// + + T* FirstNode() const { return m_first ; } + T* LastNode () const { return m_last ; } + bool IsEmpty () const { return m_first == Tail(); } + + T* FirstValidNode() const { T* res = m_first; return res->Next() ? res : NULL; } + T* LastValidNode () const { T* res = m_last ; return res->Prev() ? res : NULL; } + + T* Head() const { return (T*)((size_t)&m_first - offsetof(T, m_nextNode)); } + T* Tail() const { return (T*)((size_t)&m_last - offsetof(T, m_prevNode)); } + + //--// + +private: + + void Insert( T* prev, T* next, T* node ) + { + node->m_nextNode = next; + node->m_prevNode = prev; + + next->m_prevNode = node; + prev->m_nextNode = node; + } + +public: +#if defined(_DEBUG) + bool Exists( T* searchNode ) + { + T* node = FirstValidNode(); + while( node != NULL && node != searchNode ) + { + if (node == node->Next()) + { + ASSERT(false); + } + node = node->Next(); + } + return (node == NULL? false: true); + } +#endif + + void InsertBeforeNode( T* node, T* nodeNew ) + { + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node->Prev(), node, nodeNew ); + } + } + + void InsertAfterNode( T* node, T* nodeNew ) + { + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node, node->Next(), nodeNew ); + } + } + + void LinkAtFront( T* node ) + { + InsertAfterNode( Head(), node ); + } + + void LinkAtBack( T* node ) + { + InsertBeforeNode( Tail(), node ); + } + + T* ExtractFirstNode() + { + T* node = FirstValidNode(); + + if(node) node->Unlink(); + + return node; + } + + T* ExtractLastNode() + { + T* node = LastValidNode(); + + if(node) node->Unlink(); + + return node; + } +}; + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +template class Hal_Queue_UnknownSize +{ + size_t m_writer; + size_t m_reader; + size_t m_size; + bool m_full; + T* m_data; + +public: + void Initialize( T* data, size_t size ) + { + m_writer = 0; + m_reader = 0; + m_size = size; + m_data = data; + m_full = false; + } + + size_t NumberOfElements() + { + if(m_writer < m_reader) return m_size + m_writer - m_reader; + else if(m_full) return m_size; + else return m_writer - m_reader; + } + + bool IsEmpty() + { + return (m_writer == m_reader && !m_full); + } + + bool IsFull() + { + return m_full; + } + + T* operator[](int index) + { + if(index < 0 || index >= NumberOfElements()) return NULL; + + return &m_data[(m_reader + index) % m_size]; + } + + T* Push() + { + size_t oldWriter = m_writer; + + if(m_full) return NULL; + + m_writer++; if(m_writer == m_size) m_writer = 0; + + if(m_writer == m_reader) m_full = true; + + return &m_data[oldWriter]; + } + + T* Peek() + { + if(m_writer == m_reader && !m_full) return NULL; + + return &m_data[m_reader]; + } + + T* Pop() + { + size_t oldReader = m_reader; + + if(m_reader == m_writer && !m_full) return (T*)NULL; + + m_reader++; if(m_reader == m_size) m_reader = 0; + + m_full = false; + + return &m_data[oldReader]; + } + + T* Push( size_t &nElements ) + { + size_t oldWriter = m_writer; + size_t max = 0; + + if(m_full || (nElements == 0)) + { + nElements = 0; + return NULL; + } + + if(m_writer < m_reader) max = m_reader - m_writer; + else max = m_size - m_writer; + + nElements = (max < nElements? max: nElements); + + m_writer += nElements; if(m_writer == m_size) m_writer = 0; + + if(m_writer == m_reader) m_full = true; + + return &m_data[oldWriter]; + } + + T* Pop( size_t &nElements ) + { + size_t oldReader = m_reader; + size_t max = 0; + + if(nElements == 0) return NULL; + + if((m_reader == m_writer) && !m_full) + { + nElements = 0; + // reset the reader/writer to maximize push potential + m_reader = 0; + m_writer = 0; + return NULL; + } + + if(m_writer <= m_reader) max = m_size - m_reader; + else max = m_writer - m_reader; + + nElements = (max < nElements? max: nElements); + + m_reader += nElements; if(m_reader == m_size) m_reader = 0; + + m_full = false; + + return &m_data[oldReader]; + } + + T* Storage() { return m_data; } +}; + +template class HAL_RingBuffer +{ + size_t _dataSize; + size_t _size; + size_t _capacity; + size_t _write_index; + size_t _read_index; + T * _buffer; + +public: + + void Initialize(T* data, size_t size) + { + _dataSize = sizeof(T); + + _capacity = (size * _dataSize); + _write_index = 0; + _read_index = 0; + _size = 0; + + _buffer = data; + } + + size_t Capacity() { return (_capacity / _dataSize); } + + size_t Length() { return (_size / _dataSize); } + + // Push a single element to the buffer. + size_t Push(const T data) + { + // check for buffer full + if(_size == _capacity) + { + // buffer full + return 0; + } + + T* destination = _buffer; + destination += _write_index; + + *destination = data; + _write_index += _dataSize; + + // check if we are the end of the capacity + if (_write_index == _capacity) _write_index = 0; + + // update ring buffer size + _size += _dataSize; + + return 1; + } + + // Push N elements to the buffer. + size_t Push(const T* data, size_t length) + { + size_t lengthToWrite = 0; + + // sanity check for 0 length + if (length == 0) return 0; + + // check for buffer full + if(_size == _capacity) + { + // buffer full + return 0; + } + + if( (length * _dataSize) < (_capacity - _size)) + { + lengthToWrite = (length * _dataSize); + } + else + { + lengthToWrite = (_capacity - _size); + } + + // single memcpy + if (lengthToWrite <= _capacity - _write_index) + { + memcpy(_buffer + _write_index, data, lengthToWrite); + _write_index += lengthToWrite; + + // check if we are the end of the capacity + if (_write_index == _capacity) _write_index = 0; + } + // need to memcpy in two chunks + else + { + size_t chunk1Size = _capacity - _write_index; + memcpy(_buffer + _write_index, data, chunk1Size); + + size_t chunk2Size = lengthToWrite - chunk1Size; + memcpy(_buffer, data + chunk1Size, chunk2Size); + + _write_index = chunk2Size; + } + + // update ring buffer size + _size += lengthToWrite; + + return (lengthToWrite / _dataSize); + } + + // Pop N elements from ring buffer returning them in the data argument. + size_t Pop(T* data, size_t length) + { + size_t lengthToRead = 0; + + // sanity check for 0 length + if (length == 0) return 0; + + // check for buffer empty + if(_size == 0) + { + return 0; + } + + lengthToRead = (length * _dataSize); + + // can read in a single memcpy + if (lengthToRead <= _capacity - _read_index) + { + memcpy(data, _buffer + _read_index, lengthToRead); + _read_index += lengthToRead; + + // check if we are at end of capacity + if (_read_index == _capacity) _read_index = 0; + } + // need to memcpy in two steps + else + { + size_t chunk1Size = _capacity - _read_index; + memcpy(data, _buffer + _read_index, chunk1Size); + + size_t chunk2Size = lengthToRead - chunk1Size; + memcpy(data + chunk1Size, _buffer, chunk2Size); + + _read_index = chunk2Size; + } + + // update ring buffer size + _size -= lengthToRead; + + // check for optimization to improve sequential push + // buffer has to be empty and read and write indexes coincide + if(_size == 0 && (_write_index == _read_index)) + { + // reset the read/write index + _write_index = 0; + _read_index = 0; + } + + return (lengthToRead / _dataSize); + } + + // Pop N elements from ring buffer. The elements are not actually returned, just popped from the buffer. + size_t Pop(size_t length) + { + size_t lengthToRead = 0; + + // sanity check for 0 length + if (length == 0) return 0; + + // check for buffer empty + if(_size == 0) + { + return 0; + } + + lengthToRead = (length * _dataSize); + + // can read in a single memcpy + if (lengthToRead <= _capacity - _read_index) + { + _read_index += lengthToRead; + + // check if we are at end of capacity + if (_read_index == _capacity) _read_index = 0; + } + // need to memcpy in two steps + else + { + size_t chunk1Size = _capacity - _read_index; + size_t chunk2Size = lengthToRead - chunk1Size; + _read_index = chunk2Size; + } + + // update ring buffer size + _size -= lengthToRead; + + // check for optimization to improve sequential push + // buffer has to be empty and read and write indexes coincide + if(_size == 0 && (_write_index == _read_index)) + { + // reset the read/write index + _write_index = 0; + _read_index = 0; + } + + return (lengthToRead / _dataSize); + } + + void OptimizeSequence() + { + // no elements, so there is nothing to optimize + if(_size == 0) return; + + // read index is already at index 0, so there is nothing to optimize + if(_read_index == 0) return; + + // can move data in a single memcpy + if (_read_index < _write_index) + { + // buffer looks like this + // |...xxxxx.....| + memcpy(_buffer, _buffer + _read_index, _size); + } + // need to move data in two steps + else + { + // buffer looks like this + // |xxxx......xxxxxx| + + // store size of tail + size_t tailSize = _write_index - (1 * _dataSize); + + // 1st move tail to temp buffer (need to malloc first) + T* tempBuffer = (T*)platform_malloc(tailSize); + + memcpy(tempBuffer, _buffer, tailSize); + + // store size of remaining buffer + size_t headSize = _capacity - _read_index; + + // 2nd move head to start of buffer + memcpy(_buffer, _buffer + _read_index, headSize); + + // 3rd move temp buffer after head + memcpy(_buffer + headSize, tempBuffer, tailSize); + + // free memory + platform_free(tempBuffer); + } + + // adjust indexes + _read_index = 0; + _write_index = _size; + } + + T* Reader() { return _buffer + _read_index; } +}; + +//--// + +//#include <..\Initialization\MasterConfig.h> + + + + + + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// hal cleanup for CLR reboot + +void nanoHAL_Initialize(); +void nanoHAL_Uninitialize(); + +void HAL_EnterBooterMode(); + +typedef void (*ON_SOFT_REBOOT_HANDLER)(void); + +void HAL_AddSoftRebootHandler(ON_SOFT_REBOOT_HANDLER handler); + +//--// + + + + + + + + + + + + + + + + + +//--// + + + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//--// + +extern bool g_fDoNotUninitializeDebuggerPort; + +//--// + +#include +#include +//#include + +///////////////////////////////////////////////////////////////////// +// +// Chipset +// + +//// boot +//#include +// +//// Cache driver +//#include +// +//// Cache driver +//#include +// +//// Gp I/O driver +//#include +// +//// Gp I/O driver +//#include +// + + + + + + + + + + + + + + + + + + +// +//// SPI driver +//#include +// +//// External bus interface driver +//#include +// +//// Power control unit +//#include +// +//// Clock management unit driver +//#include +// +//// DMA driver +//#include +// +//#include +// +//// Virtual Key +//#include +// + +//// Power API +//#include + + + +// +// Chipset +// +///////////////////////////////////////////////////////////////////// + +//#include + + +// platform_selector.h (from MasterConfig.h) + +#if defined(_WIN32) + +#define GLOBAL_LOCK() +#define GLOBAL_UNLOCK() + +#if defined(_DEBUG) +#define ASSERT_IRQ_MUST_BE_ON() ASSERT(!HAL_Windows_HasGlobalLock()) +#else +#define ASSERT_IRQ_MUST_BE_ON() +#endif + +#elif defined(__arm__) | defined(PLATFORM_ESP32) +// nothing to define here just to help the nanoCLR VS project to build hapilly +#else +#error Unsupported platform +#endif + +#endif // _NANOHAL_H_ diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_ConfigurationManager.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_ConfigurationManager.h new file mode 100644 index 00000000..a1c7df09 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_ConfigurationManager.h @@ -0,0 +1,157 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOHAL_CONFIG_MANAGER_H_ +#define _NANOHAL_CONFIG_MANAGER_H_ 1 + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.DeviceConfiguration.DeviceConfigurationOption (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef enum DeviceConfigurationOption +{ + // Network configuration block + DeviceConfigurationOption_Network = 1, + + // Wireless 802.11 Network configuration block + DeviceConfigurationOption_Wireless80211Network = 2, + + // Wireless Network as AP configuration block + DeviceConfigurationOption_WirelessNetworkAP = 3, + + // X509 CA Root Certificates bundle block + DeviceConfigurationOption_X509CaRootBundle = 4, + + // All configuration blocks + DeviceConfigurationOption_All = 255, + +} DeviceConfigurationOption; + +// network interface configuration struct +// declared with a flexible array member to allow N config blocks totally independent of compilation +typedef struct HAL_CONFIGURATION_NETWORK +{ + // count of the configs elements + uint8_t Count; + + // pointer to the network interface configuration + HAL_Configuration_NetworkInterface* Configs[]; + +} HAL_CONFIGURATION_NETWORK; + +// network wireless interface configuration struct +// declared with a flexible array member to allow N config blocks totally independent of compilation +typedef struct HAL_CONFIGURATION_NETWORK_WIRELESS80211 +{ + // count of the configs elements + uint8_t Count; + + // pointer to the wireless network interface configuration + HAL_Configuration_Wireless80211* Configs[]; + +} HAL_CONFIGURATION_NETWORK_WIRELESS80211; + +// network wireless interface configuration struct +// declared with a flexible array member to allow N config blocks totally independent of compilation +typedef struct HAL_CONFIGURATION_NETWORK_WIRELESSAP +{ + // count of the configs elements + uint8_t Count; + + // pointer to the wireless network interface configuration + HAL_Configuration_WirelessAP* Configs[]; + +} HAL_CONFIGURATION_NETWORK_WIRELESSAP; + + +// certificate store struct +// declared with a flexible array member to allow N config blocks totally independent of compilation +typedef struct HAL_CONFIGURATION_X509_CERTIFICATE +{ + // count of the configs elements + uint8_t Count; + + // pointer to the certificates + HAL_Configuration_X509CaRootBundle* Certificates[]; + +} HAL_CONFIGURATION_X509_CERTIFICATE; + +// target configuration storage struct +// the memory allocation for these will have to be done as required according to the number and type of blocks found in memory +typedef struct HAL_TARGET_CONFIGURATION +{ + HAL_CONFIGURATION_NETWORK* NetworkInterfaceConfigs; + HAL_CONFIGURATION_NETWORK_WIRELESS80211* Wireless80211Configs; + HAL_CONFIGURATION_NETWORK_WIRELESSAP* WirelessAPConfigs; + HAL_CONFIGURATION_X509_CERTIFICATE* CertificateStore; + +} HAL_TARGET_CONFIGURATION; + +// Initialization of configuration manager +void ConfigurationManager_Initialize(); + +// Enumerates the configuration blocks +// This is provided as a separate function to allow it to be called when there is a need to re-enumerate the blocks +// for example when a new block is added from the debug or from the managed application +void ConfigurationManager_EnumerateConfigurationBlocks(); + +// GetConfigurationBlock() is defined in targetHAL_ConfigurationManager.cpp at target level because the target +// needs to be free to implement the storage of the configuration block as they see fit +bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex); + +// StoreConfigurationBlock() is defined in targetHAL_ConfigurationManager.cpp at target level because the target +// needs to be free to implement the storage of the configuration block as they see fit +bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize, uint32_t offset); + +// UpdateConfigurationBlock() is defined in targetHAL_ConfigurationManager.cpp at target level because the target +// needs to be free to implement the storage of the configuration block as they see fit +bool ConfigurationManager_UpdateConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex); + + +// Default initialisation for wireless config block +void InitialiseWirelessDefaultConfig(HAL_Configuration_Wireless80211 * pconfig, uint32_t configurationIndex); + +// Default initialisation for wireless AP config block +void InitialiseWirelessAPDefaultConfig(HAL_Configuration_WirelessAP * pconfig, uint32_t configurationIndex); + +// Default initialisation for Network interface config blocks +// returns FALSE if it's not possible to create a default config block +bool InitialiseNetworkDefaultConfig(HAL_Configuration_NetworkInterface * pconfig, uint32_t configurationIndex); + +// helper functions + +// function that sweeps a memory region searching for network configuration blocks +void* ConfigurationManager_FindNetworkConfigurationBlocks(uint32_t startAddress, uint32_t endAddress); + +// function that sweeps a memory region searching for wireless network configuration blocks +void* ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks(uint32_t startAddress, uint32_t endAddress); + +// function that sweeps a memory region searching for X509 certificates configuration blocks +void* ConfigurationManager_FindX509CertificateConfigurationBlocks(uint32_t startAddress, uint32_t endAddress); + +// gets the HAL_Configuration_Wireless80211 configuration block that has the specified Id, if that exists +// defined as weak needs to be free to implement the storage of the configuration block as they see fit +HAL_Configuration_Wireless80211* ConfigurationManager_GetWirelessConfigurationFromId(uint32_t configurationId); + +// gets the HAL_Configuration_WirelessAP configuration block that has the specified Id, if that exists +// defined as weak needs to be free to implement the storage of the configuration block as they see fit +HAL_Configuration_WirelessAP* ConfigurationManager_GetWirelessAPConfigurationFromId(uint32_t configurationId); + +#ifdef __cplusplus +} +#endif + +// declaration of Target configuration union as external, has to be provided at target level +extern HAL_TARGET_CONFIGURATION g_TargetConfiguration; + +#endif //_NANOHAL_CONFIG_MANAGER_H_ diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Network.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Network.h new file mode 100644 index 00000000..45644565 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Network.h @@ -0,0 +1,292 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOHAL_NETWORK_H_ +#define _NANOHAL_NETWORK_H_ 1 + +#include +#include +#include + +// this is the maximum hardware address length (MAC address) +// setting it to 6 and using the same define that lwIP uses for this +#define NETIF_MAX_HWADDR_LEN 6 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.Wireless80211Configuration.MaxPasswordLength (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// this is the maximum wireless 802.11 configuration password length +#define WIRELESS82011_CONFIG_MAX_PASSWORD_LEN 64 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.Wireless80211Configuration.MaxSsidLength (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// this is the maximum wireless 802.11 configuration SSID length +#define WIRELESS82011_CONFIG_MAX_SSID_LEN 32 + +///////////////////////////////////////// +// network configuration block markers // +///////////////////////////////////////// + +// Network configuration block start marker +static const unsigned char c_MARKER_CONFIGURATION_NETWORK_V1[] = "CN1"; + +// Network configuration block start marker +static const unsigned char c_MARKER_CONFIGURATION_WIRELESS80211_V1[] = "WN1"; + +// Wireless AP configuration block start marker +static const unsigned char c_MARKER_CONFIGURATION_WIRELESS_AP_V1[] = "AP1"; + +// X509 certificate configuration block start marker +static const unsigned char c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1[] = "XB1"; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.NetworkInterfaceType (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////// +// Description: network interface type +typedef enum __nfpack NetworkInterfaceType +{ + NetworkInterfaceType_Unknown = 1, + NetworkInterfaceType_Ethernet = 6, + NetworkInterfaceType_Wireless80211 = 71, + NetworkInterfaceType_WirelessAP = 72, +}NetworkInterfaceType; + +/////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.AddressMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////// +// Description: Startup network IP assigning modes +typedef enum __nfpack AddressMode +{ + AddressMode_DHCP = 0x01, + AddressMode_Static = 0x02, + + //////////////////////////////////////// + // for this option to be valid + // LWIP_AUTOIP (lwIP option) has to be defined + AddressMode_AutoIP = 0x03 + +}AddressMode; + +////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.AuthenticationType (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////// +// Description: authentication used in wireless network +typedef enum __nfpack AuthenticationType +{ + AuthenticationType_None = 0x00, + AuthenticationType_EAP = 0x01, + AuthenticationType_PEAP = 0x02, + AuthenticationType_WCN = 0x03, + AuthenticationType_Open = 0x04, + AuthenticationType_Shared = 0x05, + AuthenticationType_WEP = 0x06, + AuthenticationType_WPA = 0x07, + AuthenticationType_WPA2 = 0x08, + +}AuthenticationType; + +////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.EncryptionType (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////// +// Description: encryption used in wireless network +typedef enum __nfpack EncryptionType +{ + EncryptionType_None = 0x00, + EncryptionType_WEP = 0x01, + EncryptionType_WPA = 0x02, + EncryptionType_WPA2 = 0x03, + EncryptionType_WPA_PSK = 0x04, + EncryptionType_WPA2_PSK = 0x05, + EncryptionType_Certificate = 0x06, + +}EncryptionType; + +///////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.RadioType (in managed code) !!! // +///////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Description: type of radio that the wireless network uses +typedef enum __nfpack RadioType +{ + RadioType_NotSpecified = 0x00, + RadioType_802_11a = 0x01, + RadioType_802_11b = 0x02, + RadioType_802_11g = 0x03, + RadioType_802_11n = 0x04, +}RadioType; + +typedef struct __nfpack HAL_Configuration_NetworkInterface { + + // this is the marker placeholder for this configuration block + uint8_t Marker[4]; + + // Pointer to MAC address as an array of 6 unsigned bytes. + uint8_t MacAddress[6]; + + // Network IPv4 address as 32-bit unsigned integer + uint32_t IPv4Address; + + // Network IPv4 subnet mask as 32-bit unsigned integer + uint32_t IPv4NetMask; + + // Network gateway IPv4 address as 32-bit unsigned integer + uint32_t IPv4GatewayAddress; + + // DNS server 1 IPv4 address as 32-bit unsigned integer + uint32_t IPv4DNSAddress1; + + // DNS server 2 IPv4 address as 32-bit unsigned integer + uint32_t IPv4DNSAddress2; + + // Network IPv6 address as an array of 4 32-bit unsigned integers + uint32_t IPv6Address[4]; + + // Network IPv6 subnet mask as an array of 4 32-bit unsigned integers + uint32_t IPv6NetMask[4]; + + // Network gateway IPv6 address as an array of 4 32-bit unsigned integers + uint32_t IPv6GatewayAddress[4]; + + // DNS server 1 IPv6 address as an array of 4 32-bit unsigned integers + uint32_t IPv6DNSAddress1[4]; + + // DNS server 2 IPv6 address as an array of 4 32-bit unsigned integers + uint32_t IPv6DNSAddress2[4]; + + // interface type + NetworkInterfaceType InterfaceType; + + // Specific configuration Id + // Id of the configuration block specific for this interface type + // NULL otherwise + // currently in use: + // - HAL_Configuration_Wireless80211 for NetworkInterfaceType_Wireless80211 + uint32_t SpecificConfigId; + + // Option to use DNS addresses from DHCP or static ones + uint8_t AutomaticDNS; + + // Startup network addressing mode - static, DHCP, auto + AddressMode StartupAddressMode; + +} HAL_Configuration_NetworkInterface; + +typedef enum __nfpack WirelessFlags +{ + WirelessFlags_None = 0x00, + WirelessFlags_Enable = 0x01, // Enable Station or AP ( Wifi component started & memory allocated ) + WirelessFlags_Auto = 0x02, // Wireless station automatically connects on CLR start + WirelessFlags_SmartConfig = 0x04 // Enable Smart config +} WirelessFlags; + +typedef enum __nfpack WirelessAPFlags +{ + WirelessAPFlags_None = 0x00, + WirelessAPFlags_Enable = 0x01, // Enable Wireless AP ( Wifi component started & memory allocated ) + WirelessAPFlags_Auto = 0x02, // Wireless AP automatically starts on CLR start + WirelessAPFlags_Hidden_SSID = 0x04, // Wireless AP uses hidden SSID +} WirelessAPFlags; + +typedef struct __nfpack HAL_Configuration_Wireless80211 { + + // this is the marker placeholder for this configuration block + uint8_t Marker[4]; + + // Id of the configuration + uint32_t Id; + + // Type of authentication used on the wireless network, For AP is the type of Authenication to use on network. + AuthenticationType Authentication; + + // Type of encryption used on the wireless network. + EncryptionType Encryption; + + // Type of radio used by the wireless network adapter. + RadioType Radio; + + // Network SSID - For AP if no SSID given a default value of nano_xxx where xxx is last part of MAC address + uint8_t Ssid[32]; + + // Network password + uint8_t Password[64]; + + // Wireless Flags, depends if wireless Station + uint8_t Flags; + + // Rssi, station only + +} HAL_Configuration_Wireless80211; + +typedef struct __nfpack HAL_Configuration_WirelessAP { + + // this is the marker placeholder for this configuration block + uint8_t Marker[4]; + + // Id of the configuration + uint32_t Id; + + // Type of authentication used on the wireless network, For AP is the type of Authenication to use on network. + AuthenticationType Authentication; + + // Type of encryption used on the wireless network. + EncryptionType Encryption; + + // Type of radio used by the wireless network adapter. + RadioType Radio; + + // Network SSID - For AP if no SSID given a default value of nano_xxx where xxx is last part of MAC address + uint8_t Ssid[32]; + + // Network password + uint8_t Password[64]; + + // Wireless Flags for AP + uint8_t Flags; + + // channel used for AP + uint8_t Channel; + + // Max client connections + uint8_t MaxConnections; + +} HAL_Configuration_WirelessAP; + +typedef struct __nfpack HAL_Configuration_X509CaRootBundle { + + // this is the marker placeholder for this configuration block + uint8_t Marker[4]; + + // Size of the X509 CA Root certificate bundle + uint32_t CertificateSize; + + // X509 CA Root certificate bundle + uint8_t Certificate[1]; + +} HAL_Configuration_X509CaRootBundle; + + +void nanoHAL_Network_Initialize(); +void sys_signal_sock_event(); + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif //_NANOHAL_NETWORK_H_ diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Power.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Power.h new file mode 100644 index 00000000..e8e6a2bc --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Power.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOHAL_POWER_H_ +#define _NANOHAL_POWER_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum PowerLevel +{ + PowerLevel__Active, + PowerLevel__SelectiveOff, + PowerLevel__Sleep, + PowerLevel__DeepSleep, + PowerLevel__Off +}PowerLevel_type; + + +// this is used to store the CPU wakeup reason +// a target implementation can use it or not +// if it's used suggest to add the variable at targetHAL_Power.c +extern uint32_t WakeupReasonStore; + +bool CPU_IsSoftRebootSupported(); + +#ifdef __cplusplus +} +#endif + +#endif //_NANOHAL_POWER_H_ diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_ReleaseInfo.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_ReleaseInfo.h new file mode 100644 index 00000000..248b5c3e --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_ReleaseInfo.h @@ -0,0 +1,90 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOHAL_RELEASEINFO_H_ +#define _NANOHAL_RELEASEINFO_H_ 1 + +#include + +struct __nfpack NFVersion +{ + unsigned short usMajor; + unsigned short usMinor; + unsigned short usBuild; + unsigned short usRevision; + + // Version & NFReleaseInfo participate in a union in the debugging support, + // and therefore cannot have real constructors, though that would be better + // style otherwise. + static void Init(NFVersion& version, unsigned short major=0, unsigned short minor=0, unsigned short build=0, unsigned short revision=0) + { + version.usMajor = major; + version.usMinor = minor; + version.usBuild = build; + version.usRevision = revision; + } +}; + +struct __nfpack NFReleaseInfo +{ + NFVersion Version; + unsigned char InfoString[128]; + unsigned char TargetName[32]; + unsigned char PlatformName[32]; + + static void Init( + NFReleaseInfo& releaseInfo, + unsigned short major=0, + unsigned short minor=0, + unsigned short build=0, + unsigned short revision=0, + const char *info=(const char *)NULL, + size_t infoLen=0, + const char *target=(const char *)NULL, + size_t targetLen=0, + const char *platform=(const char *)NULL, + size_t platformLen=0 + ); +}; + +struct __nfpack OEM_MODEL_SKU +{ + unsigned char OEM; + unsigned char Model; + unsigned short SKU; +}; + +struct __nfpack OEM_SERIAL_NUMBERS +{ + unsigned char module_serial_number[32]; + unsigned char system_serial_number[16]; +}; + +struct __nfpack HalSystemInfo +{ + NFReleaseInfo m_releaseInfo; + OEM_MODEL_SKU m_OemModelInfo; + OEM_SERIAL_NUMBERS m_OemSerialNumbers; +}; + +//--// + +// GetHalSystemInfo() is defined in \src\HAL\nanoHAL_SystemInformation.cpp and is provided +// to allow convenient access to configuration and build information to the debugging +// system and to managed code. +bool GetHalSystemInfo(HalSystemInfo& systemInfo); + +// Solution-specific function; see nanoBooterEntry.cpp in your solution's nanoBooter directory for implementation. +unsigned int nanoBooter_GetReleaseInfo(NFReleaseInfo& releaseInfo); + +// target specific function, provide this to allow access to a vendor-provided +// informative string, platform, target and build-time version information. +bool Target_GetReleaseInfo(NFReleaseInfo&); + +//--// + + +#endif // _NANOHAL_RELEASEINFO_H_ + diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Time.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Time.h new file mode 100644 index 00000000..bb6b67ab --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Time.h @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOHAL_TIME_H_ +#define _NANOHAL_TIME_H_ 1 + +#include +#include +#include + +/// Our time origin is 1/1/1601 00:00:00.000.000. In Gregorian Calendar Jan 1, 1601 was also a Monday. +#define BASE_YEAR 1601 +#define BASE_YEAR_LEAPYEAR_ADJUST 388 +#define DAYS_IN_NORMAL_YEAR 365 +#define BASE_YEAR_DAYOFWEEK_SHIFT 1 + +#define TIME_CONVERSION__TO_MILLISECONDS 10000 +#define TIME_CONVERSION__TO_SECONDS 10000000 +#define TIME_CONVERSION__TICKUNITS 10000 +#define TIME_CONVERSION__ONESECOND 1 +#define TIME_CONVERSION__ONEMINUTE 60 +#define TIME_CONVERSION__ONEHOUR 3600 +#define TIME_CONVERSION__ONEDAY 86400 + +#define TIMEOUT_ZERO LONGLONGCONSTANT(0x0000000000000000) +#define TIMEOUT_INFINITE LONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF) + +// UNDONE: FIXME #define TIME_ZONE_OFFSET ((signed long long)Time_GetTimeZoneOffset() * 600000000) + +#define NANOHAL_TIME_CONVERSION_MICRO_TO_SECONDS 1000000 + +#define TIME_UNIX_EPOCH_AS_TICKS 116444736000000000 + +/// NOTES: Why origin is at 1/1/1601. +/// Current civil calendar is named as Gregorian calendar after Pope Gregory XIII as he made adjustments +/// in 1582 (read more at wiki http://en.wikipedia.org/wiki/Gregorian_calendar). Rules governing +/// leap years were changed from then. Also in that year month October was 21 days instead of usual 31. +/// This poses a problem on calculating date/time difference, leap years etc before 1582 using simple math. +/// For example 1500 was a leap year using old method while it is not using new. But in reality, as part of the +/// history it was leap year. Default CLR origin 1/1/01 gives wrong date time from years before 1582. For example +/// dates like 10/6/1582 does exist in history (see wiki), while CLR managed date/time will not throw an exception +/// if you are to create that date. To stay safe side 1/1/1601 is taken as origin, as was done for Windows. + + +uint64_t HAL_Time_SysTicksToTime(unsigned int sysTicks); + +/// +/// System time and date for DateTime managed class. +/// This value will be provided by the system tick or from an RTC if hardware support exists and if the board designer has enabled it in the configuration options. +/// The datePartOnly allows returning only the date part with the time fields zeroed. +/// +/// Returns current time in 100ns elapsed since 1/1/1601:00:00:00.000 UTC. +uint64_t HAL_Time_CurrentDateTime(bool datePartOnly); + +/// +/// Time according to this system. +/// +/// Returns current time in 100ns elapsed since 1/1/1601:00:00:00.000 UTC. +uint64_t HAL_Time_CurrentTime(); + +/// +/// Set UTC time of the system. This will be effective immediately. +/// +/// In 100ns since 1/1/1601:00:00:00.000 +void HAL_Time_SetUtcTime(uint64_t utcTime); + +/// +/// Retrieves time since device was booted. +/// +/// Time in 100ns. +//signed long long HAL_Time_GetMachineTime(); + +/// +/// Converts 64bit time value to SystemTime structure. 64bit time is assumed as an offset from 1/1/1601:00:00:00.000 in 100ns. +/// +/// True if conversion is successful. +bool HAL_Time_ToSystemTime(uint64_t time, SYSTEMTIME* systemTime); + +/// +/// Retrieves number of days given a month and a year. Calculates for leap years. +/// +/// S_OK if successful. +HRESULT HAL_Time_DaysInMonth(signed int year, signed int month, signed int* days); + +/// +/// Retrieves number of days since the beginning of the year given a month and a year. Calculates for leap years. +/// +/// S_OK if successful. +HRESULT HAL_Time_AccDaysInMonth(signed int year, signed int month, signed int* days); + +/// +/// Converts SYSTEMTIME structure to 64bit time, which is assumed as an offset from 1/1/1601:00:00:00.000 in 100ns. +/// +/// Time value. +uint64_t HAL_Time_ConvertFromSystemTime(const SYSTEMTIME* systemTime); + +/// APIs to convert between types +bool HAL_Time_TimeSpanToStringEx( const int64_t& ticks, char*& buf, size_t& len ); +const char* HAL_Time_CurrentDateTimeToString(); + + +uint64_t CPU_MillisecondsToTicks ( uint64_t ticks ); + +#endif //_NANOHAL_TIME_H_ diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Types.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Types.h new file mode 100644 index 00000000..6b181898 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Types.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _HAL_TYPES_H_ +#define _HAL_TYPES_H_ 1 + +#include + +#include + +#if defined (__GNUC__) +#define __int64 long long +#undef NULL +#endif + +#if defined(__arm) || defined(__GNUC__) + +#undef UNICODE + +#define NULL 0 + +#endif //defined(__arm) || defined(__GNUC__) + +#define ARRAYSIZE_CONST_EXPR(x) (sizeof(x)/sizeof(x[0])) +#if (!defined(_WIN32) && !defined(WIN32)) +#define ARRAYSIZE(x) ARRAYSIZE_CONST_EXPR(x) +#endif +#define MAXSTRLEN(x) (ARRAYSIZE(x)-1) +#define ROUNDTOMULTIPLE(x,y) ((x + sizeof(y) - 1) & ~(sizeof(y)-1)) // Only works with powers of 2. +#define CONVERTFROMSIZETOELEMENTS(x,y) ((x + sizeof(y) - 1) / sizeof(y)) +#define CONVERTFROMSIZETOHEAPBLOCKS(x) CONVERTFROMSIZETOELEMENTS(x,CLR_RT_HeapBlock) + +//--// + +#if !(defined(_WIN32) || defined(WIN32)) + +typedef struct SYSTEMTIME +{ + unsigned short wYear; + unsigned short wMonth; + unsigned short wDayOfWeek; + unsigned short wDay; + unsigned short wHour; + unsigned short wMinute; + unsigned short wSecond; + unsigned short wMilliseconds; +} SYSTEMTIME; + +#endif // !(defined(_WIN32) || defined(WIN32)) + +#endif // _HAL_TYPES_H_ + diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Watchdog.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Watchdog.h new file mode 100644 index 00000000..a4506fd4 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Watchdog.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOHAL_WATCHDOG_H_ +#define _NANOHAL_WATCHDOG_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + //Watchdog functions + void Watchdog_Init(); + void Watchdog_Reset(); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Windows_Storage.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Windows_Storage.h new file mode 100644 index 00000000..d5cd01e6 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_Windows_Storage.h @@ -0,0 +1,72 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOHAL_WINDOWS_STORAGE_H_ +#define _NANOHAL_WINDOWS_STORAGE_H_ 1 + +#include + +// FatFs define for size of file name members +// ANSI/OEM at DBCS +#define FF_LFN_BUF 255 + +// driver letters and paths +// drive letter for SD Card +#define INDEX0_DRIVE_LETTER "D:" +#define INDEX0_DRIVE_PATH INDEX0_DRIVE_LETTER"\\" +// drive letter for USB mass storage device +#define INDEX1_DRIVE_LETTER "E:" +#define INDEX1_DRIVE_PATH INDEX1_DRIVE_LETTER"\\" +// spare drive letter +#define INDEX2_DRIVE_LETTER "F:" +#define INDEX2_DRIVE_PATH INDEX2_DRIVE_LETTER"\\" +// drive letter for internal drive (SPIFFS) +#define INTERNAL_DRIVE_LETTER "I:" +#define INTERNAL_DRIVE_PATH INTERNAL_DRIVE_LETTER"\\" + +////////////////////////////////////////////////////////////////////////// +// Keep in sync with StorageEventManager.StorageEventType in managed code +// Storage events sub-categories +////////////////////////////////////////////////////////////////////////// +typedef enum StorageEventType +{ + // INVALID + StorageEventType_Invalid = 0x00, + + // removable device inserted + StorageEventType_RemovableDeviceInsertion = 0x01, + + // removable device removed + StorageEventType_RemovableDeviceRemoval = 0x02, + +}StorageEventType; + +// constants to be used throughout the code +#define SUPPORTED_DRIVES_COUNT (2) +#define DRIVE_LETTER_LENGTH sizeof(INDEX0_DRIVE_LETTER) +#define DRIVE_PATH_LENGTH sizeof(INDEX0_DRIVE_PATH) + +///////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Storage.CreationCollisionOption (in managed code) !!! // +///////////////////////////////////////////////////////////////////////////////////////// + +enum CreationCollisionOption +{ + CreationCollisionOption_GenerateUniqueName = 0, + CreationCollisionOption_ReplaceExisting, + CreationCollisionOption_FailIfExists, + CreationCollisionOption_OpenIfExists +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void Target_FileSystemInit(void); + +#ifdef __cplusplus +} +#endif + +#endif // _NANOHAL_WINDOWS_STORAGE_H_ diff --git a/source/native/nf-interpreter/src/HAL/Include/nanoHAL_v2.h b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_v2.h new file mode 100644 index 00000000..5e539139 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/Include/nanoHAL_v2.h @@ -0,0 +1,351 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOHAL_V2_H_ +#define _NANOHAL_V2_H_ 1 + +#include +#include +#include +#include + +#include +#include +#include + +typedef enum SYSTEM_STATE +{ + SYSTEM_STATE_ISR, + SYSTEM_STATE_NO_CONTINUATIONS, + SYSTEM_STATE_TOTAL_STATES +} SYSTEM_STATE_type; + +////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Microsoft.SPOT.Hardware.SleepLevel !!! // +////////////////////////////////////////////////////////////////// +typedef enum SLEEP_LEVEL +{ + SLEEP_LEVEL__AWAKE = 0x00, + SLEEP_LEVEL__SELECTIVE_OFF = 0x10, + SLEEP_LEVEL__SLEEP = 0x20, + SLEEP_LEVEL__DEEP_SLEEP = 0x30, + SLEEP_LEVEL__OFF = 0x40, +} SLEEP_LEVEL_type; + +//These events match emulator events in Framework\Tools\Emulator\Events.cs + +#define SYSTEM_EVENT_FLAG_COM_IN 0x00000001 +#define SYSTEM_EVENT_FLAG_COM_OUT 0x00000002 +#define SYSTEM_EVENT_FLAG_STORAGE_IO 0x00000004 +#define SYSTEM_EVENT_FLAG_SYSTEM_TIMER 0x00000010 +//#define SYSTEM_EVENT_FLAG_TIMER1 0x00000020 +//#define SYSTEM_EVENT_FLAG_TIMER2 0x00000040 +//#define SYSTEM_EVENT_FLAG_BUTTON 0x00000080 +#define SYSTEM_EVENT_FLAG_GENERIC_PORT 0x00000100 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00000200 0x00000200 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00000400 0x00000400 +#define SYSTEM_EVENT_FLAG_NETWORK 0x00000800 +//#define SYSTEM_EVENT_FLAG_TONE_COMPLETE 0x00001000 +//#define SYSTEM_EVENT_FLAG_TONE_BUFFER_EMPTY 0x00002000 +#define SYSTEM_EVENT_FLAG_SOCKET 0x00004000 +#define SYSTEM_EVENT_FLAG_ONEWIRE_MASTER 0x00008000 +//#define SYSTEM_EVENT_FLAG_SPI 0x00008000 +//#define SYSTEM_EVENT_FLAG_OEM_RESERVED_1 0x00020000 +//#define SYSTEM_EVENT_FLAG_OEM_RESERVED_2 0x00040000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00080000 0x00080000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00100000 0x00100000 + + + + + + + +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00200000 0x00200000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00400000 0x00400000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00800000 0x00800000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x01000000 0x01000000 +#define SYSTEM_EVENT_FLAG_SPI_MASTER 0x02000000 +#define SYSTEM_EVENT_FLAG_I2C_MASTER 0x04000000 +#define SYSTEM_EVENT_HW_INTERRUPT 0x08000000 +#define SYSTEM_EVENT_FLAG_DEBUGGER_ACTIVITY 0x20000000 +#define SYSTEM_EVENT_FLAG_MESSAGING_ACTIVITY 0x40000000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x80000000 0x80000000 +#define SYSTEM_EVENT_FLAG_ALL 0xFFFFFFFF + + +//////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Runtime.Events.EventCategory (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////// + +#define EVENT_UNKNOWN 0 +#define EVENT_CUSTOM 10 +#define EVENT_GPIO 20 +#define EVENT_SERIAL 30 +#define EVENT_NETWORK 40 +#define EVENT_WIFI 50 +#define EVENT_CAN 60 +#define EVENT_STORAGE 70 + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// + + +// COM_HANDLE Defines a type representing both a port type or "transport" and a port number +// The COM_HANDLE is a multi bit field value with the following bit fields usage +// |--------+--------+--------+--------| +// |33222222|22221111|111111 | | +// |10987654|32109876|54321098|76543210| bit position +// |--------+--------+--------+--------| +// |00000000|00000000|TTTTTTTT|pppppppp| ( transport != USB_TRANSPORT ) +// |--------+--------+--------+--------| +// |00000000|00000000|TTTTTTTT|cccppppp| ( transport == USB_TRANSPORT ) +// |--------+--------+--------+--------| +// +// where: +// T => Transport type +// USART_TRANSPORT => 1 +// USB_TRANSPORT => 2 +// SOCKET_TRANSPORT => 3 +// DEBUG_TRANSPORT => 4 +// LCD_TRANSPORT => 5 +// FLASH_WRITE_TRANSPORT => 6 +// MESSAGING_TRANSPORT => 7 +// GENERIC_TRANSPORT => 8 +// p => port instance number +// Port instances in the handle are 1 based. (e.g. p == 0 is invalid except when T == 0 ) +// c -> Controller instance number ( USB_TRANSPORT only ) +// +// NULL_PORT => T==0 && p == 0 +// +// GENERIC_TRANSPORT is any custom port that isn't one of the above, they +// are implemented for the DebugPort_xxxx APIs and the port number is +// an index into a const global table of port interfaces (structure of +// function pointers) These allow custom extensions to the normal transports +// without needing to continue defining additional transport types and modifying +// switch on transport code. To keep compatibility high and code churn low, the +// previous legacy transports remain though they should be considered deprecated. +typedef int COM_HANDLE; + +typedef struct HAL_DRIVER_CONFIG_HEADER +{ + unsigned int Enable; +}HAL_DRIVER_CONFIG_HEADER; + +typedef struct HAL_SYSTEM_MEMORY_CONFIG +{ + unsigned int Base; + unsigned int Size; +}HAL_SYSTEM_MEMORY_CONFIG; + +typedef struct HAL_SYSTEM_CONFIG +{ + HAL_DRIVER_CONFIG_HEADER Header; + + //--// + + COM_HANDLE DebuggerPort; + // communication channel for debug messages in the debugger + // which may be VS, MFDEPLOY, etc... Accessed via debug_printf + // in the HAL/PAL and System.Diagnostics.Debug.Print() in managed + // applications + COM_HANDLE DebugTextPort; + + unsigned int USART_DefaultBaudRate; + // internal HAL/PAL debug/tracing channel, this is separate + // to allow tracing messages in the driver that implements + // the transport for the Debugger and DebugTextPort. This + // channel is accessed via hal_printf() in the HAL/PAL + COM_HANDLE stdio; + + HAL_SYSTEM_MEMORY_CONFIG RAM1; + HAL_SYSTEM_MEMORY_CONFIG FLASH1; + +}HAL_SYSTEM_CONFIG; + +extern HAL_SYSTEM_CONFIG HalSystemConfig; + +#ifdef __cplusplus +extern "C" { +#endif + +void nanoHAL_Initialize_C(); +void nanoHAL_Uninitialize_C(); +void HeapLocation_C(unsigned char** baseAddress, unsigned int* sizeInBytes); + +// Call to the external memory configuration and initialization function +// If a target has external memory it has to provide the implementation for it. +void Target_ExternalMemoryInit(); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void CPU_Reset(); +void CPU_Sleep(SLEEP_LEVEL_type level, uint64_t wakeEvents); +void CPU_SetPowerMode(PowerLevel_type powerLevel); + +#ifdef __cplusplus +} +#endif + +//--// + +// +// This has to be extern "C" because we want to use platform implemented malloc +// +#ifdef __cplusplus +extern "C" { +#endif + +void* platform_malloc ( size_t size ); +void platform_free ( void* ptr ); +void* platform_realloc( void* ptr, size_t size ); + +#ifdef __cplusplus +} +#endif + +void SystemState_Set ( SYSTEM_STATE_type newState ); +void SystemState_Clear( SYSTEM_STATE_type state ); +bool SystemState_Query( SYSTEM_STATE_type state ); + +//--// + + +#ifdef __cplusplus +extern "C" { +#endif + +void SystemState_SetNoLock ( SYSTEM_STATE_type state ); +void SystemState_ClearNoLock( SYSTEM_STATE_type state ); +bool SystemState_QueryNoLock( SYSTEM_STATE_type state ); + +#ifdef __cplusplus +} +#endif + +//--// + +#define HAL_COMPLETION_IDLE_VALUE 0x0000FFFFFFFFFFFFull + +// provide platform dependent delay to CLR code +#if defined(_WIN32) +#define OS_DELAY(milliSecs); +#else +#define OS_DELAY(milliSecs) PLATFORM_DELAY(milliSecs) +#endif + +//--// +// Function macros + +#ifdef __cplusplus +extern "C" { +#endif + +void HAL_Assert ( const char* Func, int Line, const char* File ); +// HAL_AssertEx is to be defined at platform layer +void HAL_AssertEx(); + +#ifdef __cplusplus +} +#endif + +#if defined(PLATFORM_ARM) || defined(PLATFORM_ESP32) + #if !defined(BUILD_RTM) + #define ASSERT(i) { if(!(i)) HAL_AssertEx(); } + #define _SIDE_ASSERTE(i) { if(!(i)) HAL_AssertEx(); } + #endif +#else + #if defined(_DEBUG) +#if !defined _ASSERTE +#error +#endif + #define ASSERT(i) _ASSERTE(i) + #define _SIDE_ASSERTE(i) _ASSERTE(i) + #endif +#endif + +#ifndef ASSERT +#define ASSERT(i) +#endif + +#ifndef _ASSERTE +#define _ASSERTE(expr) ASSERT(expr) +#endif + +#ifndef _SIDE_ASSERTE +#define _SIDE_ASSERTE(expr) (expr) +#endif + +#if STATIC_ASSERT_SUPPORTED +#define CT_ASSERT_STRING( x ) #x +#define CT_ASSERT_UNIQUE_NAME(e,name)static_assert( (e), CT_ASSERT_STRING( name ) "@" __FILE__ CT_ASSERT_STRING(__LINE__) ); +#define CT_ASSERT(e) static_assert( (e), __FILE__ CT_ASSERT_STRING(__LINE__) ); +#else +// CT_ASSERT (compile-time assert) macro is used to test condition at compiler time and generate +// compiler error if condition is bool. +// Example: CT_ASSERT( sizeof( unsigned int ) == 2 ) would cause compilation error. +// CT_ASSERT( sizeof( unsigned int ) == 4 ) compiles without error. +// Since this declaration is just typedef - it does not create any CPU code. +// +// Reason for CT_ASSERT_UNIQUE_NAME +// The possible problem with the macro - it creates multiple identical typedefs. +// It is not a problem in global scope, but if macro is used inside of struct - it generates warnings. +// CT_ASSERT_UNIQUE_NAME is the same in essence, but it provides a way to customize the name of the type. +#define CT_ASSERT_UNIQUE_NAME(e,name) typedef char __CT_ASSERT__##name[(e)?1:-1]; +#define CT_ASSERT(e) CT_ASSERT_UNIQUE_NAME(e,nanoclr) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(BUILD_RTM) + +void debug_printf( const char *format, ... ); + +#else + +__inline void debug_printf( const char *format, ... ) {} + +#endif // !defined(BUILD_RTM) + +#ifdef __cplusplus +} +#endif +//--// + +#define NANOCLR_LOCKED_ACCESS_DECLARATION(type, name) type copy##name +#define NANOCLR_LOCKED_ACCESS_EXECUTE(name, expr) { GLOBAL_LOCK(); copy##name = expr; GLOBAL_UNLOCK(); } +#define NANOCLR_LOCKED_ACCESS_GET(name) copy##name + +//--// + +#ifdef __cplusplus +extern "C" { +#endif + +bool Target_HasNanoBooter(); +void HARD_Breakpoint(); +bool Target_ConfigUpdateRequiresErase(); +uint32_t GetPlatformCapabilities(); +uint32_t GetTargetCapabilities(); + +#ifdef __cplusplus +} +#endif + +// Watchdog driver +#include + +#include + +#endif // _NANOHAL_V2_H_ diff --git a/source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager.c b/source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager.c new file mode 100644 index 00000000..31250f31 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager.c @@ -0,0 +1,181 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +uint32_t FindNextBlock(uint32_t startAddress, uint32_t endAddress, const unsigned char* marker) +{ + // all configuration markers are 4 bytes length + + unsigned char* cursor = (unsigned char*)startAddress; + + while(cursor < (unsigned char*)endAddress - 4) + { + if(memcmp(cursor, marker, 4 ) == 0) + { + // found one! + break; + } + + cursor++; + } + + return (uint32_t)cursor; +} + +uint32_t GetBlockCount(uint32_t startAddress, uint32_t endAddress, uint32_t blockSize, const unsigned char* marker) +{ + // all configuration markers are 4 bytes length + int blockCount = 0; + + unsigned char* cursor = (unsigned char*)startAddress; + + while(cursor < (unsigned char*)endAddress - 4) + { + if(memcmp(cursor, marker, 4 ) == 0) + { + // found one! + blockCount++; + + // bump cursor to the end of the config block size + cursor +=blockSize; + } + else + { + cursor++; + } + } + + return blockCount; +} + +__nfweak void* ConfigurationManager_FindNetworkConfigurationBlocks(uint32_t startAddress, uint32_t endAddress) +{ + uint32_t nextBlock = startAddress; + + // first pass: find out how many blocks of this type we have + uint32_t blockCount = GetBlockCount(startAddress, endAddress, sizeof(HAL_Configuration_NetworkInterface), c_MARKER_CONFIGURATION_NETWORK_V1); + + // allocate config struct + HAL_CONFIGURATION_NETWORK *networkConfigs = (HAL_CONFIGURATION_NETWORK *)platform_malloc(offsetof(HAL_CONFIGURATION_NETWORK, Configs) + blockCount * sizeof(networkConfigs->Configs[0])); + + // set collection count + networkConfigs->Count = blockCount; + + if(blockCount > 0) + { + + // second pass: get address of each config block + for(uint32_t i = 0; i < blockCount; i++) + { + nextBlock = FindNextBlock(nextBlock, endAddress, c_MARKER_CONFIGURATION_NETWORK_V1); + networkConfigs->Configs[i] = (HAL_Configuration_NetworkInterface*)nextBlock; + } + } + + return networkConfigs; +} + +__nfweak void* ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks(uint32_t startAddress, uint32_t endAddress) +{ + uint32_t nextBlock = startAddress; + + // first pass: find out how many blocks of this type we have + uint32_t blockCount = GetBlockCount(startAddress, endAddress, sizeof(HAL_Configuration_Wireless80211), c_MARKER_CONFIGURATION_WIRELESS80211_V1); + + // allocate config struct + HAL_CONFIGURATION_NETWORK_WIRELESS80211 *networkWirelessConfigs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211 *)platform_malloc(offsetof(HAL_CONFIGURATION_NETWORK_WIRELESS80211, Configs) + blockCount * sizeof(networkWirelessConfigs->Configs[0])); + + // set collection count + networkWirelessConfigs->Count = blockCount; + + if(blockCount > 0) + { + // second pass: get address of each config block + for(uint32_t i = 0; i < blockCount; i++) + { + nextBlock = FindNextBlock(nextBlock, endAddress, c_MARKER_CONFIGURATION_WIRELESS80211_V1); + networkWirelessConfigs->Configs[i] = (HAL_Configuration_Wireless80211*)nextBlock; + } + } + + return networkWirelessConfigs; +} + +__nfweak void* ConfigurationManager_FindX509CertificateConfigurationBlocks(uint32_t startAddress, uint32_t endAddress) +{ + uint32_t nextBlock = startAddress; + uint32_t allocationSize = 0; + + // first pass: find out how many blocks of this type we have + // because these blocks have an unknow size, need to call this without a fixed size + uint32_t blockCount = GetBlockCount(startAddress, endAddress, 1, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1); + + // start computing allocation size, first part is the struct initial fields + allocationSize = offsetof(HAL_CONFIGURATION_X509_CERTIFICATE, Certificates); + + // second pass: find out the size of each X509 certificate (because they can have different sizes and we need this to allocate memory for the struct) + if(blockCount > 0) + { + for(uint32_t i = 0; i < blockCount; i++) + { + nextBlock = FindNextBlock(nextBlock, endAddress, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1); + + // header + allocationSize += offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + + // certificate + allocationSize += ((HAL_Configuration_X509CaRootBundle*)nextBlock)->CertificateSize; + } + } + + // allocate config struct + HAL_CONFIGURATION_X509_CERTIFICATE *certificateStore = (HAL_CONFIGURATION_X509_CERTIFICATE *)platform_malloc(allocationSize); + + // set collection count + certificateStore->Count = blockCount; + + if(blockCount > 0) + { + // second pass: get address of each config block + for(uint32_t i = 0; i < blockCount; i++) + { + nextBlock = FindNextBlock(nextBlock, endAddress, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1); + certificateStore->Certificates[i] = (HAL_Configuration_X509CaRootBundle*)nextBlock; + } + } + + return certificateStore; +} + +__nfweak HAL_Configuration_Wireless80211* ConfigurationManager_GetWirelessConfigurationFromId(uint32_t configurationId) +{ + for(int i = 0; i < g_TargetConfiguration.Wireless80211Configs->Count; i++) + { + if(g_TargetConfiguration.Wireless80211Configs->Configs[i]->Id == configurationId) + { + return g_TargetConfiguration.Wireless80211Configs->Configs[i]; + } + } + + // not found + return NULL; +} + +__nfweak HAL_Configuration_WirelessAP* ConfigurationManager_GetWirelessAPConfigurationFromId(uint32_t configurationId) +{ + for(int i = 0; i < g_TargetConfiguration.WirelessAPConfigs->Count; i++) + { + if(g_TargetConfiguration.WirelessAPConfigs->Configs[i]->Id == configurationId) + { + return g_TargetConfiguration.WirelessAPConfigs->Configs[i]; + } + } + + // not found + return NULL; +} diff --git a/source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager_stubs.c b/source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager_stubs.c new file mode 100644 index 00000000..95ee4c42 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/nanoHAL_ConfigurationManager_stubs.c @@ -0,0 +1,49 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +__nfweak void ConfigurationManager_Initialize() +{ +}; + +__nfweak void* ConfigurationManager_FindNetworkConfigurationBlocks(uint32_t startAddress, uint32_t endAddress) +{ + (void)startAddress; + (void)endAddress; + + return NULL; +} + +__nfweak void* ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks(uint32_t startAddress, uint32_t endAddress) +{ + (void)startAddress; + (void)endAddress; + + return NULL; +} + +__nfweak void* ConfigurationManager_FindX509CertificateConfigurationBlocks(uint32_t startAddress, uint32_t endAddress) +{ + (void)startAddress; + (void)endAddress; + + return NULL; +} + +__nfweak HAL_Configuration_Wireless80211* ConfigurationManager_GetWirelessConfigurationFromId(uint32_t configurationId) +{ + (void)configurationId; + + return NULL; +} + +__nfweak HAL_Configuration_WirelessAP* ConfigurationManager_GetWirelessAPConfigurationFromId(uint32_t configurationId) +{ + (void)configurationId; + + return NULL; +} diff --git a/source/native/nf-interpreter/src/HAL/nanoHAL_SystemInformation.cpp b/source/native/nf-interpreter/src/HAL/nanoHAL_SystemInformation.cpp new file mode 100644 index 00000000..9abae44d --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/nanoHAL_SystemInformation.cpp @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include + +bool GetHalSystemInfo(HalSystemInfo& systemInfo) +{ +#if defined(HAL_REDUCESIZE) + // No config update. + return FALSE; +#else + + // NFReleaseInfo: + systemInfo.m_releaseInfo.Version.usMajor = VERSION_MAJOR; + systemInfo.m_releaseInfo.Version.usMinor = VERSION_MINOR; + systemInfo.m_releaseInfo.Version.usBuild = VERSION_BUILD; + systemInfo.m_releaseInfo.Version.usRevision = VERSION_REVISION; + + size_t len = sizeof(systemInfo.m_releaseInfo.InfoString); + hal_strncpy_s ((char*)&systemInfo.m_releaseInfo.InfoString[0], len, OEMSYSTEMINFOSTRING, len-1 ); + + len = sizeof(systemInfo.m_releaseInfo.PlatformName); + hal_strncpy_s ((char*)&systemInfo.m_releaseInfo.PlatformName[0], len, TARGETNAMESTRING, len-1 ); + + len = sizeof(systemInfo.m_releaseInfo.TargetName); + hal_strncpy_s ((char*)&systemInfo.m_releaseInfo.TargetName[0], len, PLATFORMNAMESTRING, len-1 ); + + // we are not supporting this at this time + // OEM_MODEL_SKU: + //memcpy((void*)&(systemInfo.m_OemModelInfo), (void*)&(g_ConfigurationSector.OEM_Model_SKU), sizeof(OEM_MODEL_SKU)); + + // we are not supporting this at this time + // OEM_SERIAL_NUMBERS: + //memcpy((void*)&(systemInfo.m_OemSerialNumbers), (void*)&(g_ConfigurationSector.OemSerialNumbers), sizeof(OEM_SERIAL_NUMBERS)); + + return TRUE; +#endif +} + +bool Target_GetReleaseInfo(NFReleaseInfo& releaseInfo) +{ + NFReleaseInfo::Init( + releaseInfo, + VERSION_MAJOR, + VERSION_MINOR, + VERSION_BUILD, + VERSION_REVISION, + OEMSYSTEMINFOSTRING, + hal_strlen_s(OEMSYSTEMINFOSTRING), + TARGETNAMESTRING, + hal_strlen_s(TARGETNAMESTRING), + PLATFORMNAMESTRING, + hal_strlen_s(PLATFORMNAMESTRING) + ); + return TRUE; // alternatively, return false if you didn't initialize the releaseInfo structure. +} diff --git a/source/native/nf-interpreter/src/HAL/nanoHAL_Time.cpp b/source/native/nf-interpreter/src/HAL/nanoHAL_Time.cpp new file mode 100644 index 00000000..459b2893 --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/nanoHAL_Time.cpp @@ -0,0 +1,96 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +const int CummulativeDaysForMonth[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; +const int DaysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +#define IS_LEAP_YEAR(y) (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) +#define NUMBER_OF_LEAP_YEARS(y) ((((y - 1) / 4) - ((y - 1) / 100) + ((y - 1) / 400)) - BASE_YEAR_LEAPYEAR_ADJUST) /// Number of leap years until base year, not including the target year itself. +#define NUMBER_OF_YEARS(y) (y - BASE_YEAR) + +#define YEARS_TO_DAYS(y) ((NUMBER_OF_YEARS(y) * DAYS_IN_NORMAL_YEAR) + NUMBER_OF_LEAP_YEARS(y)) +#define MONTH_TO_DAYS(y, m) (CummulativeDaysForMonth[m - 1] + ((IS_LEAP_YEAR(y) && (m > 2)) ? 1 : 0)) +#define DAYS_IN_MONTH(y, m) (DaysInMonth[m - 1] + ((IS_LEAP_YEAR(y) && (m == 2)) ? 1 : 0)) + +#define TIMEUNIT_TO_MINUTES 600000000 +#define TIMEUNIT_TO_MILLISECONDS 10000 +#define MILLISECONDS_TO_SECONDS 1000 +#define SECONDS_TO_MINUTES 60 +#define MINUTES_TO_HOUR 60 +#define HOURS_TO_DAY 24 + +uint64_t HAL_Time_CurrentTime() +{ + return HAL_Time_SysTicksToTime( HAL_Time_CurrentSysTicks() ); +}; + +/// +/// Converts a SYSTEMTIME value to HAL time value +/// +uint64_t HAL_Time_ConvertFromSystemTime(const SYSTEMTIME* systemTime) +{ + uint64_t r = YEARS_TO_DAYS(systemTime->wYear) + MONTH_TO_DAYS(systemTime->wYear, systemTime->wMonth) + systemTime->wDay - 1; + r = (((( (r * HOURS_TO_DAY) + systemTime->wHour) * MINUTES_TO_HOUR + systemTime->wMinute) * SECONDS_TO_MINUTES + systemTime->wSecond ) * MILLISECONDS_TO_SECONDS + systemTime->wMilliseconds) * TIMEUNIT_TO_MILLISECONDS; + + return r; +} + +bool HAL_Time_ToSystemTime(uint64_t time, SYSTEMTIME* systemTime) +{ + uint32_t ytd = 0; + uint32_t mtd = 0; + + time /= TIMEUNIT_TO_MILLISECONDS; + systemTime->wMilliseconds = time % MILLISECONDS_TO_SECONDS; + time /= MILLISECONDS_TO_SECONDS; + systemTime->wSecond = time % SECONDS_TO_MINUTES; + time /= SECONDS_TO_MINUTES; + systemTime->wMinute = time % MINUTES_TO_HOUR; + time /= MINUTES_TO_HOUR; + systemTime->wHour = time % HOURS_TO_DAY; + time /= HOURS_TO_DAY; + + systemTime->wDayOfWeek = (time + BASE_YEAR_DAYOFWEEK_SHIFT) % 7; + systemTime->wYear = (unsigned short)(time / DAYS_IN_NORMAL_YEAR + BASE_YEAR); + ytd = YEARS_TO_DAYS(systemTime->wYear); + if (ytd > time) + { + systemTime->wYear--; + ytd = YEARS_TO_DAYS(systemTime->wYear); + } + + time -= ytd; + + systemTime->wMonth = (unsigned short)(time / 31 + 1); + mtd = MONTH_TO_DAYS(systemTime->wYear, systemTime->wMonth + 1); + + if (time >= mtd) + { + systemTime->wMonth++; + } + + mtd = MONTH_TO_DAYS(systemTime->wYear, systemTime->wMonth); + + systemTime->wDay = (unsigned short)(time - mtd + 1); + + return true; +} + +HRESULT HAL_Time_AccDaysInMonth(signed int year, signed int month, signed int* days) +{ + *days = MONTH_TO_DAYS(year, month); + + return S_OK; +} + +HRESULT HAL_Time_DaysInMonth(signed int year, signed int month, signed int* days) +{ + *days = DAYS_IN_MONTH(year, month); + + return S_OK; +} diff --git a/source/native/nf-interpreter/src/HAL/nanoHAL_Watchdog.c b/source/native/nf-interpreter/src/HAL/nanoHAL_Watchdog.c new file mode 100644 index 00000000..5cdebcaa --- /dev/null +++ b/source/native/nf-interpreter/src/HAL/nanoHAL_Watchdog.c @@ -0,0 +1,23 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +/** +* Method to initialize the watchdog. Watchdog must be initialized +* only once (when the system starts, generally in main after system and HAL initialization). +*/ +__nfweak void Watchdog_Init(){} + + +/** + * Reset the watchdog. If not done within the timout period, + * the watchdog will trigger and MCU will reset. Specific implementation + * must provide required thread-safety (e.g. whether called from thread or an + * ISR, reentrant/non-reentrant) + */ +__nfweak void Watchdog_Reset(){} + diff --git a/source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncCompletions.cpp b/source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncCompletions.cpp new file mode 100644 index 00000000..29543a29 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncCompletions.cpp @@ -0,0 +1,239 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" + +#include + +HAL_DblLinkedList g_HAL_Completion_List; + +/***************************************************************************/ + +void HAL_COMPLETION::Execute() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + +#if defined(_DEBUG) + this->Start_RTC_Ticks = 0; +#endif + + if (this->ExecuteInISR) + { + HAL_CONTINUATION* cont = this; + + cont->Execute(); + } + else + { + this->Enqueue(); + } +} + +//--// + +void HAL_COMPLETION::InitializeList() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + g_HAL_Completion_List.Initialize(); +} + +//--// + +void HAL_COMPLETION::DequeueAndExec() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + + GLOBAL_LOCK(); + + HAL_COMPLETION* ptr = (HAL_COMPLETION*)g_HAL_Completion_List.FirstNode(); + + // waitforevents does not have an associated completion, therefore we need to verify + // than their is a next completion and that the current one has expired. + if (ptr->Next()) + { + // Current one expired ? + if (HAL_Time_CurrentTime() >= ptr->EventTimeTicks) + { + Events_Set(SYSTEM_EVENT_FLAG_SYSTEM_TIMER); + + ptr->Unlink(); + +#if defined(_DEBUG) + ptr->EventTimeTicks = 0; +#endif // defined(_DEBUG) + + //// let the ISR turn on interrupts, if it needs to + ptr->Execute(); + } + + // + // Set the next timer to run otherwise set the next interrupt to be 356 years since last powerup (@25kHz). + Time_SetCompare(ptr->Next() ? ptr->EventTimeTicks : HAL_COMPLETION_IDLE_VALUE); + } + + GLOBAL_UNLOCK(); +} + +//--// + +void HAL_COMPLETION::EnqueueTicks(uint64_t eventTimeTicks) +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + ASSERT(eventTimeTicks != 0); + + this->EventTimeTicks = eventTimeTicks; + +#if defined(_DEBUG) + this->Start_RTC_Ticks = HAL_Time_CurrentSysTicks(); +#endif + + GLOBAL_LOCK(); + + HAL_COMPLETION* ptr = (HAL_COMPLETION*)g_HAL_Completion_List.FirstNode(); + HAL_COMPLETION* ptrNext; + + // If not empty list the find position in Completion list based on time + // If empty just add at head. + if (!g_HAL_Completion_List.IsEmpty()) + { + do + { + ptrNext = (HAL_COMPLETION *)ptr->Next(); + + if (eventTimeTicks < ptr->EventTimeTicks) + { + break; + } + + ptr = ptrNext; + } while (ptr); + } + + g_HAL_Completion_List.InsertBeforeNode(ptr, this); + + if (this == g_HAL_Completion_List.FirstNode()) + { + Time_SetCompare(eventTimeTicks); + } + + GLOBAL_UNLOCK(); +} + +//--// + +void HAL_COMPLETION::Abort() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + + GLOBAL_LOCK(); + + HAL_COMPLETION* firstNode = (HAL_COMPLETION*)g_HAL_Completion_List.FirstNode(); + + this->Unlink(); + +#if defined(_DEBUG) + this->Start_RTC_Ticks = 0; +#endif + + if (firstNode == this) + { + uint64_t nextTicks; + + if (g_HAL_Completion_List.IsEmpty()) + { + // + // In case there's no other request to serve, set the next interrupt to be 356 years since last powerup (@25kHz). + // + nextTicks = HAL_COMPLETION_IDLE_VALUE; + } + else + { + firstNode = (HAL_COMPLETION*)g_HAL_Completion_List.FirstNode(); + + nextTicks = firstNode->EventTimeTicks; + } + + Time_SetCompare(nextTicks); + } + + GLOBAL_UNLOCK(); +} + +//--// + + +// +// WaitForInterrupts for expireTimeInTicks time +// +// Interrupts should be disabled +// +void HAL_COMPLETION::WaitForInterrupts(uint64_t expireTimeInTicks, uint32_t sleepLevel, uint64_t wakeEvents) +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + + const int setCompare = 1; + const int resetCompare = 2; + const int nilCompare = 4; + + HAL_COMPLETION* ptr = (HAL_COMPLETION*)g_HAL_Completion_List.FirstNode(); + int state; + + // Any Completion events been Queued ? + if (ptr->Next() == NULL) + { + // No + state = setCompare | nilCompare; + } + // Is Queued event later than passed expire timeout + else if (ptr->EventTimeTicks > expireTimeInTicks) + { + // Yes + state = setCompare | resetCompare; + } + else + { + state = 0; + } + + if (state & setCompare) + { + // Set timer for expireTimeInTicks time + Time_SetCompare(expireTimeInTicks); + } + + // Wait for next interrupt ( timer etc) + CPU_Sleep((SLEEP_LEVEL_type)sleepLevel, wakeEvents); + + if (state & (resetCompare | nilCompare)) + { + // let's get the first node again + // it could have changed since CPU_Sleep re-enabled interrupts + ptr = (HAL_COMPLETION*)g_HAL_Completion_List.FirstNode(); + Time_SetCompare((state & resetCompare) ? ptr->EventTimeTicks : HAL_COMPLETION_IDLE_VALUE); + } +} + +void HAL_COMPLETION::Uninitialize() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + + HAL_COMPLETION* ptr; + + GLOBAL_LOCK(); + + while (TRUE) + { + ptr = (HAL_COMPLETION*)g_HAL_Completion_List.ExtractFirstNode(); + + if (!ptr) + { + break; + } + + } + + GLOBAL_UNLOCK(); +} diff --git a/source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncContinuations.cpp b/source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncContinuations.cpp new file mode 100644 index 00000000..9cde8e37 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/AsyncProcCall/AsyncContinuations.cpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include + +HAL_DblLinkedList g_HAL_Continuation_List; +extern HAL_DblLinkedList g_HAL_Completion_List; + +//--// + +bool HAL_CONTINUATION::IsLinked() +{ + return ((HAL_DblLinkedNode*)this)->IsLinked(); +} + +void HAL_CONTINUATION::InitializeList() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + g_HAL_Continuation_List.Initialize(); +} + +void HAL_CONTINUATION::Enqueue() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + if(this->GetEntryPoint() != NULL) + { + GLOBAL_LOCK(); + + g_HAL_Continuation_List.LinkAtBack( this ); + + GLOBAL_UNLOCK(); + } +} + +void HAL_CONTINUATION::Abort() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + GLOBAL_LOCK(); + + this->Unlink(); + + GLOBAL_UNLOCK(); +} + +bool HAL_CONTINUATION::Dequeue_And_Execute() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + + // use this as the return value + // helpfull to make the call to release the global mutext happens + bool result; + + GLOBAL_LOCK(); + HAL_CONTINUATION* ptr = g_HAL_Continuation_List.ExtractFirstNode(); + GLOBAL_UNLOCK(); + + if(ptr == NULL ) + { + result = false; + } + else + { + //SystemState_SetNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); + + HAL_CALLBACK call = ptr->Callback; + + call.Execute(); + + //SystemState_ClearNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); // nestable + + result = true; + } + + return result; +} + +void HAL_CONTINUATION::InitializeCallback( HAL_CALLBACK_FPN entryPoint, void* argument ) +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + Initialize(); + + Callback.Initialize( entryPoint, argument ); +} + +void HAL_CONTINUATION::Uninitialize() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + GLOBAL_LOCK(); + + HAL_CONTINUATION* ptr; + + while(TRUE) + { + ptr = (HAL_CONTINUATION*)g_HAL_Continuation_List.ExtractFirstNode(); + + if(!ptr) + { + break; + } + } + + GLOBAL_UNLOCK(); +} diff --git a/source/native/nf-interpreter/src/PAL/AsyncProcCall/Async_stubs.cpp b/source/native/nf-interpreter/src/PAL/AsyncProcCall/Async_stubs.cpp new file mode 100644 index 00000000..a620e97c --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/AsyncProcCall/Async_stubs.cpp @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +//--// + +// continuation list +__nfweak void HAL_CONTINUATION::InitializeList() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_CONTINUATION::Uninitialize() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_CONTINUATION::InitializeCallback( HAL_CALLBACK_FPN entryPoint, void* argument ) +{ + (void)entryPoint; + (void)argument; + + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_CONTINUATION::Enqueue() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_CONTINUATION::Abort () +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak bool HAL_CONTINUATION::Dequeue_And_Execute() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + return TRUE; +} + +__nfweak bool HAL_CONTINUATION::IsLinked() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); + return false; +} + +//-// +// completion list + +__nfweak void HAL_COMPLETION::InitializeList() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_COMPLETION::Uninitialize() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_COMPLETION::EnqueueTicks( uint64_t eventTimeTicks) +{ + (void)eventTimeTicks; + + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_COMPLETION::EnqueueDelta( uint32_t uSecFromNow ) +{ + (void)uSecFromNow; + + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_COMPLETION::Abort() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_COMPLETION::Execute() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_COMPLETION::DequeueAndExec() +{ + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} + +__nfweak void HAL_COMPLETION::WaitForInterrupts( uint64_t expireTimeInSysTicks, uint32_t sleepLevel, uint64_t wakeEvents ) +{ + (void)expireTimeInSysTicks; + (void)sleepLevel; + (void)wakeEvents; + + NATIVE_PROFILE_PAL_ASYNC_PROC_CALL(); +} diff --git a/source/native/nf-interpreter/src/PAL/BlockStorage/nanoPAL_BlockStorage.c b/source/native/nf-interpreter/src/PAL/BlockStorage/nanoPAL_BlockStorage.c new file mode 100644 index 00000000..be3122c8 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/BlockStorage/nanoPAL_BlockStorage.c @@ -0,0 +1,890 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +BlockStorageList g_BlockStorage; + + +///////////////////////////////////////////////////// +// DeviceBlockInfo stubs + +SectorAddress DeviceBlockInfo_PhysicalToSectorAddress(DeviceBlockInfo* blockInfo, const BlockRegionInfo* pRegion, ByteAddress phyAddress) +{ + return (phyAddress - pRegion->Start) / blockInfo->BytesPerSector; +} + +bool DeviceBlockInfo_FindRegionFromAddress(DeviceBlockInfo* blockInfo, ByteAddress address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + const BlockRegionInfo *pRegion; + + *blockRegionIndex = 0; + + for(uint32_t i = 0; i < blockInfo->NumRegions; i++) + { + pRegion = &blockInfo->Regions[i]; + + if(pRegion->Start <= address && address < (pRegion->Start + pRegion->NumBlocks * pRegion->BytesPerBlock)) + { + uint32_t endRangeAddr = pRegion->Start + pRegion->BytesPerBlock * pRegion->BlockRanges[0].StartBlock; + + for(uint32_t j =0; j < pRegion->NumBlockRanges; j++) + { + endRangeAddr += pRegion->BytesPerBlock * BlockRange_GetBlockCount(pRegion->BlockRanges[j]); + + if(address < endRangeAddr) + { + *blockRegionIndex = i; + *blockRangeIndex = j; + return true; + } + } + } + } + + return false; +} + +bool DeviceBlockInfo_FindNextUsageBlock(DeviceBlockInfo* blockInfo, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + BlockRegionInfo *region; + + for(uint32_t i = *blockRegionIndex; i < blockInfo->NumRegions; i++) + { + region = &blockInfo->Regions[i]; + + for( int j = *blockRangeIndex; j < (int)region->NumBlockRanges; j++) + { + BlockRange *pRange = (BlockRange*)®ion->BlockRanges[j]; + + if ((pRange->RangeType & BlockRange_USAGE_MASK) == blockUsage || blockUsage == BlockUsage_ANY) + { + *address = BlockRegionInfo_BlockAddress(region, pRange->StartBlock); + *blockRegionIndex = i; + *blockRangeIndex = j; + + return true; + } + } + + *blockRangeIndex = 0; + } + + return false; +} + +bool DeviceBlockInfo_FindForBlockUsage(DeviceBlockInfo* blockInfo, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + (void)blockInfo; + (void)blockUsage; + + address = 0; + blockRegionIndex = 0; + blockRangeIndex = 0; + + return DeviceBlockInfo_FindNextUsageBlock(blockInfo, blockUsage, address, blockRegionIndex, blockRangeIndex ); +} + + +///////////////////////////////////////////////////// +// BlockStorageStream stubs + +bool BlockStorageStream_IsXIP(BlockStorageStream *stream) +{ + (void)stream; + + return false; +} + +bool BlockStorageStream_IsReadModifyWrite(BlockStorageStream *stream) +{ + (void)stream; + + return false; +} + +bool BlockStorageStream_SetReadModifyWrite(BlockStorageStream *stream) +{ + (void)stream; + + return false; +} + +bool BlockStorageStream_Initialize(BlockStorageStream *stream, unsigned int blockUsage) +{ + return BlockStorageStream_InitializeWithBlockStorageDevice(stream, blockUsage, NULL); +} + +bool BlockStorageStream_InitializeWithBlockStorageDevice(BlockStorageStream *stream, unsigned int blockUsage, BlockStorageDevice *pDevice) +{ + DeviceBlockInfo* deviceInfo = NULL; + BlockStorageStream backupStream; + BlockStorageDevice *device = NULL; + + // backup original stream, in case this gets messed up + memcpy(&backupStream, stream, sizeof(BlockStorageStream)); + + if(pDevice != NULL) + { + device = pDevice; + + deviceInfo = BlockStorageDevice_GetDeviceInfo(pDevice); + } + else + { + for(int i = 0; i < TARGET_BLOCKSTORAGE_COUNT; i++) + { + device = g_BlockStorage.DeviceList[i]; + + deviceInfo = BlockStorageDevice_GetDeviceInfo(g_BlockStorage.DeviceList[i]); + + if(DeviceBlockInfo_FindNextUsageBlock(deviceInfo, blockUsage, &stream->BaseAddress, &stream->RegionIndex, &stream->RangeIndex)) + { + // found a block matching the request usage + break; + } + else + { + // couldn't find a block matching the request usage + // need to NULL the device info that's going to be used to fill in the stream details + deviceInfo = NULL; + } + } + } + + if(deviceInfo != NULL) + { + BlockRegionInfo* pRegion = &deviceInfo->Regions[stream->RegionIndex]; + + stream->CurrentIndex = 0; + stream->Length = BlockRange_GetBlockCount(pRegion->BlockRanges[stream->RangeIndex])* pRegion->BytesPerBlock; + stream->BlockLength = pRegion->BytesPerBlock; + stream->CurrentUsage = (pRegion->BlockRanges[stream->RangeIndex].RangeType & BlockRange_USAGE_MASK); + stream->Device = device; + + if(deviceInfo->Attribute & MediaAttribute_SupportsXIP) + { + stream->Flags |= BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP; + } + else + { + stream->Flags &= ~BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP; + } + + // check if block region is memory mapped + if(pRegion->Attributes & BlockRegionAttribute_MemoryMapped) + { + BlockStorageDevice_GetMemoryMappedAddress(device, stream->RegionIndex, stream->RangeIndex, &stream->MemoryMappedAddress); + + stream->Flags |= BLOCKSTORAGESTREAM_c_BlockStorageStream__MemoryMapped; + } + else + { + stream->Flags &= ~BLOCKSTORAGESTREAM_c_BlockStorageStream__MemoryMapped; + } + + // done here + return true; + } + + // couldn't find a device for the requested usage, revert stream from backup + memcpy(stream, &backupStream, sizeof(BlockStorageStream)); + + return false; +} + +bool BlockStorageStream_NextStream(BlockStorageStream* stream) +{ + if(stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) return false; + + const BlockRegionInfo* pRegion; + const DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(stream->Device); + + BlockStorageStream orig; + + memcpy(&orig, stream, sizeof(orig)); + + do + { + bool fLastIndex = false; + + if(stream->RangeIndex == 0) + { + if(stream->RegionIndex == 0) + { + stream->Device = BlockStorageDevice_Prev(stream->Device); + + if(stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + { + memcpy(stream, &orig, sizeof(orig)); + return false; + } + + deviceInfo = BlockStorageDevice_GetDeviceInfo(stream->Device); + + stream->RegionIndex = deviceInfo->NumRegions - 1; + } + else + { + stream->RegionIndex--; + } + + fLastIndex = true; + } + else + { + stream->RangeIndex--; + } + + pRegion = &deviceInfo->Regions[stream->RegionIndex]; + + if(fLastIndex) + { + stream->RangeIndex = pRegion->NumBlockRanges - 1; + } + + } while( BlockRange_GetBlockUsage(pRegion->BlockRanges[stream->RangeIndex]) != stream->Usage ); + + if(deviceInfo->Attribute & MediaAttribute_SupportsXIP) + { + stream->Flags |= BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP; + } + else + { + stream->Flags &= ~BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP; + } + + stream->BlockLength = pRegion->BytesPerBlock; + stream->BaseAddress = pRegion->Start + pRegion->BlockRanges[stream->RangeIndex].StartBlock * stream->BlockLength; + stream->Length = BlockRange_GetBlockCount(pRegion->BlockRanges[stream->RangeIndex]) * stream->BlockLength; + stream->CurrentIndex = 0; + + return true; +} + +bool BlockStorageStream_PrevStream(BlockStorageStream* stream) +{ + if(stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) return false; + + const BlockRegionInfo* pRegion; + const DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(stream->Device); + + BlockStorageStream orig; + + memcpy(&orig, stream, sizeof(orig)); + + do + { + bool fLastIndex = false; + + if(stream->RangeIndex == 0) + { + if(stream->RegionIndex == 0) + { + stream->Device = BlockStorageDevice_Prev(stream->Device); + + if(stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + { + memcpy(stream, &orig, sizeof(orig)); + return false; + } + + deviceInfo = BlockStorageDevice_GetDeviceInfo(stream->Device); + + stream->RegionIndex = deviceInfo->NumRegions - 1; + } + else + { + stream->RegionIndex--; + } + + fLastIndex = true; + } + else + { + stream->RangeIndex--; + } + + pRegion = &deviceInfo->Regions[stream->RegionIndex]; + + if(fLastIndex) + { + stream->RangeIndex = pRegion->NumBlockRanges - 1; + } + + } while( BlockRange_GetBlockUsage(pRegion->BlockRanges[stream->RangeIndex]) != stream->Usage ); + + if(deviceInfo->Attribute & MediaAttribute_SupportsXIP) + { + stream->Flags |= BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP; + } + else + { + stream->Flags &= ~BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP; + } + + stream->BlockLength = pRegion->BytesPerBlock; + stream->BaseAddress = pRegion->Start + pRegion->BlockRanges[stream->RangeIndex].StartBlock * stream->BlockLength; + stream->Length = BlockRange_GetBlockCount(pRegion->BlockRanges[stream->RangeIndex]) * stream->BlockLength; + stream->CurrentIndex = 0; + + return true; +} + +bool BlockStorageStream_Seek(BlockStorageStream *stream, unsigned int offset, SeekOrigin origin) +{ + int32_t seekIndex; + + switch (origin) + { + case BlockStorageStream_SeekBegin: + seekIndex = 0; + break; + + case BlockStorageStream_SeekCurrent: + seekIndex = stream->CurrentIndex; + break; + + case BlockStorageStream_SeekEnd: + seekIndex = stream->Length; + break; + + default: + + return false; + } + + seekIndex += offset; + + while (seekIndex >= (int32_t)stream->Length) + { + // out of region address space + return false; + } + + while (seekIndex < 0) + { + // out of region address space + return false; + } + + stream->CurrentIndex = seekIndex; + + return true; +} + +bool BlockStorageStream_Write(BlockStorageStream *stream, unsigned char *data, unsigned int length) +{ + (void)stream; + (void)data; + (void)length; + + return false; +} + +bool BlockStorageStream_Erase(BlockStorageStream *stream, unsigned int length) +{ + (void)stream; + (void)length; + + return false; +} + +bool BlockStorageStream_ReadIntoBuffer(BlockStorageStream *stream, unsigned char *buffer, unsigned int length) +{ + (void)stream; + (void)buffer; + (void)length; + + return false; +} + +bool BlockStorageStream_Read(BlockStorageStream* stream, unsigned char** buffer, unsigned int length) +{ + if(stream == NULL || stream->Device == NULL || buffer == 0) + { + return false; + } + + DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(stream->Device); + unsigned char* pBuffer = *buffer; + + while(length > 0) + { + int readLen = length; + + // find the next stream if we are at the end of this one + if(stream->CurrentIndex == stream->Length) + { + // TODO FIXME + // need to check implementation of this call to get pointers to stream continuation + //if(!NextStream()) return FALSE; + } + + if((stream->CurrentIndex + readLen) > stream->Length) + { + readLen = stream->Length - stream->CurrentIndex; + } + + if(deviceInfo->Attribute & MediaAttribute_SupportsXIP) + { + // XIP assumes contiguous USAGE blocks + *buffer = (unsigned char*)(BlockStorageStream_CurrentAddress(stream)); + } + else + { + // non XIP storage... + + if(stream->Flags & BLOCKSTORAGESTREAM_c_BlockStorageStream__MemoryMapped) + { + // memory mapped region, get mapped address for read + *buffer = (unsigned char*)(BlockStorageStream_CurrentMappedAddress(stream)); + } + else + { + // non mapped access... need to call driver + if(!stream->Device->m_BSD->Read(stream->Device->m_context, BlockStorageStream_CurrentAddress(stream), readLen, pBuffer)) + { + return false; + } + } + } + + length -= readLen; + pBuffer += readLen; + stream->CurrentIndex += readLen; + } + + return true; +} + +unsigned int BlockStorageStream_CurrentAddress(BlockStorageStream *stream) +{ + return stream->BaseAddress + stream->CurrentIndex; +} + +unsigned int BlockStorageStream_CurrentMappedAddress(BlockStorageStream *stream) +{ + return stream->MemoryMappedAddress + stream->CurrentIndex; +} + +bool BlockStorageStream_IsErased(BlockStorageStream *stream, unsigned int length) +{ + (void)stream; + (void)length; + + return false; +} + +///////////////////////////////////////////////////// +// BlockStorageDevice stubs + +BlockStorageDevice* BlockStorageDevice_Next(BlockStorageDevice* device) +{ + (void)device; + + return NULL; +} + +BlockStorageDevice* BlockStorageDevice_Prev(BlockStorageDevice* device) +{ + (void)device; + + return NULL; +} + +///////////////////////////////////////////////////////// +// Description: +// Initializes a given block device for use +// +// Returns: +// true if successful; false if not +// +// Remarks: +// No other functions in this interface may be called +// until after Init returns. +// +bool BlockStorageDevice_InitializeDevice(BlockStorageDevice* device) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->InitializeDevice(device->m_context); +} + +///////////////////////////////////////////////////////// +// Description: +// Initializes a given block device for use +// +// Returns: +// true if successful; false if not +// +// Remarks: +// De initializes the device when no longer needed +// +bool BlockStorageDevice_UninitializeDevice(BlockStorageDevice* device) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->UninitializeDevice(device->m_context); +} + +///////////////////////////////////////////////////////// +// Description: +// Gets the information describing the device +// +DeviceBlockInfo* BlockStorageDevice_GetDeviceInfo(BlockStorageDevice* device) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->GetDeviceInfo(device->m_context); +} + +///////////////////////////////////////////////////////// +// Description: +// Reads data from a set of sectors +// +// Input: +// startAddress - Starting Sector for the read +// numBytes - Number of sectors to read +// buffer - pointer to buffer to read the data into. +// Must be large enough to hold all of the data +// being read. +// +// pSectorMetadata - pointer to an array of structured (one for each sector) +// for the extra sector information. +// +// Returns: +// true if successful; false if not +// +// Remarks: +// This function reads the number of sectors specified from the device. +// +// pSectorBuff may be NULL. This is to allow for reading just the metadata. +// +// pSectorMetadata can be set to NULL if the caller does not need the extra +// data. +// +// If the device does not support sector Metadata it should fail if the +// pSectorMetadata parameter is not NULL. +// +bool BlockStorageDevice_Read(BlockStorageDevice* device, unsigned int startAddress, unsigned int numBytes, unsigned char* buffer) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->Read(device->m_context, startAddress, numBytes, buffer); +} + +///////////////////////////////////////////////////////// +// Description: +// Writes data to a set of sectors +// +// Input: +// startAddress - Starting Sector for the write +// numBytes - Number of sectors to write +// buffer - pointer to data to write. +// Must be large enough to hold complete sectors +// for the number of sectors being written. +// +// pSectorMetadata - pointer to an array of structures (one for each sector) +// for the extra sector information. +// +// Returns: +// true if successful; false if not +// +// Remarks: +// This function reads the number of sectors specified from the device. +// The SectorMetadata is used for flash arrays without special controllers +// to manage wear leveling etc... (mostly for NOR and NAND). The metadata +// is used by upper layers to ensure that data is moved around on the flash +// when writing to prevent failure of the device from too many erase cycles +// on a sector. +// +// If the device does not support sector Metadata it should fail if the +// pSectorMetadata parameter is not NULL. +// +// pSectorMetadata can be set to NULL if the caller does not need the extra +// data. Implementations must not attempt to write data through a NULL pointer! +// +bool BlockStorageDevice_Write(BlockStorageDevice* device, unsigned int startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->Write(device->m_context, startAddress, numBytes, buffer, readModifyWrite); +} + +bool BlockStorageDevice_Memset(BlockStorageDevice* device, unsigned int startAddress, unsigned char buffer, unsigned int numBytes) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->Memset(device->m_context, startAddress, buffer, numBytes); +} + +// bool BlockStorageDevice_GetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, SectorMetadata* pSectorMetadata); +// bool BlockStorageDevice_SetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, SectorMetadata* pSectorMetadata); + +///////////////////////////////////////////////////////// +// Description: +// Check a block is erased or not +// +// Input: +// Address - Logical Sector Address +// +// Returns: +// true it is erased; false if not +// +// Remarks: +// check the block containing the sector address specified. +// +bool BlockStorageDevice_IsBlockErased(BlockStorageDevice* device, unsigned int blockStartAddress, unsigned int length) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->IsBlockErased(device->m_context, blockStartAddress, length); +} + +///////////////////////////////////////////////////////// +// Description: +// Erases a block +// +// Input: +// Address - Logical Sector Address +// +// Returns: +// true if successful; false if not +// +// Remarks: +// Erases the block containing the sector address specified. +// +bool BlockStorageDevice_EraseBlock(BlockStorageDevice* device, unsigned int address) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->EraseBlock(device->m_context, address); +} + +///////////////////////////////////////////////////////// +// Description: +// Changes the power state of the device +// +// Input: +// state - true= power on; false = power off +// +// Remarks: +// This function allows systems to conserve power by +// shutting down the hardware when the system is +// going into low power states. +// +void BlockStorageDevice_SetPowerState(BlockStorageDevice* device, unsigned int state) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + device->m_BSD->SetPowerState(device->m_context, state); +} + +bool BlockStorageDevice_FindRegionFromAddress(BlockStorageDevice* device, unsigned int address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + ASSERT(device != NULL); + + DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(device); + + return DeviceBlockInfo_FindRegionFromAddress(deviceInfo, address, blockRegionIndex, blockRangeIndex); +} + +bool BlockStorageDevice_FindForBlockUsage(BlockStorageDevice* device, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + ASSERT(device != NULL); + + DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(device); + + return DeviceBlockInfo_FindForBlockUsage(deviceInfo, blockUsage, address, blockRegionIndex, blockRangeIndex); +} + +bool BlockStorageDevice_FindNextUsageBlock(BlockStorageDevice* device, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + ASSERT(device != NULL); + + DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(device); + + return DeviceBlockInfo_FindNextUsageBlock(deviceInfo, blockUsage, address, blockRegionIndex, blockRangeIndex); +} + +bool BlockStorageDevice_GetMemoryMappedAddress(BlockStorageDevice* device, unsigned int blockRegionIndex, unsigned int blockRangeIndex, unsigned int* address) +{ + ASSERT(device != NULL); + ASSERT(device->m_context != NULL); + + return device->m_BSD->GetMemoryMappedAddress(device->m_context, blockRegionIndex, blockRangeIndex, address); +} + +/////////////////////////////////////////////////// +// BlockStorageList declarations + +// initialize the storage +void BlockStorageList_Initialize() +{ + for(int i = 0; i < TARGET_BLOCKSTORAGE_COUNT; i++) + { + g_BlockStorage.DeviceList[i] = NULL; + } + + g_BlockStorage.DeviceCount = 0; +} + +// walk through list of devices and calls Init() function +bool BlockStorageList_InitializeDevices() +{ + // TODO FIXME + return true; +} + +// walk through list of devices and calls UnInit() function +bool BlockStorageList_UnInitializeDevices() +{ + // TODO FIXME + return true; +} + +bool BlockStorageList_AddDevice(BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, bool init) +{ + bool success = true; + + // find next empty device slot + for(int i = 0; i < TARGET_BLOCKSTORAGE_COUNT; i++) + { + if(g_BlockStorage.DeviceList[i] == NULL) + { + // found an empty slot + + // link the driver and context + pBSD->m_BSD = vtable; + pBSD->m_context = config; + + // call initialize device, if requested + if(init) + { + success = BlockStorageDevice_InitializeDevice(pBSD); + } + + // add device to list only init was successful + if(success) + { + // add the BSD + g_BlockStorage.DeviceList[i] = pBSD; + + g_BlockStorage.DeviceCount++; + + // done here + return true; + } + } + } + + return false; +} + +bool BlockStorageList_RemoveDevice(BlockStorageDevice* pBSD, bool unInit) +{ + // find device + for(int i = 0; i < TARGET_BLOCKSTORAGE_COUNT; i++) + { + if(g_BlockStorage.DeviceList[i] == pBSD) + { + // found it + + // call uninitialize device, if requested + if(unInit) + { + BlockStorageDevice_UninitializeDevice(pBSD); + } + + // remove device + g_BlockStorage.DeviceList[i] = NULL; + + // done here + return true; + } + } + + return false; +} + +bool BlockStorageList_FindDeviceForPhysicalAddress(BlockStorageDevice** pBSD, unsigned int physicalAddress, ByteAddress* blockAddress) +{ + *pBSD = NULL; + + BlockStorageDevice* block = BlockStorageList_GetFirstDevice(); + + // this has to add to make metadataprocessor happy + if(!block) return true; + + DeviceBlockInfo* pDeviceInfo = BlockStorageDevice_GetDeviceInfo(block); + + for(uint32_t i=0; i < pDeviceInfo->NumRegions; i++) + { + BlockRegionInfo* pRegion = &pDeviceInfo->Regions[i]; + + if(pRegion->Start <= physicalAddress && physicalAddress < (pRegion->Start + pRegion->NumBlocks * pRegion->BytesPerBlock)) + { + *pBSD = block; + + // get block start address + *blockAddress = (ByteAddress)((physicalAddress - pRegion->Start) / pRegion->BytesPerBlock); + *blockAddress *= pRegion->BytesPerBlock; + *blockAddress += pRegion->Start; + + return true; + } + } + + return false; +} + +BlockStorageDevice* BlockStorageList_GetFirstDevice() +{ + for(int i = 0; i < TARGET_BLOCKSTORAGE_COUNT; i++) + { + if(g_BlockStorage.DeviceList[i] != NULL) + { + return g_BlockStorage.DeviceList[i]; + } + } + + return NULL; +} + +// returns the next device in BlockStorageList +BlockStorageDevice* BlockStorageList_GetNextDevice(BlockStorageDevice* device) +{ + for(int i = 0; i < TARGET_BLOCKSTORAGE_COUNT; i++) + { + if(g_BlockStorage.DeviceList[i] == device) + { + if((i + 1) < TARGET_BLOCKSTORAGE_COUNT){ + return g_BlockStorage.DeviceList[i + 1]; + } + } + } + return NULL; +} + +// // returns number of devices has been declared in the system +unsigned int BlockStorageList_GetNumDevices() +{ + return TARGET_BLOCKSTORAGE_COUNT; +} + +///////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/src/PAL/COM/COM_stubs.c b/source/native/nf-interpreter/src/PAL/COM/COM_stubs.c new file mode 100644 index 00000000..f1892cab --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/COM_stubs.c @@ -0,0 +1,78 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +__nfweak bool DebuggerPort_Initialize(COM_HANDLE comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool DebuggerPort_Uninitialize(COM_HANDLE comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak int DebuggerPort_Write(COM_HANDLE comPortNum, const char* data, size_t size, int maxRetries) +{ + (void)maxRetries; + + NATIVE_PROFILE_PAL_COM(); + + // minimum implementation is calling generic port to be able to use SWO (if available) + GenericPort_Write( comPortNum, data, size ); + + return 0; +} + +__nfweak int DebuggerPort_Read(COM_HANDLE comPortNum, char* data, size_t size) +{ + (void)comPortNum; + (void)data; + (void)size; + + NATIVE_PROFILE_PAL_COM(); + return 0; +} + +__nfweak bool DebuggerPort_Flush(COM_HANDLE comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool DebuggerPort_IsSslSupported(COM_HANDLE comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return false; +} + +__nfweak bool DebuggerPort_UpgradeToSsl(COM_HANDLE comPortNum, unsigned int flags) +{ + (void)comPortNum; + (void)flags; + + NATIVE_PROFILE_PAL_COM(); + return false; +} + +__nfweak bool DebuggerPort_IsUsingSsl(COM_HANDLE comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return false; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/ComDirector.cpp b/source/native/nf-interpreter/src/PAL/COM/ComDirector.cpp new file mode 100644 index 00000000..040b4050 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/ComDirector.cpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +int DebuggerPort_Write( COM_HANDLE ComPortNum, const char* Data, size_t size, int maxRetries ) +{ + NATIVE_PROFILE_PAL_COM(); + + UINT32 transport = ExtractTransport(ComPortNum); + const char* dataTmp = Data; + INT32 totWrite = 0; + int retries = maxRetries + 1; + + while(size > 0 && retries > 0 ) + { + int ret = 0; + + switch(transport) + { + case USART_TRANSPORT: + ret = USART_Write( ConvertCOM_ComPort( ComPortNum ), dataTmp, size ); + break; + case USB_TRANSPORT: + ret = USB_Write( ConvertCOM_UsbStream( ComPortNum ), dataTmp, size ); + break; + case SOCKET_TRANSPORT: + ret = SOCKETS_Write( ConvertCOM_SockPort(ComPortNum), dataTmp, size ); + break; + + case GENERIC_TRANSPORT: + return GenericPort_Write( ConvertCOM_GenericPort( ComPortNum ), dataTmp, size ); + } + + if(ret < 0) + { // error condition, bug out + break; + } + else if(ret == 0) + { // didn't send any data ( assume buffer full ) + --retries; + + // if interrupts are off and buffer is full or out of retries + // then there is nothing more to do. + if(!INTERRUPTS_ENABLED_STATE() || retries <= 0 ) + break; + + Events_WaitForEvents(0, 1); + } + else + { // succesfully transmitted at least some of the data + // update counters and loop back to try sending more + retries = maxRetries + 1; + size -= ret; + dataTmp += ret; + totWrite += ret; + } + } + + return totWrite; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/GenericPort_stubs.c b/source/native/nf-interpreter/src/PAL/COM/GenericPort_stubs.c new file mode 100644 index 00000000..8de1d3bd --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/GenericPort_stubs.c @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +__nfweak bool GenericPort_Initialize(int comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool GenericPort_Uninitialize(int comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak uint32_t GenericPort_Write(int comPortNum, const char* data, size_t size) +{ + (void)comPortNum; + (void)data; + (void)size; + + NATIVE_PROFILE_PAL_COM(); + return 0; +} + +__nfweak int GenericPort_Read(int comPortNum, char* data, size_t size) +{ + (void)comPortNum; + (void)data; + (void)size; + + NATIVE_PROFILE_PAL_COM(); + return 0; +} + +__nfweak bool GenericPort_Flush(int comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool GenericPort_IsSslSupported(int comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return false; +} + +__nfweak bool GenericPort_UpgradeToSsl(int comPortNum, unsigned int flags) +{ + (void)comPortNum; + (void)flags; + + NATIVE_PROFILE_PAL_COM(); + return false; +} + +__nfweak bool GenericPort_IsUsingSsl(int comPortNum) +{ + (void)comPortNum; + + NATIVE_PROFILE_PAL_COM(); + return false; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/Sockets_debugger.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/Sockets_debugger.cpp new file mode 100644 index 00000000..17ef409e --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/Sockets_debugger.cpp @@ -0,0 +1,640 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sockets_lwip.h" +#include + +HAL_COMPLETION Sockets_LWIP_Driver::s_DebuggerTimeoutCompletion; + +static HAL_CONTINUATION MulticastResponseContinuation; + +int g_DebuggerPort_SslCtx_Handle = -1; + +// +// Methods used by the Network Debugger +// + +bool SOCKETS_DbgInitialize( int ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + + return Sockets_LWIP_Driver::InitializeDbgListener( ComPortNum ); +} + +bool SOCKETS_DbgUninitialize( int ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::UninitializeDbgListener( ComPortNum ); +} + +int32_t SOCKETS_Write( int32_t ComPortNum, const char* Data, size_t size ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Write( ComPortNum, Data, size ); +} + +int32_t SOCKETS_Read( int32_t ComPortNum, char* Data, size_t size ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Read( ComPortNum, Data, size ); +} + +bool SOCKETS_Flush( int32_t ComPortNum ) +{ + (void)ComPortNum; + + NATIVE_PROFILE_PAL_COM(); + //Events_WaitForEvents(0, 2); + return TRUE; +} + +bool SOCKETS_UpgradeToSsl( int32_t ComPortNum, const int8_t* pCACert, uint32_t caCertLen, const int8_t* pDeviceCert, uint32_t deviceCertLen, LPCSTR szTargetHost ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::UpgradeToSsl( ComPortNum, pCACert, caCertLen, pDeviceCert, deviceCertLen, szTargetHost ); +} + +bool SOCKETS_IsUsingSsl( int32_t ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::IsUsingSsl( ComPortNum ); +} + +void Sockets_LWIP_Driver::Debugger_Initialize() +{ + if(!s_initializedDbg) + { + memset(&MulticastResponseContinuation, 0, sizeof(MulticastResponseContinuation)); + memset(&s_DebuggerTimeoutCompletion, 0, sizeof(s_DebuggerTimeoutCompletion)); + + g_Sockets_LWIP_Driver.m_multicastSocket = SOCK_SOCKET_ERROR; + g_Sockets_LWIP_Driver.m_SocketDebugStream = SOCK_SOCKET_ERROR; + g_Sockets_LWIP_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR; + + g_Sockets_LWIP_Driver.m_stateDebugSocket = DbgSock_Uninitialized; + + g_Sockets_LWIP_Driver.m_usingSSL = FALSE; + + s_initializedDbg = TRUE; + } +} + + +void Sockets_LWIP_Driver::Debugger_Uninitialize() +{ + g_Sockets_LWIP_Driver.m_multicastSocket = SOCK_SOCKET_ERROR; + g_Sockets_LWIP_Driver.m_SocketDebugStream = SOCK_SOCKET_ERROR; + g_Sockets_LWIP_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR; + s_initializedDbg = FALSE; +} + +void Sockets_LWIP_Driver::Debugger_Abort() +{ + MulticastResponseContinuation.Abort(); + s_DebuggerTimeoutCompletion.Abort(); + + g_Sockets_LWIP_Driver.m_stateDebugSocket = DbgSock_Uninitialized; +} + + +bool Sockets_LWIP_Driver::InitializeDbgListener( int ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + SOCK_sockaddr_in sockAddr; + int nonblocking = 1; + int32_t optval = 1; + int32_t optLinger = 0; + void *dummyPtr; + SOCKET_CHECK_ENTER(); + + Debugger_Initialize(); + + if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return FALSE; + + if(g_Sockets_LWIP_Driver.m_SocketDebugListener != SOCK_SOCKET_ERROR) return TRUE; + + s_DebuggerTimeoutCompletion.InitializeForUserMode(OnDebuggerTimeout); + + //-- debug api socket --// + + g_Sockets_LWIP_Driver.m_SocketDebugListener = Socket( SOCK_AF_INET, SOCK_SOCK_STREAM, SOCK_IPPROTO_TCP, TRUE ); + SOCKET_CHECK_RESULT( g_Sockets_LWIP_Driver.m_SocketDebugListener ); + + memset( &sockAddr, 0, sizeof(sockAddr) ); + sockAddr.sin_family = SOCK_AF_INET; + sockAddr.sin_port = SOCK_htons(DEBUG_SOCKET_PORT); + sockAddr.sin_addr.S_un.S_addr = SOCK_htonl(SOCK_INADDR_ANY); + + SOCKET_CHECK_RESULT( SOCK_ioctl(g_Sockets_LWIP_Driver.m_SocketDebugListener, SOCK_FIONBIO, &nonblocking) ); + + SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt( g_Sockets_LWIP_Driver.m_SocketDebugListener, SOCK_IPPROTO_TCP, SOCK_TCP_NODELAY, (char*)&optval, sizeof(optval) ) ); + + SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt(g_Sockets_LWIP_Driver.m_SocketDebugListener, SOCK_SOL_SOCKET, SOCK_SOCKO_LINGER, (const char*)&optLinger, sizeof(int32_t)) ); + + // need this to keep the compiler happy about the cast to SOCK_sockaddr + // which is intended and perfectly safe + dummyPtr = &sockAddr; + + SOCKET_CHECK_RESULT( + SOCK_bind( + g_Sockets_LWIP_Driver.m_SocketDebugListener, + (const SOCK_sockaddr*)dummyPtr, + sizeof(sockAddr)) + ); + + SOCKET_CHECK_RESULT( SOCK_listen( g_Sockets_LWIP_Driver.m_SocketDebugListener, 1 ) ); + + g_Sockets_LWIP_Driver.m_stateDebugSocket = DbgSock_Listening; + + InitializeMulticastDiscovery(); + MulticastDiscoverySchedule(); + + SOCKET_CLEANUP(); + + if(g_Sockets_LWIP_Driver.m_SocketDebugListener != SOCK_SOCKET_ERROR) + { + SOCK_close(g_Sockets_LWIP_Driver.m_SocketDebugListener); + g_Sockets_LWIP_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR; + + debug_printf("DBGLISTENER SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() ); + } + + SOCKET_CHECK_EXIT_bool_CLEANUP(); +} + +bool Sockets_LWIP_Driver::UninitializeDbgListener( int ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + + if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return FALSE; + + g_Sockets_LWIP_Driver.m_stateDebugSocket = DbgSock_Uninitialized; + + CloseDebuggerSocket(); + + if(g_Sockets_LWIP_Driver.m_SocketDebugListener != SOCK_SOCKET_ERROR) + { + SOCK_close( g_Sockets_LWIP_Driver.m_SocketDebugListener ); + + g_Sockets_LWIP_Driver.m_SocketDebugListener = SOCK_SOCKET_ERROR; + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// +// Write - The Write method will write data to the debugger stream socket (if a connection is active). +// In addition if the write fails for a reason other than EWOULDBLOCK then we should shutdown +// the debugger stream socket and change to the listening state +// +//----------------------------------------------------------------------------- +int Sockets_LWIP_Driver::Write( int ComPortNum, const char* Data, size_t size ) +{ + NATIVE_PROFILE_PAL_COM(); + int32_t ret; + + if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return SOCK_SOCKET_ERROR; + + if((g_Sockets_LWIP_Driver.m_stateDebugSocket != DbgSock_Connected) || + (g_Sockets_LWIP_Driver.m_SocketDebugStream == SOCK_SOCKET_ERROR)) + { + return SOCK_SOCKET_ERROR; + } + + if(g_Sockets_LWIP_Driver.m_usingSSL) + { + ret = SSL_Write(g_Sockets_LWIP_Driver.m_SocketDebugStream, Data, size); + } + else + { + ret = SOCK_send( g_Sockets_LWIP_Driver.m_SocketDebugStream, Data, size, 0 ); + } + + if(ret < 0) + { + int32_t err = SOCK_getlasterror(); + + // debugger stream is no longer active, change to listening state + if(err != SOCK_EWOULDBLOCK) + { + CloseDebuggerSocket(); + } + else + { + ret = 0; + } + } + + return ret; +} + +//----------------------------------------------------------------------------- +// +// Read - the Read method performs two duties: first to read data from the debug stream; and +// second to manage the debugger connection state. The initial state is to be listening for debug +// connections, and therefore each read performs an accept to see if there is a pending connection. +// Once a connection is made the state changes to connected and the debugger stream socket +// is read for each Read call. During the Connected state an Accept is still called so that no other +// connections will be handled. If the debugger is still receiving data on the debugger stream, then +// new connections will be closed immediately. If the debugger stream socket has been closed then +// the state return to the listening state (unless there is an pending connection in which case the +// pending connection becomes the new debugger stream). +// +//----------------------------------------------------------------------------- +int Sockets_LWIP_Driver::Read( int ComPortNum, char* Data, size_t size ) +{ + NATIVE_PROFILE_PAL_COM(); + SOCK_SOCKET sock; + SOCK_sockaddr addr; + int len; + int32_t ret = 0; + SOCK_timeval timeout; + SOCK_fd_set readSet; + + if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return 0; + + if(g_Sockets_LWIP_Driver.m_stateDebugSocket == DbgSock_Uninitialized) return 0; + + memset(&addr, 0, sizeof(addr)); + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + readSet.fd_array[0] = g_Sockets_LWIP_Driver.m_SocketDebugListener; + readSet.fd_count = 1; + + // if we are connected, then read from the debug stream + if(g_Sockets_LWIP_Driver.m_stateDebugSocket == DbgSock_Connected) + { + if(g_Sockets_LWIP_Driver.m_usingSSL) + { + ret = SSL_Read(g_Sockets_LWIP_Driver.m_SocketDebugStream, Data, size); + } + else + { + ret = SOCK_recv(g_Sockets_LWIP_Driver.m_SocketDebugStream, Data, size, 0); + } + + // return value of zero indicates a shutdown of the socket. Also we shutdown for any error except + // ewouldblock. If either of these happens, then we go back to the listening state + if((ret == 0) || (ret == SOCK_SOCKET_ERROR && SOCK_getlasterror() != SOCK_EWOULDBLOCK)) + { + CloseDebuggerSocket(); + } + else if(ret != SOCK_SOCKET_ERROR && s_DebuggerTimeoutCompletion.IsLinked()) + { + // we either got data or the socket was closed, so kill the timeout + s_DebuggerTimeoutCompletion.Abort(); + } + } + + if(SOCK_SOCKET_ERROR != HAL_SOCK_select( SOCK_FD_SETSIZE, &readSet, NULL, NULL, &timeout)) + { + // we always perform an accept so that we handle pending connections + // if we already are connected and the debug stream socket is still active, then we immediately close + // the pending connection + sock = Accept( g_Sockets_LWIP_Driver.m_SocketDebugListener, &addr, &len, TRUE ); + + if(SOCK_SOCKET_ERROR != sock) + { + int nonblocking = 1; + bool optval = 1; + int32_t optLinger = 0; + + // if we are already in the connected state, then verify that the debugger stream socket is still active + if(DbgSock_Connected == g_Sockets_LWIP_Driver.m_stateDebugSocket) + { + // the debugger stream is still active, so shutdown the pending connection + HAL_SOCK_setsockopt( sock, SOCK_SOL_SOCKET, SOCK_SOCKO_LINGER, (const char*)&optLinger, sizeof(int32_t) ); + SOCK_close(sock); + + // set timeout since another connection is trying to use us. + if(!s_DebuggerTimeoutCompletion.IsLinked()) + { + s_DebuggerTimeoutCompletion.EnqueueDelta(5000000); // 5 seconds + } + } + else // we are in the listening state, so accept the pending connection and update the state + { + g_Sockets_LWIP_Driver.m_SocketDebugStream = sock; + SOCKET_CHECK_RESULT( SOCK_ioctl(g_Sockets_LWIP_Driver.m_SocketDebugStream, SOCK_FIONBIO, &nonblocking) ); + SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt( g_Sockets_LWIP_Driver.m_SocketDebugStream, SOCK_IPPROTO_TCP, SOCK_TCP_NODELAY, (char*)&optval, sizeof(optval) ) ); + SOCKET_CHECK_RESULT( HAL_SOCK_setsockopt( g_Sockets_LWIP_Driver.m_SocketDebugStream, SOCK_SOL_SOCKET, SOCK_SOCKO_LINGER, (const char*)&optLinger, sizeof(int32_t) ) ); + + g_Sockets_LWIP_Driver.m_stateDebugSocket = DbgSock_Connected; + + SOCKET_CLEANUP() + + if(g_Sockets_LWIP_Driver.m_SocketDebugStream != SOCK_SOCKET_ERROR) + { + SOCK_close(g_Sockets_LWIP_Driver.m_SocketDebugStream); + g_Sockets_LWIP_Driver.m_SocketDebugStream = SOCK_SOCKET_ERROR; + + debug_printf("DBGSTREAM SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() ); + } + + SOCKET_CHECK_EXIT_NORETURN(); + } + + HAL_SOCK_EventsSet( SOCKET_EVENT_FLAG_SOCKET ); + } + } + + if(ret < 0) + { + ret = 0; + } + + return ret; +} + +void Sockets_LWIP_Driver::CloseDebuggerSocket() +{ + if(g_Sockets_LWIP_Driver.m_SocketDebugStream != SOCK_SOCKET_ERROR) + { + if(g_Sockets_LWIP_Driver.m_usingSSL) + { + SSL_CloseSocket( g_Sockets_LWIP_Driver.m_SocketDebugStream ); + } + else + { + SOCK_close( g_Sockets_LWIP_Driver.m_SocketDebugStream ); + } + + g_Sockets_LWIP_Driver.m_usingSSL = FALSE; + + g_Sockets_LWIP_Driver.m_SocketDebugStream = SOCK_SOCKET_ERROR; + + g_Sockets_LWIP_Driver.m_stateDebugSocket = DbgSock_Listening; + + s_DebuggerTimeoutCompletion.Abort(); + } +} + +void Sockets_LWIP_Driver::OnDebuggerTimeout(void* arg) +{ + (void)arg; + + CloseDebuggerSocket(); +} + +bool Sockets_LWIP_Driver::IsUsingSsl( int ComPortNum ) +{ + if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return FALSE; + if(g_Sockets_LWIP_Driver.m_stateDebugSocket == DbgSock_Uninitialized) return FALSE; + + if(g_Sockets_LWIP_Driver.m_stateDebugSocket == DbgSock_Connected) + { + return g_Sockets_LWIP_Driver.m_usingSSL; + } + + return FALSE; +} + +bool Sockets_LWIP_Driver::UpgradeToSsl( int ComPortNum, const int8_t* pCACert, uint32_t caCertLen, const int8_t* pDeviceCert, uint32_t deviceCertLen, const char* szTargetHost ) +{ + if(ComPortNum != ConvertCOM_SockPort(COM_SOCKET_DBG)) return 0; + if(g_Sockets_LWIP_Driver.m_stateDebugSocket == DbgSock_Uninitialized) return 0; + + if(g_Sockets_LWIP_Driver.m_stateDebugSocket == DbgSock_Connected) + { + if(g_Sockets_LWIP_Driver.m_usingSSL) return TRUE; + + // TLS only and Verify=Required --> only verify the server + if(SSL_ClientInit( 0x10, 0x04, (const char*)pDeviceCert, deviceCertLen, NULL, 0 , NULL, 0, g_DebuggerPort_SslCtx_Handle )) + { + int32_t ret; + + SSL_AddCertificateAuthority( g_DebuggerPort_SslCtx_Handle, (const char*)pCACert, caCertLen, NULL); + + do + { + ret = SSL_Connect( g_Sockets_LWIP_Driver.m_SocketDebugStream, szTargetHost, g_DebuggerPort_SslCtx_Handle ); + } + while(ret == SOCK_EWOULDBLOCK || ret == SOCK_TRY_AGAIN); + + + if(ret != 0) + { + SSL_CloseSocket(g_Sockets_LWIP_Driver.m_SocketDebugStream); + SSL_ExitContext(g_DebuggerPort_SslCtx_Handle); + } + else + { + g_Sockets_LWIP_Driver.m_usingSSL = TRUE; + } + + return ret == 0; + } + } + + return FALSE; +} + +//----------------------------------------------------------------------------- +// +// InitializeMulticastDiscovery - Initialize the NETMF discovery service for +// sockets. We use multicast sockets to create the discovery mechanism. +// +//----------------------------------------------------------------------------- +bool Sockets_LWIP_Driver::InitializeMulticastDiscovery() +{ + NATIVE_PROFILE_PAL_COM(); + SOCKET_CHECK_ENTER(); + SOCK_sockaddr_in sockAddr; + void *dummyPtr; + int nonblocking = 1; + + if(g_Sockets_LWIP_Driver.s_discoveryInitialized) return TRUE; + + MulticastResponseContinuation.InitializeCallback(MulticastDiscoveryRespond, NULL); + + // set up discovery socket to list to defined discovery port for any ip address + memset( &sockAddr, 0, sizeof(sockAddr) ); + sockAddr.sin_family = SOCK_AF_INET; + sockAddr.sin_port = SOCK_htons(SOCK_DISCOVERY_MULTICAST_PORT); + sockAddr.sin_addr.S_un.S_addr = SOCK_htonl(SOCK_INADDR_ANY); + + // UDP socket is easier in our scenario because it isn't session based + g_Sockets_LWIP_Driver.m_multicastSocket = Socket( SOCK_AF_INET, SOCK_SOCK_DGRAM, SOCK_IPPROTO_UDP, FALSE ); + SOCKET_CHECK_RESULT( g_Sockets_LWIP_Driver.m_multicastSocket ); + + // set sock option for multicast + SOCK_ip_mreq multicast; + multicast.imr_multiaddr.S_un.S_addr = SOCK_htonl(SOCK_DISCOVERY_MULTICAST_IPADDR); + multicast.imr_interface.S_un.S_addr = SOCK_htonl(SOCK_INADDR_ANY); + + SOCKET_CHECK_RESULT( SOCK_ioctl(g_Sockets_LWIP_Driver.m_multicastSocket, SOCK_FIONBIO, &nonblocking) ); + + SOCKET_CHECK_RESULT( SOCK_setsockopt( g_Sockets_LWIP_Driver.m_multicastSocket, SOCK_IPPROTO_IP, SOCK_IPO_ADD_MEMBERSHIP, (const char*)&multicast, sizeof(multicast) ) ); + + // need this to keep the compiler happy about the cast to SOCK_sockaddr + // which is intended and perfectly safe + dummyPtr = &sockAddr; + + SOCKET_CHECK_RESULT( + SOCK_bind( + g_Sockets_LWIP_Driver.m_multicastSocket, + (const SOCK_sockaddr*)&dummyPtr, + sizeof(sockAddr)) + ); + + g_Sockets_LWIP_Driver.s_discoveryInitialized = TRUE; + + + SOCKET_CLEANUP() + + if(g_Sockets_LWIP_Driver.m_multicastSocket != SOCK_SOCKET_ERROR) + { + SOCK_close(g_Sockets_LWIP_Driver.m_multicastSocket); + g_Sockets_LWIP_Driver.m_multicastSocket = SOCK_SOCKET_ERROR; + + debug_printf("MULTICAST SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() ); + } + + SOCKET_CHECK_EXIT_bool_CLEANUP(); +} + +// TODO. Schedule the Discovery Multicast Response + +//----------------------------------------------------------------------------- +// +// MulticastDiscoveryRespond - Respond to a NETMF multicast message. This is +// a simple discovery mechanism that uses multicast sockets over UDP. The +// client will send a message to the ip address defined by +// SOCK_DISCOVERY_MULTICAST_IPADDR +// over port +// SOCK_DISCOVERY_MULTICAST_PORT +// If the message contains the string "NETMF", then a response is sent with the +// the data structure SOCK_discoveryinfo (which includes the ip address and mac +// address of the device). +// +//----------------------------------------------------------------------------- + +void Sockets_LWIP_Driver::MulticastDiscoverySchedule() +{ + if (g_Sockets_LWIP_Driver.m_multicastSocket != SOCK_SOCKET_ERROR) + { + SOCK_fd_set privRead; + SOCK_timeval to; + + to.tv_sec = 0; + to.tv_usec = 0; + + privRead.fd_array[0] = g_Sockets_LWIP_Driver.m_multicastSocket; + privRead.fd_count = 1; + + if (1 == HAL_SOCK_select(1, &privRead, NULL, NULL, &to)) + { + if (!MulticastResponseContinuation.IsLinked()) + { + MulticastResponseContinuation.Enqueue(); + } + } + } +} + +void Sockets_LWIP_Driver::MulticastDiscoveryRespond(void* arg) +{ + (void)arg; + + NATIVE_PROFILE_PAL_COM(); + SOCK_sockaddr from; + void *dummyPtr; + + char data[64]; + int fromlen = sizeof(from); + + // intentionally call the HAL recvfrom so as not to invoke the signalnotifythread + int len = HAL_SOCK_recvfrom( g_Sockets_LWIP_Driver.m_multicastSocket, data, sizeof(data), 0, &from, &fromlen ); + + if(len > 0) + { + int32_t idx = 0; + bool fFound = FALSE; + const char* c_Signature = SOCK_DISCOVERY_MULTICAST_TOKEN; + int32_t sigLen = hal_strlen_s(c_Signature); + + // search for discovery token + while(idx <= (len-sigLen)) + { + if(0 == memcmp( &data[idx], c_Signature, sigLen)) + { + fFound = TRUE; + break; + } + idx++; + } + + if(fFound) + { + // HAL_Configuration_NetworkInterface current; + // SOCK_discoveryinfo info; + SOCK_sockaddr_in sockAddr; + SOCK_sockaddr_in sockAddrMulticast; + int32_t opt = 64; + SOCK_SOCKET sock; + int nonblocking = 1; + SOCKET_CHECK_ENTER(); + + // // Load is required here because the g_NetworkConfig contains only the static ip address (not DHCP) + // HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(0, ¤t); + + // info.ipaddr = current.ipaddr; + // info.macAddressLen = current.macAddressLen; + // memcpy( &info.macAddressBuffer[0], ¤t.macAddressBuffer[0], current.macAddressLen ); + + sock = Socket(SOCK_AF_INET, SOCK_SOCK_DGRAM, SOCK_IPPROTO_UDP, FALSE); + SOCKET_CHECK_RESULT(sock); + + memset( &sockAddr, 0, sizeof(sockAddr) ); + sockAddr.sin_family = SOCK_AF_INET; + sockAddr.sin_port = SOCK_htons(0); + // sockAddr.sin_addr.S_un.S_addr = info.ipaddr; + + memset( &sockAddrMulticast, 0, sizeof(sockAddrMulticast) ); + sockAddrMulticast.sin_family = SOCK_AF_INET; + sockAddrMulticast.sin_port = SOCK_htons(SOCK_DISCOVERY_MULTICAST_PORT); + sockAddrMulticast.sin_addr.S_un.S_addr = SOCK_htonl(SOCK_DISCOVERY_MULTICAST_IPADDR_SND); + + SOCKET_CHECK_RESULT(HAL_SOCK_ioctl(sock, SOCK_FIONBIO, &nonblocking)); + SOCKET_CHECK_RESULT(HAL_SOCK_setsockopt(sock, SOCK_IPPROTO_IP, SOCK_IPO_MULTICAST_TTL, (const char *) &opt, sizeof(opt))); + + // need this to keep the compiler happy about the cast to SOCK_sockaddr + // which is intended and perfectly safe + dummyPtr = &sockAddr; + + SOCKET_CHECK_RESULT( + HAL_SOCK_bind( + sock, + (const SOCK_sockaddr*)&dummyPtr, + sizeof(sockAddr)) + ); + + // send a multicast socket back to the caller + // SOCKET_CHECK_RESULT(SendTo(sock, (const char*)&info, sizeof(info), 0, (SOCK_sockaddr*)&sockAddrMulticast, sizeof(sockAddrMulticast))); + + SOCK_close(sock); + + SOCKET_CLEANUP(); + + if(sock != SOCK_SOCKET_ERROR) + { + SOCK_close(sock); + + debug_printf("MULTICAST RESP SOCKET_ERROR: %d\r\n", HAL_SOCK_getlasterror() ); + } + + SOCKET_CHECK_EXIT_NORETURN(); + } + } + + MulticastDiscoverySchedule(); +} + + +bool Sockets_LWIP_Driver::s_initializedDbg=FALSE; \ No newline at end of file diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.cpp new file mode 100644 index 00000000..028c2ec7 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.cpp @@ -0,0 +1,481 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sockets_lwip.h" + +//--// + +Sockets_LWIP_Driver g_Sockets_LWIP_Driver; + +SOCK_SOCKET SOCK_socket( int family, int type, int protocol ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Socket( family, type, protocol, FALSE ); +} +int SOCK_bind( SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int addressLen ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_bind( socket, address, addressLen ); +} +int SOCK_connect(SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int addressLen) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Connect(socket, address, addressLen); +} +int SOCK_send(SOCK_SOCKET socket, const char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Send(socket, buf, len, flags); +} +int SOCK_recv(SOCK_SOCKET socket, char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Recv(socket, buf, len, flags); +} +int SOCK_close(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Close(socket); +} +int SOCK_listen( SOCK_SOCKET socket, int backlog ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Listen( socket, backlog ); +} +SOCK_SOCKET SOCK_accept( SOCK_SOCKET socket, struct SOCK_sockaddr* address, int* addressLen ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Accept( socket, address, addressLen, FALSE ); +} +int SOCK_shutdown( SOCK_SOCKET socket, int how ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_shutdown( socket, how ); +} +int SOCK_getaddrinfo( const char* nodename, char* servname, const struct SOCK_addrinfo* hints, struct SOCK_addrinfo** res ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_getaddrinfo( nodename, servname, hints, res ); +} +void SOCK_freeaddrinfo( struct SOCK_addrinfo* ai ) +{ + NATIVE_PROFILE_PAL_COM(); + HAL_SOCK_freeaddrinfo( ai ); +} +int SOCK_ioctl( SOCK_SOCKET socket, int cmd, int* data ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_ioctl( socket, cmd, data ); +} +int SOCK_getlasterror() +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_getlasterror(); +} +int SOCK_getsocklasterror(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_getsocklasterror(socket); +} +int SOCK_select( int nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* except, const struct SOCK_timeval* timeout ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Select( nfds, readfds, writefds, except, timeout ); +} +int SOCK_setsockopt( SOCK_SOCKET socket, int level, int optname, const char* optval, int optlen ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_setsockopt( socket, level, optname, optval, optlen ); +} +int SOCK_getsockopt( SOCK_SOCKET socket, int level, int optname, char* optval, int* optlen ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_getsockopt( socket, level, optname, optval, optlen ); +} +int SOCK_getpeername( SOCK_SOCKET socket, struct SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_getpeername( socket, name, namelen ); +} +int SOCK_getsockname( SOCK_SOCKET socket, struct SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_getsockname( socket, name, namelen ); +} +int SOCK_recvfrom( SOCK_SOCKET s, char* buf, int len, int flags, struct SOCK_sockaddr* from, int* fromlen ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::RecvFrom( s, buf, len, flags, from, fromlen ); +} +int SOCK_sendto( SOCK_SOCKET s, const char* buf, int len, int flags, const struct SOCK_sockaddr* to, int tolen ) +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::SendTo( s, buf, len, flags, to, tolen ); +} + +bool Network_Initialize() +{ + NATIVE_PROFILE_PAL_COM(); + return Sockets_LWIP_Driver::Initialize( ); +} + +bool Network_Uninitialize() +{ + NATIVE_PROFILE_PAL_COM(); + + return Sockets_LWIP_Driver::Uninitialize( ); +} + +void SOCKETS_CloseConnections() +{ + NATIVE_PROFILE_PAL_COM(); + Sockets_LWIP_Driver::CloseConnections(FALSE); +} + +HRESULT SOCK_CONFIGURATION_LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(config, interfaceIndex); +} + +HRESULT SOCK_CONFIGURATION_UpdateAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex, uint32_t updateFlags) +{ + NATIVE_PROFILE_PAL_COM(); + HRESULT hr = S_OK; + bool success = FALSE; + + const uint32_t c_reInitFlag = UpdateOperation_Dhcp | + UpdateOperation_DhcpRenew | + UpdateOperation_Mac; + + const uint32_t c_uninitFlag = c_reInitFlag | UpdateOperation_DhcpRelease; + + if(0 != (updateFlags & c_uninitFlag)) + { + success = SOCKETS_DbgUninitialize(COM_SOCKET_DBG); + } + + hr = HAL_SOCK_CONFIGURATION_UpdateAdapterConfiguration(config, interfaceIndex, updateFlags); + + if(!SUCCEEDED(hr)) + { + return S_FALSE; + } + + if(0 != (updateFlags & c_reInitFlag)) + { + if(success) SOCKETS_DbgInitialize(COM_SOCKET_DBG); + } + + return hr; +} + +HRESULT SOCK_CONFIGURATION_LoadConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex) +{ + NATIVE_PROFILE_PAL_COM(); + HRESULT hr = S_OK; + + // load current DCHP settings + hr = SOCK_CONFIGURATION_LoadAdapterConfiguration(config, interfaceIndex); + + return hr; +} + +#define SOCKET_SHUTDOWN_READ 0 +#define SOCKET_SHUTDOWN_WRITE 1 +#define SOCKET_SHUTDOWN_READ_WRITE 2 + +#define ISSET_SOCKET_FLAG(x,y) ((y) == ((y) & (x).m_flags)) +#define SET_SOCKET_FLAG(x,y) (x).m_flags |= (y) +#define CLEAR_SOCKET_FLAG(x,y) (x).m_flags &= ~(y) + +//----------------------------------------------------------------------------- +// +// CloseConnections - close all connections with the option of leaving the debugger sockets open. +// debugger sockets are left open on CLR reboot so that communication with the debugger is not +// lost. +// +//----------------------------------------------------------------------------- +void Sockets_LWIP_Driver::CloseConnections(bool fCloseDbg) +{ + NATIVE_PROFILE_PAL_COM(); + + int32_t cnt = g_Sockets_LWIP_Driver.m_cntSockets; + int32_t idx = 0; + + // round one - close all SSL sockets + for( int32_t i=cnt-1; i>=0; i-- ) + { + struct SocketRegisterMap& entry = g_Sockets_LWIP_Driver.m_socketHandles[i]; + + if(entry.m_socket != SOCK_SOCKET_ERROR && + entry.m_sslData != NULL) + { + SSL_CloseSocket(entry.m_socket); + } + } + + // round two - close all non-SSL sockets + cnt = g_Sockets_LWIP_Driver.m_cntSockets; + + for( int32_t i=0; i 0) + { + memcpy( &g_Sockets_LWIP_Driver.m_socketHandles[i], + &g_Sockets_LWIP_Driver.m_socketHandles[idx++], + sizeof(g_Sockets_LWIP_Driver.m_socketHandles[i]) ); + } + } + } +} + +//--// + +SOCK_SOCKET Sockets_LWIP_Driver::Socket( int32_t family, int32_t type, int32_t protocol, bool fDebug ) +{ + NATIVE_PROFILE_PAL_COM(); + + int ret = HAL_SOCK_socket(family, type, protocol); + + if (ret != SOCK_SOCKET_ERROR) + { + RegisterSocket(ret, (protocol != SOCK_IPPROTO_TCP), fDebug); + } + return ret; +} +int Sockets_LWIP_Driver::Connect(SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int32_t addressLen) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_connect(socket, address, addressLen); +} +int Sockets_LWIP_Driver::Send(SOCK_SOCKET socket, const char* buf, int32_t len, int32_t flags) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_send(socket, buf, len, flags); +} +int Sockets_LWIP_Driver::Recv(SOCK_SOCKET socket, char* buf, int32_t len, int32_t flags) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_recv(socket, buf, len, flags); +} + +int Sockets_LWIP_Driver::Shutdown(SOCK_SOCKET sock, int32_t how) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_shutdown(sock, how); +} + +//----------------------------------------------------------------------------- +// +// Close - The close method marks a socket to be closed by the select thread. Close is handled +// in this way because (at least for one implementation) the select method can not be set for a +// closed socket. Therfore in the select thread the socket is closed. +// +//----------------------------------------------------------------------------- +int Sockets_LWIP_Driver::Close(SOCK_SOCKET sock) +{ + NATIVE_PROFILE_PAL_COM(); + UnregisterSocket(sock); + return HAL_SOCK_close(sock); +} +int Sockets_LWIP_Driver::Listen( SOCK_SOCKET socket, int32_t backlog ) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_listen(socket, backlog); +} +SOCK_SOCKET Sockets_LWIP_Driver::Accept( SOCK_SOCKET socket, struct SOCK_sockaddr* address, int* addressLen, bool fDebug ) +{ + NATIVE_PROFILE_PAL_COM(); + + int ret = HAL_SOCK_accept(socket, address, addressLen); + + if (ret != SOCK_SOCKET_ERROR) + { + RegisterSocket(ret, TRUE, fDebug); + } + + return ret; +} + +int Sockets_LWIP_Driver::Select( int32_t nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* exceptfds, const SOCK_timeval* timeout ) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_select(nfds, readfds, writefds, exceptfds, timeout); +} + +int Sockets_LWIP_Driver::RecvFrom( SOCK_SOCKET s, char* buf, int32_t len, int32_t flags, struct SOCK_sockaddr* from, int* fromlen ) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_recvfrom(s, buf, len, flags, from, fromlen); +} + +int Sockets_LWIP_Driver::SendTo( SOCK_SOCKET s, const char* buf, int32_t len, int32_t flags, const struct SOCK_sockaddr* to, int32_t tolen ) +{ + NATIVE_PROFILE_PAL_COM(); + + return HAL_SOCK_sendto(s, buf, len, flags, to, tolen); +} + +bool Sockets_LWIP_Driver::Initialize() +{ + NATIVE_PROFILE_PAL_COM(); + SOCKET_CHECK_ENTER(); + + if(!s_initialized) + { + g_Sockets_LWIP_Driver.m_fShuttingDown = FALSE; + + g_Sockets_LWIP_Driver.m_cntSockets = 0; + + for( int32_t i=0; i= SOCKETS_MAX_COUNT) return; + + GLOBAL_LOCK_SOCKETS(lock); + + g_Sockets_LWIP_Driver.m_socketHandles[g_Sockets_LWIP_Driver.m_cntSockets].m_socket = sock; + g_Sockets_LWIP_Driver.m_socketHandles[g_Sockets_LWIP_Driver.m_cntSockets].m_flags = 0; + g_Sockets_LWIP_Driver.m_socketHandles[g_Sockets_LWIP_Driver.m_cntSockets].m_sslData = NULL; + + if(fDebug) SET_SOCKET_FLAG(g_Sockets_LWIP_Driver.m_socketHandles[g_Sockets_LWIP_Driver.m_cntSockets], SocketRegisterMap::c_DebugSocket); + + g_Sockets_LWIP_Driver.m_cntSockets++; +} + +//----------------------------------------------------------------------------- +// +// UnregisterSocket - No longer track a given socket for clean up and selection. +// This method should only be called immediately before closing down a socket. +// +//----------------------------------------------------------------------------- +void Sockets_LWIP_Driver::UnregisterSocket( SOCK_SOCKET sock ) +{ + int32_t index= -1; + + NATIVE_PROFILE_PAL_COM(); + GLOBAL_LOCK_SOCKETS(lock); + + g_Sockets_LWIP_Driver.GetSocketSslData(sock, index); + + if (index == -1) return; + + g_Sockets_LWIP_Driver.m_cntSockets--; + + if(index != g_Sockets_LWIP_Driver.m_cntSockets) + { + memcpy( &g_Sockets_LWIP_Driver.m_socketHandles[index], + &g_Sockets_LWIP_Driver.m_socketHandles[g_Sockets_LWIP_Driver.m_cntSockets], + sizeof(g_Sockets_LWIP_Driver.m_socketHandles[index]) ); + } + + g_Sockets_LWIP_Driver.m_socketHandles[g_Sockets_LWIP_Driver.m_cntSockets].m_socket = SOCK_SOCKET_ERROR; + g_Sockets_LWIP_Driver.m_socketHandles[g_Sockets_LWIP_Driver.m_cntSockets].m_flags = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// weak implementations of the functions (to be replaced with _strong_ implementations if and when required) // +// C++ version +// __nfweak void debug_printf( const char* format, ... ) +// { +// return; +// } + +bool Sockets_LWIP_Driver::s_initialized=FALSE; +bool Sockets_LWIP_Driver::s_wirelessInitialized=FALSE; +bool Sockets_LWIP_Driver::s_discoveryInitialized=FALSE; + + diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.h b/source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.h new file mode 100644 index 00000000..bb7b972c --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/sockets_lwip.h @@ -0,0 +1,187 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _SOCKETS_H_ +#define _SOCKETS_H_ 1 + +//--// + +#include "nanoHAL.h" + +//--// + +#define SOCKET_CHECK_ENTER() \ + int32_t ret=0 \ + +#define SOCKET_CLEANUP() \ + goto RETURN_OK; \ + SOCKET_CHECK_RETURN: \ + +#define SOCKET_CHECK_EXIT_CLEANUP() \ + RETURN_OK: \ + ASSERT(ret != SOCK_SOCKET_ERROR); \ + return ret; \ + +#define SOCKET_CHECK_EXIT() \ + SOCKET_CLEANUP() \ + RETURN_OK: \ + ASSERT(ret != SOCK_SOCKET_ERROR); \ + return ret; \ + +#define SOCKET_CHECK_EXIT_bool() \ + SOCKET_CLEANUP() \ + RETURN_OK: \ + return ret != SOCK_SOCKET_ERROR; \ + +#define SOCKET_CHECK_EXIT_bool_CLEANUP()\ + RETURN_OK: \ + return ret != SOCK_SOCKET_ERROR; \ + +#define SOCKET_CHECK_RESULT(x) \ + if((ret = (x)) == SOCK_SOCKET_ERROR)\ + { \ + goto SOCKET_CHECK_RETURN; \ + } \ + +#define SOCKET_CHECK_bool(x) \ + if(!(x)) \ + { \ + ret = SOCK_SOCKET_ERROR; \ + goto SOCKET_CHECK_RETURN; \ + } \ + +#define SOCKET_CHECK_EXIT_NORETURN() \ + RETURN_OK: \ + +struct Sockets_LWIP_Driver +{ + static SOCK_SOCKET Socket( int32_t family, int32_t type, int32_t protocol, bool fDebug ); + static int Connect(SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int32_t addressLen) ; + static int Send(SOCK_SOCKET socket, const char* buf, int32_t len, int32_t flags) ; + static int Recv(SOCK_SOCKET socket, char* buf, int32_t len, int32_t flags); + static int Close(SOCK_SOCKET socket); + static int Listen( SOCK_SOCKET socket, int32_t backlog ); + static SOCK_SOCKET Accept( SOCK_SOCKET socket, struct SOCK_sockaddr* address, int* addressLen, bool fDebug ); + static int Select( int32_t nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* except, const struct SOCK_timeval* timeout ); + static int RecvFrom( SOCK_SOCKET s, char* buf, int32_t len, int32_t flags, struct SOCK_sockaddr* from, int* fromlen ); + static int SendTo( SOCK_SOCKET s, const char* buf, int32_t len, int32_t flags, const struct SOCK_sockaddr* to, int32_t tolen ); + static int Shutdown( SOCK_SOCKET s, int32_t how); + + static bool Initialize(); + static bool Uninitialize(); + static void CloseConnections(bool fCloseDbg); + + static void SaveConfig(int32_t index, HAL_Configuration_NetworkInterface *cfg); + + // Debugger methods ( socket_debugger.cpp ) + static void Debugger_Initialize(); + static void Debugger_Uninitialize(); + static void Debugger_Abort(); + + static bool InitializeDbgListener( int ComPortNum ); + static bool UninitializeDbgListener( int ComPortNum ); + static int Write( int ComPortNum, const char* Data, size_t size ); + static int Read ( int ComPortNum, char* Data, size_t size ); + static bool UpgradeToSsl( int ComPortNum, const int8_t* pCACert, uint32_t caCertLen, const int8_t* pDeviceCert, uint32_t deviceCertLen, const char* szTargetHost ); + static bool IsUsingSsl( int ComPortNum ); + + void* GetSocketSslData(SOCK_SOCKET socket) + { + int32_t tmp; + + return GetSocketSslData(socket, tmp); + } + + void* GetSocketSslData(SOCK_SOCKET socket, int32_t &sockIndex) + { + GLOBAL_LOCK_SOCKETS(x); + + for(int i=m_cntSockets-1; i>=0; i--) + { + if(socket == m_socketHandles[i].m_socket) + { + sockIndex = i; + return m_socketHandles[i].m_sslData; + } + } + + return NULL; + } + + void SetSocketSslData(SOCK_SOCKET socket, void* sslObj) + { + GLOBAL_LOCK_SOCKETS(x); + + for(int i=m_cntSockets-1; i>=0; i--) + { + if(socket == m_socketHandles[i].m_socket) + { + m_socketHandles[i].m_sslData = sslObj; + + break; + } + } + } + + // required by SSL + static void UnregisterSocket( int index ); + + + static void ClearStatusBitsForSocket(SOCK_SOCKET sock, bool fWrite); + static bool InitializeMulticastDiscovery(); + +private: + + static void RegisterSocket( SOCK_SOCKET sock, bool selectable, bool fDebug ); + + struct SocketRegisterMap + { + SOCK_SOCKET m_socket; + uint32_t m_flags; + void* m_sslData; + + static const uint32_t c_SelectableSocket = 0x0001; + static const uint32_t c_DebugSocket = 0x0002; + static const uint32_t c_CloseSocket = 0x0004; + }; + + enum DebuggerState + { + DbgSock_Uninitialized = 0, + DbgSock_Listening = 1, + DbgSock_Connected = 2, + } m_stateDebugSocket; + + bool m_usingSSL; + + static void MulticastDiscoveryRespond(void* arg); + static void MulticastDiscoverySchedule(); + + static void CloseDebuggerSocket(); + static void OnDebuggerTimeout(void* arg); + + static HAL_COMPLETION s_DebuggerTimeoutCompletion; + + SOCK_SOCKET m_SocketDebugListener; + SOCK_SOCKET m_SocketDebugStream; + SOCK_SOCKET m_multicastSocket; + + bool m_fShuttingDown; + + int32_t m_cntSockets; + struct SocketRegisterMap m_socketHandles[SOCKETS_MAX_COUNT]; + + static bool s_initialized; + static bool s_initializedDbg; + static const int32_t c_WellKnownDebugPort = DEBUG_SOCKET_PORT; + static bool s_wirelessInitialized; + static bool s_discoveryInitialized; +}; + +extern Sockets_LWIP_Driver g_Sockets_LWIP_Driver; + +#endif //_SOCKETS_H_ + diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/mbedtls.h b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/mbedtls.h new file mode 100644 index 00000000..75f164ce --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/mbedtls.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef MBEDTLS_H +#define MBEDTLS_H + +#include + +#include + +#include "mbedtls/platform.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + +typedef struct mbedTLS_NFContext +{ + mbedtls_entropy_context* entropy; + mbedtls_ctr_drbg_context* ctr_drbg; + mbedtls_ssl_config* conf; + mbedtls_ssl_context* ssl; + mbedtls_net_context* server_fd; + mbedtls_x509_crt* x509_crt; + mbedtls_pk_context* pk; +}mbedTLS_NFContext; + +int net_would_block( const mbedtls_net_context *ctx ); +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, uint32_t timeout ); +void mbedtls_net_free( mbedtls_net_context *ctx ); + +// debug output declaration +void nf_debug( void *ctx, int level, const char *file, int line, const char *str ); + +#ifdef __cplusplus +extern "C" { +#endif + +// function returning the system date and time in Unix Epoch +time_t nf_get_unix_epoch(); + +#ifdef __cplusplus +} +#endif + +#define SOCKET_DRIVER g_Sockets_LWIP_Driver + +#endif diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h new file mode 100644 index 00000000..0b33bb1a --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h @@ -0,0 +1,192 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// See LICENSE file in the project root for full license information. +// + +#ifndef NF_MBEDTLS_CONFIG_H +#define NF_MBEDTLS_CONFIG_H + +#include +#include +#include + +// need to declare this as external to be picked up by mbed TLS platform_time +#ifdef __cplusplus +extern "C" { +#endif + +time_t nf_get_unix_epoch(); + +#ifdef __cplusplus +} +#endif + +/* System support */ +#define MBEDTLS_HAVE_ASM + +#define MBEDTLS_HAVE_TIME + +#define MBEDTLS_HAVE_TIME_DATE + +// need to define this as the alternative to standard time function +#define MBEDTLS_PLATFORM_TIME_MACRO nf_get_unix_epoch + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_CFB +#define MBEDTLS_CIPHER_MODE_CTR +#define MBEDTLS_CIPHER_MODE_OFB +#define MBEDTLS_CIPHER_MODE_XTS +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#define MBEDTLS_PK_PARSE_EC_EXTENDED +#define MBEDTLS_ERROR_STRERROR_DUMMY +#define MBEDTLS_GENPRIME +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_PK_RSA_ALT_SUPPORT +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define MBEDTLS_SSL_FALLBACK_SCSV +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING +#define MBEDTLS_SSL_RENEGOTIATION +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define MBEDTLS_SSL_PROTO_TLS1 +#define MBEDTLS_SSL_PROTO_TLS1_1 +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_ALPN +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE +#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define MBEDTLS_SSL_SERVER_NAME_INDICATION +#define MBEDTLS_SSL_TRUNCATED_HMAC +#define MBEDTLS_X509_CHECK_KEY_USAGE +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/* mbed TLS modules */ +#define MBEDTLS_AESNI_C +#define MBEDTLS_AES_C +#define MBEDTLS_ARC4_C +#define MBEDTLS_ASN1_PARSE_C + +//#define MBEDTLS_ASN1_WRITE_C + +#define MBEDTLS_BASE64_C + +#define MBEDTLS_BIGNUM_C + +#define MBEDTLS_BLOWFISH_C + +#define MBEDTLS_CAMELLIA_C +#define MBEDTLS_CCM_C + +#define MBEDTLS_CIPHER_C + +#define MBEDTLS_CTR_DRBG_C + +#define MBEDTLS_DES_C +#define MBEDTLS_DHM_C +#define MBEDTLS_ECDH_C + +//#define MBEDTLS_ECDSA_C + +#define MBEDTLS_ECP_C + +#define MBEDTLS_ENTROPY_C + +#define MBEDTLS_ERROR_C + +#define MBEDTLS_GCM_C + +#define MBEDTLS_HKDF_C + +#define MBEDTLS_HMAC_DRBG_C + +#define MBEDTLS_MD_C + +#define MBEDTLS_MD5_C + +#define MBEDTLS_OID_C +#define MBEDTLS_PADLOCK_C + +#define MBEDTLS_PEM_PARSE_C + +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C + +#define MBEDTLS_PKCS5_C +#define MBEDTLS_PKCS12_C + +#define MBEDTLS_PLATFORM_C + +#define MBEDTLS_POLY1305_C + +#define MBEDTLS_RIPEMD160_C + +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CACHE_C +#define MBEDTLS_SSL_COOKIE_C +#define MBEDTLS_SSL_TICKET_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C + +#define MBEDTLS_X509_USE_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_CRL_PARSE_C + +#define MBEDTLS_X509_CSR_PARSE_C + +#define MBEDTLS_XTEA_C + +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +//////////////////////////////////////////////////////////////////////////// +// This define depends on the platform having a hardware random generator. +// Requires that a function mbedtls_hardware_poll() exits as explained in mbed TLS documentation. +// Because it's target dependent, the define PLATFORM_HAS_RNG belongs in the target_common header +#if (PLATFORM_HAS_RNG == TRUE) +#define MBEDTLS_ENTROPY_HARDWARE_ALT +#endif +////////////////////////////////////////////////////////////////////////// + +#include + +#endif // NF_MBEDTLS_CONFIG_H diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_accept_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_accept_internal.cpp new file mode 100644 index 00000000..346e7215 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_accept_internal.cpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + +int ssl_accept_internal( + int sd, + int contextHandle ) +{ + mbedTLS_NFContext* context; + mbedtls_ssl_context *ssl; + int nonblock = 0; + int ret = SOCK_SOCKET_ERROR; + + // Check contextHandle range + if((contextHandle >= (int)ARRAYSIZE(g_SSL_Driver.ContextArray)) || (contextHandle < 0)) + { + goto error; + } + + context = (mbedTLS_NFContext*)g_SSL_Driver.ContextArray[contextHandle].Context; + ssl = context->ssl; + + // sanity check + if(ssl == NULL) + { + return SOCK_SOCKET_ERROR; + } + + // set socket in network context + context->server_fd->fd = sd; + + // setup internal SSL context and calls to transport layer send, receive and receive with timeout + mbedtls_ssl_set_bio( context->ssl, context->server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); + + // Set non blocking socket + SOCK_ioctl(sd, SOCK_FIONBIO, &nonblock); + + // connection is set up now proceed to SSL handshake + + // perform SSL handshake + while( ( ret = mbedtls_ssl_handshake( context->ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + // SSL handshake failed + //mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + goto error; + } + } + + nonblock = 1; + SOCK_ioctl(sd, SOCK_FIONBIO, &nonblock); + + // Save SSL context against socket + SOCKET_DRIVER.SetSocketSslData(sd, (void*)context); + +error: + + return ret; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_add_cert_auth_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_add_cert_auth_internal.cpp new file mode 100644 index 00000000..24afcc71 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_add_cert_auth_internal.cpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + +bool ssl_add_cert_auth_internal( + int contextHandle, + const char* certificate, + int certLength, + const char* certPassword ) +{ + (void)certPassword; + + mbedTLS_NFContext* context; + + // Check contextHandle range + if((contextHandle >= (int)ARRAYSIZE(g_SSL_Driver.ContextArray)) || (contextHandle < 0)) + { + return false; + } + + // Retrieve SSL struct from g_SSL_Driver + // sd should already have been created + context = (mbedTLS_NFContext*)g_SSL_Driver.ContextArray[contextHandle].Context; + + if (context != NULL) + { + ///////////////////////////////////////////////////////////////////////////////////////////////// + // developer notes: // + // this call parses certificates in both string and binary formats // + // when the formart is a string it has to include the terminator otherwise the parse will fail // + ///////////////////////////////////////////////////////////////////////////////////////////////// + if( mbedtls_x509_crt_parse(context->x509_crt, (const unsigned char*)certificate, certLength ) == 0) + { + // add to CA chain + mbedtls_ssl_conf_ca_chain( + context->conf, + context->x509_crt, + NULL ); + + // done + return true; + } + } + + return false; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_close_socket_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_close_socket_internal.cpp new file mode 100644 index 00000000..053492e1 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_close_socket_internal.cpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + +int ssl_close_socket_internal( int sd ) +{ + mbedTLS_NFContext* context= (mbedTLS_NFContext*)SOCKET_DRIVER.GetSocketSslData(sd); + + // sanity check + if(context != NULL) + { + mbedtls_ssl_context *ssl = context->ssl; + + // be nice and notify the peer that the connection is being closed + mbedtls_ssl_close_notify(ssl); + + SOCKET_DRIVER.SetSocketSslData(sd, NULL); + } + + SOCK_close( sd ); + + return 0; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_connect_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_connect_internal.cpp new file mode 100644 index 00000000..56112f25 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_connect_internal.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + +int ssl_connect_internal( + int sd, + const char* szTargetHost, + int contextHandle) +{ + mbedTLS_NFContext* context; + int nonblock = 0; + + int ret = SOCK_SOCKET_ERROR; + + // Check contextHandle range + if((contextHandle >= (int)ARRAYSIZE(g_SSL_Driver.ContextArray)) || (contextHandle < 0)) + { + goto error; + } + + // Retrieve SSL struct from g_SSL_Driver + // sd should already have been created + // Now do the SSL negotiation + context = (mbedTLS_NFContext*)g_SSL_Driver.ContextArray[contextHandle].Context; + if (context == NULL) + { + return false; + } + + // set socket in network context + context->server_fd->fd = sd; + + if(szTargetHost != NULL && szTargetHost[0] != 0) + { + if( (ret = mbedtls_ssl_set_hostname( context->ssl, szTargetHost )) != 0 ) + { + // hostname_failed + goto error; + } + } + + // setup internal SSL context and calls to transport layer send, receive and receive with timeout + mbedtls_ssl_set_bio( context->ssl, context->server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); + + SOCK_ioctl(sd, SOCK_FIONBIO, &nonblock); + + // perform SSL handshake + while( ( ret = mbedtls_ssl_handshake( context->ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + // SSL handshake failed + //mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + goto error; + } + } + + nonblock = 1; + SOCK_ioctl(sd, SOCK_FIONBIO, &nonblock); + + // store SSL context in sockets driver + SOCKET_DRIVER.SetSocketSslData(sd, (void*)context); + +error: + return ret; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_decode_private_key_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_decode_private_key_internal.cpp new file mode 100644 index 00000000..255aee3b --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_decode_private_key_internal.cpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "mbedtls.h" + +extern void SSL_GetCertDateTime_internal(DATE_TIME_INFO * dt, mbedtls_x509_time * mt ); + +int ssl_decode_private_key_internal( + const unsigned char *key, + size_t keyLength, + const unsigned char *password, + size_t passwordLength) +{ + mbedtls_pk_context pkey; + + int retCode; + + mbedtls_pk_init( &pkey ); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // developer notes: // + // this call parses certificates in both string and binary formats // + // when the formart is a string it has to include the terminator otherwise the parse will fail // + ///////////////////////////////////////////////////////////////////////////////////////////////// + retCode = mbedtls_pk_parse_key( + &pkey, + key, + keyLength, + password, + passwordLength); + + + // need to free this here + mbedtls_pk_free( &pkey ); + + return retCode; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_exit_context_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_exit_context_internal.cpp new file mode 100644 index 00000000..d6c45e2a --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_exit_context_internal.cpp @@ -0,0 +1,57 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + + +bool ssl_exit_context_internal( int contextHandle ) +{ + mbedTLS_NFContext* context; + + // Check contextHandle range + if((contextHandle >= (int)ARRAYSIZE(g_SSL_Driver.ContextArray)) || (contextHandle < 0) || (g_SSL_Driver.ContextArray[contextHandle].Context == NULL)) + { + return false; + } + + context = (mbedTLS_NFContext*)g_SSL_Driver.ContextArray[contextHandle].Context; + if (context == NULL) + { + return false; + } + + mbedtls_pk_free(context->pk); + mbedtls_net_free(context->server_fd); + mbedtls_ctr_drbg_free( context->ctr_drbg ); + mbedtls_entropy_free( context->entropy ); + mbedtls_ssl_config_free( context->conf ); + mbedtls_x509_crt_free(context->x509_crt); + mbedtls_ssl_free(context->ssl); + + // zero memory to wipe any security critical info in RAM + memset(context->ssl, 0, sizeof(mbedtls_ssl_context)); + + // free memory + if(context->pk != NULL) + { + platform_free(context->pk); + } + platform_free(context->server_fd); + platform_free(context->entropy); + platform_free(context->ctr_drbg); + platform_free(context->conf); + platform_free(context->x509_crt); + platform_free(context->ssl); + platform_free(context); + + memset(&g_SSL_Driver.ContextArray[contextHandle], 0, sizeof(g_SSL_Driver.ContextArray[contextHandle])); + + g_SSL_Driver.ContextCount --; + + return true; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic.cpp new file mode 100644 index 00000000..a272ebb8 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic.cpp @@ -0,0 +1,232 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "mbedtls.h" + +#include "lwip/sockets.h" + + +// this one lives in lwIPSocket.cpp +extern int errno; + +int sslRecv( + void *ctx, + unsigned char *buf, + size_t len) +{ + (void)buf; + (void)len; + (void)ctx; + + //int sd = (int)ctx; + + // int ret = socket->recv(buf, len); + + // if (ret == NSAPI_ERROR_WOULD_BLOCK) + // ret = MBEDTLS_ERR_SSL_WANT_READ; + // else if (ret < 0) + // mbedtls_printf("socket.recv() returned %d\n", ret); + + // return ret; + return 0; +} + +// mbedTLS requires a function with this signature, so we are wrapping the call to our debug_printf here +void nf_debug( + void *ctx, + int level, + const char *file, + int line, + const char *str ) +{ + (void)level; + (void)ctx; + (void)file; + (void)line; + + // the following line outputs the source code file name and line number + // for verbose output SWO is overhelmed and output fails at some point + //debug_printf( "%s:%04d: %s", file, line, str ); + + // this is a lightheight version with just the debug messages + debug_printf( "%s", str ); +} + +int net_would_block( const mbedtls_net_context *ctx ) +{ + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + int val = 0; + + if( ( fcntl( ctx->fd, F_GETFL, val) & O_NONBLOCK ) != O_NONBLOCK ) + return( 0 ); + + switch( errno ) + { + #if defined EAGAIN + case EAGAIN: + #endif + #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: + #endif + return( 1 ); + } + + return( 0 ); +} + +int mbedtls_net_recv( + void *ctx, + unsigned char *buf, + size_t len ) +{ + int32_t ret; + int32_t fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + { + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + } + + ret = (int32_t) read( fd, buf, len ); + + if( ret < 0 ) + { + if(net_would_block((mbedtls_net_context *)ctx) != 0) + { + return MBEDTLS_ERR_SSL_WANT_READ; + } + + if(errno == EPIPE || errno == ECONNRESET) + { + return MBEDTLS_ERR_NET_CONN_RESET; + } + + if(errno == EINTR) + { + return MBEDTLS_ERR_SSL_WANT_READ; + } + + return MBEDTLS_ERR_NET_RECV_FAILED; + } + + return ret; +} + +int mbedtls_net_send( + void *ctx, + const unsigned char *buf, + size_t len ) +{ + int32_t ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + { + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + } + + ret = (int32_t) write(fd, buf, len); + + if( ret < 0 ) + { + if(net_would_block((mbedtls_net_context *)ctx) != 0) + { + return MBEDTLS_ERR_SSL_WANT_WRITE; + } + + if(errno == EPIPE || errno == ECONNRESET) + { + return MBEDTLS_ERR_NET_CONN_RESET; + } + + if(errno == EINTR) + { + return MBEDTLS_ERR_SSL_WANT_WRITE; + } + + return MBEDTLS_ERR_NET_SEND_FAILED; + } + + return ret; +} + +int mbedtls_net_recv_timeout( + void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { + #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + #else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + #endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +// Gracefully closes the connection +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +// get Unix Epoch time from HAL SystemTime +time_t nf_get_unix_epoch() +{ + struct tm time; + SYSTEMTIME systemTime; + + // get HAL time in SYSTEMTIME format + HAL_Time_ToSystemTime(HAL_Time_CurrentDateTime(false), &systemTime); + + // fill in the tm struct + time.tm_sec = systemTime.wSecond; + time.tm_min = systemTime.wMinute; + time.tm_hour = systemTime.wHour; + time.tm_mday = systemTime.wDay; + time.tm_mon = systemTime.wMonth - 1; + time.tm_year = systemTime.wYear - 1900; + + return mktime(&time); +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic_init_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic_init_internal.cpp new file mode 100644 index 00000000..47c4bdee --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_generic_init_internal.cpp @@ -0,0 +1,310 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" +#include "mbedtls/debug.h" + +bool ssl_generic_init_internal( + int sslMode, + int sslVerify, + const char* certificate, + int certLength, + const uint8_t* privateKey, + int privateKeyLength, + const char* password, + int passwordLength, + int& contextHandle, + bool isServer ) +{ + (void)sslMode; + + int minVersion = MBEDTLS_SSL_MINOR_VERSION_3; + int maxVersion = MBEDTLS_SSL_MINOR_VERSION_1; + int sslContexIndex = -1; + int authMode = MBEDTLS_SSL_VERIFY_NONE; + int endpoint = 0; + int ret = 0; + + mbedtls_x509_crt* ownCertificate = NULL; + + // we only have one CA root bundle, so this is fixed to 0 + uint32_t configIndex = 0; + + /////////////////////// + mbedTLS_NFContext* context; + + for(uint32_t i=0; iserver_fd = (mbedtls_net_context*)platform_malloc(sizeof(mbedtls_net_context)); + if(context->server_fd == NULL) + { + goto error; + } + + if(isServer) + { + endpoint = MBEDTLS_SSL_IS_SERVER; + } + else + { + endpoint = MBEDTLS_SSL_IS_CLIENT; + } + + // create and init CTR_DRBG + // this needs to be freed in ssl_exit_context_internal + context->ctr_drbg = (mbedtls_ctr_drbg_context*)platform_malloc(sizeof(mbedtls_ctr_drbg_context)); + if(context->ctr_drbg == NULL) + { + goto error; + } + mbedtls_ctr_drbg_init( context->ctr_drbg ); + + // create and init SSL context + // this needs to be freed in ssl_exit_context_internal + context->ssl = (mbedtls_ssl_context*)platform_malloc(sizeof(mbedtls_ssl_context)); + if(context->ssl == NULL) + { + goto error; + } + mbedtls_ssl_init(context->ssl); + + // create and init SSL configuration + // this needs to be freed in ssl_exit_context_internal + context->conf = (mbedtls_ssl_config*)platform_malloc(sizeof(mbedtls_ssl_config)); + if(context->conf == NULL) + { + goto error; + } + + mbedtls_ssl_config_init( context->conf ); + + // create and init X509 CRT + // this needs to be freed in ssl_exit_context_internal + context->x509_crt = (mbedtls_x509_crt*)platform_malloc(sizeof(mbedtls_x509_crt)); + if(context->x509_crt == NULL) + { + goto error; + } + mbedtls_x509_crt_init( context->x509_crt ); + + // create and init entropy context + // this needs to be freed in ssl_exit_context_internal + context->entropy = (mbedtls_entropy_context*)platform_malloc(sizeof(mbedtls_entropy_context)); + if(context->entropy == NULL) + { + goto error; + } + mbedtls_entropy_init( context->entropy ); + + // TODO: review if we can add some instance-unique data to the custom argument below + if( mbedtls_ctr_drbg_seed( context->ctr_drbg, mbedtls_entropy_func, context->entropy, NULL, 0 ) != 0 ) + { + // ctr_drbg_seed_failed + goto error; + } + + if( mbedtls_ssl_config_defaults( context->conf, + endpoint, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) != 0 ) + { + // ssl_config_defaults_failed + goto error; + } + + // figure out the min and max protocol version to support + // sanity check for none, application has to set the supported protocols + if((SslProtocols)sslMode == SslProtocols_None) + { + goto error; + } + + // find minimum version + if(sslMode & (SslProtocols_TLSv11 | SslProtocols_TLSv1)) + { + minVersion = MBEDTLS_SSL_MINOR_VERSION_2; + } + if(sslMode & SslProtocols_TLSv1) + { + minVersion = MBEDTLS_SSL_MINOR_VERSION_1; + } + mbedtls_ssl_conf_min_version( + context->conf, MBEDTLS_SSL_MAJOR_VERSION_3, + minVersion ); + + // find maximum version + if(sslMode & (SslProtocols_TLSv12 | SslProtocols_TLSv11)) + { + maxVersion = MBEDTLS_SSL_MINOR_VERSION_2; + } + if(sslMode & SslProtocols_TLSv12) + { + maxVersion = MBEDTLS_SSL_MINOR_VERSION_3; + } + mbedtls_ssl_conf_max_version( + context->conf, MBEDTLS_SSL_MAJOR_VERSION_3, + maxVersion ); + + // configure random generator + mbedtls_ssl_conf_rng( context->conf, mbedtls_ctr_drbg_random, context->ctr_drbg ); + + // CA root certs from store, if available + if(g_TargetConfiguration.CertificateStore->Count > 0) + { + ///////////////////////////////////////////////////////////////////////////////////////////////// + // developer notes: // + // don't care about failure in processing the CA cert bundle // + // the outcome is that the CA certs won't be loaded into the trusted CA chain // + // this call parses certificates in both string and binary formats // + // when the formart is a string it has to include the terminator otherwise the parse will fail // + ///////////////////////////////////////////////////////////////////////////////////////////////// + mbedtls_x509_crt_parse( + context->x509_crt, + (const unsigned char*)g_TargetConfiguration.CertificateStore->Certificates[configIndex]->Certificate, + g_TargetConfiguration.CertificateStore->Certificates[configIndex]->CertificateSize ); + + } + + // parse "own" certificate if passed + if(certificate != NULL && certLength > 0) + { + // create and init private key context + // this needs to be freed in ssl_exit_context_internal + context->pk = (mbedtls_pk_context*)platform_malloc(sizeof(mbedtls_pk_context)); + if(context->pk == NULL) + { + goto error; + } + + mbedtls_pk_init( context->pk ); + + // is there a private key? + if(privateKey != NULL && privateKeyLength > 0) + { + + if( mbedtls_pk_parse_key( + context->pk, + privateKey, + privateKeyLength, + (const unsigned char *)password, + passwordLength) < 0) + { + // private key parse failed + goto error; + } + } + + // parse certificate + ownCertificate = (mbedtls_x509_crt*)platform_malloc(sizeof(mbedtls_x509_crt)); + if(ownCertificate == NULL) + { + goto error; + } + + mbedtls_x509_crt_init( ownCertificate ); + + if( mbedtls_x509_crt_parse( ownCertificate, (const unsigned char *) certificate, certLength ) ) + { + // failed parsing own certificate failed + goto error; + } + + if( mbedtls_ssl_conf_own_cert( context->conf, ownCertificate, context->pk ) ) + { + // configuring own certificate failed + goto error; + } + + } + else + { + // no PK, need to set it to NULL + context->pk = NULL; + } + + mbedtls_ssl_conf_ca_chain( context->conf, context->x509_crt, NULL ); + + // set certificate verification + // the current options provided by mbed TLS are only verify or don't verify + if((SslVerification)sslVerify == SslVerification_CertificateRequired) + { + authMode = MBEDTLS_SSL_VERIFY_REQUIRED; + } + mbedtls_ssl_conf_authmode( context->conf, authMode ); + + // setup debug stuff + // only required if output debug is enabled in mbedtls_config.h + #ifdef MBEDTLS_DEBUG_C + mbedtls_debug_set_threshold( MBEDTLS_DEBUG_THRESHOLD ); + mbedtls_ssl_conf_dbg( context->conf, nf_debug, stdout ); + #endif + + ret = mbedtls_ssl_setup( context->ssl, context->conf ); + if( ret != 0 ) + { + // ssl_setup_failed + goto error; + } + + ////////////////////////////////////// + + g_SSL_Driver.ContextArray[sslContexIndex].Context = context; + g_SSL_Driver.ContextCount++; + + contextHandle = sslContexIndex; + + return true; + +error: + mbedtls_pk_free(context->pk); + mbedtls_net_free(context->server_fd); + mbedtls_ctr_drbg_free( context->ctr_drbg ); + mbedtls_entropy_free( context->entropy ); + mbedtls_x509_crt_free(context->x509_crt); + mbedtls_ssl_config_free( context->conf ); + mbedtls_ssl_free(context->ssl); + + // check for any memory allocation that needs to be freed before exiting + if(context->ssl != NULL) platform_free(context->ssl); + if(context->conf != NULL) platform_free(context->conf); + if(context->entropy != NULL) platform_free(context->entropy); + if(context->ctr_drbg != NULL) platform_free(context->ctr_drbg); + if(context->server_fd != NULL) platform_free(context->server_fd); + if(context->x509_crt != NULL) platform_free(context->x509_crt); + if(context->pk != NULL) platform_free(context->pk); + + if(ownCertificate != NULL) + { + mbedtls_x509_crt_free( ownCertificate ); + platform_free(ownCertificate); + } + if(context->pk != NULL) + { + platform_free(context); + } + + return false; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_initialize_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_initialize_internal.cpp new file mode 100644 index 00000000..7450d355 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_initialize_internal.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + +bool ssl_initialize_internal() +{ + memset(&g_SSL_Driver, 0, sizeof(g_SSL_Driver)); + + return true; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_parse_certificate_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_parse_certificate_internal.cpp new file mode 100644 index 00000000..8169de41 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_parse_certificate_internal.cpp @@ -0,0 +1,71 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "mbedtls.h" + +void SSL_GetCertDateTime_internal( + DATE_TIME_INFO * dt, + mbedtls_x509_time * mt ) +{ + dt->year = mt->year; + dt->month = mt->mon; + dt->day = mt->day; + dt->hour = mt->hour; + dt->minute = mt->min; + dt->second = mt->sec; + + dt->dlsTime = 0; + dt->tzOffset = 0; +} + +bool ssl_parse_certificate_internal( + void * certificate, + size_t size, + void* pwd, + void* x509CertData) +{ + (void)pwd; + + int ret; + X509CertData* x509 = (X509CertData*)x509CertData; + + mbedtls_x509_crt cacert; + mbedtls_x509_crt_init(&cacert); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // developer notes: // + // this call parses certificates in both string and binary formats // + // when the formart is a string it has to include the terminator otherwise the parse will fail // + ///////////////////////////////////////////////////////////////////////////////////////////////// + ret = mbedtls_x509_crt_parse( + &cacert, + (const unsigned char *)certificate, + size); + if(ret < 0) + { + return false; + } + + mbedtls_x509_dn_gets( + x509->Issuer, + sizeof(x509->Issuer)-1, + &cacert.issuer ); + + mbedtls_x509_dn_gets( + x509->Subject, + sizeof(x509->Subject)-1, + &cacert.subject ); + + SSL_GetCertDateTime_internal( + &x509->EffectiveDate, + &cacert.valid_from ); + + SSL_GetCertDateTime_internal( + &x509->ExpirationDate, + &cacert.valid_to ); + + return true; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_pending_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_pending_internal.cpp new file mode 100644 index 00000000..2fafa75d --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_pending_internal.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include "mbedtls.h" + +int ssl_pending_internal( int sd ) +{ + mbedTLS_NFContext* context= (mbedTLS_NFContext*)SOCKET_DRIVER.GetSocketSslData(sd); + mbedtls_ssl_context *ssl = context->ssl; + + // sanity check + if(ssl == NULL) + { + return SOCK_SOCKET_ERROR; + } + + return mbedtls_ssl_check_pending(ssl); +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_read_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_read_internal.cpp new file mode 100644 index 00000000..1d8254b1 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_read_internal.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + +int ssl_read_internal( + int sd, + char* data, + size_t size ) +{ + mbedTLS_NFContext* context= (mbedTLS_NFContext*)SOCKET_DRIVER.GetSocketSslData(sd); + mbedtls_ssl_context *ssl = context->ssl; + + // sanity check + if(ssl == NULL) + { + return SOCK_SOCKET_ERROR; + } + + int ret = mbedtls_ssl_read(ssl, (unsigned char *)(data), size); + if ( ret < 0 ) + { + return 0; + } + + return ret; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_uninitialize_internal.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_uninitialize_internal.cpp new file mode 100644 index 00000000..fe044c2e --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/mbedTLS/ssl_uninitialize_internal.cpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "mbedtls.h" + +// TODO if and when implementing store certificate +// extern volatile int ssl_x509_store_ctx_idx; + +bool ssl_uninitialize_internal() +{ + bool result = true; + + for(uint32_t i = 0; i +#include "mbedtls.h" + +int ssl_write_internal( + int sd, + const char* data, + size_t req_len) +{ + int ret; + + mbedTLS_NFContext* context= (mbedTLS_NFContext*)SOCKET_DRIVER.GetSocketSslData(sd); + mbedtls_ssl_context *ssl = context->ssl; + + // sanity check + if(ssl == NULL) + { + return SOCK_SOCKET_ERROR; + } + + // Loop until all data has been sent or error + size_t req_offset = 0; + do + { + ret = mbedtls_ssl_write( ssl, (const unsigned char *)(data + req_offset), req_len - req_offset); + if (ret > 0) + { + req_offset += static_cast(ret); + } + } + while( req_offset < req_len && + (ret > 0 || + ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_SSL_WANT_READ) ); + + if (ret < 0) + { + //mbedtls_printf("mbedtls_ssl_write() returned -0x%04X\n", -ret); + return 0; + } + + return req_len; +} diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl.cpp new file mode 100644 index 00000000..84bfa0bd --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl.cpp @@ -0,0 +1,241 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +SSL_Driver g_SSL_Driver; + +// Flag to postpone init until after heap has been cleared +// in tinyhal.cpp +static bool s_InitDone = false; + +bool SSL_Initialize() +{ + NATIVE_PROFILE_PAL_COM(); + + memset(&g_SSL_Driver, 0, sizeof(g_SSL_Driver)); + + return true; +} + +bool SSL_Uninitialize() +{ + NATIVE_PROFILE_PAL_COM(); + + for(uint32_t i = 0; i +#include + +struct SSL_Driver +{ + static const int c_MaxSslContexts = SOCKETS_MAX_COUNT; + + //--// + + struct SSL_Context + { + void * Context; + }; + + SSL_Context ContextArray[c_MaxSslContexts]; + int32_t ContextCount; +}; + +extern SSL_Driver g_SSL_Driver; + +#endif // _NANO_SSL_H_ diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_functions.h b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_functions.h new file mode 100644 index 00000000..7bf171a8 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_functions.h @@ -0,0 +1,85 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef SSL_FUNCTIONS_H +#define SSL_FUNCTIONS_H + +#include + +// Keep these in sync with SslProtocols in System.Net + +/////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.Security.SslProtocols (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////// +enum SslProtocols +{ + SslProtocols_None = 0x00, + SslProtocols_TLSv1 = 0x10, + SslProtocols_TLSv11 = 0x20, + SslProtocols_TLSv12 = 0x40, +}; + +////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.Security.SslVerification (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////// +enum SslVerification +{ + SslVerification_Invalid = 0, + SslVerification_NoVerification = 1, + SslVerification_VerifyPeer = 2, + SslVerification_CertificateRequired = 4, + SslVerification_VerifyClientOnce = 8, +}; + +bool ssl_parse_certificate_internal( + void* buf, + size_t size, + void* pwd, + void* x509 ); +int ssl_decode_private_key_internal( + const unsigned char *key, + size_t keyLength, + const unsigned char *pwd, + size_t pwdLength ); +int ssl_connect_internal( + int sd, + const char* szTargetHost, + int contextHandle); +int ssl_accept_internal( + int socket, + int contextHandle ); +int ssl_read_internal( + int socket, + char* data, + size_t size ); +int ssl_write_internal( + int socket, + const char* data, + size_t size); +int ssl_close_socket_internal( int sd ); +int ssl_pending_internal( int sd ); +bool ssl_exit_context_internal( int contextHandle ); +bool ssl_generic_init_internal( + int sslMode, + int sslVerify, + const char* certificate, + int certLength, + const uint8_t* privateKey, + int privateKeyLength, + const char* password, + int passwordLength, + int& contextHandle, + bool isServer ); +bool ssl_initialize_internal(); +bool ssl_uninitialize_internal(); +bool ssl_add_cert_auth_internal( + int contextHandle, + const char* certificate, + int certLength, + const char* certPassword ); + +#endif // SSL_FUNCTIONS_H diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_stubs.cpp b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_stubs.cpp new file mode 100644 index 00000000..1025cc34 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_stubs.cpp @@ -0,0 +1,212 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nanoHal.h" + +//--// + +extern "C" +{ +void ssl_rand_seed(const void *seed, int length) +{ + (void)seed; + (void)length; +} +} + +__nfweak bool SSL_Initialize() +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +__nfweak bool SSL_Uninitialize() +{ + NATIVE_PROFILE_PAL_COM(); + return TRUE; +} + +__nfweak bool SSL_ServerInit( + int sslMode, + int sslVerify, + const char* certificate, + int certLength, + const uint8_t* privateKey, + int privateKeyLength, + const char* password, + int passwordLength, + int& contextHandle ) +{ + (void)sslMode; + (void)sslVerify; + (void)certificate; + (void)certLength; + (void)privateKey; + (void)privateKeyLength; + (void)password; + (void)passwordLength; + (void)contextHandle; + + NATIVE_PROFILE_PAL_COM(); + + return TRUE; +} + +__nfweak bool SSL_ClientInit( + int sslMode, + int sslVerify, + const char* certificate, + int certLength, + const uint8_t* privateKey, + int privateKeyLength, + const char* password, + int passwordLength, + int& contextHandle ) +{ + (void)sslMode; + (void)sslVerify; + (void)certificate; + (void)certLength; + (void)privateKey; + (void)privateKeyLength; + (void)password; + (void)passwordLength; + (void)contextHandle; + + NATIVE_PROFILE_PAL_COM(); + + return TRUE; +} + +__nfweak bool SSL_AddCertificateAuthority( + int contextHandle, + const char* certificate, + int certLength, + const char* certPassword ) +{ + (void)contextHandle; + (void)certificate; + (void)certLength; + (void)certPassword; + + NATIVE_PROFILE_PAL_COM(); + + return TRUE; +} + +__nfweak bool SSL_ExitContext( int contextHandle ) +{ + (void)contextHandle; + + NATIVE_PROFILE_PAL_COM(); + + return TRUE; +} + +__nfweak int SSL_Accept( + SOCK_SOCKET socket, + int contextHandle ) +{ + (void)socket; + (void)contextHandle; + + NATIVE_PROFILE_PAL_COM(); + + return 0; +} + +__nfweak int SSL_Connect( + SOCK_SOCKET socket, + const char* szTargetHost, + int contextHandle ) +{ + (void)socket; + (void)szTargetHost; + (void)contextHandle; + + NATIVE_PROFILE_PAL_COM(); + + return 0; +} + +__nfweak int SSL_Write( + SOCK_SOCKET socket, + const char* data, + size_t size ) +{ + (void)socket; + (void)data; + (void)size; + + NATIVE_PROFILE_PAL_COM(); + + return 0; +} + +__nfweak int SSL_Read( + SOCK_SOCKET socket, + char* data, + size_t size ) +{ + (void)socket; + (void)data; + (void)size; + + NATIVE_PROFILE_PAL_COM(); + + return 0; +} + +__nfweak int SSL_CloseSocket( SOCK_SOCKET socket ) +{ + (void)socket; + + NATIVE_PROFILE_PAL_COM(); + + return 0; +} + +__nfweak bool SSL_ParseCertificate( + const char* certificate, + size_t certLength, + const char* password, + X509CertData* certData ) +{ + (void)certificate; + (void)certLength; + (void)password; + (void)certData; + + NATIVE_PROFILE_PAL_COM(); + + return TRUE; +} + +__nfweak int SSL_DecodePrivateKey( + const unsigned char *key, + size_t keyLength, + const unsigned char *pwd, + size_t pwdLength ) +{ + (void)key; + (void)keyLength; + (void)pwd; + (void)pwdLength; + + NATIVE_PROFILE_PAL_COM(); + + return -1; +} + +__nfweak int SSL_DataAvailable( SOCK_SOCKET socket ) +{ + (void)socket; + + NATIVE_PROFILE_PAL_COM(); + + return 0; +} + diff --git a/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_types.h b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_types.h new file mode 100644 index 00000000..53960da5 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/COM/sockets/ssl/ssl_types.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef SSL_TYPES_H +#define SSL_TYPES_H + + +#define NANOCLR_SSL_STRLEN hal_strlen_s +#define TINYCLR_SSL_STRNCPY(a,b,c) hal_strncpy_s(a,c+1,b,c) +#define NANOCLR_SSL_STRNCPY(a,b) hal_strcpy_s(a,hal_strlen_s(b)+1,b) + +#endif // SSL_TYPES_H diff --git a/source/native/nf-interpreter/src/PAL/Double/nanoPAL_NativeDouble.cpp b/source/native/nf-interpreter/src/PAL/Double/nanoPAL_NativeDouble.cpp new file mode 100644 index 00000000..99d96ab1 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Double/nanoPAL_NativeDouble.cpp @@ -0,0 +1,223 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "nanoPAL_NativeDouble.h" + +#include + +#ifdef WIN32 +#include + +#define __isnand _isnan +#define __isinfd(x) (!_finite(x)) + +inline int __signbitd(double x) +{ + unsigned char *ptr = (unsigned char*) &x; + return (*(ptr + (sizeof(double) - 1)) & 0x80) != 0; +} + +#define rint(x) floor((x) + 0.5) +#define remainder(x,y) ((x) - ((y) * rint((x) / (y)))) + +#define isgreater(param0,param1) (param0 > param1) +#define isless(param0,param1) (param0 < param1) + +#elif defined(__GNUC__) + +#if !defined( isgreater ) +#define isgreater __builtin_isgreater +#endif + +#if !defined( isless ) +#define isless __builtin_isless +#endif + +#if !defined( __isnand ) +#define __isnand __builtin_isnan +#endif + +#if !defined( __isinfd ) +#define __isinfd __builtin_isinf +#endif + +#if !defined( __signbitd ) +#define __signbitd __builtin_signbit +#endif + +#endif + + + +using namespace System; +// Summary: +// Compares this instance to a specified double-precision floating-point number +// and returns an integer that indicates whether the value of this instance +// is less than, equal to, or greater than the value of the specified double-precision +// floating-point number. +// +// Parameters: +// value: +// A double-precision floating-point number to compare. +// +// Returns: +// A signed number indicating the relative values of this instance and value. +// Return Value Description +// Less than zero +// This instance is less than value. -or- +// This instance is not a number (System.Double.NaN) and value is a number. +// Zero +// This instance is equal to value. -or- +// Both this instance and value are not a number (System.Double.NaN), +// System.Double.PositiveInfinity, or System.Double.NegativeInfinity. +// Greater than zero +// This instance is greater than value. -or- +// This instance is a number and value is not a number (System.Double.NaN). +int32_t System::Double::CompareTo( double d, double val ) +{ + if (__isnand(d)) + { + // Instance is not a number + if (__isnand(val)) + { + // value is not a number + return 0; + } + else + { + //value is a number + return -1; + } + } + else + { + // Instance is a number + if (__isnand(val)) + { + // value is not a number + return 1; + } + } + + if ( __isinfd(d) && __isinfd(val) ) + { + // both are Infinity + return 0; + } + + if (isgreater(d,val)) + { + // this instance is greater than value + return 1; + } + + if (isless(d,val)) + { + // this instance is less than value + return -1; + } + + // assume values are equal as all other options have been checked. + return 0; +} + +// +// Summary: +// Returns a value indicating whether the specified number evaluates to negative +// or positive infinity +// +// Parameters: +// d: +// A double-precision floating-point number. +// +// Returns: +// true if d evaluates to System.Double.PositiveInfinity or System.Double.NegativeInfinity; +// otherwise, false. +bool System::Double::IsInfinity( double d ) +{ + if(__isnand(d)) + return false; + + /* Return 1 if __x is infinite, 0 otherwise */ + /* Used by isinf macro */ + bool retVal = __isinfd(d); + return retVal; +} + +// +// Summary: +// Returns a value indicating whether the specified number evaluates to a value +// that is not a number (System.Double.NaN). +// +// Parameters: +// d: +// A double-precision floating-point number. +// +// Returns: +// true if d evaluates to System.Double.NaN; otherwise, false. +bool System::Double::IsNaN( double d ) +{ + /* Return 1 if __x is a NaN, 0 otherwise */ + /* Used by isnan macro */ + bool retVal = __isnand(d) != 0; + return retVal; +} + +// +// Summary: +// Returns a value indicating whether the specified number evaluates to negative +// infinity. +// +// Parameters: +// d: +// A double-precision floating-point number. +// +// Returns: +// true if d evaluates to System.Double.NegativeInfinity; otherwise, false. +bool System::Double::IsNegativeInfinity( double d ) +{ + if(__isnand(d) != 0) + return false; + + /* Return signbit of __x */ + /* Used by signbit macro */ + int8_t signBit = __signbitd(d); + + /* Return 1 if __x is infinite, 0 otherwise */ + /* Used by isinf macro */ + int8_t infiniteBit = __isinfd(d) != 0; + + bool retVal = (signBit != 0) && (infiniteBit != 0); + return retVal; +} +// +// Summary: +// Returns a value indicating whether the specified number evaluates to positive +// infinity. +// +// Parameters: +// d: +// A double-precision floating-point number. +// +// Returns: +// true if d evaluates to System.Double.PositiveInfinity; otherwise, false. +bool System::Double::IsPositiveInfinity( double d ) +{ + if(__isnand(d) != 0) + return false; + + /* Return signbit of __x */ + /* Used by signbit macro */ + int8_t signBit = __signbitd(d); + + /* Return 1 if __x is infinite, 0 otherwise */ + /* Used by isinf macro */ + int8_t infiniteBit = __isinfd(d); + + bool retVal = (signBit == 0) && (infiniteBit != 0); + return retVal; +} diff --git a/source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_driver.cpp b/source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_driver.cpp new file mode 100644 index 00000000..655bebdd --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_driver.cpp @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +PalEventDriver g_palEventDriver; + +bool PalEventDriver::s_initialized = FALSE; + +HRESULT PalEventDriver::Initialize() +{ + if (!g_palEventDriver.s_initialized) + { + g_palEventDriver.listenerList.Initialize(); + PalEventDriver::s_initialized = TRUE; + } + + return S_OK; +} + +HRESULT PalEventDriver::Uninitialize() +{ + if (PalEventDriver::s_initialized) + { + PalEventDriver::s_initialized = FALSE; + + /// Remove all nodes. + g_palEventDriver.listenerList.Initialize(); + } + + return S_OK; +} + +HRESULT PalEventDriver::PostEvent(uint32_t e, uint32_t param) +{ + PalEventListener *listener = g_palEventDriver.listenerList.FirstNode(); + + while(listener->Next() != NULL) + { + if (listener->m_eventMask & e) + { + listener->m_palEventListener(e, param); + } + + listener = listener->Next(); + } + + return S_OK; +} + +HRESULT PalEventDriver::EnlistListener(PalEventListener* listener) +{ + listener->Initialize(); + g_palEventDriver.listenerList.LinkAtBack(listener); + + return S_OK; +} diff --git a/source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_functions.cpp b/source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_functions.cpp new file mode 100644 index 00000000..7e0c3628 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Events/nanoPAL_Events_functions.cpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +HRESULT PalEvent_Initialize() +{ + return g_palEventDriver.Initialize(); +} + +HRESULT PalEvent_Uninitialize() +{ + return g_palEventDriver.Uninitialize(); +} + +HRESULT PalEvent_Post(unsigned int e, unsigned int param) +{ + return g_palEventDriver.PostEvent(e, param); +} + +HRESULT PalEvent_Enlist(PalEventListener* listener) +{ + return g_palEventDriver.EnlistListener(listener); +} diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoCRT.h b/source/native/nf-interpreter/src/PAL/Include/nanoCRT.h new file mode 100644 index 00000000..145cf42b --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoCRT.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOCRT_DECL_H_ +#define _NANOCRT_DECL_H_ 1 + +#if defined(PLATFORM_EMULATED_FLOATINGPOINT) +int hal_snprintf_float( char* buffer, size_t len, const char* format, int32_t f ); +int hal_snprintf_double( char* buffer, size_t len, const char* format, int64_t& d ); +#else +int hal_snprintf_float( char* buffer, size_t len, const char* format, float f ); +int hal_snprintf_double( char* buffer, size_t len, const char* format, double d ); +#endif + +// Compares 2 ASCII strings case insensitive. Always defined in our code ( nanoCRT.cpp ) +int hal_stricmp( const char * dst, const char * src ); + +#endif // _NANOCRT_DECL_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL.h new file mode 100644 index 00000000..0fe17e35 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL.h @@ -0,0 +1,255 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOPAL_H_ +#define _NANOPAL_H_ 1 + +//#include + +#include +#include +#include +#include +#include +#include +#include +#include + + + + + +#include +// +#include + + + + + + + + + + +// +//#include + +//#include (must be before events_decl.h) + + + + + + + + + + + + + + +//#include + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//#include + +//#include + +// This function returns location of the CLR heap. +void HeapLocation(unsigned char*& BaseAddress, unsigned int& SizeInBytes); + + + + +// +//#include +// +//#include +//#include +//#include +// +//#include +// + + +// + +//#include + +// +// !!! KEEP IN SYNC WITH Microsoft.SPOT.Hardware.PowerLevel !!! +// +enum POWER_LEVEL +{ + POWER_LEVEL__HIGH_POWER = 0x10, + POWER_LEVEL__MID_POWER = 0x20, + POWER_LEVEL__LOW_POWER = 0x30, +}; + + +//#include +//#include + +//#include + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//#include + + +//#include + +#if defined(PLATFORM_ARM) || defined(PLATFORM_ESP32) + +#define strcpy DoNotUse_*strcpy [] +#define strncpy DoNotUse_*strcpy [] +#define strlen DoNotUse_*strlen [] +#define strncmp DoNotUse_*strncmp [] + +int hal_strcpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc ); +int hal_strncpy_s( char* strDst, size_t sizeInBytes, const char* strSrc, size_t count ); +size_t hal_strlen_s (const char * str); +int hal_strncmp_s( const char* str1, const char* str2, size_t num ); + +#elif defined(_WIN32) + +int hal_vprintf( const char* format, va_list arg ); +int hal_vfprintf( COM_HANDLE stream, const char* format, va_list arg ); +int hal_snprintf( char* buffer, size_t len, const char* format, ... ); +int hal_vsnprintf( char* buffer, size_t len, const char* format, va_list arg ); + +#define hal_strcpy_s(strDst, sizeInBytes, strSrc) strcpy_s(strDst, sizeInBytes, strSrc) +#define hal_strncpy_s(strDst, sizeInBytes, strSrc, count) strncpy_s(strDst, sizeInBytes, strSrc, count) +#define hal_strlen_s(str) strlen(str) +#define hal_strncmp_s(str1, str2, num) strncmp(str1, str2, num) + +#else +!ERROR +#endif + + +//#include +//#include +//#include +//#include +//#include +// +#include "TargetPAL_BlockStorage.h" + +//#include + +//#include "..\pal\Diagnostics\Native_Profiler.h" +// native profiler +#define NATIVE_PROFILE_PAL_HEAP() +#define NATIVE_PROFILE_PAL_CRT() + +#endif // _NANOPAL_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_AsyncProcCalls_decl.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_AsyncProcCalls_decl.h new file mode 100644 index 00000000..811d4f38 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_AsyncProcCalls_decl.h @@ -0,0 +1,134 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOPAL_ASYNCPROCCALLS_DECL_H_ +#define _NANOPAL_ASYNCPROCCALLS_DECL_H_ 1 + +#include + +//--// + +#if NATIVE_PROFILE_PAL & NATIVE_PROFILE_PAL_ASYNC_PROC_CALL__flag + #define NATIVE_PROFILE_PAL_ASYNC_PROC_CALL() Native_Profiler profiler_obj +#else + #define NATIVE_PROFILE_PAL_ASYNC_PROC_CALL() +#endif + +typedef void (*HAL_CALLBACK_FPN)( void* arg ); + +struct HAL_CALLBACK +{ +public: + HAL_CALLBACK_FPN EntryPoint; + void* Argument; + +public: + void Initialize( HAL_CALLBACK_FPN EntryPoint, void* Argument ) + { + this->EntryPoint = EntryPoint; + this->Argument = Argument; + } + + void SetArgument( void* Argument ) + { + this->Argument = Argument; + } + + HAL_CALLBACK_FPN GetEntryPoint() const { return this->EntryPoint; } + void* GetArgument () const { return this->Argument ; } + + void Execute() const + { + HAL_CALLBACK_FPN EntryPoint = this->EntryPoint; + void* Argument = this->Argument; + + if(EntryPoint) + { + EntryPoint( Argument ); + } + } +}; + + +struct HAL_CONTINUATION : public HAL_DblLinkedNode +{ + +private: + HAL_CALLBACK Callback; + +public: + void InitializeCallback( HAL_CALLBACK_FPN EntryPoint, void* Argument = NULL ); + + void SetArgument( void* Argument ) + { + Callback.SetArgument( Argument ); + } + + HAL_CALLBACK_FPN GetEntryPoint() const { return Callback.GetEntryPoint(); } + void* GetArgument () const { return Callback.GetArgument (); } + + void Execute() const { Callback.Execute(); } + + bool IsLinked(); + void Enqueue(); + void Abort (); + + //--// + + static void Uninitialize(); + + static void InitializeList(); + + static bool Dequeue_And_Execute(); +}; + +//--// + +struct HAL_COMPLETION : public HAL_CONTINUATION +{ + uint64_t EventTimeTicks; + bool ExecuteInISR; + +#if defined(_DEBUG) + uint64_t Start_RTC_Ticks; +#endif + + void InitializeForISR( HAL_CALLBACK_FPN EntryPoint, void* Argument = NULL ) + { + ExecuteInISR = true; + + InitializeCallback( EntryPoint, Argument ); + } + + void InitializeForUserMode( HAL_CALLBACK_FPN EntryPoint, void* Argument = NULL ) + { + ExecuteInISR = false; + + InitializeCallback( EntryPoint, Argument ); + } + + void EnqueueTicks ( uint64_t eventTimeTicks ); + void EnqueueDelta64 ( uint64_t miliSecondsFromNow ); + void EnqueueDelta ( uint32_t miliSecondsFromNow ); + + void Abort(); + + void Execute(); + + //--// + + static void Uninitialize(); + + static void InitializeList(); + + static void DequeueAndExec(); + + static void WaitForInterrupts( uint64_t expireTimeInSysTicks, uint32_t sleepLevel, uint64_t wakeEvents ); +}; + +//--// + +#endif //_NANOPAL_ASYNCPROCCALLS_DECL_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_BlockStorage.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_BlockStorage.h new file mode 100644 index 00000000..d0a43788 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_BlockStorage.h @@ -0,0 +1,647 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOPAL_BLOCKSTORAGE_H_ +#define _NANOPAL_BLOCKSTORAGE_H_ 1 + +#include +#include +#include +#include +#include + +///////////////////////////////////////////////////////// +// Description: +// Definitions for the Block Storage device interface +// for the nanoFramework +// +// Terminology: +// Block Storage Device - device that stores data addressable +// as a chunk as opposed to byte or unsigned short level +// +// Sector - smallest unit of storage for a Block device. Data is +// read or written as a complete sector(unless the device +// supports XIP which allows byte addresssing and reading +// directly from the processor memory bus) +// +// Block - smallest eraseable unit of the storage device. A block +// contains one or more sectors that are erased as a whole. +// All sectors within a block are always the same size. +// +// Region - Group of adjacent blocks that all contain sectors of the +// same size. +// +// Execute-In-Place (XIP) - Attribute of some storage types, NOR, ROM, +// RAM, that allows direct execution of code from the device. +// XIP capable devices are at least read-only and byte addresable +// on the CPU memory bus. +// + + +// In flash media the distinction between a block and a sector is important +// so we define the sector address to make it clear. +typedef unsigned int ByteAddress; +typedef unsigned int SectorAddress; + +////////////////////////////////////////////////////////// +// Description: +// Flags to Indicate the status of a particular block in +// flash. ALL sectors for a block *MUST* share the same +// status. +// +// Remarks: +// When the block is reserved the lower 16 bits specifies a +// USAGE_XXXX value to indicate the purpose of the block. +// +// The BlockRange information is technically dynamic in the +// sense that it is not fixed or defined in hardware. Rather, +// it is defined by the system designer. However, the BlockRange +// info does not and *MUST* not change at run-time. The only +// exceptions to this rule is in the boot loader where the +// storage device is being formated or re-laid out as part +// of an update etc... and when an FS discovers a bad block +// it should mark it as bad. WIthout this restriction +// implementing an FS is virtually impossible since the FS +// would have to deal with the possibility that the usage for +// a Block could change at any point in time. +// +typedef enum BlockUsage +{ + BlockUsage_BOOTSTRAP = 0x0010, + BlockUsage_CODE = 0x0020, + BlockUsage_CONFIG = 0x0030, + BlockUsage_FILESYSTEM = 0x0040, + + BlockUsage_DEPLOYMENT = 0x0050, + + BlockUsage_UPDATE = 0x0060, + + BlockUsage_SIMPLE_A = 0x0090, + BlockUsage_SIMPLE_B = 0x00A0, + + BlockUsage_STORAGE_A = 0x00E0, + BlockUsage_STORAGE_B = 0x00F0, + + + BlockUsage_ANY = 0x0000, + +}BlockUsage; + +// upper 4 bits of USAGE_XXXX identifies the base type of info stored in the block +// using these values it is possible to scan a device for all managed code or all +// native code without worrying about the finer details of what it's for. + +// Block contains XIP system native code +#define BlockRange_DATATYPE_NATIVECODE ((unsigned int)0x1000) +// Block contains managed code assemblies +#define BlockRange_DATATYPE_MANAGEDCODE ((unsigned int)0x2000) +// Block contains raw data +#define BlockRange_DATATYPE_RAW ((unsigned int)0x4000) + +// use to mark the block is used for special purpose +#define BlockRange_ATTRIB_PRIMARY ((unsigned int)0x10000) + + +#define BlockRange_EXECUTABLE ((unsigned int)0x80000000) +#define BlockRange_RESERVED ((unsigned int)0x40000000) +#define BlockRange_READONLY ((unsigned int)0x20000000) + +// Values for the Usage information (This helps map the new storage APIs to the needs of existing code) +#define BlockRange_ALL_MASK ((unsigned int)0xFFFFFFFF) +#define BlockRange_USAGE_MASK ((unsigned int)0x000000FF) +#define BlockRange_NON_USAGE_MASK ((unsigned int)0xFFFFFF00) + +// for secondary devices to set dirtybits +#define BlockRange_BLOCKTYPE_RESERVED (BlockRange_RESERVED) +#define BlockRange_BLOCKTYPE_DIRTYBIT ( BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_CONFIG) +// Configuration data that contains all the unique data +#define BlockRange_BLOCKTYPE_CONFIG (BlockRange_ATTRIB_PRIMARY | BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_CONFIG) + +// Boot loader and boot strap code +#define BlockRange_BLOCKTYPE_BOOTSTRAP (BlockRange_EXECUTABLE | BlockRange_RESERVED | BlockRange_DATATYPE_NATIVECODE | BlockUsage_BOOTSTRAP) +// CLR or other native code "application" +#define BlockRange_BLOCKTYPE_CODE (BlockRange_EXECUTABLE | BlockRange_RESERVED | BlockRange_DATATYPE_NATIVECODE | BlockUsage_CODE) +// Deployment area for MFdeploy & Visual Studio +#define BlockRange_BLOCKTYPE_DEPLOYMENT ( BlockRange_RESERVED | BlockRange_DATATYPE_MANAGEDCODE | BlockUsage_DEPLOYMENT) +// Part A of Simple Storage +#define BlockRange_BLOCKTYPE_SIMPLE_A ( BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_SIMPLE_A) +// Part B of Simple Storage +#define BlockRange_BLOCKTYPE_SIMPLE_B ( BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_SIMPLE_B) +// Part A of EWR Storage +#define BlockRange_BLOCKTYPE_STORAGE_A ( BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_STORAGE_A ) +// Part B of EWR Storage +#define BlockRange_BLOCKTYPE_STORAGE_B ( BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_STORAGE_B) +// File System +#define BlockRange_BLOCKTYPE_FILESYSTEM ( BlockRange_DATATYPE_RAW | BlockUsage_FILESYSTEM) +// Used for MFUpdate for firmware/assembly/etc updates +#define BlockRange_BLOCKTYPE_UPDATE ( BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_UPDATE) + +//////////////////////////////////////////////////////// +// + +//typedef struct BLOCKRANGE BlockRange; + +typedef struct BlockRange +{ + unsigned int RangeType; + unsigned int StartBlock; + unsigned int EndBlock; +}BlockRange; + +#define BlockRange_GetBlockCount(block) (block.EndBlock - block.StartBlock + 1) +#define BlockRange_GetBlockUsage(block) (block.RangeType & BlockRange_USAGE_MASK) +#define BlockRange_IsDeployment(block) ((block.RangeType & BlockRange_USAGE_MASK) == BlockUsage_DEPLOYMENT) +#define BlockRange_IsConfig(block) ((block.RangeType & BlockRange_BLOCKTYPE_CONFIG) == BlockRange_BLOCKTYPE_CONFIG) + +///////////////////////////////////////////////////////// +// Description: +// This structure defines characteristics of a particular +// region of a block device. +// +// Remarks: +// There is often more than one instance of this structure for each +// block device. +// +// The BytesPerBlock value is an optimization to prevent the need +// to routinely calculate it from SectorsPerBlock * DataBytesPerSector +// + +typedef enum BlockRegionAttribute +{ + // block region is memory mapped + + BlockRegionAttribute_MemoryMapped = 0x0001, + +}BlockRegionAttribute; + +typedef struct BLOCKREGIONINFO BlockRegionInfo; + +#define BlockRegionInfo_Size(region) (region->NumBlocks * region->BytesPerBlock) +#define BlockRegionInfo_BlockAddress(region, blockIndex) (region->Start + (blockIndex * region->BytesPerBlock)) +#define BlockRegionInfo_OffsetFromBlock(region, address) ((address - region->Start) % region->BytesPerBlock) +#define BlockRegionInfo_BlockIndexFromAddress(region, address) ((address - region->Start) / region->BytesPerBlock) + +struct BLOCKREGIONINFO +{ + // attributes for the block region + BlockRegionAttribute Attributes; + + // Starting Sector address + ByteAddress Start; + + unsigned int NumBlocks; + + // total number of blocks in this region + unsigned int BytesPerBlock; // Total number of bytes per block + + unsigned int NumBlockRanges; + const BlockRange *BlockRanges; +}; + +///////////////////////////////////////////////////////// + +typedef struct DEVICEBLOCKINFO DeviceBlockInfo; + +typedef enum MediaAttribute +{ + MediaAttribute_Removable = 0x0001, + MediaAttribute_SupportsXIP = 0x0002, + MediaAttribute_WriteProtected = 0x0004, + MediaAttribute_SupportsCopyBack = 0x0008, + MediaAttribute_ErasedBitsAreZero = 0x0010, + +}MediaAttribute; + +#ifdef __cplusplus +extern "C" { +#endif + + SectorAddress DeviceBlockInfo_PhysicalToSectorAddress(DeviceBlockInfo* blockInfo, const BlockRegionInfo* pRegion, ByteAddress phyAddress); + bool DeviceBlockInfo_FindRegionFromAddress(DeviceBlockInfo* blockInfo, ByteAddress address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex); + bool DeviceBlockInfo_FindForBlockUsage(DeviceBlockInfo* blockInfo, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex); + bool DeviceBlockInfo_FindNextUsageBlock(DeviceBlockInfo* blockInfo, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex); + +#ifdef __cplusplus +} +#endif + +//typedef struct DEVICEBLOCKINFO +struct DEVICEBLOCKINFO +{ + MediaAttribute Attribute; + + // Bytes Per Sector + uint32_t BytesPerSector; + + // count of regions in the flash. + uint32_t NumRegions; + + // pointer to an array (NumRegions long) of region information + BlockRegionInfo *Regions; +}; + +///////////////////////////////////////////////////////// +// Description: +// This structure defines an interface for block devices +// +// Remarks: +// It is possible a given system might have more than one +// storage device type. This interface abstracts the +// hardware specifics from the rest of the system. +// +// All of the functions take at least one void* parameter +// that normally points to a driver specific data structure +// containing hardware specific settings to use. This +// allows a single driver to support multiple instances of +// the same type of storage device in the system. +// +// The sector read and write functions provide a parameter +// for Sector Metadata. The metadata is used for flash arrays +// without special controllers to manage wear leveling etc... +// (mostly for directly attached NOR and NAND). The metadata +// is used by upper layers for wear leveling to ensure that +// data is moved around on the flash when writing to prevent +// failure of the device from too many erase cycles on a sector. +// +// TODO: +// Define standard method of notification that media is +// removed for all removeable media. This will likely +// be a continuation so that the FS Manager can mount +// an FS and then notify the managed app of the new FS. +// + +typedef struct IBLOCKSTORAGEDEVICE IBlockStorageDevice; + +struct IBLOCKSTORAGEDEVICE +{ + ///////////////////////////////////////////////////////// + // Description: + // Initializes a given block device for use + // + // Input: + // + // Returns: + // true if successful; false if not + // + // Remarks: + // No other functions in this interface may be called + // until after Init returns. + // + bool (*InitializeDevice)(void*); + + ///////////////////////////////////////////////////////// + // Description: + // Initializes a given block device for use + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // De initializes the device when no longer needed + // + bool (*UninitializeDevice)(void*); + + ///////////////////////////////////////////////////////// + // Description: + // Gets the information describing the device + // + DeviceBlockInfo* (*GetDeviceInfo)(void*); + + ///////////////////////////////////////////////////////// + // Description: + // Reads data from a set of sectors + // + // Input: + // startAddress - Starting Sector for the read + // numBytes - Number of bytes to read + // buffer - pointer to buffer to read the data into. + // Must be large enough to hold all of the data + // being read. + // + // pSectorMetadata - pointer to an array of structured (one for each sector) + // for the extra sector information. + // + // Returns: + // true if successful; false if not + // + // Remarks: + // This function reads the number of sectors specified from the device. + // + // pSectorBuff may be NULL. This is to allow for reading just the metadata. + // + // pSectorMetadata can be set to NULL if the caller does not need the extra + // data. + // + // If the device does not support sector Metadata it should fail if the + // pSectorMetadata parameter is not NULL. + // + bool (*Read)(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer); + + ///////////////////////////////////////////////////////// + // Description: + // Writes data to a set of sectors + // + // Input: + // startAddress - Starting Sector for the write + // numBytes - Number of bytes to write + // buffer - pointer to data to write. + // Must be large enough to hold complete sectors + // for the number of sectors being written. + // + // pSectorMetadata - pointer to an array of structures (one for each sector) + // for the extra sector information. + // + // Returns: + // true if successful; false if not + // + // Remarks: + // This function reads the number of sectors specified from the device. + // The SectorMetadata is used for flash arrays without special controllers + // to manage wear leveling etc... (mostly for NOR and NAND). The metadata + // is used by upper layers to ensure that data is moved around on the flash + // when writing to prevent failure of the device from too many erase cycles + // on a sector. + // + // If the device does not support sector Metadata it should fail if the + // pSectorMetadata parameter is not NULL. + // + // pSectorMetadata can be set to NULL if the caller does not need the extra + // data. Implementations must not attempt to write data through a NULL pointer! + // + bool (*Write)(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite); + + bool (*Memset)(void*, ByteAddress startAddress, unsigned char data, unsigned int numBytes); + + //bool (*GetSectorMetadata)(void*, ByteAddress startAddress, SectorMetadata* pSectorMetadata); + + //bool (*SetSectorMetadata)(void*, ByteAddress startAddress, SectorMetadata* pSectorMetadata); + + ///////////////////////////////////////////////////////// + // Description: + // Check a block is erased or not. + // + // Input: + // blockStartAddress - Logical Sector Address + // + // Returns: + // true if it is erased, otherwise false + // + // Remarks: + // Check the block containing the sector address specified. + // + bool (*IsBlockErased)(void*, ByteAddress blockStartAddress, unsigned int length); + + ///////////////////////////////////////////////////////// + // Description: + // Erases a block + // + // Input: + // address - Logical Sector Address + // + // Returns: + // true if successful; false if not + // + // Remarks: + // Erases the block containing the sector address specified. + // + bool (*EraseBlock)(void*, ByteAddress address); + + ///////////////////////////////////////////////////////// + // Description: + // Changes the power state of the device + // + // Input: + // State - true= power on; false = power off + // + // Remarks: + // This function allows systems to conserve power by + // shutting down the hardware when the system is + // going into low power states. + // + void (*SetPowerState)(void*, unsigned int state); + + ///////////////////////////////////////////////////////// + // Description: + // Gets the memory mapped address for the specified block range. + // + // Input: + // blockRegionIndex - index of the block region + // blockRangeIndex - index of the block range in the region + // address - memory mapped address for the block range + // + // Returns: + // true if the block region is memory mapped, otherwise false + // + // Remarks: + // Being memory mapped, is expected that a block region is in the same physical device. + // This implementation is useful for systems that offer the possibility to map external storage + // to flash addressess. Tipically read only. + // + bool (*GetMemoryMappedAddress)(void*, unsigned int, unsigned int, ByteAddress*); +}; + +typedef struct BLOCKSTORAGEDEVICE +{ + IBlockStorageDevice* m_BSD; + void* m_context; +}BlockStorageDevice; + +///////////////////////////////////////////////////////////////////// +#ifdef __cplusplus +extern "C" { +#endif + + BlockStorageDevice* BlockStorageDevice_Next(BlockStorageDevice* device); + BlockStorageDevice* BlockStorageDevice_Prev(BlockStorageDevice* device); + bool BlockStorageDevice_InitializeDevice(BlockStorageDevice* device); + bool BlockStorageDevice_UninitializeDevice(BlockStorageDevice* device); + DeviceBlockInfo* BlockStorageDevice_GetDeviceInfo(BlockStorageDevice* device); + bool BlockStorageDevice_Read(BlockStorageDevice* device, unsigned int startAddress, unsigned int numBytes, unsigned char* buffer); + bool BlockStorageDevice_Write(BlockStorageDevice* device, unsigned int startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite); + bool BlockStorageDevice_Memset(BlockStorageDevice* device, unsigned int startAddress, unsigned char buffer, unsigned int numBytes); + // bool BlockStorageDevice_GetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, SectorMetadata* pSectorMetadata); + // bool BlockStorageDevice_SetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, SectorMetadata* pSectorMetadata); + bool BlockStorageDevice_IsBlockErased(BlockStorageDevice* device, unsigned int blockStartAddress, unsigned int length); + bool BlockStorageDevice_EraseBlock(BlockStorageDevice* device, unsigned int address); + void BlockStorageDevice_SetPowerState(BlockStorageDevice* device, unsigned int state); + bool BlockStorageDevice_FindRegionFromAddress(BlockStorageDevice* device, unsigned int address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex); + bool BlockStorageDevice_FindForBlockUsage(BlockStorageDevice* device, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex); + bool BlockStorageDevice_FindNextUsageBlock(BlockStorageDevice* device, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex); + bool BlockStorageDevice_GetMemoryMappedAddress(BlockStorageDevice* device, unsigned int blockRegionIndex, unsigned int blockRangeIndex, unsigned int* address); + +#ifdef __cplusplus +} +#endif + + +///////////////////////////////////////////////////// +// BlockStorageStream declarations + +typedef struct BLOCKSTORAGESTREAM BlockStorageStream; + +typedef enum SeekOrigin +{ + BlockStorageStream_SeekBegin = 0, + BlockStorageStream_SeekCurrent = 1, + BlockStorageStream_SeekEnd = 2, + +}SeekOrigin; + +#ifdef __cplusplus +extern "C" { +#endif + + bool BlockStorageStream_IsXIP(BlockStorageStream* stream); + bool BlockStorageStream_IsReadModifyWrite(BlockStorageStream* stream); + bool BlockStorageStream_SetReadModifyWrite(BlockStorageStream* stream); + + bool BlockStorageStream_Initialize(BlockStorageStream* stream, unsigned int blockUsage); + bool BlockStorageStream_InitializeWithBlockStorageDevice(BlockStorageStream* stream, unsigned int blockUsage, BlockStorageDevice* pDevice); + bool BlockStorageStream_NextStream(BlockStorageStream* stream); + bool BlockStorageStream_PrevStream(BlockStorageStream* stream); + bool BlockStorageStream_Seek(BlockStorageStream* stream, unsigned int offset, SeekOrigin origin); + bool BlockStorageStream_Write(BlockStorageStream* stream, unsigned char* data, unsigned int length); + bool BlockStorageStream_Erase(BlockStorageStream* stream, unsigned int length); + bool BlockStorageStream_ReadIntoBuffer(BlockStorageStream* stream, unsigned char* buffer, unsigned int length); + bool BlockStorageStream_Read(BlockStorageStream* stream, unsigned char** buffer, unsigned int length); + unsigned int BlockStorageStream_CurrentAddress(BlockStorageStream* stream); + unsigned int BlockStorageStream_CurrentMappedAddress(BlockStorageStream* stream); + bool BlockStorageStream_IsErased(BlockStorageStream* stream, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#define BLOCKSTORAGESTREAM_STREAM_SEEK_NEXT_BLOCK ((unsigned int)0x7FFFFFFF) +#define BLOCKSTORAGESTREAM_STREAM_SEEK_PREV_BLOCK ((unsigned int)0x7FFFFFFE) + +#define BLOCKSTORAGESTREAM_c_BlockStorageStream__XIP ((unsigned int)0x00000001) +#define BLOCKSTORAGESTREAM_c_BlockStorageStream__ReadModWrite ((unsigned int)0x00000002) +#define BLOCKSTORAGESTREAM_c_BlockStorageStream__MemoryMapped ((unsigned int)0x00000004) + +struct BLOCKSTORAGESTREAM +{ + unsigned int BaseAddress; + unsigned int MemoryMappedAddress; + unsigned int CurrentIndex; + unsigned int Length; + unsigned int BlockLength; + unsigned int Usage; + unsigned int Flags; + unsigned int RegionIndex; + unsigned int RangeIndex; + unsigned int CurrentUsage; + BlockStorageDevice *Device; + +}; + +/////////////////////////////////////////////////// +// BlockStorageList declarations + +typedef struct BLOCKSTORAGELIST BlockStorageList; + +#ifdef __cplusplus +extern "C" { +#endif + + // initialize the storage + void BlockStorageList_Initialize(); + // walk through list of devices and calls Init() function + bool BlockStorageList_InitializeDevices(); + // walk through list of devices and calls UnInit() function + bool BlockStorageList_UnInitializeDevices(); + // add pBSD to the list + // If Init=true, the Init() will be called. + bool BlockStorageList_AddDevice(BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, bool init); + // remove pBSD from the list + // Uninit = true, UnInit() will be called. + bool BlockStorageList_RemoveDevice(BlockStorageDevice* pBSD, bool unInit); + // Find the right Device with the corresponding phyiscal address. + bool BlockStorageList_FindDeviceForPhysicalAddress(BlockStorageDevice** pBSD, unsigned int physicalAddress, ByteAddress* blockAddress); + BlockStorageDevice* BlockStorageList_GetFirstDevice(); + BlockStorageDevice* BlockStorageList_GetNextDevice(BlockStorageDevice* device); + // returns number of devices has been declared in the system + unsigned int BlockStorageList_GetNumDevices(); + +#ifdef __cplusplus +} +#endif + +// default (and absolute minimum!!) block storage devices count is 1 (ONE) +// otherwise a target wouldn't have storage +#ifndef TARGET_BLOCKSTORAGE_COUNT +#define TARGET_BLOCKSTORAGE_COUNT 1 +#endif + +struct BLOCKSTORAGELIST +{ + // global pointer of all the storage devices + BlockStorageDevice* DeviceList[TARGET_BLOCKSTORAGE_COUNT]; + + uint32_t DeviceCount; + + // bool Initialized; +}; + +////////////////////////////////////////////////////////// +// TODO: evaluate if these typedefs below should go away +// and be replaced with others or completely ditched + + +typedef struct CPU_MEMORY_CONFIG +{ + unsigned char ChipSelect; + unsigned char ReadOnly; + unsigned int WaitStates; + unsigned int ReleaseCounts; + unsigned int BitWidth; + unsigned int BaseAddress; + unsigned int SizeInBytes; + unsigned char XREADYEnable; // 0,1 + unsigned char ByteSignalsForRead; // 0,1 + unsigned char ExternalBufferEnable; // 0,1 + +}CPU_MEMORY_CONFIG; + +typedef unsigned int GPIO_PIN; + +typedef struct GPIO_FLAG +{ + GPIO_PIN Pin; + bool ActiveState; + +}GPIO_FLAG; + +typedef struct BLOCK_CONFIG +{ + GPIO_FLAG WriteProtectionPin; + DeviceBlockInfo* BlockDeviceInformation; + +}BLOCK_CONFIG; + +typedef struct MEMORY_MAPPED_NOR_BLOCK_CONFIG +{ + BLOCK_CONFIG BlockConfig; + CPU_MEMORY_CONFIG Memory; + unsigned int ChipProtection; + unsigned int ManufacturerCode; + unsigned int DeviceCode; + +}MEMORY_MAPPED_NOR_BLOCK_CONFIG; + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////// +// function to included in all target devices to be added +void BlockStorage_AddDevices(); + +#ifdef __cplusplus +} +#endif + +#endif // _NANOPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_COM.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_COM.h new file mode 100644 index 00000000..10defc06 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_COM.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOPAL_COM_H_ +#define _NANOPAL_COM_H_ 1 + +#include +#include + +#define COM_MAX_RETRIES 99 +#define NATIVE_PROFILE_PAL_COM() + + +#ifdef __cplusplus +extern "C" { +#endif + +bool GenericPort_Initialize( COM_HANDLE comPortNum ); +bool GenericPort_Uninitialize( COM_HANDLE comPortNum ); +uint32_t GenericPort_Write( int portNum, const char* data, size_t size ); +int GenericPort_Read( COM_HANDLE comPortNum, char* data, size_t size ); +bool GenericPort_Flush( COM_HANDLE comPortNum ); +bool GenericPort_IsSslSupported( COM_HANDLE comPortNum ); +bool GenericPort_UpgradeToSsl( COM_HANDLE comPortNum, unsigned int flags ); +bool GenericPort_IsUsingSsl( COM_HANDLE comPortNum ); + +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus +int DebuggerPort_Write( COM_HANDLE comPortNum, const char* data, size_t size ); +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +bool DebuggerPort_Initialize( COM_HANDLE comPortNum ); +bool DebuggerPort_Uninitialize( COM_HANDLE comPortNum ); +int DebuggerPort_Write( COM_HANDLE comPortNum, const char* data, size_t size, int maxRetries ); +int DebuggerPort_Read( COM_HANDLE comPortNum, char* data, size_t size ); +bool DebuggerPort_Flush( COM_HANDLE comPortNum ); +bool DebuggerPort_IsSslSupported( COM_HANDLE comPortNum ); +bool DebuggerPort_UpgradeToSsl( COM_HANDLE comPortNum, unsigned int flags ); +bool DebuggerPort_IsUsingSsl( COM_HANDLE comPortNum ); + +#ifdef __cplusplus +} +#endif + +#endif // _NANOPAL_COMDECL_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Events.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Events.h new file mode 100644 index 00000000..6454775c --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Events.h @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOPAL_EVENTS_H_ +#define _NANOPAL_EVENTS_H_ 1 + +#include +#include + +typedef void (*set_Event_Callback)( void* ); + +#define EVENTS_TIMEOUT_INFINITE 0xFFFFFFFF + +#if NATIVE_PROFILE_PAL & NATIVE_PROFILE_PAL_EVENTS__flag + #define NATIVE_PROFILE_PAL_EVENTS() Native_Profiler profiler_obj +#else + #define NATIVE_PROFILE_PAL_EVENTS() +#endif + + + bool Events_Initialize(); + bool Events_Uninitialize(); + void Events_Set( uint32_t events ); + +// destructive read system event flags + uint32_t Events_Get( uint32_t eventsOfInterest ); + +// non-destructive read system event flags + uint32_t Events_MaskedRead( uint32_t eventsOfInterest ); + +// returns 0 for timeout, non-zero are events that have happened and were asked to be waiting on (non-destructive read) +// timeout limit is about 3034 milliseconds currently +// values greater than this are capped to this + +// sleep relative time into the future, or until a SystemEvent occurs, which occurs first +// timeout is a non-negative number of 1mSec ticks, or -1 (any negative value) to sleep forever until a SystemEvent occurs + +// Events_WaitForEvents(0, n), sleeps for n milliseconds independent of events +// Events_WaitForEvents(0, EVENTS_TIMEOUT_INFINITE) sleeps forever. Don't do that. +// Events_WaitForEvents(flags, EVENTS_TIMEOUT_INFINITE) waits forever for that event. + +uint32_t Events_WaitForEvents( uint32_t powerLevel, uint32_t wakeupSystemEvents, uint32_t timeoutMilliseconds ); + +__inline uint32_t Events_WaitForEvents( uint32_t wakeupSystemEvents, uint32_t timeoutMilliseconds ) +{ + return Events_WaitForEvents( SLEEP_LEVEL__SLEEP, wakeupSystemEvents, timeoutMilliseconds ); +} + + void Events_SetBoolTimer( bool* timerCompleteFlag, uint32_t millisecondsFromNow ); + void Events_SetCallback( set_Event_Callback pfn, void* arg ); + void FreeManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2); + + +#ifdef __cplusplus +extern "C" { +#endif + + void PostManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2); + +#ifdef __cplusplus +} +#endif + +//--// + +typedef void (*PALEVENTLISTENER) (uint32_t e, uint32_t param); + +struct PalEventListener : public HAL_DblLinkedNode +{ + PALEVENTLISTENER m_palEventListener; + uint32_t m_eventMask; +}; + + +HRESULT PalEvent_Initialize(); +HRESULT PalEvent_Uninitialize(); +HRESULT PalEvent_Post(uint32_t e, uint32_t param); +HRESULT PalEvent_Enlist(PalEventListener* listener); + +//--// + +struct PalEventDriver +{ +public: + + HAL_DblLinkedList listenerList; + + static HRESULT Initialize(); + static HRESULT Uninitialize(); + static HRESULT PostEvent(uint32_t e, uint32_t param); + static HRESULT EnlistListener(PalEventListener* listener); + +private: + static bool s_initialized; +}; + +extern PalEventDriver g_palEventDriver; + +#endif //_NANOPAL_EVENTS_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_GPIO.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_GPIO.h new file mode 100644 index 00000000..c7ebbc16 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_GPIO.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOPAL_GPIO_H_ +#define _NANOPAL_GPIO_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// +/// Performs initialization of GPIO pins and associated drivers. +/// +void GPIO_Initialize(); +void GPIO_Uninitialize(); + +#ifdef __cplusplus +} +#endif + +#endif //_NANOPAL_GPIO_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_NativeDouble.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_NativeDouble.h new file mode 100644 index 00000000..ebb21b2c --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_NativeDouble.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _NANOPAL_DOUBLE_DECL_H_ +#define _NANOPAL_DOUBLE_DECL_H_ + +#include + +namespace System +{ + struct Double + { + static int32_t CompareTo( double d, double val ); + static bool IsInfinity( double d ); + static bool IsNaN( double d ); + static bool IsNegativeInfinity( double d ); + static bool IsPositiveInfinity( double d ); + }; +} + +#endif //_NANOPAL_DOUBLE_DECL_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Network.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Network.h new file mode 100644 index 00000000..a2d79034 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Network.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NETWORK_DECL_H_ +#define _NETWORK_DECL_H_ 1 + + +#ifdef PLATFORM_DEPENDENT__SOCKETS_MAX_COUNT +#define SOCKETS_MAX_COUNT PLATFORM_DEPENDENT__SOCKETS_MAX_COUNT +#else +#define SOCKETS_MAX_COUNT 1 // required to have at least one for array init +#endif + +#ifdef PLATFORM_DEPENDENT__SOCKETS_MAX_SEND_LENGTH +#define SOCKETS_MAX_SEND_LENGTH PLATFORM_DEPENDENT__SOCKETS_MAX_SEND_LENGTH +#endif + +#if !defined(DEBGGER_NETWORK_INTERFACE_INDEX) +#define DEBGGER_NETWORK_INTERFACE_INDEX 0 +#endif + +#endif //_NETWORK_DECL_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_PerformanceCounters.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_PerformanceCounters.h new file mode 100644 index 00000000..a068d5a8 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_PerformanceCounters.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _PERFORMANCE_COUNTERS_H_ +#define _PERFORMANCE_COUNTERS_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void PAL_PerformanceCounter_Initialize(); +void PAL_PerformanceCounter_Uninitialize(); +uint32_t PAL_PerformanceCounter(); + +#ifdef __cplusplus +} +#endif + +#endif //_PERFORMANCE_COUNTERS_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Sockets.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Sockets.h new file mode 100644 index 00000000..57b4deaa --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Sockets.h @@ -0,0 +1,664 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _DRIVERS_SOCKETS_DECL_H_ +#define _DRIVERS_SOCKETS_DECL_H_ 1 + +#if defined(_WIN32) +#define GLOBAL_LOCK_SOCKETS(x) +#endif +//--// + + +typedef struct _DATE_TIME_INFO +{ + unsigned int year; /* year, AD */ + unsigned int month; /* 1 = January, 12 = December */ + unsigned int day; /* 1 = first of the month */ + unsigned int hour; /* 0 = midnight, 12 = noon */ + unsigned int minute; /* minutes past the hour */ + unsigned int second; /* seconds in minute */ + unsigned int msec; /* milliseconds in second */ + + /* These two fields help */ + /* interpret the absolute */ + /* time meaning of the */ + /* above values. */ + unsigned int dlsTime; /* boolean; daylight savings time is in effect */ + int tzOffset; /* signed int; difference in seconds imposed by timezone (from GMT) */ +} DATE_TIME_INFO; + +typedef struct _X509CertData +{ + char Issuer[256]; + char Subject[256]; + DATE_TIME_INFO EffectiveDate; + DATE_TIME_INFO ExpirationDate; +} X509CertData; + + +//Avoid including windows socket definitions + +#ifndef NANOCLR_SOCK_STRUCTURES +#define NANOCLR_SOCK_STRUCTURES + +#define SOCK_EINTR 10004L +#define SOCK_EBADF 10009L +#define SOCK_EACCES 10013L +#define SOCK_EFAULT 10014L +#define SOCK_EINVAL 10022L +#define SOCK_EMFILE 10024L +#define SOCK_EWOULDBLOCK 10035L /*WSAEWOULDBLOCK*/ +#define SOCK_EINPROGRESS 10036L /*WSAEINPROGRESS*/ +#define SOCK_EALREADY 10037L +#define SOCK_ENOTSOCK 10038L +#define SOCK_EDESTADDRREQ 10039L +#define SOCK_EMSGSIZE 10040L +#define SOCK_EPROTOTYPE 10041L +#define SOCK_ENOPROTOOPT 10042L +#define SOCK_EPROTONOSUPPORT 10043L +#define SOCK_ESOCKTNOSUPPORT 10044L +#define SOCK_EOPNOTSUPP 10045L +#define SOCK_EPFNOSUPPORT 10046L +#define SOCK_EAFNOSUPPORT 10047L +#define SOCK_EADDRINUSE 10048L +#define SOCK_EADDRNOTAVAIL 10049L +#define SOCK_ENETDOWN 10050L +#define SOCK_ENETUNREACH 10051L +#define SOCK_ENETRESET 10051L +#define SOCK_ECONNABORTED 10053L +#define SOCK_ECONNRESET 10054L +#define SOCK_ENOBUFS 10055L +#define SOCK_EISCONN 10056L +#define SOCK_ENOTCONN 10057L +#define SOCK_ESHUTDOWN 10058L +#define SOCK_ETOOMANYREFS 10059L +#define SOCK_ETIMEDOUT 10060L +#define SOCK_ECONNREFUSED 10061L +#define SOCK_ELOOP 10062L +#define SOCK_ENAMETOOLONG 10063L +#define SOCK_EHOSTDOWN 10064L +#define SOCK_EHOSTUNREACH 10065L +#define SOCK_ENOTEMPTY 10066L +#define SOCK_EPROCLIM 10067L +#define SOCK_EUSERS 10068L +#define SOCK_EDQUOT 10069L +#define SOCK_ESTALE 10070L +#define SOCK_EREMOTE 10071L +#define SOCK_SYSNOTREADY 10091L +#define SOCK_VERNOTSUPPORTED 10092L +#define SOCK_NOTINITIALISED 10093L +#define SOCK_EDISCON 10101L +#define SOCK_ENOMORE 10102L +#define SOCK_ECANCELLED 10103L +#define SOCK_EINVALIDPROCTABLE 10104L +#define SOCK_EINVALIDPROVIDER 10105L +#define SOCK_EPROVIDERFAILEDINIT 10106L +#define SOCK_SYSCALLFAILURE 10107L +#define SOCK_SERVICE_NOT_FOUND 10108L +#define SOCK_TYPE_NOT_FOUND 10109L +#define SOCK__E_NO_MORE 10110L +#define SOCK__E_CANCELLED 10111L +#define SOCK_EREFUSED 10112L +#define SOCK_HOST_NOT_FOUND 11001L +#define SOCK_TRY_AGAIN 11002L +#define SOCK_NO_RECOVERY 11003L +#define SOCK_NO_DATA 11004L +// +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +typedef unsigned __int64 u_int64; +// +// +#define SOCK_AF_UNSPEC 0 /* unspecified */ +#define SOCK_AF_INET 2 /* internetwork: UDP, TCP, etc. */ +#define SOCK_AF_INET6 28 + +typedef int SOCK_SOCKET; + +#define SOCK_INADDR_ANY 0x00000000UL +#define SOCK_INADDR_LOOPBACK 0x7F000001UL + + +#define SOCK_SOCK_STREAM 1 +#define SOCK_SOCK_DGRAM 2 +#define SOCK_SOCK_RAW 3 +#define SOCK_SOCK_RDM 4 +#define SOCK_SOCK_SEQPACKET 5 +#define SOCK_SOCK_PACK_EX 6 + +#define SOCK_TCP_NODELAY 0x0001 + +#define SOCK_IPPROTO_IP 0 +#define SOCK_IPPROTO_ICMP 1 +#define SOCK_IPPROTO_IGMP 2 +#define SOCK_IPPROTO_IPV4 4 /* IP-in-IP encapsulation */ +#define SOCK_IPPROTO_TCP 6 +#define SOCK_IPPROTO_PUP 12 +#define SOCK_IPPROTO_UDP 17 +#define SOCK_IPPROTO_IDP 22 +#define SOCK_IPPROTO_IPV6 41 +#define SOCK_IPPROTO_IPv6RoutingHeader 43 +#define SOCK_IPPROTO_IPv6FragmentHeader 44 +#define SOCK_IPPROTO_RDP 46 +#define SOCK_IPPROTO_GRE 47 +#define SOCK_IPPROTO_IPSecEncapsulatingSecurityPayload 50 +#define SOCK_IPPROTO_IPSecAuthenticationHeader 51 +#define SOCK_IPPROTO_IcmpV6 58 +#define SOCK_IPPROTO_IPv6NoNextHeader 59 +#define SOCK_IPPROTO_IPv6DestinationOptions 60 +#define SOCK_IPPROTO_ND 77 +#define SOCK_IPPROTO_OSPF 89 +#define SOCK_IPPROTO_TPACKET 127 +#define SOCK_IPPROTO_RAW 255 +#define SOCK_IPPROTO_IPX 1000 +#define SOCK_IPPROTO_SPX 1256 +#define SOCK_IPPROTO_SPXII 1257 +#define SOCK_SOL_SOCKET 0xFFFF + +/* Option flags per-socket */ +#define SOCK_SOCKO_DEBUG 0x0001 // turn on debugging info recording +#define SOCK_SOCKO_NOCHECKSUM 0x0001 +#define SOCK_SOCKO_ACCEPTCONNECTION 0x0002 // socket has had listen() +#define SOCK_SOCKO_REUSEADDRESS 0x0004 // allow local address reuse +#define SOCK_SOCKO_KEEPALIVE 0x0008 // keep connections alive +#define SOCK_SOCKO_DONTROUTE 0x0010 // just use interface addresses +#define SOCK_SOCKO_BROADCAST 0x0020 // permit sending of broadcast msgs +#define SOCK_SOCKO_USELOOPBACK 0x0040 // bypass hardware when possible +#define SOCK_SOCKO_LINGER 0x0080 // linger on close if data present +#define SOCK_SOCKO_OUTOFBANDINLINE 0x0100 // leave received OOB data in line +#define SOCK_SOCKO_DONTLINGER ~SOCK_SOCKO_LINGER +#define SOCK_SOCKO_EXCLUSIVEADDRESSUSE ~SOCK_SOCKO_REUSEADDRESS // disallow local address reuse +#define SOCK_SOCKO_SENDBUFFER 0x1001 // send buffer size +#define SOCK_SOCKO_SNDBUF SOCK_SOCKO_SENDBUFFER +#define SOCK_SOCKO_RECEIVEBUFFER 0x1002 // receive buffer size +#define SOCK_SOCKO_RCVBUF SOCK_SOCKO_RECEIVEBUFFER +#define SOCK_SOCKO_SENDLOWWATER 0x1003 // send low-water mark +#define SOCK_SOCKO_RECEIVELOWWATER 0x1004 // receive low-water mark +#define SOCK_SOCKO_SENDTIMEOUT 0x1005 // send timeout +#define SOCK_SOCKO_RECEIVETIMEOUT 0x1006 // receive timeout +#define SOCK_SOCKO_ERROR 0x1007 // get error status and clear +#define SOCK_SOCKO_UPDATE_ACCEPT_CTX 0x700B // This option updates the properties of the socket which are inherited from the listening socket. +#define SOCK_SOCKO_UPDATE_CONNECT_CTX 0x7010 // This option updates the properties of the socket after the connection is established. +#define SOCK_SOCKO_MAXCONNECTIONS 0x7FFFFFFF // Maximum queue length specifiable by listen. + +/* Option flags per-IP */ +#define SOCK_IPO_OPTIONS 0x0001 +#define SOCK_IPO_HDRINCL 0x0002 +#define SOCK_IPO_TOS 0x0003 +#define SOCK_IPO_TTL 0x0004 +#define SOCK_IPO_MULTICAST_IF 0x0009 +#define SOCK_IPO_MULTICAST_TTL 0x000A +#define SOCK_IPO_MULTICAST_LOOP 0x000B +#define SOCK_IPO_ADD_MEMBERSHIP 0x000C +#define SOCK_IPO_DROP_MEMBERSHIP 0x000D +#define SOCK_IPO_IP_DONTFRAGMENT 0x000E +#define SOCK_IPO_ADD_SOURCE_MEMBERSHIP 0x000F +#define SOCK_IPO_DROP_SOURCE_MEMBERSHIP 0x0010 +#define SOCK_IPO_BLOCK_SOURCE 0x0011 +#define SOCK_IPO_UBLOCK_SOURCE 0x0012 +#define SOCK_IPO_PACKET_INFO 0x0013 + + +#define SOCK_SOCKET_ERROR -1 +#define SOCK_WSATRY_AGAIN 11002 +#define SOCK_WSAEINVAL 10022 +#define SOCK_WSANO_RECOVERY 11003 +#define SOCK_WSAEAFNOSUPPORT 10047 +#define SOCK_WSA_NOT_ENOUGH_MEMORY -1 +#define SOCK_WSAHOST_NOT_FOUND 11001 +#define SOCK_WSATYPE_NOT_FOUND 10109 +#define SOCK_WSAESOCKTNOSUPPORT 10044 +// +#define SOCK_IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */ +#define SOCK_IOC_VOID 0x20000000 /* no parameters */ +#define SOCK_IOC_OUT 0x40000000 /* copy out parameters */ +#define SOCK_IOC_IN 0x80000000 /* copy in parameters */ +#define SOCK_IOC_INOUT (SOCK_IOC_IN|SOCK_IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define SOCK__IO(x,y) (SOCK_IOC_VOID|((x)<<8)|(y)) + +#define SOCK__IOR(x,y,t) (SOCK_IOC_OUT|(((long)sizeof(t)&SOCK_IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define SOCK__IOW(x,y,t) (SOCK_IOC_IN|(((long)sizeof(t)&SOCK_IOCPARM_MASK)<<16)|((x)<<8)|(y)) +// +#define SOCK_FIONREAD SOCK__IOR('f', 127, u_long) /* get # bytes to read */ +#define SOCK_FIONBIO SOCK__IOW('f', 126, u_long) /* set/clear non-blocking i/o */ +#define SOCK_FIOASYNC SOCK__IOW('f', 125, u_long) /* set/clear async i/o */ +// + +#define SOCK_FD_SETSIZE 256 +#define SOCK_MAX_ADDR_SIZE 14 + +typedef struct SOCK_fd_set { + unsigned int fd_count; + int fd_array[SOCK_FD_SETSIZE]; +}SOCK_fd_set; + +typedef struct SOCK_sockaddr { + unsigned short sa_family; /* address family */ + char sa_data[SOCK_MAX_ADDR_SIZE]; /* up to SOCK_MAX_ADDR_SIZE bytes of direct address */ +}SOCK_sockaddr; + +CT_ASSERT_UNIQUE_NAME(sizeof(SOCK_sockaddr)==(16), SOCK_SOCKADDR) + +typedef struct GNU_PACKED SOCK_in_addr{ + union GNU_PACKED { + struct GNU_PACKED { + u_char s_b1,s_b2,s_b3,s_b4; + } S_un_b; + + struct GNU_PACKED { + u_short s_w1,s_w2; + } S_un_w; + + u_long S_addr; + } S_un; +} SOCK_in_addr; + +typedef struct GNU_PACKED SOCK_sockaddr_in { + short sin_family; + u_short sin_port; + SOCK_in_addr sin_addr; + char sin_zero[8]; +} SOCK_sockaddr_in; + +CT_ASSERT_UNIQUE_NAME(sizeof(SOCK_sockaddr_in)==16, SOCK_SOCKADDR_IN) + +typedef struct SOCK_addrinfo +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char* ai_canonname; + struct SOCK_sockaddr* ai_addr; + struct SOCK_addrinfo* ai_next; +}SOCK_addrinfo; + +typedef struct SOCK_ip_mreq +{ + SOCK_in_addr imr_multiaddr; /* IPv4 Class D multicast address */ + SOCK_in_addr imr_interface; /* IPv4 address of local interface */ +} SOCK_ip_mreq; + +typedef struct SOCK_discoveryinfo +{ + uint32_t ipaddr; + uint32_t macAddressLen; + char macAddressBuffer[64]; +} SOCK_discoveryinfo; + +#define SOCK_MAKE_IP_ADDR(w,x,y,z) ((uint32_t)(w) & 0xFF)<<24 | ((uint32_t)(x) & 0xff)<<16 | ((uint32_t)(y) & 0xff)<<8 | ((uint32_t)(z) & 0xff) +#define SOCK_MAKE_IP_ADDR_LITTLEEND(w,x,y,z) ((uint32_t)(z) & 0xFF)<<24 | ((uint32_t)(y) & 0xff)<<16 | ((uint32_t)(x) & 0xff)<<8 | ((uint32_t)(w) & 0xff) + +#ifndef SOCKET_READ_PEEK_OPTION +#define SOCKET_READ_PEEK_OPTION 2 +#endif + +#ifndef DEBUG_SOCKET_PORT +#define DEBUG_SOCKET_PORT 26000 +#endif + +#ifndef SOCK_DISCOVERY_MULTICAST_PORT +#define SOCK_DISCOVERY_MULTICAST_PORT 26001 +#endif + +//A multicast address is an IP address which belongs to classe D included in the range between 224.0.0.0 and 239.255.255.255 +#ifndef SOCK_DISCOVERY_MULTICAST_IPADDR +#define SOCK_DISCOVERY_MULTICAST_IPADDR SOCK_MAKE_IP_ADDR(234,102,98,44) +#endif + +#ifndef SOCK_DISCOVERY_MULTICAST_IPADDR_SND +#define SOCK_DISCOVERY_MULTICAST_IPADDR_SND SOCK_MAKE_IP_ADDR(234,102,98,45) +#endif + +#ifndef SOCK_DISCOVERY_MULTICAST_TOKEN +#define SOCK_DISCOVERY_MULTICAST_TOKEN "DOTNETMF" +#endif + +#define SOCKET_EVENT_WAIT_FOREVER 0xFFFFFFFF +#define SOCKET_EVENT_FLAG_SOCKETS_SHUTDOWN 0x00000001 +#define SOCKET_EVENT_FLAG_SOCKETS_READY 0x00000002 +#define SOCKET_EVENT_FLAG_SOCKET 0x00000004 + +/* + * Structure used in select() call, taken from the BSD file sys/time.h. + */ +typedef struct SOCK_timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}SOCK_timeval; + + +#define SOCK_NETWORKCONFIGURATION_FLAGS_DHCP 0x00000001 +#define SOCK_NETWORKCONFIGURATION_FLAGS_DYNAMIC_DNS 0x00000002 + +/// Bits 19-16 of HAL_Configuration_NetworkInterface.flags: Type of HAL_Configuration_NetworkInterface +/// 0 - NetworkInterface +/// 1 - Wireless +#define SOCK_NETWORKCONFIGURATION_FLAGS_NETWORK_INTERFACE 0 +#define SOCK_NETWORKCONFIGURATION_FLAGS_WIRELESS 1 +#define SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__mask 0x000F0000 +#define SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__shift 16 +#define SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__value(x) (((x) & SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__mask) >> SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__shift) +#define SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__set(x) (((x) << SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__shift) & SOCK_NETWORKCONFIGURATION_FLAGS_TYPE__mask) +#define SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__mask 0x00F00000 +#define SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__shift 20 +#define SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__value(x) (((x) & SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__mask) >> SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__shift) +#define SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__set(x) (((x) << SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__shift) & SOCK_NETWORKCONFIGURATION_FLAGS_SUBINDEX__mask) + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.NetworkInterface.UpdateOperation (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +enum UpdateOperation +{ + UpdateOperation_Invalid = 0x00, + UpdateOperation_Dns = 0x01, + UpdateOperation_Dhcp = 0x02, + UpdateOperation_DhcpRenew = 0x04, + UpdateOperation_DhcpRelease = 0x08, + UpdateOperation_Mac = 0x10, +}; + +#define SOCK_NETWORKCONFIGURATION_INTERFACETYPE_UNKNOWN 0 +#define SOCK_NETWORKCONFIGURATION_INTERFACETYPE_ETHERNET 6 +#define SOCK_NETWORKCONFIGURATION_INTERFACETYPE_WIRELESS_80211 71 + + +//--// + +/// +/// Keep these values in sync with the manged code enumeration Wireless80211.AuthenticationType in wireless.cs +/// +// Wireless flags bits 0 - 3 +#define WIRELESS_FLAG_AUTHENTICATION_NONE 0 +#define WIRELESS_FLAG_AUTHENTICATION_EAP 1 +#define WIRELESS_FLAG_AUTHENTICATION_PEAP 2 +#define WIRELESS_FLAG_AUTHENTICATION_WCN 3 +#define WIRELESS_FLAG_AUTHENTICATION_OPEN 4 +#define WIRELESS_FLAG_AUTHENTICATION_SHARED 5 +#define WIRELESS_FLAG_AUTHENTICATION__shift 0 +#define WIRELESS_FLAG_AUTHENTICATION__mask 0x0000000F +#define WIRELESS_FLAG_AUTHENTICATION__value(x) (((x) & WIRELESS_FLAG_AUTHENTICATION__mask) >> WIRELESS_FLAG_AUTHENTICATION__shift) +#define WIRELESS_FLAG_AUTHENTICATION__set(x) (((x) << WIRELESS_FLAG_AUTHENTICATION__shift) & WIRELESS_FLAG_AUTHENTICATION__mask) + +/// +/// Keep these values in sync with the manged code enumeration Wireless80211.EncryptionType in wireless.cs +/// + +// Wireless flags bits 4 - 7 +#define WIRELESS_FLAG_ENCRYPTION_NONE 0 +#define WIRELESS_FLAG_ENCRYPTION_WEP 1 +#define WIRELESS_FLAG_ENCRYPTION_WPA 2 +#define WIRELESS_FLAG_ENCRYPTION_WPAPSK 3 +#define WIRELESS_FLAG_ENCRYPTION_Certificate 4 +#define WIRELESS_FLAG_ENCRYPTION__shift 4 +#define WIRELESS_FLAG_ENCRYPTION__mask 0x000000F0 +#define WIRELESS_FLAG_ENCRYPTION__value(x) (((x) & WIRELESS_FLAG_ENCRYPTION__mask) >> WIRELESS_FLAG_ENCRYPTION__shift) +#define WIRELESS_FLAG_ENCRYPTION__set(x) (((x) << WIRELESS_FLAG_ENCRYPTION__shift) & WIRELESS_FLAG_ENCRYPTION__mask) + +/// +/// Keep these values in sync with the manged code enumeration Wireless80211.RadioType in wireless.cs +/// + +// Wireless flags bits 8 - 11 +#define WIRELESS_FLAG_RADIO_a 1 +#define WIRELESS_FLAG_RADIO_b 2 +#define WIRELESS_FLAG_RADIO_g 4 +#define WIRELESS_FLAG_RADIO_n 8 +#define WIRELESS_FLAG_RADIO__shift 8 +#define WIRELESS_FLAG_RADIO__mask 0x00000F00 +#define WIRELESS_FLAG_RADIO__value(x) (((x) & WIRELESS_FLAG_RADIO__mask) >> WIRELESS_FLAG_RADIO__shift) +#define WIRELESS_FLAG_RADIO__set(x) (((x) << WIRELESS_FLAG_RADIO__shift) & WIRELESS_FLAG_RADIO__mask) + + +// Wireless flags bits 12 - 15 +#define WIRELESS_FLAG_DATA_ENCRYPTED 1 +#define WIRELESS_FLAG_DATA__shift 12 +#define WIRELESS_FLAG_DATA__mask 0x0000F000 +#define WIRELESS_FLAG_DATA__value(x) (((x) & WIRELESS_FLAG_DATA__mask) >> WIRELESS_FLAG_DATA__shift) +#define WIRELESS_FLAG_DATA__set(x) (((x) << WIRELESS_FLAG_DATA__shift) & WIRELESS_FLAG_DATA__mask) + + +//extern const ConfigurationSector g_ConfigurationSector; + +//--// + +#define SOCK_htons(x) ( (((x) & 0x000000FFUL) << 8) | (((x) & 0x0000FF00UL) >> 8) ) +#define SOCK_htonl(x) ( (((x) & 0x000000FFUL) << 24) | (((x) & 0x0000FF00UL) << 8) | (((x) & 0x00FF0000UL) >> 8) | (((x) & 0xFF000000UL) >> 24) ) +#define SOCK_ntohs(x) SOCK_htons(x) +#define SOCK_ntohl(x) ( (((x) & 0x000000FFUL) << 24) | (((x) & 0x0000FF00UL) << 8) | (((x) & 0x00FF0000UL) >> 8) | (((x) & 0xFF000000UL) >> 24) ) + +#define SOCK_FD_ZERO(x) memset(x, 0, sizeof(*x)) +__inline bool SOCK_FD_ISSET(int y, SOCK_fd_set* x) +{ + GLOBAL_LOCK_SOCKETS(irq); + + for(int i=0; i<(int)x->fd_count; i++) + { + if(x->fd_array[i] == y) + { + return true; + } + } + return false; +} + +__inline void SOCK_FD_SET(int y, SOCK_fd_set* x) +{ + if(SOCK_FD_ISSET(y, x)) return; + + GLOBAL_LOCK_SOCKETS(irq); + + if(x->fd_count < SOCK_FD_SETSIZE) + { + x->fd_array[x->fd_count++] = y; + } + else + { + ASSERT(false); + } +} + +__inline void SOCK_FD_CLR(int y, SOCK_fd_set* x) +{ + GLOBAL_LOCK_SOCKETS(irq); + + for(int i=0; i<(int)x->fd_count; i++) + { + if(x->fd_array[i] == y) + { + x->fd_count--; + + if(i < (int)x->fd_count) + { + x->fd_array[i] = x->fd_array[x->fd_count]; + } + x->fd_array[x->fd_count] = 0; + break; + } + } +} + +#endif //NANOCLR_SOCK_STRUCTURES + +#ifndef DEBUG_SOCKET_PORT // default debug socket port +#define DEBUG_SOCKET_PORT 26000 +#endif + + +//struct HAL_Configuration_NetworkInterface; +struct HAL_Configuration_Wireless80211; + +//--// + +bool Network_Initialize(); +bool Network_Uninitialize(); + +bool Network_Interface_Bind(int index); +int Network_Interface_Open(int index); +bool Network_Interface_Close(int index); +int Network_Interface_Disconnect(int index); +int Network_Interface_Connect(int index, const char * ssid, const char * passphase, int options); +bool Network_Interface_Start_Scan(int index); + +// Wireless AP methods +void Network_Interface_Add_Station(uint16_t index, uint8_t * macAddress); +void Network_Interface_Remove_Station(uint16_t index); +int Network_Interface_Max_Stations(); +bool Network_Interface_Get_Station(uint16_t index, uint8_t * macAddress, uint8_t * rssi, uint32_t * phyModes); +void Network_Interface_Deauth_Station(uint16_t index); + +//--// + +// Network_Interface_Connect options +#define NETWORK_CONNECT_SAVE_CONFIG 1 +#define NETWORK_CONNECT_RECONNECT 2 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.NetworkChange.NetworkEventType (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +enum NetworkEventType +{ + NetworkEventType_Invalid = 0, + NetworkEventType_AvailabilityChanged = 1, + NetworkEventType_AddressChanged = 2, + NetworkEventType_APClientChanged = 3, +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.WiFi.WiFiEventType (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +enum WiFiEventType +{ + WiFiEventType_Invalid = 0, + WiFiEventType_ScanComplete = 1, +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.NetworkChange.NetworkEventFlags (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +enum NetworkEventFlags +{ + NetworkEventFlags_NetworkNOTAvailable = 0x00, + NetworkEventFlags_NetworkAvailable = 0x01, +}; + +void Network_PostEvent(unsigned int eventType, unsigned int flags, unsigned int index); + +//--// +// Debugger Methods +bool SOCKETS_DbgInitialize( int ComPortNum ); +bool SOCKETS_DbgUninitialize( int ComPortNum ); +int SOCKETS_Write( int ComPortNum, const char* Data, size_t size ); +int SOCKETS_Read( int ComPortNum, char* Data, size_t size ); +bool SOCKETS_Flush( int ComPortNum ); +bool SOCKETS_UpgradeToSsl( int ComPortNum, const uint8_t* pCACert, uint32_t caCertLen, const uint8_t* pDeviceCert, uint32_t deviceCertLen, LPCSTR szTargetHost ); +bool SOCKETS_IsUsingSsl( int32_t ComPortNum ); + + +void SOCKETS_CloseConnections(); +// RTIP +bool SOCKETS_ProcessSocketActivity(SOCK_SOCKET signalSocket); +//LWIP +void SOCKETS_CreateTcpIpProcessor(HAL_CALLBACK_FPN callback, void* arg); +void SOCKETS_RestartTcpIpProcessor(uint32_t timeFromNow_us); + +// BSD style Sockets +int SOCK_socket( int family, int type, int protocol ); +int SOCK_bind( int socket, const struct SOCK_sockaddr* address, int addressLen ); +int SOCK_connect(int socket, const struct SOCK_sockaddr* address, int addressLen ); +int SOCK_send(int socket, const char* buf, int len, int flags ); +int SOCK_recv(int socket, char* buf, int len, int flags ); +int SOCK_close(int socket); +int SOCK_listen( int socket, int backlog ); +int SOCK_accept( int socket, struct SOCK_sockaddr* address, int* addressLen ); +int SOCK_shutdown( int socket, int how ); +int SOCK_getaddrinfo( const char* nodename, char* servname, const struct SOCK_addrinfo* hints, struct SOCK_addrinfo** res ); +void SOCK_freeaddrinfo( struct SOCK_addrinfo* ai ); +int SOCK_ioctl( int socket, int cmd, int* data ); +int SOCK_getlasterror(); +int SOCK_getsocklasterror( int socket ); +int SOCK_select( int socket, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* except, const struct SOCK_timeval* timeout ); +int SOCK_setsockopt( int socket, int level, int optname, const char* optval, int optlen ); +int SOCK_getsockopt( int socket, int level, int optname, char* optval, int* optlen ); +int SOCK_getpeername( int socket, struct SOCK_sockaddr* name, int* namelen ); +int SOCK_getsockname( int socket, struct SOCK_sockaddr* name, int* namelen ); +int SOCK_recvfrom( int s, char* buf, int len, int flags, struct SOCK_sockaddr* from, int* fromlen ); +int SOCK_sendto( int s, const char* buf, int len, int flags, const struct SOCK_sockaddr* to, int tolen ); + +//network adapter settings +HRESULT SOCK_CONFIGURATION_LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex); +HRESULT SOCK_CONFIGURATION_UpdateAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex, uint32_t updateFlags); +HRESULT SOCK_CONFIGURATION_LoadConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex); + +//--// SSL + +typedef void (*SSL_DATE_TIME_FUNC)(DATE_TIME_INFO* pdt); + +#define SSL_RESULT__WOULD_BLOCK -2 + +bool SSL_Initialize (); +bool SSL_Uninitialize(); +bool SSL_ServerInit ( int sslMode, int sslVerify, const char* certificate, int certLength, const uint8_t* privateKey, int privateKeyLength, const char* password, int passwordLength, int& sslContextHandle ); +bool SSL_ClientInit ( int sslMode, int sslVerify, const char* certificate, int certLength, const uint8_t* privateKey, int privateKeyLength, const char* password, int passwordLength, int& sslContextHandle ); +bool SSL_AddCertificateAuthority( int sslContextHandle, const char* certificate, int certLength, const char* certPassword ); +bool SSL_ExitContext( int sslContextHandle ); +int SSL_Accept ( int socket, int sslContextHandle ); +int SSL_Connect ( int socket, const char* szTargetHost, int sslContextHandle ); +int SSL_Write ( int socket, const char* Data, size_t size ); +int SSL_Read ( int socket, char* Data, size_t size ); +int SSL_CloseSocket( int socket ); +bool SSL_ParseCertificate( const char* certificate, size_t certLength, const char* password, X509CertData* certData ); +int SSL_DecodePrivateKey( const unsigned char *key, size_t keyLength, const unsigned char *password, size_t passwordLength ); +int SSL_DataAvailable( int socket ); + +//--// + + +bool HAL_SOCK_Initialize(); +bool HAL_SOCK_Uninitialize(); +void HAL_SOCK_SignalSocketThread(); +int HAL_SOCK_socket( int family, int type, int protocol ); +int HAL_SOCK_bind( int socket, const struct SOCK_sockaddr* address, int addressLen ); +int HAL_SOCK_connect(int socket, const struct SOCK_sockaddr* address, int addressLen ); +int HAL_SOCK_send(int socket, const char* buf, int len, int flags ); +int HAL_SOCK_recv(int socket, char* buf, int len, int flags ); +int HAL_SOCK_close(int socket); +int HAL_SOCK_listen( int socket, int backlog ); +int HAL_SOCK_accept( int socket, struct SOCK_sockaddr* address, int* addressLen ); +int HAL_SOCK_shutdown( int socket, int how ); +int HAL_SOCK_getaddrinfo( const char* nodename, char* servname, const struct SOCK_addrinfo* hints, struct SOCK_addrinfo** res ); +void HAL_SOCK_freeaddrinfo( struct SOCK_addrinfo* ai ); +int HAL_SOCK_ioctl( int socket, int cmd, int* data ); +int HAL_SOCK_getlasterror(); +int HAL_SOCK_getsocklasterror( int socket ); +int HAL_SOCK_select( int socket, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* except, const struct SOCK_timeval* timeout ); +int HAL_SOCK_setsockopt( int socket, int level, int optname, const char* optval, int optlen ); +int HAL_SOCK_getsockopt( int socket, int level, int optname, char* optval, int* optlen ); +int HAL_SOCK_getpeername( int socket, struct SOCK_sockaddr* name, int* namelen ); +int HAL_SOCK_getsockname( int socket, struct SOCK_sockaddr* name, int* namelen ); +int HAL_SOCK_recvfrom( int s, char* buf, int len, int flags, struct SOCK_sockaddr* from, int* fromlen ); +int HAL_SOCK_sendto( int s, const char* buf, int len, int flags, const struct SOCK_sockaddr* to, int tolen ); + +HRESULT HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex); +HRESULT HAL_SOCK_CONFIGURATION_UpdateAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex, uint32_t updateFlags); + +void* HAL_SOCK_GlobalLockContext(); +void HAL_SOCK_EventsSet(uint32_t events); + +//--// + +#endif // _DRIVERS_SOCKETS_DECL_H_ diff --git a/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Time.h b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Time.h new file mode 100644 index 00000000..597427e3 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Include/nanoPAL_Time.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOPAL_TIME_H_ +#define _NANOPAL_TIME_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// +/// Initializes PAL Time drivers, must be called before any of the Time_* PAL +/// methods could be used. +/// +HRESULT Time_Initialize ( ); +HRESULT Time_Uninitialize ( ); +void Time_SetCompare ( uint64_t compareValueTicks ); + +#ifdef __cplusplus +} +#endif + +#endif //_NANOPAL_TIME_H_ diff --git a/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.cpp b/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.cpp new file mode 100644 index 00000000..0e5c0c8b --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.cpp @@ -0,0 +1,1341 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + + +#include "LWIP_sockets.h" + +extern "C" +{ +#include "lwip\init.h" +#include "lwip\tcpip.h" +#include "lwip\dns.h" +#include "lwip\netifapi.h" +#include "lwip\Netdb.h" +#include "lwip\tcp.h" +#include "lwip\Sockets.h" +#include "lwip\dhcp.h" +#include "lwip\netif.h" +} + + +int errorCode; + +//--// + +#if defined(DEBUG) +#define DEBUG_HANDLE_SOCKET_ERROR(t,a) +// assume there is something to add in later?? +#else +#define DEBUG_HANDLE_SOCKET_ERROR(t,a) +#endif + +struct netif *netif_find_interface(int num); + +// + +// declaration of function not available in standard lwIP API +extern "C" +{ +extern uint32_t lwip_socket_get_err(int s); +} +//--// + +LWIP_SOCKETS_Driver g_LWIP_SOCKETS_Driver; + +//--// +#if LWIP_NETIF_STATUS_CALLBACK == 1 +static HAL_CONTINUATION PostAddressChangedContinuation; +#endif +#if LWIP_NETIF_LINK_CALLBACK == 1 +static HAL_CONTINUATION PostAvailabilityOnContinuation; +static HAL_CONTINUATION PostAvailabilityOffContinuation; +#endif + +void LWIP_SOCKETS_Driver::PostAddressChanged(void* arg) +{ + (void)arg; + + Network_PostEvent(NetworkEventType_AddressChanged, 0, 0); +} + +void LWIP_SOCKETS_Driver::PostAvailabilityOn(void* arg) +{ + (void)arg; + + Network_PostEvent(NetworkEventType_AvailabilityChanged, NetworkEventFlags_NetworkAvailable, 0); +} + +void LWIP_SOCKETS_Driver::PostAvailabilityOff(void* arg) +{ + (void)arg; + + Network_PostEvent(NetworkEventType_AvailabilityChanged, NetworkEventFlags_NetworkNOTAvailable, 0); +} + +#if LWIP_NETIF_LINK_CALLBACK == 1 +void LWIP_SOCKETS_Driver::Link_callback(struct netif *netif) +{ + if (netif_is_link_up(netif)) + { + if (!PostAvailabilityOnContinuation.IsLinked()) + PostAvailabilityOnContinuation.Enqueue(); + } + else + { + if (!PostAvailabilityOffContinuation.IsLinked()) + PostAvailabilityOffContinuation.Enqueue(); + } + Events_Set(SYSTEM_EVENT_FLAG_SOCKET); + Events_Set(SYSTEM_EVENT_FLAG_NETWORK); +} +#endif + +#if LWIP_NETIF_STATUS_CALLBACK == 1 +void LWIP_SOCKETS_Driver::Status_callback(struct netif *netif) +{ + if (!PostAddressChangedContinuation.IsLinked()) + PostAddressChangedContinuation.Enqueue(); + +#if !defined(BUILD_RTM) + // lcd_printf("\f\n\n\n\n\n\nLink Update: %s\n", (netif_is_up(netif) ? "UP " : "DOWN")); + // lcd_printf(" IP: %d.%d.%d.%d\n", (netif->ip_addr.addr >> 0) & 0xFF, + // (netif->ip_addr.addr >> 8) & 0xFF, + // (netif->ip_addr.addr >> 16) & 0xFF, + // (netif->ip_addr.addr >> 24) & 0xFF); + // lcd_printf(" SM: %d.%d.%d.%d\n", (netif->netmask.addr >> 0) & 0xFF, + // (netif->netmask.addr >> 8) & 0xFF, + // (netif->netmask.addr >> 16) & 0xFF, + // (netif->netmask.addr >> 24) & 0xFF); + // lcd_printf(" GW: %d.%d.%d.%d\n", (netif->gw.addr >> 0) & 0xFF, + // (netif->gw.addr >> 8) & 0xFF, + // (netif->gw.addr >> 16) & 0xFF, + // (netif->gw.addr >> 24) & 0xFF); + +//FIXME debug_printf("IP Address: %d.%d.%d.%d\n", (netif->ip_addr.u_addr.ip4.addr >> 0) & 0xFF, +// (netif->ip_addr.u_addr.ip4.addr >> 8) & 0xFF, +// (netif->ip_addr.u_addr.ip4.addr >> 16) & 0xFF, +// (netif->ip_addr.u_addr.ip4.addr >> 24) & 0xFF); +#if LWIP_DNS + if (netif->flags & NETIF_FLAG_ETHARP) + { + //ip_addr_t * dns1 = dns_getserver(0); + //ip_addr_t * dns2 = dns_getserver(1); + + // lcd_printf(" dns1: %d.%d.%d.%d\n", (dns1.addr >> 0) & 0xFF, + // (dns1.addr >> 8) & 0xFF, + // (dns1.addr >> 16) & 0xFF, + // (dns1.addr >> 24) & 0xFF); + + // lcd_printf(" dns2: %d.%d.%d.%d\n", (dns2.addr >> 0) & 0xFF, + // (dns2.addr >> 8) & 0xFF, + // (dns2.addr >> 16) & 0xFF, + // (dns2.addr >> 24) & 0xFF); + } +#endif +#endif + Events_Set(SYSTEM_EVENT_FLAG_SOCKET); + Events_Set(SYSTEM_EVENT_FLAG_NETWORK); +} +#endif + +bool LWIP_SOCKETS_Driver::Initialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + + struct netif *networkInterface; + HAL_Configuration_NetworkInterface networkConfiguration; + int interfaceNumber; + +#if LWIP_NETIF_STATUS_CALLBACK == 1 + PostAddressChangedContinuation.InitializeCallback(PostAddressChanged, NULL); +#endif +#if LWIP_NETIF_LINK_CALLBACK == 1 + PostAvailabilityOnContinuation.InitializeCallback(PostAvailabilityOn, NULL); + PostAvailabilityOffContinuation.InitializeCallback(PostAvailabilityOff, NULL); +#endif + + // create m_interfaceNumber array + int interfaceCount = g_TargetConfiguration.NetworkInterfaceConfigs->Count; + g_LWIP_SOCKETS_Driver.m_interfaces = (LWIP_DRIVER_INTERFACE_DATA*)platform_malloc(interfaceCount * sizeof(LWIP_DRIVER_INTERFACE_DATA)); + + /* Initialize the target board lwIP stack */ + nanoHAL_Network_Initialize(); + + for (int i = 0; i < g_TargetConfiguration.NetworkInterfaceConfigs->Count; i++) + { + // load network interface configuration from storage + if(!ConfigurationManager_GetConfigurationBlock((void*)&networkConfiguration, DeviceConfigurationOption_Network, i)) + { + // failed to load configuration + // FIXME output error? + // move to the next, if any + continue; + } + _ASSERTE(networkConfiguration.StartupAddressMode > 0); + + /* Bind and Open the Ethernet driver */ + Network_Interface_Bind(i); + interfaceNumber = Network_Interface_Open(i); + + if (interfaceNumber == SOCK_SOCKET_ERROR) + { + DEBUG_HANDLE_SOCKET_ERROR("Network init", FALSE); +//FIXME debug_printf("SocketError: %d\n", errorCode); + continue; + } + + g_LWIP_SOCKETS_Driver.m_interfaces[i].m_interfaceNumber = interfaceNumber; + + UpdateAdapterConfiguration(i, (UpdateOperation_Dhcp | UpdateOperation_Dns), &networkConfiguration); + + networkInterface = netif_find_interface(interfaceNumber); + + if (networkInterface) + { +#if LWIP_NETIF_LINK_CALLBACK == 1 + netif_set_link_callback(networkInterface, Link_callback); + + if (netif_is_link_up(networkInterface)) + { + Link_callback(networkInterface); + } +#endif +#if LWIP_NETIF_STATUS_CALLBACK == 1 + netif_set_status_callback(networkInterface, Status_callback); + + if (netif_is_up(networkInterface)) + { + Status_callback(networkInterface); + } +#endif + + // default debugger interface + if (0 == i) + { +#if LWIP_IPV6 + //uint8_t* addr = (uint8_t*)&networkInterface->ip_addr.u_addr.ip4.addr; +#else + //uint8_t* addr = (uint8_t*)&networkInterface->ip_addr.addr; +#endif +// lcd_printf("\f\n\n\n\n\n\n\nip address: %d.%d.%d.%d\r\n", addr[0], addr[1], addr[2], addr[3]); +// FIXME debug_printf("ip address from interface info: %d.%d.%d.%d\r\n", addr[0], addr[1], addr[2], addr[3]); + } + } + } + + return TRUE; +} + +bool LWIP_SOCKETS_Driver::Uninitialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + +#if LWIP_NETIF_STATUS_CALLBACK == 1 + PostAddressChangedContinuation.Abort(); +#endif +#if LWIP_NETIF_LINK_CALLBACK == 1 + PostAvailabilityOnContinuation.Abort(); + PostAvailabilityOffContinuation.Abort(); +#endif + + for(int i=0; iCount; i++) + { + Network_Interface_Close(i); + } + +//FIXME tcpip_shutdown(); +// tcpip_shutdown is MS method added to lwip tcpip.c + + return TRUE; +} + +extern void debug_printf( const char* format, ... ); + +SOCK_SOCKET LWIP_SOCKETS_Driver::Socket(int family, int type, int protocol) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + switch(protocol) + { + case SOCK_IPPROTO_TCP: + protocol = IPPROTO_TCP; + break; + case SOCK_IPPROTO_UDP: + protocol = IPPROTO_UDP; + break; + case SOCK_IPPROTO_ICMP: + protocol = IP_PROTO_ICMP; + break; + + case SOCK_IPPROTO_IGMP: + protocol = IP_PROTO_IGMP; + break; + } + + return lwip_socket(family, type, protocol); +} + +int LWIP_SOCKETS_Driver::Bind(SOCK_SOCKET socket, const SOCK_sockaddr* address, int addressLen) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + sockaddr_in addr; + + SOCK_SOCKADDR_TO_SOCKADDR(address, addr, &addressLen); + + return lwip_bind(socket, (sockaddr*)&addr, addressLen); +} + +int LWIP_SOCKETS_Driver::Connect(SOCK_SOCKET socket, const SOCK_sockaddr* address, int addressLen) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + sockaddr_in addr; + + SOCK_SOCKADDR_TO_SOCKADDR(address, addr, &addressLen); + + return lwip_connect(socket, (sockaddr*)&addr, addressLen); +} + +int LWIP_SOCKETS_Driver::Send(SOCK_SOCKET socket, const char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + return lwip_send(socket, (const void*)buf, len, flags); +} + + +int LWIP_SOCKETS_Driver::Recv(SOCK_SOCKET socket, char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int nativeFlag; + + switch (flags) + { + case SOCKET_READ_PEEK_OPTION: + nativeFlag = MSG_PEEK; + break; + default: + nativeFlag = flags; + break; + } + + return lwip_recv(socket,(void*)buf, len, nativeFlag); +} + +int LWIP_SOCKETS_Driver::Close(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_NETWORK(); + +#ifdef PLATFORM_ESP32 + // We have to call lwip_close_r() method otherwise the socket doesn't get freed up and we run out of sockets. + // We could also call the posix closesocket() which should work for all platforms and change all other methods to + // call the posix version to be consistent.(TODO) + return lwip_close_r(socket); +#else + return lwip_close(socket); +#endif +} + +int LWIP_SOCKETS_Driver::Listen(SOCK_SOCKET socket, int backlog) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + return lwip_listen(socket, backlog); +} + +SOCK_SOCKET LWIP_SOCKETS_Driver::Accept(SOCK_SOCKET socket, SOCK_sockaddr* address, int* addressLen) +{ + NATIVE_PROFILE_PAL_NETWORK(); + SOCK_SOCKET ret; + + sockaddr_in addr; + + if (address) + { + SOCK_SOCKADDR_TO_SOCKADDR(address, addr, addressLen); + } + + ret = lwip_accept(socket, address?(sockaddr*)&addr:NULL, (u32_t*)addressLen); + + if(address) + { + SOCKADDR_TO_SOCK_SOCKADDR(address, addr, addressLen); + } + + return ret; +} + +int LWIP_SOCKETS_Driver::Shutdown( SOCK_SOCKET socket, int how ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + return lwip_shutdown (socket, how); +} + +int LWIP_SOCKETS_Driver::GetAddrInfo(const char* nodename, char* servname, const SOCK_addrinfo* hints, SOCK_addrinfo** res) +{ + #if LWIP_DNS + NATIVE_PROFILE_PAL_NETWORK(); + + SOCK_addrinfo *ai; + void *dummyPtr; + SOCK_sockaddr_in *sa = NULL; + int total_size = sizeof(SOCK_addrinfo) + sizeof(SOCK_sockaddr_in); + struct addrinfo *lwipAddrinfo = NULL; + + if(res == NULL) return SOCK_SOCKET_ERROR; + + *res = NULL; + + // if the nodename == "" then return the IP address of this device + if(nodename[0] == 0 && servname == NULL) + { + struct netif *networkInterface = netif_find_interface(g_LWIP_SOCKETS_Driver.m_interfaces[0].m_interfaceNumber); + + if(networkInterface == NULL) return -1; + + ai = (SOCK_addrinfo*)mem_malloc(total_size); + if (ai == NULL) + { + return -1; + } + memset(ai, 0, total_size); + sa = (SOCK_sockaddr_in*)((u8_t*)ai + sizeof(SOCK_addrinfo)); + + /* set up sockaddr */ + #if LWIP_IPV6 + sa->sin_addr.S_un.S_addr = networkInterface->ip_addr.u_addr.ip4.addr; + #else + sa->sin_addr.S_un.S_addr = networkInterface->ip_addr.addr; + #endif + + sa->sin_family = AF_INET; + sa->sin_port = 0; + + /* set up addrinfo */ + ai->ai_family = AF_INET; + if (hints != NULL) + { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + + // need this to keep the compiler happy about the cast to SOCK_sockaddr + // which is intended and perfectly safe + dummyPtr = sa; + + ai->ai_addrlen = sizeof(SOCK_sockaddr_in); + ai->ai_addr = (SOCK_sockaddr*)dummyPtr; + + *res = ai; + + return 0; + } + + int err = lwip_getaddrinfo(nodename, servname, (addrinfo*)hints, &lwipAddrinfo); + + if(err == 0) + { + /// + /// Marshal addrinfo data + /// + struct sockaddr_in* lwip_sockaddr_in; + + ai = (SOCK_addrinfo*)mem_malloc(total_size); + if (ai == NULL) + { + lwip_freeaddrinfo(lwipAddrinfo); + return -1; + } + memset(ai, 0, total_size); + + lwip_sockaddr_in = ((struct sockaddr_in*)lwipAddrinfo->ai_addr); + + sa = (SOCK_sockaddr_in*)((u8_t*)ai + sizeof(SOCK_addrinfo)); + /* set up sockaddr */ + sa->sin_addr.S_un.S_addr = lwip_sockaddr_in->sin_addr.s_addr; + sa->sin_family = lwip_sockaddr_in->sin_family; + sa->sin_port = lwip_sockaddr_in->sin_port; + + /* set up addrinfo */ + ai->ai_family = lwipAddrinfo->ai_family; + if (hints != NULL) + { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + + // need this to keep the compiler happy about the cast to SOCK_sockaddr + // which is intended and perfectly safe + dummyPtr = sa; + + ai->ai_addrlen = sizeof(SOCK_sockaddr_in); + ai->ai_addr = (SOCK_sockaddr*)dummyPtr; + + *res = ai; + + // free marshalled addrinfo + lwip_freeaddrinfo(lwipAddrinfo); + + return 0; + } + else + { + // map DNS error with socket errors + switch(err) + { + case HOST_NOT_FOUND: + errorCode = SOCK_HOST_NOT_FOUND; + break; + + default: + errorCode = SOCK_NO_RECOVERY; + } + + } + + return SOCK_SOCKET_ERROR; + + #else + return SOCK_SOCKET_ERROR; + #endif +} + +void LWIP_SOCKETS_Driver::FreeAddrInfo( SOCK_addrinfo* ai ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + SOCK_addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + mem_free(ai); + ai = next; + } +} + +int LWIP_SOCKETS_Driver::Ioctl( SOCK_SOCKET socket, int cmd, int* data ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + return lwip_ioctl(socket,cmd,data); +} + +int LWIP_SOCKETS_Driver::GetLastError() +{ + NATIVE_PROFILE_PAL_NETWORK(); + + return GetNativeError(errorCode); +} + +int LWIP_SOCKETS_Driver::GetSockLastError(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + // get last error number from socket + errorCode = lwip_socket_get_err(socket); + + return GetNativeError(errorCode); +} + +static int MARSHAL_SOCK_FDSET_TO_FDSET(SOCK_fd_set *sf, fd_set *f) +{ + if(f != NULL && sf != NULL) + { + FD_ZERO(f); + + for(unsigned int i=0; i < sf->fd_count; i++) + { + FD_SET(sf->fd_array[i], f); + } + return sf->fd_count; + } + + return 0; +} + +static void MARSHAL_FDSET_TO_SOCK_FDSET(SOCK_fd_set *sf, fd_set *f) +{ + if(sf != NULL && f != NULL) + { + int cnt = sf->fd_count; + sf->fd_count = 0; + for(int i=0; ifd_array[i],f)) + { + sf->fd_array[sf->fd_count] = sf->fd_array[i]; + sf->fd_count++; + } + } + } +} + + +int LWIP_SOCKETS_Driver::Select( int nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* exceptfds, const SOCK_timeval* timeout ) +{ + (void)nfds; + + NATIVE_PROFILE_PAL_NETWORK(); + int ret = 0; + + fd_set read; + fd_set write; + fd_set excpt; + + fd_set* pR = (readfds != NULL) ? &read : NULL; + fd_set* pW = (writefds != NULL) ? &write : NULL; + fd_set* pE = (exceptfds != NULL) ? &excpt : NULL; + + // If the network goes down then we should alert any pending socket actions + if(exceptfds != NULL && exceptfds->fd_count > 0) + { + struct netif *networkInterface = netif_find_interface(g_LWIP_SOCKETS_Driver.m_interfaces[0].m_interfaceNumber); + + if(networkInterface != NULL) + { + if(!netif_is_up(networkInterface)) + { + if(readfds != NULL) readfds->fd_count = 0; + if(writefds != NULL) writefds->fd_count = 0; + + errorCode = ENETDOWN; + + return exceptfds->fd_count; + } + } + } + + MARSHAL_SOCK_FDSET_TO_FDSET(readfds , pR); + MARSHAL_SOCK_FDSET_TO_FDSET(writefds , pW); + MARSHAL_SOCK_FDSET_TO_FDSET(exceptfds, pE); + + int max_sd = MEMP_NUM_NETCONN; + #if defined(PLATFORM_ESP32) + max_sd = LWIP_SOCKET_OFFSET + MEMP_NUM_NETCONN; + #endif + + // developer note: + // our declaration of SOCK_timeval is dependent of "long" type which is platform dependent + // so it's not safe to cast it to "timeval" + timeval timeoutCopy; + timeoutCopy.tv_sec = timeout->tv_sec; + timeoutCopy.tv_usec = timeout->tv_usec; + + ret = select(max_sd, pR, pW, pE, &timeoutCopy); + + MARSHAL_FDSET_TO_SOCK_FDSET(readfds , pR); + MARSHAL_FDSET_TO_SOCK_FDSET(writefds , pW); + MARSHAL_FDSET_TO_SOCK_FDSET(exceptfds, pE); + + return ret; +} + +int LWIP_SOCKETS_Driver::SetSockOpt( SOCK_SOCKET socket, int level, int optname, const char* optval, int optlen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int nativeLevel; + int nativeOptionName; + int nativeIntValue; + char *pNativeOptionValue = (char*)optval; + struct linger lopt = {0,0}; + + switch(level) + { + case SOCK_IPPROTO_IP: + nativeLevel = IPPROTO_IP; + nativeOptionName = GetNativeIPOption(optname); + break; + case SOCK_IPPROTO_TCP: + nativeLevel = IPPROTO_TCP; + nativeOptionName = GetNativeTcpOption(optname); + break; + case SOCK_IPPROTO_UDP: + case SOCK_IPPROTO_ICMP: + case SOCK_IPPROTO_IGMP: + case SOCK_IPPROTO_IPV4: + case SOCK_SOL_SOCKET: + nativeLevel = SOL_SOCKET; + nativeOptionName = GetNativeSockOption(optname); + + switch(optname) + { + // If linger value negative then linger off + // otherwise enabled and linger value is number of seconds + case SOCK_SOCKO_LINGER: + { + int lingerValue = *(int*)optval; + if ( lingerValue >= 0 ) + { + lopt.l_onoff = 1; + lopt.l_linger = abs(lingerValue); + } + pNativeOptionValue = (char*)&lopt; + optlen = sizeof(lopt); + } + break; + + case SOCK_SOCKO_DONTLINGER: + case SOCK_SOCKO_EXCLUSIVEADDRESSUSE: + nativeIntValue = !*(int*)optval; + pNativeOptionValue = (char*)&nativeIntValue; + break; + default: + break; + } + break; + default: + nativeLevel = 0; + nativeOptionName = 0; + break; + } + + return lwip_setsockopt(socket, nativeLevel, nativeOptionName, pNativeOptionValue, optlen); +} + +int LWIP_SOCKETS_Driver::GetSockOpt( SOCK_SOCKET socket, int level, int optname, char* optval, int* optlen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int nativeLevel; + int nativeOptionName; + char* pNativeOptval = optval; + int ret; + + switch(level) + { + case SOCK_IPPROTO_IP: + nativeLevel = IPPROTO_IP; + nativeOptionName = GetNativeIPOption(optname); + break; + case SOCK_IPPROTO_TCP: + nativeLevel = IPPROTO_TCP; + nativeOptionName = GetNativeTcpOption(optname); + break; + case SOCK_IPPROTO_UDP: + case SOCK_IPPROTO_ICMP: + case SOCK_IPPROTO_IGMP: + case SOCK_IPPROTO_IPV4: + case SOCK_SOL_SOCKET: + nativeLevel = SOL_SOCKET; + nativeOptionName = GetNativeSockOption(optname); + break; + default: + nativeLevel = level; + nativeOptionName = optname; + break; + } + + ret = lwip_getsockopt(socket, nativeLevel, nativeOptionName, pNativeOptval, (u32_t*)optlen); + + if(ret == 0) + { + switch(level) + { + case SOCK_SOL_SOCKET: + switch(optname) + { + case SOCK_SOCKO_EXCLUSIVEADDRESSUSE: + case SOCK_SOCKO_DONTLINGER: + *optval = !(*(int*)optval != 0); + break; + + case SOCK_SOCKO_ACCEPTCONNECTION: + case SOCK_SOCKO_BROADCAST: + case SOCK_SOCKO_KEEPALIVE: + *optval = (*(int*)optval != 0); + break; + } + break; + } + } + + return ret; +} + +int LWIP_SOCKETS_Driver::GetPeerName( SOCK_SOCKET socket, SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int ret; + + sockaddr_in addr; + + SOCK_SOCKADDR_TO_SOCKADDR(name, addr, namelen); + + ret = lwip_getpeername(socket, (sockaddr*)&addr, (u32_t*)namelen); + + SOCKADDR_TO_SOCK_SOCKADDR(name, addr, namelen); + + return ret; +} + +int LWIP_SOCKETS_Driver::GetSockName( SOCK_SOCKET socket, SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int ret; + + sockaddr_in addr; + + SOCK_SOCKADDR_TO_SOCKADDR(name, addr, namelen); + + ret = lwip_getsockname(socket, (sockaddr*)&addr, (u32_t*)namelen); + + SOCKADDR_TO_SOCK_SOCKADDR(name, addr, namelen); + + return ret; +} + +int LWIP_SOCKETS_Driver::RecvFrom( SOCK_SOCKET socket, char* buf, int len, int flags, SOCK_sockaddr* from, int* fromlen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + sockaddr_in addr; + sockaddr *pFrom = NULL; + int ret; + + if(from) + { + SOCK_SOCKADDR_TO_SOCKADDR(from, addr, fromlen); + pFrom = (sockaddr*)&addr; + } + + ret = lwip_recvfrom(socket, buf, len, flags, pFrom, (u32_t*)fromlen); + + if(from && ret != SOCK_SOCKET_ERROR) + { + SOCKADDR_TO_SOCK_SOCKADDR(from, addr, fromlen); + } + + return ret; +} + +int LWIP_SOCKETS_Driver::SendTo( SOCK_SOCKET socket, const char* buf, int len, int flags, const SOCK_sockaddr* to, int tolen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + sockaddr_in addr; + + SOCK_SOCKADDR_TO_SOCKADDR(to, addr, &tolen); + + return lwip_sendto(socket, buf, len, flags, (sockaddr*)&addr, (u32_t)tolen); +} + +HRESULT LWIP_SOCKETS_Driver::LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + if(config->StartupAddressMode == AddressMode_DHCP) + { + struct netif *networkInterface; + + if ((networkInterface = netif_find_interface(g_LWIP_SOCKETS_Driver.m_interfaces[interfaceIndex].m_interfaceNumber))) + { +#if LWIP_IPV6 + config->IPv4Address = networkInterface->ip_addr.u_addr.ip4.addr; + config->IPv4NetMask = networkInterface->netmask.u_addr.ip4.addr; + config->IPv4GatewayAddress = networkInterface->gw.u_addr.ip4.addr; + + // FIXME IPV6 + // config->IPv6Address = networkInterface->ip_addr.u_addr.ip6.addr; + // config->IPv6NetMask = networkInterface->netmask.u_addr.ip6.addr; + // config->IPv6GatewayAddress = networkInterface->gw.u_addr.ip6.addr; +#else + config->IPv4Address = networkInterface->ip_addr.addr; + config->IPv4NetMask = networkInterface->netmask.addr; + config->IPv4GatewayAddress = networkInterface->gw.addr; +#endif + +#if LWIP_DNS +#if LWIP_IPV6 +#if LWIP_VERSION_MAJOR == 2 + +#if defined(PLATFORM_ESP32) + // ESP32 return ip_addr_t instead of ip_addr_t * on statndard lwip + config->IPv4DNSAddress1 = dns_getserver(0).u_addr.ip4.addr; + config->IPv4DNSAddress2 = dns_getserver(1).u_addr.ip4.addr; +#else + config->IPv4DNSAddress1 = dns_getserver(0)->u_addr.ip4.addr; + config->IPv4DNSAddress2 = dns_getserver(1)->u_addr.ip4.addr; +#endif + // FIXME IPV6 + // config->IPv6DNSAddress1 = dns_getserver(0)->u_addr.ip6.addr; + // config->IPv6DNSAddress2 = dns_getserver(1)->u_addr.ip6.addr; +#else + config->IPv4DNSAddress1 = dns_getserver(0).u_addr.ip4.addr; + config->IPv4DNSAddress2 = dns_getserver(1).u_addr.ip4.addr; + + // FIXME IPV6 + // config->IPv6DNSAddress1 = dns_getserver(0).u_addr.ip6.addr; + // config->IPv6DNSAddress2 = dns_getserver(1).u_addr.ip6.addr; +#endif +#else +#if LWIP_VERSION_MAJOR == 2 + config->IPv4DNSAddress1 = dns_getserver(0)->addr; + config->IPv4DNSAddress2 = dns_getserver(1)->addr; +#else + config->IPv4DNSAddress1 = dns_getserver(0).addr; + config->IPv4DNSAddress2 = dns_getserver(1).addr; +#endif + +#endif +#endif + } + else + { + config->IPv4Address = 0; + config->IPv4NetMask = 0; + config->IPv4GatewayAddress = 0; + } + } + + return S_OK; +} + +struct dhcp_client_id +{ + uint8_t code; + uint8_t length; + uint8_t type; + uint8_t clientId[6]; +}; + +HRESULT LWIP_SOCKETS_Driver::UpdateAdapterConfiguration( uint32_t interfaceIndex, uint32_t updateFlags, HAL_Configuration_NetworkInterface* config ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + bool enableDHCP = (config->StartupAddressMode == AddressMode_DHCP); + + struct netif *networkInterface = netif_find_interface(g_LWIP_SOCKETS_Driver.m_interfaces[interfaceIndex].m_interfaceNumber); + if (NULL == networkInterface) + { + return CLR_E_FAIL; + } + +#if LWIP_DNS + // when using DHCP do not use the static settings + if(0 != (updateFlags & UpdateOperation_Dns)) + { + // FIXME IPV6 + if(config->AutomaticDNS == 0) + { + // user defined DNS addresses + if(config->IPv4DNSAddress1 != 0) + { + // need to convert this first + ip_addr_t dnsServer; + ip_addr_set_ip4_u32(&dnsServer, config->IPv4DNSAddress1); + + dns_setserver(0, &dnsServer); + } + if(config->IPv4DNSAddress2 != 0) + { + // need to convert this first + ip_addr_t dnsServer; + ip_addr_set_ip4_u32(&dnsServer, config->IPv4DNSAddress2); + + dns_setserver(1, &dnsServer); + } + } + } +#endif + +#if LWIP_DHCP + if(0 != (updateFlags & UpdateOperation_Dhcp)) + { + if(enableDHCP) + { + // need to start DHCP + if(ERR_OK != dhcp_start(networkInterface)) + { + return CLR_E_FAIL; + } + } + else + { + // stop DHCP + dhcp_stop(networkInterface); + + // need to convert these first + ip_addr_t ipAddress, mask, gateway; + ip_addr_set_ip4_u32(&ipAddress, config->IPv4Address); + ip_addr_set_ip4_u32(&mask, config->IPv4NetMask); + ip_addr_set_ip4_u32(&gateway, config->IPv4GatewayAddress); + + // set interface with our static IP configs + netif_set_addr( + networkInterface, + (const ip4_addr_t*)&ipAddress, + (const ip4_addr_t*)&mask, + (const ip4_addr_t*)&gateway); + + // we should be polite and let the DHCP server that we are now using a static IP + dhcp_inform(networkInterface); + } + } + + if(enableDHCP) + { + // developer note: on legacy source there was a hack of trying to renew before release and + // also setting the release flag in managed call when the intent was to renew only + // nowadays lwIP seems to be doing what is told, so no need for these hacks anymore + // also it's NOT possible to renew & release on the same pass, so adding an extra else-if for that + // just in case it's request from the managed code + + if(0 != (updateFlags & UpdateOperation_DhcpRelease)) + { + dhcp_release(networkInterface); + } + else if(0 != (updateFlags & UpdateOperation_DhcpRenew)) + { + dhcp_renew(networkInterface); + } + else if(0 != (updateFlags & (UpdateOperation_DhcpRelease | UpdateOperation_DhcpRenew)) ) + { + return CLR_E_INVALID_PARAMETER; + } + } +#endif + + if(0 != (updateFlags & UpdateOperation_Mac)) + { + memcpy(networkInterface->hwaddr, config->MacAddress, NETIF_MAX_HWADDR_LEN); + networkInterface->hwaddr_len = NETIF_MAX_HWADDR_LEN; + + // mac address requires stack re-init + Network_Interface_Close(interfaceIndex); + g_LWIP_SOCKETS_Driver.m_interfaces[interfaceIndex].m_interfaceNumber = Network_Interface_Open(interfaceIndex); + } + + return S_OK; +} + +int LWIP_SOCKETS_Driver::GetNativeTcpOption (int optname) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int nativeOptionName = 0; + + switch(optname) + { + case SOCK_TCP_NODELAY: + nativeOptionName = TCP_NODELAY; + break; + + case SOCK_SOCKO_KEEPALIVE: + nativeOptionName = TCP_KEEPALIVE; + break; + + // allow the C# user to specify LWIP options that our managed enum + // doesn't support + default: + nativeOptionName = optname; + break; + } + return nativeOptionName; +} + +int LWIP_SOCKETS_Driver::GetNativeSockOption (int optname) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int nativeOptionName = 0; + + switch(optname) + { + case SOCK_SOCKO_DONTLINGER: + case SOCK_SOCKO_LINGER: + nativeOptionName = SO_LINGER; + break; + case SOCK_SOCKO_SENDTIMEOUT: + nativeOptionName = SO_SNDTIMEO; + break; + case SOCK_SOCKO_RECEIVETIMEOUT: + nativeOptionName = SO_RCVTIMEO; + break; + case SOCK_SOCKO_EXCLUSIVEADDRESSUSE: + case SOCK_SOCKO_REUSEADDRESS: + nativeOptionName = SO_REUSEADDR; + break; + case SOCK_SOCKO_KEEPALIVE: + nativeOptionName = SO_KEEPALIVE; + break; + case SOCK_SOCKO_ERROR: + nativeOptionName = SO_ERROR; + break; + case SOCK_SOCKO_BROADCAST: + nativeOptionName = SO_BROADCAST; + break; + case SOCK_SOCKO_RECEIVEBUFFER: + nativeOptionName = SO_RCVBUF; + break; + case SOCK_SOCKO_SENDBUFFER: + nativeOptionName = SO_SNDBUF; + break; + case SOCK_SOCKO_ACCEPTCONNECTION: + nativeOptionName = SO_ACCEPTCONN; + break; + case SOCK_SOCKO_USELOOPBACK: + nativeOptionName = SO_USELOOPBACK; + break; + case SOCK_SOCKO_DONTROUTE: + nativeOptionName = SO_DONTROUTE; + break; + case SOCK_SOCKO_OUTOFBANDINLINE: + nativeOptionName = SO_OOBINLINE; + break; + + case SOCK_SOCKO_DEBUG: + nativeOptionName = SO_DEBUG; + break; + + case SOCK_SOCKO_SENDLOWWATER: + nativeOptionName = SO_SNDLOWAT; + break; + + case SOCK_SOCKO_RECEIVELOWWATER: + nativeOptionName = SO_RCVLOWAT; + break; + +// case SOCK_SOCKO_MAXCONNECTIONS: //don't support + case SOCK_SOCKO_UPDATE_ACCEPT_CTX: + case SOCK_SOCKO_UPDATE_CONNECT_CTX: + nativeOptionName = 0; + break; + + // allow the C# user to specify LWIP options that our managed enum + // doesn't support + default: + nativeOptionName = optname; + break; + + } + + return nativeOptionName; +} + +int LWIP_SOCKETS_Driver::GetNativeIPOption (int optname) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int nativeOptionName = 0; + + switch(optname) + { + case SOCK_IPO_TTL: + nativeOptionName = IP_TTL; + break; + case SOCK_IPO_TOS: + nativeOptionName = IP_TOS; + break; +#if LWIP_IGMP + case SOCK_IPO_MULTICAST_IF: + nativeOptionName = IP_MULTICAST_IF; + break; + case SOCK_IPO_MULTICAST_TTL: + nativeOptionName = IP_MULTICAST_TTL; + break; + case SOCK_IPO_MULTICAST_LOOP: + nativeOptionName = IP_MULTICAST_LOOP; + break; + case SOCK_IPO_ADD_MEMBERSHIP: + nativeOptionName = IP_ADD_MEMBERSHIP; + break; + case SOCK_IPO_DROP_MEMBERSHIP: + nativeOptionName = IP_DROP_MEMBERSHIP; + break; +#else + case SOCK_IPO_MULTICAST_IF: + case SOCK_IPO_MULTICAST_TTL: + case SOCK_IPO_MULTICAST_LOOP: + case SOCK_IPO_ADD_MEMBERSHIP: + case SOCK_IPO_DROP_MEMBERSHIP: +#endif + case SOCK_IPO_ADD_SOURCE_MEMBERSHIP: + case SOCK_IPO_DROP_SOURCE_MEMBERSHIP: + case SOCK_IPO_OPTIONS: + case SOCK_IPO_HDRINCL: + case SOCK_IPO_IP_DONTFRAGMENT: + case SOCK_IPO_BLOCK_SOURCE: + case SOCK_IPO_UBLOCK_SOURCE: + case SOCK_IPO_PACKET_INFO: + nativeOptionName = 0; + break; + + // allow the C# user to specify LWIP options that our managed enum + // doesn't support + default: + nativeOptionName = optname; + break; + } + + return nativeOptionName; +} + +int LWIP_SOCKETS_Driver::GetNativeError ( int error ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + int ret; + + switch(error) + { + case EINTR: + ret = SOCK_EINTR; + break; + + case EACCES: + ret = SOCK_EACCES; + break; + + case EFAULT: + ret = SOCK_EFAULT; + break; + + case EINVAL: + ret = SOCK_EINVAL; + break; + + case EMFILE: + ret = SOCK_EMFILE; + break; + + case EAGAIN: + case EBUSY: + /* case EWOULDBLOCK: same as EINPROGRESS */ + case EINPROGRESS: + ret = SOCK_EWOULDBLOCK; + break; + + case EALREADY: + ret = SOCK_EALREADY; + break; + + case ENOTSOCK: + ret = SOCK_ENOTSOCK; + break; + + case EDESTADDRREQ: + ret = SOCK_EDESTADDRREQ; + break; + + case EMSGSIZE: + ret = SOCK_EMSGSIZE; + break; + + case EPROTOTYPE: + ret = SOCK_EPROTOTYPE; + break; + + case ENOPROTOOPT: + ret = SOCK_ENOPROTOOPT; + break; + + case EPROTONOSUPPORT: + ret = SOCK_EPROTONOSUPPORT; + break; +// TODO nanoframework check why missing + // case ESOCKTNOSUPPORT: + // ret = SOCK_ESOCKTNOSUPPORT; + // break; + + case EPFNOSUPPORT: + ret = SOCK_EPFNOSUPPORT; + break; + + case EAFNOSUPPORT: + ret = SOCK_EAFNOSUPPORT; + break; + + case EADDRINUSE: + ret = SOCK_EADDRINUSE; + break; + + case EADDRNOTAVAIL: + ret = SOCK_EADDRNOTAVAIL; + break; + + case ENETDOWN: + ret = SOCK_ENETDOWN; + break; + + case ENETUNREACH: + ret = SOCK_ENETUNREACH; + break; + + case ENETRESET: + ret = SOCK_ENETRESET; + break; + + case ECONNABORTED: + ret = SOCK_ECONNABORTED; + break; + + case ECONNRESET: + ret = SOCK_ECONNRESET; + break; + + case ENOBUFS: + case ENOMEM: + ret = SOCK_ENOBUFS; + break; + + case EISCONN: + ret = SOCK_EISCONN; + break; + + case ENOTCONN: + ret = SOCK_EISCONN; + break; + +#if !defined(__GNUC__) // same as ENOTSOCK for GCC + case ESHUTDOWN: + ret = SOCK_ESHUTDOWN; + break; +#endif + + case ETIMEDOUT: + ret = SOCK_ETIMEDOUT; + break; + + case ECONNREFUSED: + ret = SOCK_ECONNREFUSED; + break; + + case EHOSTDOWN: + ret = SOCK_EHOSTDOWN; + break; + + case EHOSTUNREACH: + ret = SOCK_EHOSTUNREACH; + break; + + case ENODATA: + ret = SOCK_NO_DATA; + break; + + default: + ret = error; + break; + } + + return (ret); +} + +/** + * Find a network interface by searching for its number + * Similar to LWIP's netif_find(char *name) + */ +struct netif *netif_find_interface(int num) +{ + struct netif *networkInterface; + + for (networkInterface = netif_list; networkInterface != NULL; networkInterface = networkInterface->next) + { + if (num == networkInterface->num) + { + return networkInterface; + } + } + return NULL; +} diff --git a/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.h b/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.h new file mode 100644 index 00000000..18bc841c --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _LWIP_SOCKETS_H_ +#define _LWIP_SOCKETS_H_ + +#include +#include + +#define NATIVE_PROFILE_PAL_NETWORK() + +////////////////////////////////////////////////////////////////////////////// +// SOCKET driver +// + +struct LWIP_DRIVER_INTERFACE_DATA +{ + int m_interfaceNumber; +}; + +#define SOCK_SOCKADDR_TO_SOCKADDR(ssa, sa, addrLen) \ + sa.sin_len = (u8_t)sizeof(sa); \ + sa.sin_family = (u8_t)((SOCK_sockaddr_in*)ssa)->sin_family; \ + sa.sin_port = ((SOCK_sockaddr_in*)ssa)->sin_port; \ + sa.sin_addr.s_addr = ((SOCK_sockaddr_in*)ssa)->sin_addr.S_un.S_addr; \ + memcpy(sa.sin_zero, ((SOCK_sockaddr_in*)ssa)->sin_zero, sizeof(sa.sin_zero)); \ + *addrLen = sizeof(sa) + +#define SOCKADDR_TO_SOCK_SOCKADDR(ssa, sa, addrLen) \ + ((SOCK_sockaddr_in*)ssa)->sin_port = sa.sin_port; \ + ((SOCK_sockaddr_in*)ssa)->sin_addr.S_un.S_addr = sa.sin_addr.s_addr; \ + ((SOCK_sockaddr_in*)ssa)->sin_family = sa.sin_family; \ + memcpy(((SOCK_sockaddr_in*)ssa)->sin_zero, sa.sin_zero, sizeof(((SOCK_sockaddr_in*)ssa)->sin_zero)); \ + *addrLen = sizeof(SOCK_sockaddr_in) + + +struct LWIP_SOCKETS_Driver +{ + static bool Initialize(); + + static bool Uninitialize(); + + static SOCK_SOCKET Socket( int family, int type, int protocol ); + + static int Bind( SOCK_SOCKET socket, const SOCK_sockaddr* address, int addressLen ); + + static int Connect(SOCK_SOCKET socket, const SOCK_sockaddr* address, int addressLen); + + static int Send(SOCK_SOCKET socket, const char* buf, int len, int flags); + + static int Recv(SOCK_SOCKET socket, char* buf, int len, int flags); + + static int Close(SOCK_SOCKET socket); + + static int Listen(SOCK_SOCKET socket, int backlog ); + + static SOCK_SOCKET Accept(SOCK_SOCKET socket, SOCK_sockaddr* address, int* addressLen ); + + + static int Shutdown(SOCK_SOCKET socket, int how ); + + static int GetAddrInfo(const char* nodename, + char* servname, + const SOCK_addrinfo* hints, + SOCK_addrinfo** res ); + + static void FreeAddrInfo(SOCK_addrinfo* ai ); + + static int Ioctl(SOCK_SOCKET socket, int cmd, int* data ); + + static int GetLastError(); + + static int GetSockLastError(SOCK_SOCKET socket); + + static int GetNativeTcpOption (int optname); + + static int GetNativeSockOption (int optname); + + static int GetNativeError( int error ); + + static int GetNativeIPOption (int optname); + + static int Select(int nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* exceptfds, const SOCK_timeval* timeout ); + + static int SetSockOpt(SOCK_SOCKET socket, int level, int optname, const char* optval, int optlen ); + + static int GetSockOpt(SOCK_SOCKET socket, int level, int optname, char* optval, int* optlen ); + + static int GetPeerName(SOCK_SOCKET socket, SOCK_sockaddr* name, int* namelen ); + + static int GetSockName(SOCK_SOCKET socket, SOCK_sockaddr* name, int* namelen ); + + static int RecvFrom(SOCK_SOCKET s, char* buf, int len, int flags, SOCK_sockaddr* from, int* fromlen ); + + static int SendTo(SOCK_SOCKET s, const char* buf, int len, int flags, const SOCK_sockaddr* to, int tolen ); + + static HRESULT LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex); + + static HRESULT UpdateAdapterConfiguration( uint32_t interfaceIndex, uint32_t updateFlags, HAL_Configuration_NetworkInterface* config ); + + static HRESULT LoadWirelessConfiguration( uint32_t interfaceIndex, HAL_Configuration_Wireless80211* wirelessConfig ); + + +private: + static void Status_callback(struct netif *netif); + + static void Link_callback(struct netif *netif); + + static void PostAddressChanged(void* arg); + + static void PostAvailabilityOn(void* arg); + + static void PostAvailabilityOff(void* arg); + + LWIP_DRIVER_INTERFACE_DATA* m_interfaces; +}; + +// +// SOCKET driver +///////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _LWIP_SOCKETS_H_ 1 + diff --git a/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets_functions.cpp b/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets_functions.cpp new file mode 100644 index 00000000..e1e73178 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Lwip/lwIP_Sockets_functions.cpp @@ -0,0 +1,152 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "LWIP_Sockets.h" + + +bool HAL_SOCK_Initialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Initialize(); +} + +bool HAL_SOCK_Uninitialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Uninitialize(); +} + +SOCK_SOCKET HAL_SOCK_socket( int family, int type, int protocol ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Socket( family, type, protocol ); +} +int HAL_SOCK_bind( SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int addressLen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Bind( socket, address, addressLen ); +} +int HAL_SOCK_connect(SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int addressLen) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Connect(socket, address, addressLen); +} +int HAL_SOCK_send(SOCK_SOCKET socket, const char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Send(socket, buf, len, flags); +} +int HAL_SOCK_recv(SOCK_SOCKET socket, char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Recv(socket, buf, len, flags); +} +int HAL_SOCK_close(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Close(socket); +} +int HAL_SOCK_listen( SOCK_SOCKET socket, int backlog ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Listen( socket, backlog ); +} +SOCK_SOCKET HAL_SOCK_accept( SOCK_SOCKET socket, struct SOCK_sockaddr* address, int* addressLen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Accept( socket, address, addressLen ); +} +int HAL_SOCK_shutdown( SOCK_SOCKET socket, int how ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Shutdown( socket, how ); +} +int HAL_SOCK_getaddrinfo( const char* nodename, char* servname, const struct SOCK_addrinfo* hints, struct SOCK_addrinfo** res ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::GetAddrInfo( nodename, servname, hints, res ); +} +void HAL_SOCK_freeaddrinfo( struct SOCK_addrinfo* ai ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + LWIP_SOCKETS_Driver::FreeAddrInfo( ai ); +} +int HAL_SOCK_ioctl( SOCK_SOCKET socket, int cmd, int* data ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Ioctl( socket, cmd, data ); +} +int HAL_SOCK_getlasterror() +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::GetLastError(); +} +int HAL_SOCK_getsocklasterror(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::GetSockLastError(socket); +} +int HAL_SOCK_select( int nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* except, const struct SOCK_timeval* timeout ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::Select( nfds, readfds, writefds, except, timeout ); +} +int HAL_SOCK_setsockopt( SOCK_SOCKET socket, int level, int optname, const char* optval, int optlen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::SetSockOpt( socket, level, optname, optval, optlen ); +} +int HAL_SOCK_getsockopt( SOCK_SOCKET socket, int level, int optname, char* optval, int* optlen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::GetSockOpt( socket, level, optname, optval, optlen ); +} +int HAL_SOCK_getpeername( SOCK_SOCKET socket, struct SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::GetPeerName( socket, name, namelen ); +} +int HAL_SOCK_getsockname( SOCK_SOCKET socket, struct SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::GetSockName( socket, name, namelen ); +} +int HAL_SOCK_recvfrom( SOCK_SOCKET s, char* buf, int len, int flags, struct SOCK_sockaddr* from, int* fromlen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::RecvFrom( s, buf, len, flags, from, fromlen ); +} +int HAL_SOCK_sendto( SOCK_SOCKET s, const char* buf, int len, int flags, const struct SOCK_sockaddr* to, int tolen ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::SendTo( s, buf, len, flags, to, tolen ); +} + +HRESULT HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::LoadAdapterConfiguration(config, interfaceIndex); +} + +HRESULT HAL_SOCK_CONFIGURATION_UpdateAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex, uint32_t updateFlags) +{ + NATIVE_PROFILE_PAL_NETWORK(); + return LWIP_SOCKETS_Driver::UpdateAdapterConfiguration(interfaceIndex, updateFlags, config); +} + +void HAL_SOCK_EventsSet( uint32_t events ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + ASSERT( (events == SOCKET_EVENT_FLAG_SOCKET) || (events == SOCKET_EVENT_FLAG_SOCKETS_READY)); + + Events_Set( SYSTEM_EVENT_FLAG_SOCKET ); +} + +void * HAL_SOCK_GlobalLockContext() +{ + NATIVE_PROFILE_PAL_NETWORK(); + return NULL; +} diff --git a/source/native/nf-interpreter/src/PAL/Profiler/nanoPAL_PerformanceCounters_stubs.cpp b/source/native/nf-interpreter/src/PAL/Profiler/nanoPAL_PerformanceCounters_stubs.cpp new file mode 100644 index 00000000..ca72a4bb --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/Profiler/nanoPAL_PerformanceCounters_stubs.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +__nfweak void PAL_PerformanceCounter_Initialize() +{ +} + +__nfweak void PAL_PerformanceCounter_Uninitialize() +{ +} + +__nfweak uint32_t PAL_PerformanceCounter() +{ + return 0; +} diff --git a/source/native/nf-interpreter/src/PAL/nanoPAL_Network_stubs.cpp b/source/native/nf-interpreter/src/PAL/nanoPAL_Network_stubs.cpp new file mode 100644 index 00000000..a079c544 --- /dev/null +++ b/source/native/nf-interpreter/src/PAL/nanoPAL_Network_stubs.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +__nfweak bool Network_Initialize() +{ + return true; +}; + +__nfweak bool Network_Uninitialize() +{ + return true; +}; + +__nfweak void SOCKETS_CloseConnections() +{ + NATIVE_PROFILE_PAL_COM(); +} diff --git a/source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.cpp b/source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.cpp new file mode 100644 index 00000000..fdc74d60 --- /dev/null +++ b/source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.cpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "sys_dev_dac_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_dev_dac_native_System_Devices_Dac_DacChannel::NativeWriteValue___VOID__U2, + Library_sys_dev_dac_native_System_Devices_Dac_DacChannel::NativeDispose___VOID__BOOLEAN, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeOpenChannel___VOID__I4, + Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeGetChannelCount___I4, + Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeGetResolutionInBits___I4, + Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeInit___VOID, + NULL, + NULL, + Library_sys_dev_dac_native_System_Devices_Dac_DacController::GetDeviceSelector___STATIC__STRING, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Devices_Dac = +{ + "System.Devices.Dac", + 0x9B932004, + method_lookup, + { 100, 0, 0, 5 } +}; diff --git a/source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.h b/source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.h new file mode 100644 index 00000000..15b13a4a --- /dev/null +++ b/source/native/nf-interpreter/src/System.Devices.Dac/sys_dev_dac_native.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _SYS_DEV_DAC_NATIVE_H_ +#define _SYS_DEV_DAC_NATIVE_H_ + +#include +#include +#include + +struct Library_sys_dev_dac_native_System_Devices_Dac_DacChannel +{ + static const int FIELD___syncLock = 1; + static const int FIELD___channelNumber = 2; + static const int FIELD___dacController = 3; + static const int FIELD___disposed = 4; + + NANOCLR_NATIVE_DECLARE(NativeWriteValue___VOID__U2); + NANOCLR_NATIVE_DECLARE(NativeDispose___VOID__BOOLEAN); + + //--// + +}; + +struct Library_sys_dev_dac_native_System_Devices_Dac_DacController +{ + static const int FIELD___syncLock = 1; + static const int FIELD___controllerId = 2; + static const int FIELD__s_deviceCollection = 3; + + NANOCLR_NATIVE_DECLARE(NativeOpenChannel___VOID__I4); + NANOCLR_NATIVE_DECLARE(NativeGetChannelCount___I4); + NANOCLR_NATIVE_DECLARE(NativeGetResolutionInBits___I4); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + +}; + +struct Library_sys_dev_dac_native_System_Devices_Dac_DacControllerManager +{ + static const int FIELD_STATIC___syncLock = 0; + static const int FIELD_STATIC__s_controllersCollection = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Devices_Dac; + +#endif //_SYS_DEV_DAC_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.cpp b/source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.cpp new file mode 100644 index 00000000..e0258993 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.cpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_adc_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeReadValue___I4, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeDisposeChannel___VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeOpenChannel___VOID__I4, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetChannelCount___I4, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMaxValue___I4, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMinValue___I4, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeIsChannelModeSupported___BOOLEAN__I4, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetResolutionInBits___I4, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeInit___VOID, + NULL, + NULL, + Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::GetDeviceSelector___STATIC__STRING, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Adc = +{ + "Windows.Devices.Adc", + 0xDEDF1136, + method_lookup, + { 100, 1, 3, 2 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.h b/source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.h new file mode 100644 index 00000000..9911ef50 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Adc/win_dev_adc_native.h @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_ADC_NATIVE_H_ +#define _WIN_DEV_ADC_NATIVE_H_ + +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Adc.AdcChannelMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// +enum AdcChannelMode +{ + SingleEnded = 0, + Differential +}; + +struct Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel +{ + static const int FIELD___syncLock = 1; + static const int FIELD___channelNumber = 2; + static const int FIELD___adcController = 3; + static const int FIELD___disposed = 4; + + NANOCLR_NATIVE_DECLARE(NativeReadValue___I4); + NANOCLR_NATIVE_DECLARE(NativeDisposeChannel___VOID); + + //--// + +}; + +struct Library_win_dev_adc_native_Windows_Devices_Adc_AdcController +{ + static const int FIELD___syncLock = 1; + static const int FIELD___controllerId = 2; + static const int FIELD___channelMode = 3; + static const int FIELD__s_deviceCollection = 4; + + NANOCLR_NATIVE_DECLARE(NativeOpenChannel___VOID__I4); + NANOCLR_NATIVE_DECLARE(NativeGetChannelCount___I4); + NANOCLR_NATIVE_DECLARE(NativeGetMaxValue___I4); + NANOCLR_NATIVE_DECLARE(NativeGetMinValue___I4); + NANOCLR_NATIVE_DECLARE(NativeIsChannelModeSupported___BOOLEAN__I4); + NANOCLR_NATIVE_DECLARE(NativeGetResolutionInBits___I4); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + +}; + +struct Library_win_dev_adc_native_Windows_Devices_Adc_AdcControllerManager +{ + static const int FIELD_STATIC___syncLock = 0; + static const int FIELD_STATIC__s_controllersCollection = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Adc; + +#endif //_WIN_DEV_ADC_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.cpp b/source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.cpp new file mode 100644 index 00000000..4228fdd0 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.cpp @@ -0,0 +1,103 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_gpio_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeInit___VOID, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeRead___U8__BOOLEAN, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStart___VOID, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStop___VOID, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeDispose___VOID, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController::get_PinCount___I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Read___WindowsDevicesGpioGpioPinValue, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Toggle___VOID, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::DisposeNative___VOID, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeInit___BOOLEAN__I4, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDebounceTimeout___VOID, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::WriteNative___VOID__WindowsDevicesGpioGpioPinValue, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetAlternateFunction___VOID__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Gpio = +{ + "Windows.Devices.Gpio", + 0x2432E7EB, + method_lookup, + { 100, 1, 2, 0 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.h b/source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.h new file mode 100644 index 00000000..84220227 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Gpio/win_dev_gpio_native.h @@ -0,0 +1,155 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_GPIO_NATIVE_H_ +#define _WIN_DEV_GPIO_NATIVE_H_ + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Gpio.GpioPinDriveMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// + +enum GpioPinDriveMode +{ + GpioPinDriveMode_Input = 0, + GpioPinDriveMode_InputPullDown, + GpioPinDriveMode_InputPullUp, + GpioPinDriveMode_Output, + GpioPinDriveMode_OutputOpenDrain, + GpioPinDriveMode_OutputOpenDrainPullUp, + GpioPinDriveMode_OutputOpenSource, + GpioPinDriveMode_OutputOpenSourcePullDown +}; + +/////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Gpio.GpioPinValue (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////// + +enum GpioPinValue +{ + GpioPinValue_Low = 0, + GpioPinValue_High, +}; + +/////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Gpio.GpioChangePolarity (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////// + +enum GpioChangePolarity +{ + Both = 0, + Falling, + Rising +}; + + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCount +{ + static const int FIELD__Count = 1; + static const int FIELD__RelativeTime = 2; + + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter +{ + static const int FIELD___pinNumber = 1; + static const int FIELD___inputMode = 2; + static const int FIELD___polarity = 3; + static const int FIELD___CountActive = 4; + static const int FIELD___readTime = 5; + static const int FIELD___syncLock = 6; + static const int FIELD___disposedValue = 7; + + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(NativeRead___U8__BOOLEAN); + NANOCLR_NATIVE_DECLARE(NativeStart___VOID); + NANOCLR_NATIVE_DECLARE(NativeStop___VOID); + NANOCLR_NATIVE_DECLARE(NativeDispose___VOID); + + //--// + +}; + + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController +{ + static const int FIELD_STATIC___syncLock = 0; + static const int FIELD_STATIC__s_instance = 1; + + NANOCLR_NATIVE_DECLARE(get_PinCount___I4); + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin +{ + static const int FIELD_STATIC__s_eventListener = 2; + + static const int FIELD___syncLock = 1; + static const int FIELD___pinNumber = 2; + static const int FIELD___driveMode = 3; + static const int FIELD___debounceTimeout = 4; + static const int FIELD___callbacks = 5; + static const int FIELD___lastOutputValue = 6; + static const int FIELD___lastInputValue = 7; + static const int FIELD___disposedValue = 8; + + NANOCLR_NATIVE_DECLARE(Read___WindowsDevicesGpioGpioPinValue); + NANOCLR_NATIVE_DECLARE(Toggle___VOID); + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + NANOCLR_NATIVE_DECLARE(NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode); + NANOCLR_NATIVE_DECLARE(NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode); + NANOCLR_NATIVE_DECLARE(NativeInit___BOOLEAN__I4); + NANOCLR_NATIVE_DECLARE(NativeSetDebounceTimeout___VOID); + NANOCLR_NATIVE_DECLARE(WriteNative___VOID__WindowsDevicesGpioGpioPinValue); + NANOCLR_NATIVE_DECLARE(NativeSetAlternateFunction___VOID__I4); + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPinEvent +{ + static const int FIELD__PinNumber = 3; + static const int FIELD__Edge = 4; + + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPinEventListener +{ + static const int FIELD___pinMap = 1; + + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPinValueChangedEventArgs +{ + static const int FIELD___edge = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Gpio; + +#endif //_WIN_DEV_GPIO_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.cpp b/source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.cpp new file mode 100644 index 00000000..1dc2ad14 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::NativeInit___VOID, + NULL, + NULL, + Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::GetDeviceSelector___STATIC__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeInit___VOID, + Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeDispose___VOID__BOOLEAN, + Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeTransmit___WindowsDevicesI2cI2cTransferResult__SZARRAY_U1__SZARRAY_U1, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_I2c = +{ + "Windows.Devices.I2c", + 0x8D1C8F95, + method_lookup, + { 100, 2, 0, 1 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.h b/source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.h new file mode 100644 index 00000000..eca7cb98 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.I2c/win_dev_i2c_native.h @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_I2C_NATIVE_H_ +#define _WIN_DEV_I2C_NATIVE_H_ + +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.I2c.I2cSharingMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// +enum I2cSharingMode +{ + Exclusive = 0, + Shared +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.I2c.I2cTransferStatus (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// + enum I2cTransferStatus +{ + I2cTransferStatus_FullTransfer = 0, + I2cTransferStatus_ClockStretchTimeout, + I2cTransferStatus_PartialTransfer, + I2cTransferStatus_SlaveAddressNotAcknowledged, + I2cTransferStatus_UnknownError +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.I2c.I2cBusSpeed (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// +enum I2cBusSpeed +{ + I2cBusSpeed_StandardMode = 0, + I2cBusSpeed_FastMode +}; + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// + +struct Library_win_dev_i2c_native_Windows_Devices_I2c_I2cConnectionSettings +{ + static const int FIELD___slaveAddress = 1; + static const int FIELD___busSpeed = 2; + static const int FIELD___sharingMode = 3; + + + //--// + +}; + +struct Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController +{ + static const int FIELD___syncLock = 1; + static const int FIELD___controllerId = 2; + static const int FIELD__s_deviceCollection = 3; + + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + +}; + +struct Library_win_dev_i2c_native_Windows_Devices_I2c_I2cControllerManager +{ + static const int FIELD_STATIC___syncLock = 0; + static const int FIELD_STATIC__s_controllersCollection = 1; + + + //--// + +}; + +struct Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice +{ + static const int FIELD___syncLock = 1; + static const int FIELD___deviceId = 2; + static const int FIELD___connectionSettings = 3; + static const int FIELD___disposed = 4; + + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(NativeDispose___VOID__BOOLEAN); + NANOCLR_NATIVE_DECLARE(NativeTransmit___WindowsDevicesI2cI2cTransferResult__SZARRAY_U1__SZARRAY_U1); + + //--// + +}; + +struct Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult +{ + static const int FIELD___bytesTransferred = 1; + static const int FIELD___status = 2; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_I2c; + +#endif //_WIN_DEV_I2C_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.cpp b/source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.cpp new file mode 100644 index 00000000..f9e80727 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.cpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_pwm_native.h" + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MaxFrequency___R8, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MinFrequency___R8, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_PinCount___I4, + NULL, + NULL, + NULL, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::NativeSetDesiredFrequency___U4__U4, + NULL, + NULL, + NULL, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::GetDeviceSelector___STATIC__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeInit___VOID, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetActiveDutyCyclePercentage___VOID__U4, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetPolarity___VOID__U1, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStart___VOID, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStop___VOID, + Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::DisposeNative___VOID, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Pwm = +{ + "Windows.Devices.Pwm", + 0x84D8B10C, + method_lookup, + { 100, 1, 3, 2 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.h b/source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.h new file mode 100644 index 00000000..a58cd007 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Pwm/win_dev_pwm_native.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_PWM_NATIVE_H_ +#define _WIN_DEV_PWM_NATIVE_H_ + +#include +#include +#include + +struct Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController +{ + static const int FIELD___controllerId = 1; + static const int FIELD___actualFrequency = 2; + static const int FIELD___pwmTimer = 3; + + NANOCLR_NATIVE_DECLARE(get_MaxFrequency___R8); + NANOCLR_NATIVE_DECLARE(get_MinFrequency___R8); + NANOCLR_NATIVE_DECLARE(get_PinCount___I4); + NANOCLR_NATIVE_DECLARE(NativeSetDesiredFrequency___U4__U4); + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + +}; + +struct Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmControllerManager +{ + static const int FIELD_STATIC___syncLock = 0; + static const int FIELD_STATIC__s_controllersCollection = 1; + + + //--// + +}; + +struct Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin +{ + static const int FIELD___syncLock = 1; + static const int FIELD___pwmController = 2; + static const int FIELD___polarity = 3; + static const int FIELD___dutyCyclePercentage = 4; + static const int FIELD___dutyCycle = 5; + static const int FIELD___pinNumber = 6; + static const int FIELD___pwmTimer = 7; + static const int FIELD___isStarted = 8; + static const int FIELD___disposed = 9; + + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(NativeSetActiveDutyCyclePercentage___VOID__U4); + NANOCLR_NATIVE_DECLARE(NativeSetPolarity___VOID__U1); + NANOCLR_NATIVE_DECLARE(NativeStart___VOID); + NANOCLR_NATIVE_DECLARE(NativeStop___VOID); + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Pwm; + +#endif //_WIN_DEV_PWM_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.cpp b/source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.cpp new file mode 100644 index 00000000..0a524fda --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_serial_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::get_BytesToRead___U4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeDispose___VOID, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeInit___VOID, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeConfig___VOID, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeWrite___VOID__SZARRAY_U1, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeStore___U4, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeRead___U4__SZARRAY_U1__I4__I4, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeSetWatchChar___VOID, + NULL, + Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::GetDeviceSelector___STATIC__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_SerialCommunication = +{ + "Windows.Devices.SerialCommunication", + 0x8E46E2E2, + method_lookup, + { 100, 1, 1, 0 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.h b/source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.h new file mode 100644 index 00000000..a3b099fd --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.SerialCommunication/win_dev_serial_native.h @@ -0,0 +1,184 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_SERIAL_NATIVE_H_ +#define _WIN_DEV_SERIAL_NATIVE_H_ + +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.SerialCommunication.SerialHandshake (in managed code) !!! // +///////////////////////////////////////////////////////////////////////////////////////////////////// +enum SerialHandshake +{ + SerialHandshake_None = 0, + SerialHandshake_RequestToSend, + SerialHandshake_RequestToSendXOnXOff, + SerialHandshake_XOnXOff +}; + +////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.SerialCommunication.SerialParity (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////// +enum SerialParity +{ + SerialParity_None = 0, + SerialParity_Even, + SerialParity_Mark, + SerialParity_Odd, + SerialParity_Space +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.SerialCommunication.SerialStopBitCount (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////////////////// +enum SerialStopBitCount +{ + SerialStopBitCount_One = 0, + SerialStopBitCount_OnePointFive, + SerialStopBitCount_Two +}; + +///////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Storage.Streams.InputStreamOptions (in managed code) !!! // +///////////////////////////////////////////////////////////////////////////////////////////// + +enum InputStreamOptions +{ + InputStreamOptions_None = 0, + InputStreamOptions_Partial, + InputStreamOptions_ReadAhead +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.SerialCommunication.SerialData (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////////// +enum SerialData +{ + SerialData_Chars = 0, + SerialData_WatchChar, +}; + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_ErrorReceivedEventArgs +{ + static const int FIELD___error = 1; + + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_PinChangedEventArgs +{ + static const int FIELD___pinChange = 1; + + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDataEvent +{ + static const int FIELD__SerialDeviceIndex = 3; + static const int FIELD__Event = 4; + + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDataReceivedEventArgs +{ + static const int FIELD___data = 1; + + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice +{ + static const int FIELD_STATIC__s_eventListener = 0; + + static const int FIELD___disposed = 1; + static const int FIELD___syncLock = 2; + static const int FIELD___opened = 3; + static const int FIELD___deviceId = 4; + static const int FIELD___portIndex = 5; + static const int FIELD___outputStream = 6; + static const int FIELD___inputStream = 7; + static const int FIELD___readTimeout = 8; + static const int FIELD___writeTimeout = 9; + static const int FIELD___baudRate = 10; + static const int FIELD___dataBits = 11; + static const int FIELD___handshake = 12; + static const int FIELD___parity = 13; + static const int FIELD___stopBits = 14; + static const int FIELD___bytesReceived = 15; + static const int FIELD___watchChar = 16; + static const int FIELD___callbacksDataReceivedEvent = 17; + + NANOCLR_NATIVE_DECLARE(get_BytesToRead___U4); + NANOCLR_NATIVE_DECLARE(NativeDispose___VOID); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(NativeConfig___VOID); + NANOCLR_NATIVE_DECLARE(NativeWrite___VOID__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(NativeStore___U4); + NANOCLR_NATIVE_DECLARE(NativeRead___U4__SZARRAY_U1__I4__I4); + NANOCLR_NATIVE_DECLARE(NativeSetWatchChar___VOID); + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDeviceController +{ + static const int FIELD_STATIC___syncLock = 1; + static const int FIELD_STATIC__s_instance = 2; + static const int FIELD_STATIC__s_deviceCollection = 3; + + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDeviceEventListener +{ + static const int FIELD___serialDevicesMap = 1; + + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDeviceInputStream +{ + static const int FIELD___serialDevice = 1; + + + //--// + +}; + +struct Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDeviceOutputStream +{ + static const int FIELD___serialDevice = 1; + static const int FIELD___unstoredBufferLength = 2; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_SerialCommunication; + +#endif //_WIN_DEV_SERIAL_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.cpp b/source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.cpp new file mode 100644 index 00000000..995bf22c --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.cpp @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_spi_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MaxClockFrequency___I4, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MinClockFrequency___I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiController::GetDeviceSelector___STATIC__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::DisposeNative___VOID, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeInit___VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Spi = +{ + "Windows.Devices.Spi", + 0xEA555AF2, + method_lookup, + { 100, 1, 4, 0 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.h b/source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.h new file mode 100644 index 00000000..1655de3d --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Spi/win_dev_spi_native.h @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_SPI_NATIVE_H_ +#define _WIN_DEV_SPI_NATIVE_H_ + + +#include +#include +#include + + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Spi.SpiMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// + +enum DataBitOrder +{ + DataBitOrder_MSB = 0, + DataBitOrder_LSB +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Spi.SpiMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// + +enum SpiModes +{ + SpiModes_Mode0 = 0, + SpiModes_Mode1, + SpiModes_Mode2, + SpiModes_Mode3 +}; + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo +{ + static const int FIELD___chipSelectLineCount = 1; + + NANOCLR_NATIVE_DECLARE(get_MaxClockFrequency___I4); + NANOCLR_NATIVE_DECLARE(get_MinClockFrequency___I4); + + //--// + +}; + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiConnectionSettings +{ + static const int FIELD___csLine = 1; + static const int FIELD___clockFrequency = 2; + static const int FIELD___databitLength = 3; + static const int FIELD___spiMode = 4; + static const int FIELD___spiSharingMode = 5; + static const int FIELD___bitOrder = 6; + + + //--// + +}; + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiController +{ + static const int FIELD___syncLock = 1; + static const int FIELD___controllerId = 2; + static const int FIELD__s_deviceCollection = 3; + + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + +}; + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiControllerManager +{ + static const int FIELD_STATIC__s_syncLock = 0; + static const int FIELD_STATIC__s_controllersCollection = 1; + + + //--// + +}; + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice +{ + static const int FIELD___syncLock = 1; + static const int FIELD___spiBus = 2; + static const int FIELD___deviceId = 3; + static const int FIELD___connectionSettings = 4; + static const int FIELD___disposedValue = 5; + + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + NANOCLR_NATIVE_DECLARE(NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN); + NANOCLR_NATIVE_DECLARE(NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + + //--// + + static HRESULT NativeTransfer(CLR_RT_StackFrame& stack, bool bufferIs16bits); +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Spi; + +#endif //_WIN_DEV_SPI_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.cpp b/source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.cpp new file mode 100644 index 00000000..7967b885 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_wifi_native.h" + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::DisposeNative___VOID, + Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeInit___VOID, + Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeConnect___WindowsDevicesWiFiWiFiConnectionStatus__STRING__STRING__WindowsDevicesWiFiWiFiReconnectionKind, + Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeDisconnect___VOID, + Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeScanAsync___VOID, + Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::GetNativeScanReport___SZARRAY_U1, + NULL, + Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeFindWirelessAdapters___STATIC__SZARRAY_U1, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Wifi = +{ + "Windows.Devices.Wifi", + 0x5AC050C9, + method_lookup, + { 100, 0, 6, 0 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.h b/source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.h new file mode 100644 index 00000000..6100027f --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Devices.Wifi/win_dev_wifi_native.h @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_WIFI_NATIVE_H_ +#define _WIN_DEV_WIFI_NATIVE_H_ + +#include +#include +#include + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter +{ + static const int FIELD_STATIC__s_eventListener = 0; + + static const int FIELD___networkInterface = 1; + static const int FIELD___syncLock = 2; + static const int FIELD__AvailableNetworksChanged = 3; + static const int FIELD___disposedValue = 4; + + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(NativeConnect___WindowsDevicesWiFiWiFiConnectionStatus__STRING__STRING__WindowsDevicesWiFiWiFiReconnectionKind); + NANOCLR_NATIVE_DECLARE(NativeDisconnect___VOID); + NANOCLR_NATIVE_DECLARE(NativeScanAsync___VOID); + NANOCLR_NATIVE_DECLARE(GetNativeScanReport___SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(NativeFindWirelessAdapters___STATIC__SZARRAY_U1); + + //--// + + static HRESULT GetNetInterfaceIndex(CLR_RT_StackFrame& stack, int * pNetIndex); +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAvailableNetwork +{ + static const int FIELD___bsid = 1; + static const int FIELD___ssid = 2; + static const int FIELD___rssi = 3; + static const int FIELD___networkKind = 4; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiConnectionResult +{ + static const int FIELD___ConnectionStatus = 1; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiEvent +{ + static const int FIELD__EventType = 3; + static const int FIELD__Time = 4; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiEventListener +{ + static const int FIELD__wifiAdapters = 1; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiNetworkReport +{ + static const int FIELD___wifiNetworks = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Wifi; + +#endif //_WIN_DEV_WIFI_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.cpp b/source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.cpp new file mode 100644 index 00000000..cc85cebb --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.cpp @@ -0,0 +1,119 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_net_sockets_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::socket___STATIC__I4__I4__I4__I4, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::bind___STATIC__VOID__OBJECT__SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::connect___STATIC__VOID__OBJECT__SZARRAY_U1__BOOLEAN, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::send___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::recv___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::close___STATIC__I4__OBJECT, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::listen___STATIC__VOID__OBJECT__I4, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::accept___STATIC__I4__OBJECT, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::shutdown___STATIC__VOID__OBJECT__I4__BYREF_I4, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::sendto___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::recvfrom___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__BYREF_SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getpeername___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getsockname___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::setsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::poll___STATIC__BOOLEAN__OBJECT__I4__I4, + Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::ioctl___STATIC__VOID__OBJECT__U4__BYREF_U4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Networking_Sockets = +{ + "Windows.Networking.Sockets", + 0x03D7E1A6, + method_lookup, + { 1, 0, 0, 0 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.h b/source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.h new file mode 100644 index 00000000..9b2d9775 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Networking.Sockets/win_net_sockets_native.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +//--------------------------------------------------------------------------- + +#ifndef _WIN_NET_SOCKETS_NATIVE_H_ +#define _WIN_NET_SOCKETS_NATIVE_H_ + +#include +#include +#include + + +struct Library_win_net_sockets_native_Windows_Networking_EndpointPair +{ + static const int FIELD__localHostName = 1; + static const int FIELD__localServiceName = 2; + static const int FIELD__remoteHostName = 3; + static const int FIELD__remoteServiceName = 4; + + + //--// + +}; + +struct Library_win_net_sockets_native_Windows_Networking_HostName +{ + static const int FIELD__canonicalName = 1; + static const int FIELD__displayName = 2; + static const int FIELD__rawName = 3; + static const int FIELD__hostNameType = 4; + + + //--// + +}; + +struct Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative +{ + NANOCLR_NATIVE_DECLARE(socket___STATIC__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(bind___STATIC__VOID__OBJECT__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(connect___STATIC__VOID__OBJECT__SZARRAY_U1__BOOLEAN); + NANOCLR_NATIVE_DECLARE(send___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(recv___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4); + NANOCLR_NATIVE_DECLARE(close___STATIC__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(listen___STATIC__VOID__OBJECT__I4); + NANOCLR_NATIVE_DECLARE(accept___STATIC__I4__OBJECT); + NANOCLR_NATIVE_DECLARE(getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(shutdown___STATIC__VOID__OBJECT__I4__BYREF_I4); + NANOCLR_NATIVE_DECLARE(sendto___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(recvfrom___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__BYREF_SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(getpeername___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(getsockname___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(getsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(setsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(poll___STATIC__BOOLEAN__OBJECT__I4__I4); + NANOCLR_NATIVE_DECLARE(ioctl___STATIC__VOID__OBJECT__U4__BYREF_U4); + + //--// + static HRESULT MarshalSockAddress( struct SOCK_sockaddr* addrDst, CLR_UINT32& addrLenDst, const CLR_RT_HeapBlock& blkSrc ); + static HRESULT MarshalSockAddress( CLR_RT_HeapBlock& blkDst, const struct SOCK_sockaddr* addrSrc, CLR_UINT32 addrLenSrc ); + static HRESULT SendRecvHelper( CLR_RT_StackFrame& stack, bool fSend, bool fAddress ); + static HRESULT SockOptHelper( CLR_RT_StackFrame& stack, bool fGet ); + static HRESULT SockNameHelper( CLR_RT_StackFrame& stack, bool fPeer ); + static HRESULT BindConnectHelper( CLR_RT_StackFrame& stack, bool fBind ); + static HRESULT ThrowOnError( CLR_RT_StackFrame& stack, CLR_INT32 err ); + static void ThrowError( CLR_RT_StackFrame& stack, CLR_INT32 errorCode ); + + static CLR_INT32 Helper__SelectSocket( CLR_INT32 socket, CLR_INT32 mode ); + + /* WARNING!!! + * The value of this constant is the offset for the m_Handle field in the System.Net.Sockets.Socket class. + * It is defined here to avoid a circular reference issue. + */ + static const int FIELD__m_Handle = 1; + + static const int DISPOSED_HANDLE = -1; +}; + +struct Library_win_net_sockets_native_Windows_Networking_Sockets_StreamSocket +{ + static const int FIELD__control = 1; + static const int FIELD__socketHandle = 2; + + + //--// + +}; + +struct Library_win_net_sockets_native_Windows_Networking_Sockets_StreamSocketControl +{ + static const int FIELD__keepAlive = 1; + static const int FIELD__minProtectionLevel = 2; + static const int FIELD__noDelay = 3; + static const int FIELD__outboundBufferSizeInBytes = 4; + static const int FIELD__outboundUnicastHopLimit = 5; + static const int FIELD__qualityOfService = 6; + static const int FIELD__serializeConnectionAttempts = 7; + + + //--// + +}; + +struct Library_win_net_sockets_native_Windows_Networking_Sockets_StreamSocketInformation +{ + static const int FIELD__localAddress = 1; + static const int FIELD__localPort = 2; + static const int FIELD__protectionLevel = 3; + static const int FIELD__remoteAddress = 4; + static const int FIELD__remoteHostName = 5; + static const int FIELD__remotePort = 6; + static const int FIELD__remoteServiceName = 7; + + + //--// + +}; + + + //--// + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Networking_Sockets; + +#endif //_WIN_NET_SOCKETS_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/Windows.Storage/win_storage_native.cpp b/source/native/nf-interpreter/src/Windows.Storage/win_storage_native.cpp new file mode 100644 index 00000000..96e3df5c --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Storage/win_storage_native.cpp @@ -0,0 +1,111 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_storage_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_storage_native_Windows_Storage_Devices_SDCard::MountMMCNative___STATIC__VOID__BOOLEAN, + Library_win_storage_native_Windows_Storage_Devices_SDCard::MountSpiNative___STATIC__VOID__I4__I4, + Library_win_storage_native_Windows_Storage_Devices_SDCard::UnmountNative___STATIC__VOID, + NULL, + NULL, + NULL, + NULL, + Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__VOID__WindowsStorageIStorageFile__SZARRAY_U1, + Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__VOID__WindowsStorageIStorageFile__STRING, + Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_SZARRAY_U1, + Library_win_storage_native_Windows_Storage_FileIO::ReadTextNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_storage_native_Windows_Storage_StorageFile::DeleteFileNative___VOID, + Library_win_storage_native_Windows_Storage_StorageFile::RenameFileNative___VOID__STRING, + NULL, + NULL, + Library_win_storage_native_Windows_Storage_StorageFile::GetFileFromPathNative___STATIC__WindowsStorageStorageFile__STRING__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder, + Library_win_storage_native_Windows_Storage_StorageFolder::GetInternalStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder, + Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder, + Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFilesNative___SZARRAY_WindowsStorageStorageFile__U4__U4, + Library_win_storage_native_Windows_Storage_StorageFolder::CreateFileNative___WindowsStorageStorageFile__STRING__U4, + Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNative___WindowsStorageStorageFolder__STRING__U4, + Library_win_storage_native_Windows_Storage_StorageFolder::DeleteFolderNative___VOID, + Library_win_storage_native_Windows_Storage_StorageFolder::RenameFolderNative___VOID__STRING, + Library_win_storage_native_Windows_Storage_StorageFolder::GetFolderNative___WindowsStorageStorageFolder__STRING, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Storage = +{ + "Windows.Storage", + 0x8D8C8026, + method_lookup, + { 100, 0, 1, 0 } +}; diff --git a/source/native/nf-interpreter/src/Windows.Storage/win_storage_native.h b/source/native/nf-interpreter/src/Windows.Storage/win_storage_native.h new file mode 100644 index 00000000..d6cf2f74 --- /dev/null +++ b/source/native/nf-interpreter/src/Windows.Storage/win_storage_native.h @@ -0,0 +1,114 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_STORAGE_NATIVE_H_ +#define _WIN_STORAGE_NATIVE_H_ + +#include +#include + +struct Library_win_storage_native_Windows_Storage_RemovableDeviceEventArgs +{ + static const int FIELD___path = 1; + static const int FIELD___event = 2; + + + //--// + +}; + +struct Library_win_storage_native_Windows_Storage_StorageEventManager +{ + static const int FIELD_STATIC__RemovableDeviceInserted = 0; + static const int FIELD_STATIC__RemovableDeviceRemoved = 1; + + + //--// + +}; + +struct Library_win_storage_native_Windows_Storage_StorageEventManager__StorageEvent +{ + static const int FIELD__EventType = 3; + static const int FIELD__DriveIndex = 4; + static const int FIELD__Time = 5; + + + //--// + +}; + +struct Library_win_storage_native_Windows_Storage_Devices_SDCard +{ + static const int FIELD_STATIC___mounted = 2; + + NANOCLR_NATIVE_DECLARE(MountMMCNative___STATIC__VOID__BOOLEAN); + NANOCLR_NATIVE_DECLARE(MountSpiNative___STATIC__VOID__I4__I4); + NANOCLR_NATIVE_DECLARE(UnmountNative___STATIC__VOID); + + //--// + +}; + +struct Library_win_storage_native_Windows_Storage_FileIO +{ + NANOCLR_NATIVE_DECLARE(WriteBytes___STATIC__VOID__WindowsStorageIStorageFile__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(WriteText___STATIC__VOID__WindowsStorageIStorageFile__STRING); + NANOCLR_NATIVE_DECLARE(ReadBufferNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(ReadTextNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_STRING); + + //--// + +}; + +struct Library_win_storage_native_Windows_Storage_StorageFile +{ + static const int FIELD___dateCreated = 1; + static const int FIELD___name = 2; + static const int FIELD___path = 3; + + NANOCLR_NATIVE_DECLARE(DeleteFileNative___VOID); + NANOCLR_NATIVE_DECLARE(RenameFileNative___VOID__STRING); + NANOCLR_NATIVE_DECLARE(GetFileFromPathNative___STATIC__WindowsStorageStorageFile__STRING__STRING); + + //--// + +}; + +struct Library_win_storage_native_Windows_Storage_StorageFolder +{ + static const int FIELD___knownFolderId = 1; + static const int FIELD___dateCreated = 2; + static const int FIELD___name = 3; + static const int FIELD___path = 4; + + NANOCLR_NATIVE_DECLARE(GetRemovableStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder); + NANOCLR_NATIVE_DECLARE(GetInternalStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder); + NANOCLR_NATIVE_DECLARE(GetStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder); + NANOCLR_NATIVE_DECLARE(GetStorageFilesNative___SZARRAY_WindowsStorageStorageFile__U4__U4); + NANOCLR_NATIVE_DECLARE(CreateFileNative___WindowsStorageStorageFile__STRING__U4); + NANOCLR_NATIVE_DECLARE(CreateFolderNative___WindowsStorageStorageFolder__STRING__U4); + NANOCLR_NATIVE_DECLARE(DeleteFolderNative___VOID); + NANOCLR_NATIVE_DECLARE(RenameFolderNative___VOID__STRING); + NANOCLR_NATIVE_DECLARE(GetFolderNative___WindowsStorageStorageFolder__STRING); + + //--// + +}; + +struct Library_win_storage_native_Windows_Storage_StorageProvider +{ + static const int FIELD___displayName = 1; + static const int FIELD___id = 2; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Storage; + +#endif //_WIN_STORAGE_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.cpp b/source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.cpp new file mode 100644 index 00000000..c0a668af --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.cpp @@ -0,0 +1,70 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_devices_can_native.h" + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::WriteMessage___VOID__nanoFrameworkDevicesCanCanMessage, + NULL, + NULL, + NULL, + NULL, + Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::GetMessage___nanoFrameworkDevicesCanCanMessage, + Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::DisposeNative___VOID, + Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::NativeInit___VOID, + Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::NativeUpdateCallbacks___VOID, + NULL, + NULL, + Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::GetDeviceSelector___STATIC__STRING, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Devices_Can = +{ + "nanoFramework.Devices.Can", + 0xC90BF0BB, + method_lookup, + { 100, 0, 4, 0 } +}; diff --git a/source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.h b/source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.h new file mode 100644 index 00000000..02416df9 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Devices.Can/nf_devices_can_native.h @@ -0,0 +1,124 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _NF_DEVICES_CAN_NATIVE_H_ +#define _NF_DEVICES_CAN_NATIVE_H_ + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Devices.Can.CanEvent (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////// + +enum CanEvent +{ + CanEvent_MessageReceived = 0, + CanEvent_ErrorOccurred, +}; + +//////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Devices.Can.CanMessageIdType (in managed code) !!! // +//////////////////////////////////////////////////////////////////////////////////////////// + +enum CanMessageIdType +{ + CanMessageIdType_SID = 0, + CanMessageIdType_EID, +}; + +/////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Devices.Can.CanMessageFrameType (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////////////// + +enum CanMessageFrameType +{ + CanMessageFrameType_Data = 0, + CanMessageFrameType_RemoteRequest, +}; + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// + +struct Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController +{ + static const int FIELD_STATIC__s_eventListener = 0; + + static const int FIELD___disposed = 1; + static const int FIELD___callbacks = 2; + static const int FIELD___syncLock = 3; + static const int FIELD___controllerId = 4; + static const int FIELD___settings = 5; + static const int FIELD___message = 6; + static const int FIELD__ControllerId = 7; + + NANOCLR_NATIVE_DECLARE(WriteMessage___VOID__nanoFrameworkDevicesCanCanMessage); + NANOCLR_NATIVE_DECLARE(GetMessage___nanoFrameworkDevicesCanCanMessage); + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(NativeUpdateCallbacks___VOID); + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + +}; + +struct Library_nf_devices_can_native_nanoFramework_Devices_Can_CanControllerEventListener +{ + static const int FIELD___canControllersMap = 1; + + + //--// + +}; + +struct Library_nf_devices_can_native_nanoFramework_Devices_Can_CanControllerManager +{ + static const int FIELD_STATIC___syncLock = 1; + static const int FIELD_STATIC__s_controllersCollection = 2; + + + //--// + +}; + +struct Library_nf_devices_can_native_nanoFramework_Devices_Can_CanMessage +{ + static const int FIELD___id = 1; + static const int FIELD___identifierType = 2; + static const int FIELD___frameType = 3; + static const int FIELD___message = 4; + + + //--// + +}; + +struct Library_nf_devices_can_native_nanoFramework_Devices_Can_CanMessageEvent +{ + static const int FIELD__ControllerIndex = 3; + static const int FIELD__Event = 4; + + + //--// + +}; + +struct Library_nf_devices_can_native_nanoFramework_Devices_Can_CanSettings +{ + static const int FIELD___baudRatePrescaler = 1; + static const int FIELD___phaseSegment1 = 2; + static const int FIELD___phaseSegment2 = 3; + static const int FIELD___syncJumpWidth = 4; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Devices_Can; + +#endif //_NF_DEVICES_CAN_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.cpp b/source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.cpp new file mode 100644 index 00000000..88998b46 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_devices_onewire_native.h" + +static const CLR_RT_MethodHandler method_lookup[] = +{ + Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchReset___BOOLEAN, + Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchBit___BOOLEAN__BOOLEAN, + Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchByte___U1__U1, + Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::WriteByte___U1__U1, + Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::ReadByte___U1, + Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::FindFirstDevice___BOOLEAN__BOOLEAN__BOOLEAN, + Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::FindNextDevice___BOOLEAN__BOOLEAN__BOOLEAN, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Devices_OneWire = +{ + "nanoFramework.Devices.OneWire", + 0xC7BEAEBC, + method_lookup, + { 100, 0, 3, 3 } +}; diff --git a/source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.h b/source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.h new file mode 100644 index 00000000..176f4681 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Devices.OneWire/nf_devices_onewire_native.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_DEVICES_ONEWIRE_NATIVE_H_ +#define _NF_DEVICES_ONEWIRE_NATIVE_H_ + +#include +#include +#include + +struct Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController +{ + static const int FIELD___syncLock = 1; + static const int FIELD___serialNumber = 2; + + NANOCLR_NATIVE_DECLARE(TouchReset___BOOLEAN); + NANOCLR_NATIVE_DECLARE(TouchBit___BOOLEAN__BOOLEAN); + NANOCLR_NATIVE_DECLARE(TouchByte___U1__U1); + NANOCLR_NATIVE_DECLARE(WriteByte___U1__U1); + NANOCLR_NATIVE_DECLARE(ReadByte___U1); + NANOCLR_NATIVE_DECLARE(FindFirstDevice___BOOLEAN__BOOLEAN__BOOLEAN); + NANOCLR_NATIVE_DECLARE(FindNextDevice___BOOLEAN__BOOLEAN__BOOLEAN); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Devices_OneWire; + +#endif //_NF_DEVICES_ONEWIRE_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.cpp b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.cpp new file mode 100644 index 00000000..142ed51a --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.cpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nf_system_resourcemanager.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObjectInternal___OBJECT__I2, + Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObjectInternal___OBJECT__I2__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_system_resourcemanager_System_Resources_ResourceManager::FindResource___STATIC__I4__STRING__mscorlibSystemReflectionAssembly, + Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum, + Library_nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum, + Library_nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum__I4__I4, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_ResourceManager = +{ + "nanoFramework.ResourceManager", + 0xCDF9E76C, + method_lookup, + //////////////////////////////////////////////////////////////////////////////////// + // check if the version bellow matches the one in AssemblyNativeVersion attribute // + //////////////////////////////////////////////////////////////////////////////////// + { 100, 0, 0, 0 } +}; diff --git a/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.h b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.h new file mode 100644 index 00000000..0ceee94d --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager.h @@ -0,0 +1,47 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_SYSTEM_RESOURCEMANAGER_H_ +#define _NF_SYSTEM_RESOURCEMANAGER_H_ + +#include +#include +#include + +struct Library_nf_system_resourcemanager_System_Resources_ResourceManager +{ + static const int FIELD___resourceFileId = 1; + static const int FIELD___assembly = 2; + static const int FIELD___baseAssembly = 3; + static const int FIELD___baseName = 4; + static const int FIELD___cultureName = 5; + static const int FIELD___rmFallback = 6; + + NANOCLR_NATIVE_DECLARE(GetObjectInternal___OBJECT__I2); + NANOCLR_NATIVE_DECLARE(GetObjectInternal___OBJECT__I2__I4__I4); + NANOCLR_NATIVE_DECLARE(FindResource___STATIC__I4__STRING__mscorlibSystemReflectionAssembly); + NANOCLR_NATIVE_DECLARE(GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum); + + //--// + + NANOCLR_NATIVE_DECLARE(GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum__I4__I4); + +}; + +struct Library_nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility +{ + NANOCLR_NATIVE_DECLARE(GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum); + NANOCLR_NATIVE_DECLARE(GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum__I4__I4); + + //--// + +}; + + + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_ResourceManager; + +#endif //_NF_SYSTEM_RESOURCEMANAGER_H_ diff --git a/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_System_Resources_ResourceManager.cpp b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_System_Resources_ResourceManager.cpp new file mode 100644 index 00000000..be7e5d15 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_System_Resources_ResourceManager.cpp @@ -0,0 +1,218 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nf_system_resourcemanager.h" + + +HRESULT Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObjectInternal___OBJECT__I2( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly_Instance assm; + CLR_UINT32 size; + const CLR_RECORD_RESOURCE* resource; + CLR_RT_Assembly* pAssm; + const CLR_UINT8* buf; + CLR_RT_HeapBlock* pThis = stack.This(); + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_UINT32 resourceFileId = pThis[ FIELD___resourceFileId ].NumericByRefConst().s4; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + // + // Set up for restart on out of memory. + // + if(stack.m_customState == 0) + { + stack.m_customState = 1; + stack.m_flags |= CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; + } + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_Assembly::GetTypeDescriptor( *pThis[ FIELD___assembly ].Dereference(), assm )); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.LocateResource( assm, resourceFileId, pArgs[ 0 ].NumericByRefConst().s2, resource, size )); + + if(resource != NULL) //otherwise NULL is returned + { + pAssm = assm.m_assm; + buf = pAssm->GetResourceData( resource->offset ); + + switch(resource->kind) + { + case CLR_RECORD_RESOURCE::RESOURCE_String: + { + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( top, (const char*)buf, pAssm )); + } + break; + + case CLR_RECORD_RESOURCE::RESOURCE_Binary: + { + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, size, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + memcpy( top.DereferenceArray()->GetFirstElement(), buf, size ); + } + break; + + default: + _ASSERTE(false); + break; + } + } + + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObjectInternal___OBJECT__I2__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly_Instance assm; + CLR_UINT32 size; + const CLR_RECORD_RESOURCE* resource; + CLR_RT_Assembly* pAssm; + const CLR_UINT8* buf; + CLR_RT_HeapBlock* pThis = stack.This(); + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_UINT32 resourceFileId = pThis[ FIELD___resourceFileId ].NumericByRefConst().s4; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_UINT32 offset = pArgs[ 1 ].NumericByRef().s4; + CLR_UINT32 length = pArgs[ 2 ].NumericByRef().s4; + + // + // Set up for restart on out of memory. + // + if(stack.m_customState == 0) + { + stack.m_customState = 1; + stack.m_flags |= CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; + } + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_Assembly::GetTypeDescriptor( *pThis[FIELD___assembly].Dereference(), assm )); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.LocateResource( assm, resourceFileId, pArgs[ 0 ].NumericByRefConst().s2, resource, size )); + + + if(resource != NULL) //otherwise NULL is returned + { + pAssm = assm.m_assm; + buf = pAssm->GetResourceData( resource->offset ); + + switch(resource->kind) + { + // + // Chunked access is only possible for binary resources + // + case CLR_RECORD_RESOURCE::RESOURCE_String: + case CLR_RECORD_RESOURCE::RESOURCE_Bitmap: + case CLR_RECORD_RESOURCE::RESOURCE_Font: + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + break; + case CLR_RECORD_RESOURCE::RESOURCE_Binary: + { + // throw out-of-range when offset is too large... + if(offset >= size) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); + } + // ... but trim length if necessary + else + { + if(offset + length >= size) + { + length = size - offset; + } + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, length, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + memcpy( top.DereferenceArray()->GetFirstElement() , buf + offset, length ); + } + break; + + default: + _ASSERTE(false); + break; + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_resourcemanager_System_Resources_ResourceManager::FindResource___STATIC__I4__STRING__mscorlibSystemReflectionAssembly( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_Assembly_Instance assm; + CLR_INT32 resourceFileId; + CLR_RT_HeapBlock* pArgs = &stack.Arg0(); + + const char* szText = pArgs[ 0 ].RecoverString(); FAULT_ON_NULL(szText); + + NANOCLR_CHECK_HRESULT(Library_corlib_native_System_Reflection_Assembly::GetTypeDescriptor( *pArgs[ 1 ].Dereference(), assm )); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.LocateResourceFile( assm, szText, resourceFileId )); + + stack.SetResult_I4( resourceFileId ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& blkResourceManager = stack.Arg0(); + CLR_RT_HeapBlock& blkEnumObj = stack.Arg1(); + CLR_RT_HeapBlock* blkVT = blkEnumObj.Dereference(); + CLR_RT_HeapBlock* blkEnum = blkVT + 1; + CLR_RT_MethodDef_Instance md; + + if(stack.m_customState == 0) + { + stack.m_customState = 1; + + FAULT_ON_NULL(blkVT); + + if(blkEnum->DataType() != DATATYPE_I2 && blkEnum->DataType() != DATATYPE_U2) NANOCLR_SET_AND_LEAVE( CLR_E_INVALID_PARAMETER ); + + //call back into ResourceManager.GetObjectFromId(short id); + + _SIDE_ASSERTE(md.InitializeFromIndex( g_CLR_RT_WellKnownMethods.m_ResourceManager_GetObjectFromId )); + + NANOCLR_CHECK_HRESULT( stack.MakeCall( md, &blkResourceManager, blkEnum, 1 )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock& blkResourceManager = stack.Arg0(); + CLR_RT_MethodDef_Instance md; + + if(stack.m_customState == 0) + { + stack.m_customState = 1; + + //call back into ResourceManager.GetObjectFromId(short id, int offset, int length); + + _SIDE_ASSERTE(md.InitializeFromIndex( g_CLR_RT_WellKnownMethods.m_ResourceManager_GetObjectChunkFromId )); + + NANOCLR_CHECK_HRESULT( stack.MakeCall( md, &blkResourceManager, &stack.Arg1(), 3 )); + } + + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility.cpp b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility.cpp new file mode 100644 index 00000000..274f98b6 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.ResourceManager/nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nf_system_resourcemanager.h" + + +HRESULT Library_nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum( stack ); +} + +HRESULT Library_nf_system_resourcemanager_nanoFramework_Runtime_Native_ResourceUtility::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Library_nf_system_resourcemanager_System_Resources_ResourceManager::GetObject___STATIC__OBJECT__SystemResourcesResourceManager__mscorlibSystemEnum__I4__I4( stack ); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.cpp new file mode 100644 index 00000000..a1dbaf84 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_events_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::EnableInterrupt___VOID, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::DisableInterrupt___VOID, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::Dispose___VOID__BOOLEAN, + NULL, + NULL, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::_ctor___VOID__STRING__U8, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink::EventConfig___VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Combine___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Remove___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events = +{ + "nanoFramework.Runtime.Events", + 0x7B4AC2F2, + method_lookup, + { 100, 0, 7, 0 } +}; diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.h b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.h new file mode 100644 index 00000000..30a1049f --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native.h @@ -0,0 +1,131 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _NF_RT_EVENTS_NATIVE_H_ +#define _NF_RT_EVENTS_NATIVE_H_ + + +#include +#include +#include + + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_CustomEvent +{ + static const int FIELD_STATIC__CustomEventPosted = 0; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_BaseEvent +{ + static const int FIELD__Source = 1; + static const int FIELD__Message = 2; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_CustomEvent__CustomEventInternal +{ + static const int FIELD__Data1 = 3; + static const int FIELD__Data2 = 4; + static const int FIELD__Time = 5; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher +{ + static const int FIELD__threadSpawn = 1; + static const int FIELD__callbacks = 2; + static const int FIELD__disposed = 3; + static const int FIELD___NativeEventDispatcher = 4; + + NANOCLR_NATIVE_DECLARE(EnableInterrupt___VOID); + NANOCLR_NATIVE_DECLARE(DisableInterrupt___VOID); + NANOCLR_NATIVE_DECLARE(Dispose___VOID__BOOLEAN); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__STRING__U8); + + //--// + static CLR_RT_ObjectToEvent_Source* GetEventDispReference( CLR_RT_StackFrame& stack ); + static HRESULT GetEventDispatcher ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_NativeEventDispatcher*& event ); + static CLR_RT_HeapBlock_NativeEventDispatcher* GetEventDispatcher ( CLR_RT_StackFrame& stack ); +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink +{ + static const int FIELD_STATIC__s_eventSink = 1; + static const int FIELD_STATIC__s_eventInfoTable = 2; + + NANOCLR_NATIVE_DECLARE(EventConfig___VOID); + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink__EventInfo +{ + static const int FIELD__EventListener = 1; + static const int FIELD__EventFilter = 2; + static const int FIELD__EventProcessor = 3; + static const int FIELD__Category = 4; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventArgs +{ + static const int FIELD_STATIC__Empty = 3; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_CustomEventArgs +{ + static const int FIELD___data1 = 1; + static const int FIELD___data2 = 2; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_GenericEvent +{ + static const int FIELD__Category = 3; + static const int FIELD__Data = 4; + static const int FIELD__Time = 5; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate +{ + NANOCLR_NATIVE_DECLARE(Combine___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate); + NANOCLR_NATIVE_DECLARE(Remove___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events; + +#endif //_NF_RT_EVENTS_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp new file mode 100644 index 00000000..05593f92 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nf_rt_events_native.h" + +static CLR_RT_HeapBlock_NativeEventDispatcher *g_Context = NULL; + +void PostManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2) +{ + if(g_Context != NULL) + { + uint32_t d = ((uint32_t)data1 << 16) | (category << 8) | subCategory; + + SaveNativeEventToHALQueue( g_Context, d, data2 ); + } +} + +static HRESULT InitializeEventSink( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, uint64_t userData ) +{ + (void)userData; + + g_Context = pContext; + + return S_OK; +} + +static HRESULT EnableDisableEventSink( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, bool fEnable ) +{ + (void)pContext; + (void)fEnable; + + return S_OK; +} + +static HRESULT CleanupEventSink( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +{ + (void)pContext; + + g_Context = NULL; + + CleanupNativeEventsFromHALQueue( pContext ); + + return S_OK; +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink::EventConfig___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + return S_OK; +} + +static const CLR_RT_DriverInterruptMethods g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink = +{ + InitializeEventSink, + EnableDisableEventSink, + CleanupEventSink +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs = +{ + "EventSink", + DRIVER_INTERRUPT_METHODS_CHECKSUM, + &g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink, + { 1, 0, 0, 0 } +}; diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp new file mode 100644 index 00000000..9dd7d315 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp @@ -0,0 +1,183 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_events_native.h" + + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::EnableInterrupt___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD__disposed ].NumericByRef().s1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Calls driver to enable interrupts. Consider that there could be no driver + // associated to this object so check that the driver methods are set + if(pNativeDisp->driverMethods == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + + NANOCLR_CHECK_HRESULT(pNativeDisp->driverMethods->enableProcessor( pNativeDisp, true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::DisableInterrupt___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD__disposed ].NumericByRef().s1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Calls driver to enable interrupts. Consider that there could be no driver + // associated to this object so check that the driver methods are set + // we will be tolerant in this case and not throw any exception + if(pNativeDisp->driverMethods != NULL) + { + NANOCLR_CHECK_HRESULT(pNativeDisp->driverMethods->enableProcessor( pNativeDisp, false )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::Dispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Cleanup the HAL queue from the instance of associated CLR_RT_HeapBlock_NativeEventDispatcher + pNativeDisp->RemoveFromHALQueue(); + + // Calls driver to enable interrupts. Consider that there could be no driver + // associated to this object so check that the driver methods are set + // we will be tolerant in this case and not throw any exception + if(pNativeDisp->driverMethods != NULL) + { + NANOCLR_CHECK_HRESULT(pNativeDisp->driverMethods->cleanupProcessor( pNativeDisp )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::_ctor___VOID__STRING__U8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_DriverInterruptMethods* pDriverMethods; + const CLR_RT_NativeAssemblyData* pNativeDriverData; + CLR_RT_HeapBlock_NativeEventDispatcher* pNativeDisp = NULL; + + const char * driverName; + uint64_t driverData; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieve paramenters; + if (stack.Arg1().DataType() != DATATYPE_OBJECT) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + driverName = stack.Arg1().RecoverString(); FAULT_ON_NULL(driverName); + driverData = stack.Arg2().NumericByRef().u8; + + // Throw NULL exception if string is empty. + if(hal_strlen_s( driverName ) == 0) + { + NANOCLR_CHECK_HRESULT(CLR_E_ARGUMENT_NULL); + } + + // Retrives pointers to driver implemented functions. + pNativeDriverData = GetAssemblyNativeData( driverName ); + + // Validates check sum and presence of the structure. + if(pNativeDriverData == NULL || pNativeDriverData->m_checkSum != DRIVER_INTERRUPT_METHODS_CHECKSUM) + { + NANOCLR_CHECK_HRESULT(CLR_E_DRIVER_NOT_REGISTERED); + } + + // Get pointer to CLR_RT_DriverInterruptMethods + pDriverMethods = (CLR_RT_DriverInterruptMethods *)pNativeDriverData->m_pNativeMethods; + + // Check that all methods are present: + if( pDriverMethods->initProcessor == NULL || + pDriverMethods->enableProcessor == NULL || + pDriverMethods->cleanupProcessor == NULL) + { + NANOCLR_CHECK_HRESULT(CLR_E_DRIVER_NOT_REGISTERED); + } + + // So we found driver by name and now we create instance of CLR_RT_HeapBlock_NativeEventDispatcher + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_NativeEventDispatcher::CreateInstance( *pThis, pThis[ FIELD___NativeEventDispatcher ] )); + + // Initialize the driver with and provide the instance of CLR_RT_HeapBlock_NativeEventDispatcher + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Now call the driver. First save pointer to driver data. + pNativeDisp->driverMethods = pDriverMethods; + + NANOCLR_CHECK_HRESULT(pDriverMethods->initProcessor( pNativeDisp, driverData )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_ObjectToEvent_Source* Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::GetEventDispReference( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + CLR_RT_HeapBlock* pThis = stack.This(); + + return CLR_RT_ObjectToEvent_Source::ExtractInstance( pThis[ FIELD___NativeEventDispatcher ] ); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::GetEventDispatcher( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_NativeEventDispatcher*& event ) +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + NANOCLR_HEADER(); + + event = GetEventDispatcher( stack ); + if(event == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock_NativeEventDispatcher* Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::GetEventDispatcher( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + CLR_RT_ObjectToEvent_Source* src = GetEventDispReference( stack ); + + return (src == NULL) ? NULL : (CLR_RT_HeapBlock_NativeEventDispatcher*)src->m_eventPtr; +} diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp new file mode 100644 index 00000000..14c5f1a6 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_events_native.h" + + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Combine___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Delegate_List::Combine( stack.PushValue(), stack.Arg0(), stack.Arg1(), true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Remove___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Delegate_List::Remove( stack.PushValue(), stack.Arg0(), stack.Arg1() )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.cpp new file mode 100644 index 00000000..6cba76c1 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.cpp @@ -0,0 +1,49 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nf_rt_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::GetSystemVersion___STATIC__VOID__BYREF_I4__BYREF_I4__BYREF_I4__BYREF_I4, + NULL, + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_OEMString___STATIC__STRING, + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_OEM___STATIC__U1, + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_Model___STATIC__U1, + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_SKU___STATIC__U2, + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_TargetName___STATIC__STRING, + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_Platform___STATIC__STRING, + NULL, + Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::GetNativeFloatingPointSupport___STATIC__U1, + NULL, + Library_nf_rt_native_nanoFramework_Runtime_Native_Debug::GC___STATIC__U4__BOOLEAN, + Library_nf_rt_native_nanoFramework_Runtime_Native_Debug::EnableGCMessages___STATIC__VOID__BOOLEAN, + NULL, + NULL, + NULL, + Library_nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint::Install___STATIC__VOID__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_rt_native_nanoFramework_Runtime_Native_Power::NativeReboot___STATIC__VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_rt_native_nanoFramework_Runtime_Native_Rtc::Native_RTC_SetSystemTime___STATIC__BOOLEAN__I4__U1__U1__U1__U1__U1__U1, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Native = +{ + "nanoFramework.Runtime.Native", + 0x035EC7E8, + method_lookup, + { 100, 0, 6, 0 } +}; diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.h b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.h new file mode 100644 index 00000000..2912874b --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_RT_NATIVE_H_ +#define _NF_RT_NATIVE_H_ + +#include +#include + + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Runtime.Native.SystemInfo.FloatingPoint (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +enum FloatingPoint +{ + FloatingPoint_None = 0, + FloatingPoint_SinglePrecisionSoftware = 1, + FloatingPoint_SinglePrecisionHardware = 2, + FloatingPoint_DoublePrecisionSoftware = 3, + FloatingPoint_DoublePrecisionHardware = 4, +}; + +struct Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo +{ + NANOCLR_NATIVE_DECLARE(GetSystemVersion___STATIC__VOID__BYREF_I4__BYREF_I4__BYREF_I4__BYREF_I4); + NANOCLR_NATIVE_DECLARE(get_OEMString___STATIC__STRING); + NANOCLR_NATIVE_DECLARE(get_OEM___STATIC__U1); + NANOCLR_NATIVE_DECLARE(get_Model___STATIC__U1); + NANOCLR_NATIVE_DECLARE(get_SKU___STATIC__U2); + NANOCLR_NATIVE_DECLARE(get_TargetName___STATIC__STRING); + NANOCLR_NATIVE_DECLARE(get_Platform___STATIC__STRING); + NANOCLR_NATIVE_DECLARE(GetNativeFloatingPointSupport___STATIC__U1); + + //--// + +}; +struct Library_nf_rt_native_nanoFramework_Runtime_Native_Debug +{ + NANOCLR_NATIVE_DECLARE(GC___STATIC__U4__BOOLEAN); + NANOCLR_NATIVE_DECLARE(EnableGCMessages___STATIC__VOID__BOOLEAN); + + //--// + +}; +struct Library_nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint +{ + NANOCLR_NATIVE_DECLARE(Install___STATIC__VOID__I4__I4); + + //--// + +}; + +struct Library_nf_rt_native_nanoFramework_Runtime_Native_Power +{ + static const int FIELD_STATIC__OnRebootEvent = 0; + + NANOCLR_NATIVE_DECLARE(NativeReboot___STATIC__VOID); + + //--// + +}; +struct Library_nf_rt_native_nanoFramework_Runtime_Native_Rtc +{ + NANOCLR_NATIVE_DECLARE(Native_RTC_SetSystemTime___STATIC__BOOLEAN__I4__U1__U1__U1__U1__U1__U1); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Native; + +#endif //_NF_RT_NATIVE_H_ diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Hardware_SystemInfo.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Hardware_SystemInfo.cpp new file mode 100644 index 00000000..52033233 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Hardware_SystemInfo.cpp @@ -0,0 +1,163 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_native.h" +#include "nanoHAL_ReleaseInfo.h" + + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::GetSystemVersion___STATIC__VOID__BYREF_I4__BYREF_I4__BYREF_I4__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock hbMajor; + CLR_RT_HeapBlock hbMinor; + CLR_RT_HeapBlock hbBuild; + CLR_RT_HeapBlock hbRevision; + + NFReleaseInfo releaseInfo; + + Target_GetReleaseInfo( releaseInfo ); + + hbMajor.SetInteger( releaseInfo.Version.usMajor ); + NANOCLR_CHECK_HRESULT(hbMajor.StoreToReference( stack.Arg0(), 0 )); + + hbMinor.SetInteger( releaseInfo.Version.usMinor ); + NANOCLR_CHECK_HRESULT(hbMinor.StoreToReference( stack.Arg1(), 0 )); + + hbBuild.SetInteger( releaseInfo.Version.usBuild ); + NANOCLR_CHECK_HRESULT(hbBuild.StoreToReference( stack.Arg2(), 0 )); + + hbRevision.SetInteger( releaseInfo.Version.usRevision ); + NANOCLR_CHECK_HRESULT(hbRevision.StoreToReference( stack.Arg3(), 0 )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_OEMString___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + { + NFReleaseInfo releaseInfo; + + Target_GetReleaseInfo( releaseInfo ); + + NANOCLR_SET_AND_LEAVE(stack.SetResult_String( (char*)releaseInfo.InfoString )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_OEM___STATIC__U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + // we are not supporting this right now + //stack.SetResult( OEM_Model_SKU.OEM, DATATYPE_U1 ); + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + //NANOCLR_NOCLEANUP_NOLABEL(); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_Model___STATIC__U1( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + // we are not supporting this right now + // stack.SetResult( OEM_Model_SKU.Model, DATATYPE_U1 ); + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + //NANOCLR_NOCLEANUP_NOLABEL(); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_SKU___STATIC__U2( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + // we are not supporting this right now + // stack.SetResult( OEM_Model_SKU.SKU, DATATYPE_U2 ); + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + //NANOCLR_NOCLEANUP_NOLABEL(); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_TargetName___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + NFReleaseInfo releaseInfo; + + Target_GetReleaseInfo( releaseInfo ); + + NANOCLR_SET_AND_LEAVE(stack.SetResult_String( (char*)releaseInfo.TargetName )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::get_Platform___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + + NFReleaseInfo releaseInfo; + + Target_GetReleaseInfo( releaseInfo ); + + NANOCLR_SET_AND_LEAVE(stack.SetResult_String( (char*)releaseInfo.PlatformName )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_SystemInfo::GetNativeFloatingPointSupport___STATIC__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + FloatingPoint floatingPointOption = FloatingPoint_None; + + #if !defined(NANOCLR_EMULATED_FLOATINGPOINT) + + #if (USE_FPU_IS_TRUE == TRUE) + + #if (DP_FLOATINGPOINT == TRUE) + floatingPointOption = FloatingPoint_DoublePrecisionHardware; + #else + floatingPointOption = FloatingPoint_SinglePrecisionHardware; + #endif + + #else + + #if (DP_FLOATINGPOINT == TRUE) + floatingPointOption = FloatingPoint_DoublePrecisionSoftware; + #else + floatingPointOption = FloatingPoint_SinglePrecisionSoftware; + #endif + + #endif // (USE_FPU_IS_TRUE == TRUE) + + #endif // defined(NANOCLR_EMULATED_FLOATINGPOINT) + + stack.SetResult_U1((int8_t)floatingPointOption); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Debug.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Debug.cpp new file mode 100644 index 00000000..c75fa041 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Debug.cpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_native.h" + + + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_Debug::GC___STATIC__U4__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + +#if defined(NANOCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_GC >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: Debug.GC.\r\n" ); + } +#endif + + stack.SetResult_I4( g_CLR_RT_ExecutionEngine.PerformGarbageCollection() ); + + if(stack.Arg0().NumericByRefConst().u1) + { + // + // Decrement the number of GC, otherwise the outer loop may request another compaction. + // + g_CLR_RT_GarbageCollector.m_numberOfGarbageCollections--; + + g_CLR_RT_ExecutionEngine.PerformHeapCompaction(); + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_Debug::EnableGCMessages___STATIC__VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + #if defined(NANOCLR_TRACE_MEMORY_STATS) + s_CLR_RT_fTrace_MemoryStats = stack.Arg0().NumericByRefConst().u1 != 0 ? c_CLR_RT_Trace_Info : c_CLR_RT_Trace_None; + #else + (void)stack; + #endif + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint.cpp new file mode 100644 index 00000000..326b32bb --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint.cpp @@ -0,0 +1,70 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_native.h" + + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_ExecutionConstraint::Install___STATIC__VOID__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + NANOCLR_HEADER(); + + CLR_RT_StackFrame* caller; + CLR_RT_SubThread* sth; + CLR_INT32 timeout; + CLR_INT32 pri; + + caller = stack.Caller(); FAULT_ON_NULL(caller); // We need to set the constraint on the caller, not on us... + timeout = stack.Arg0().NumericByRef().s4; + pri = stack.Arg1().NumericByRef().s4; + + // + // Find the owned subthread or create a new one. + // + sth = (CLR_RT_SubThread*)caller->m_owningSubThread->Next(); + if(sth->Next()) + { + if(sth->m_owningStackFrame != caller) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + else + { + CLR_RT_SubThread* sthNew; + + NANOCLR_CHECK_HRESULT(CLR_RT_SubThread::CreateInstance( stack.m_owningThread, caller, 0, sthNew )); + + sth = sthNew; + } + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( sth->m_timeConstraint, timeout )); + + // + // Compensate for time spent inside system calls. + // + if(sth->m_timeConstraint != TIMEOUT_INFINITE) + { + sth->m_timeConstraint -= CLR_RT_ExecutionEngine::s_compensation.Adjust( 0 ); + + CLR_RT_ExecutionEngine::InvalidateTimerCache(); + } + + // + // Only threads with priority above zero can raise their priority. + // + if(pri > 0 && caller->m_owningSubThread->m_priority < 0) + { + pri = caller->m_owningSubThread->m_priority; + } + + sth->m_priority = pri; + sth->m_status &= CLR_RT_SubThread::STATUS_Triggered; + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Power.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Power.cpp new file mode 100644 index 00000000..2d49398c --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Power.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_native.h" + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_Power::NativeReboot___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + g_CLR_RT_ExecutionEngine.Reboot(true); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc_stubs.cpp b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc_stubs.cpp new file mode 100644 index 00000000..ec344dcd --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc_stubs.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "nf_rt_native.h" +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// these functions are declared as 'weak' so they can be replaced by the actual ones when they exist on the target platform +// they should be located at targets\NNNN\YYYY\nanoCLR\nanoFramework.Runtime.Native +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +__nfweak HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_Rtc::Native_RTC_SetSystemTime___STATIC__BOOLEAN__I4__U1__U1__U1__U1__U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.cpp b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.cpp new file mode 100644 index 00000000..2b59644b --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.cpp @@ -0,0 +1,100 @@ +#include "nf_system_collections.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_system_collections_System_Collections_Queue::Clear___VOID, + Library_nf_system_collections_System_Collections_Queue::CopyTo___VOID__mscorlibSystemArray__I4, + Library_nf_system_collections_System_Collections_Queue::Enqueue___VOID__OBJECT, + NULL, + Library_nf_system_collections_System_Collections_Queue::Dequeue___OBJECT, + Library_nf_system_collections_System_Collections_Queue::Peek___OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_system_collections_System_Collections_Stack::Clear___VOID, + NULL, + NULL, + NULL, + NULL, + Library_nf_system_collections_System_Collections_Stack::Peek___OBJECT, + Library_nf_system_collections_System_Collections_Stack::Pop___OBJECT, + Library_nf_system_collections_System_Collections_Stack::Push___VOID__OBJECT, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_System_Collections = +{ + "nanoFramework.System.Collections", + 0xC7167094, + method_lookup, + //////////////////////////////////////////////////////////////////////////////////// + // check if the version bellow matches the one in AssemblyNativeVersion attribute // + //////////////////////////////////////////////////////////////////////////////////// + { 100, 0, 0, 0 } +}; diff --git a/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.h b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.h new file mode 100644 index 00000000..ae439b85 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections.h @@ -0,0 +1,113 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_SYSTEM_COLLECTIONS_H_ +#define _NF_SYSTEM_COLLECTIONS_H_ + +#include +#include + +struct Library_nf_system_collections_System_Collections_Hashtable +{ + static const int FIELD___buckets = 1; + static const int FIELD___numberOfBuckets = 2; + static const int FIELD___count = 3; + static const int FIELD___loadFactor = 4; + static const int FIELD___maxLoadFactor = 5; + static const int FIELD___growthFactor = 6; + + + //--// + +}; + +struct Library_nf_system_collections_System_Collections_Hashtable__Entry +{ + static const int FIELD__key = 1; + static const int FIELD__value = 2; + static const int FIELD__next = 3; + + + //--// + +}; + +struct Library_nf_system_collections_System_Collections_Hashtable__HashtableEnumerator +{ + static const int FIELD__ht = 1; + static const int FIELD__temp = 2; + static const int FIELD__index = 3; + static const int FIELD__returnType = 4; + + + //--// + +}; + +struct Library_nf_system_collections_System_Collections_Hashtable__KeyCollection +{ + static const int FIELD__ht = 1; + + + //--// + +}; + +struct Library_nf_system_collections_System_Collections_DictionaryEntry +{ + static const int FIELD__Key = 1; + static const int FIELD__Value = 2; + + + //--// + +}; + +struct Library_nf_system_collections_System_Collections_Queue +{ + static const int FIELD___array = 1; + static const int FIELD___head = 2; + static const int FIELD___tail = 3; + static const int FIELD___size = 4; + + NANOCLR_NATIVE_DECLARE(Clear___VOID); + NANOCLR_NATIVE_DECLARE(CopyTo___VOID__mscorlibSystemArray__I4); + NANOCLR_NATIVE_DECLARE(Enqueue___VOID__OBJECT); + NANOCLR_NATIVE_DECLARE(Dequeue___OBJECT); + NANOCLR_NATIVE_DECLARE(Peek___OBJECT); + + //--// + +}; + +struct Library_nf_system_collections_System_Collections_Stack +{ + static const int FIELD___array = 1; + static const int FIELD___size = 2; + + NANOCLR_NATIVE_DECLARE(Clear___VOID); + NANOCLR_NATIVE_DECLARE(Peek___OBJECT); + NANOCLR_NATIVE_DECLARE(Pop___OBJECT); + NANOCLR_NATIVE_DECLARE(Push___VOID__OBJECT); + + //--// + +}; + +struct Library_nf_system_collections_System_Collections_Hashtable__ValueCollection +{ + static const int FIELD__ht = 1; + + + //--// + +}; + + + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_System_Collections; + +#endif //_NF_SYSTEM_COLLECTIONS_H_ diff --git a/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Queue.cpp b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Queue.cpp new file mode 100644 index 00000000..806c19e8 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Queue.cpp @@ -0,0 +1,80 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nf_system_collections.h" + + +HRESULT Library_nf_system_collections_System_Collections_Queue::CopyTo___VOID__mscorlibSystemArray__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Queue* pThis; + CLR_RT_HeapBlock_Array* array; + CLR_INT32 index; + + pThis = (CLR_RT_HeapBlock_Queue*)stack.This(); FAULT_ON_NULL(pThis); + array = stack.Arg1().DereferenceArray(); FAULT_ON_NULL_ARG(array); + index = stack.Arg2().NumericByRef().s4; + + NANOCLR_SET_AND_LEAVE(pThis->CopyTo( array, index )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_collections_System_Collections_Queue::Clear___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Queue* pThis = (CLR_RT_HeapBlock_Queue*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->Clear()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_collections_System_Collections_Queue::Enqueue___VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Queue* pThis = (CLR_RT_HeapBlock_Queue*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->Enqueue( stack.Arg1().Dereference() )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_collections_System_Collections_Queue::Dequeue___OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Queue* pThis = (CLR_RT_HeapBlock_Queue*)stack.This(); FAULT_ON_NULL(pThis); + CLR_RT_HeapBlock* value; + + NANOCLR_CHECK_HRESULT(pThis->Dequeue( value )); + + stack.SetResult_Object( value ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_collections_System_Collections_Queue::Peek___OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Queue* pThis = (CLR_RT_HeapBlock_Queue*)stack.This(); FAULT_ON_NULL(pThis); + CLR_RT_HeapBlock* value; + + NANOCLR_CHECK_HRESULT(pThis->Peek( value )); + + stack.SetResult_Object( value ); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Stack.cpp b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Stack.cpp new file mode 100644 index 00000000..d5449c24 --- /dev/null +++ b/source/native/nf-interpreter/src/nanoFramework.System.Collections/nf_system_collections_System_Collections_Stack.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nf_system_collections.h" + + +HRESULT Library_nf_system_collections_System_Collections_Stack::Clear___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Stack* pThis = (CLR_RT_HeapBlock_Stack*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->Clear()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_collections_System_Collections_Stack::Peek___OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Stack* pThis = (CLR_RT_HeapBlock_Stack*)stack.This(); FAULT_ON_NULL(pThis); + CLR_RT_HeapBlock* value; + + NANOCLR_CHECK_HRESULT(pThis->Peek( value )); + + stack.SetResult_Object( value ); + + NANOCLR_NOCLEANUP(); + +} + +HRESULT Library_nf_system_collections_System_Collections_Stack::Pop___OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Stack* pThis = (CLR_RT_HeapBlock_Stack*)stack.This(); FAULT_ON_NULL(pThis); + CLR_RT_HeapBlock* value; + + NANOCLR_CHECK_HRESULT(pThis->Pop( value )); + + stack.SetResult_Object( value ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_system_collections_System_Collections_Stack::Push___VOID__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Stack* pThis = (CLR_RT_HeapBlock_Stack*)stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_SET_AND_LEAVE(pThis->Push( stack.Arg1().Dereference() )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/startocd.bat b/source/native/nf-interpreter/startocd.bat new file mode 100644 index 00000000..9ac719d0 --- /dev/null +++ b/source/native/nf-interpreter/startocd.bat @@ -0,0 +1,48 @@ +REM Starts OpenOCD - designed to be called from GDB, itself started from Visual Studio launch.vs.json +REM If already running it will fail and exit, leaving the existing one to handle GDB requests +REM Template allows for multiple target interfaces and boards - add new ones as required +REM DAV 26FEB19 +setlocal +set cmd=C:/Esp32_Tools/openocd-esp32/bin/openocd.exe -s C:/Esp32_Tools/openocd-esp32/share/openocd/scripts + +if %1.==. goto ESP32_JLINK +call :%1 +if %errorlevel% equ 1 goto :lblerror +goto end + +REM Start OpenOCD +:start +start %cmd% %iface% +goto :eof + +:end +endlocal +exit + +:lblerror +mshta javascript:alert("Error: Unknown label %1");close(); +goto end + +REM Add additional interface/board combinations here, and add the label to the launch.vs.json file + +:ESP32_JLINK +set iface=-f interface/jlink.cfg -f target/esp32.cfg -c "adapter_khz 3000" +goto start + +:ESP32_OLIMEX +set iface=-f interface/ftdi/olimex-arm-usb-ocd-h.cfg -f target/esp32.cfg -c "adapter_khz 3000" +goto start + +:ESP32_WROVER +set iface=-f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp32-wrover.cfg +goto start + +:STM32_STLINK +REM Note: I tried using the Eclipse OpenOCD without much success here, then switched to the ESP32 version, and it works right out of the box! +REM set cmd=C:/nanoFramework_Tools/Tools/openocd/bin/openocd.exe -s C:/nanoFramework_Tools/Tools/openocd/bin/scripts +set iface=-f interface/stlink-v2-1.cfg -f board/stm32f7discovery.cfg +goto start + + + + diff --git a/source/native/nf-interpreter/targets-community/.github/ISSUE_TEMPLATE.md b/source/native/nf-interpreter/targets-community/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..e1cd4a8d --- /dev/null +++ b/source/native/nf-interpreter/targets-community/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,2 @@ +Please DO NOT open issues in this repository. +We are now using the Home repository for centralized issue management. diff --git a/source/native/nf-interpreter/targets-community/.github/PULL_REQUEST_TEMPLATE.md b/source/native/nf-interpreter/targets-community/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..35f30cf8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,4 @@ + +- Fixes/Closes/Resolves nanoFramework/Home#NNNN + + diff --git a/source/native/nf-interpreter/targets-community/.gitignore b/source/native/nf-interpreter/targets-community/.gitignore new file mode 100644 index 00000000..87747b24 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/.gitignore @@ -0,0 +1,60 @@ +# ignore all ZIP files +*.zip +/zips/ + +# ignore build folder +/build/ +/build/.gitkeep + +# ignore cmake-variants file (will change frequently per user/board setup, use should derive content from cmake-variants.TEMPLATE.json) +cmake-variants.json + +# ignore any content inside the Interop assemblies folder +InteropAssemblies/* + +# Visual Studio Code +# ignore C/C++ launch file (will change frequently per user/board setup, use should derive content from launch.TEMPLATE.json) +.vscode/launch.json +.vscode/.cmaketools.json +.vscode/settings.json +.vscode/tasks.json +.vscode/extensions.json +.vscode/c_cpp_properties.json +.vscode/cmake-kits.json +.vscode/ipch + +# ignore CMake modules for Interop assemblies +CMake/Modules/FindINTEROP*.cmake + +# Visual Studio +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user + +# Build results +[Dd]ebug/ +[Rr]elease/ +[Rr]eleases/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio cache/options directory contents but not the example launch.vs.json +!.vs/ +.vs/* +!.vs/launch.vs.SAMPLE.json +!.vs/tasks.vs.SAMPLE.json + +# Visual C++ cache files +*.VC.db + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/CMakeLists.txt new file mode 100644 index 00000000..235396be --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/CMakeLists.txt @@ -0,0 +1,228 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F405xG_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F405xG_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F405xG_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F405xG_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +############################################################################ +# CRT heap is assigned to RAM4 region @ CCM SRAM so we are OK to use it all +############################################################################ +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x10000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x10000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) + +# if HEX2DFU tool is available pack the binaries into a DFU package +if(HEX2DFU_TOOL_AVAILABLE) + + #################################################################################################### + ## when changing the linker file make sure to update the new addresses for the image files bellow ## + ## DO NOT use the leading 0x notation, just the address in plain hexadecimal formating ## + #################################################################################################### + if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08008000 + ${PROJECT_SOURCE_DIR}/build/nanobooter-nanoclr.dfu + ) + else() + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08004000 + ${PROJECT_SOURCE_DIR}/build/nanobooter-nanoclr.dfu + ) + endif() + +endif() diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/README.md new file mode 100644 index 00000000..56397fa0 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/README.md @@ -0,0 +1,56 @@ +![GHI FEZ CERB40](https://github.com/nanoframework/nf-Community-Targets/blob/master/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/resources/cerb40.jpg) + +----- + +## Board introduction ## + +The board here used is a GHI Fez Cerb40 based upon an STM32F405RGT6 supporting a 1MB Flash and up to 192KB RAM in a LQFP64 package. On this board the LSE is soldered in case you have a board without the LSE please make sure you have it configured correctly in both the mcuconf.h files for nanoBooter as well as nanoCLR. + +The available pins have been set as can be read in the board.h file and it is there where you can set the pin usage for your required use. Visiting the official site [here](http://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f4-series/stm32f405-415/stm32f405rg.html) and per datasheet looking at Table 9. Alternate function mapping you will find possible alternative uses of the various pins. In its initial release the following pin configuration and usage has been verified. Looking at the board from the above (MCU visible) and with the USB connector at the top we have pin 1 on the left hand side. + +| PCB Pin | MCU | Usage | Comment | Date | +|:-|---|---|---|---| +| 01 | VCC | 3.3V | | | +| 02 | GND | | | | +| 03 | PA8 | | | | +| 04 | PA13 | | | | +| 05 | PA7 | SPI1 MISO | | | +| 06 | PA6 | SPI1 MOSI | | | +| 07 | PC10 | | | | +| 08 | PA14 | | | | +| 09 | PC11 | | | | +| 10 | PB4 | | | | +| 11 | PB9 | I2C1 SDA | Confirmed and working | 2018-02-07 | +| 12 | PB3 | | | | +| 13 | PD2 | | | | +| 14 | PC12 | | | | +| 15 | VBAT | | | | +| 16 | PB8 | I2C1 SCL | Confirmed and working | 2018-02-07 | +| 17 | LODR | | | | +| 18 | PB7 | UART1 RX | Confirmed and working | 2018-02-09 | +| 19 | PB6 | UART1 TX | Confirmed and working | 2018-02-09 | +| 20 | PB5 | GPIO, PWM | GPIO confirmed, PWM not done yet | 2018-02-07 | +| 21 | Reset | | Confirmed | 2018-02-07 | +| 22 | PC0 | A0 | | | +| 23 | PC1 | A1 | | | +| 24 | PC2 | A2 | | | +| 25 | PC3 | A3 | | | +| 26 | PA0 | UART2 CTS | | | +| 27 | PA1 | UART2 RTS | | | +| 28 | PA2 | UART2 TX | Confirmed and working | 2018-02-08 | +| 29 | PA3 | UART2 RX | Confirmed and working | 2018-02-09 | +| 30 | PA4 | | | | +| 31 | PA5 | SPI1 SCK | | | +| 32 | PB10 | I2C2 SCL | Confirmed and working | 2018-02-07 | +| 33 | PB11 | I2C2 SDA | Confirmed and working | 2018-02-07 | +| 34 | PB14 | | | | +| 35 | PB15 | | | | +| 36 | PC6 | | | | +| 37 | PC7 | | | | +| 38 | PC8 | | | | +| 39 | PC9 | | | | +| 40 | USB | | | | + +For more information on the board specifics you can have a look at the [GHI Electronics Cerb40 page](http://old.ghielectronics.com/catalog/product/353) + +**NOTE: this configuration was successfully tested in a GHI_FEZ_CERB40_NF board using the Serial over USB connection on USB port 1 that creates a virtual COM port.** diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.c new file mode 100644 index 00000000..fc29a0c0 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.c @@ -0,0 +1,265 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.h new file mode 100644 index 00000000..0369e951 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/board.h @@ -0,0 +1,1612 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#ifndef BOARD_H +#define BOARD_H + +/* + * Setup for GHI Fez CERB40 board. + */ + +/* + * Board identifier. + */ +#define BOARD_GHI_FEZ_CERB40_NF +#define BOARD_NAME "GHI Fez Cerb40 board" + +#define BOARD_OTG_NOVBUSSENS + +/* + * Board oscillators-related settings. + * NOTE: LSE fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 12000000U +#endif + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F405xx + +/* + * IO pins assignments. + */ +#define GPIOA_UART2_CTS 0U +#define GPIOA_UART2_RTS 1U +#define GPIOA_UART2_TX 2U +#define GPIOA_UART2_RX 3U +#define GPIOA_LRCK 4U +#define GPIOA_SPC 5U +#define GPIOA_SDO 6U +#define GPIOA_SDI 7U +#define GPIOA_PIN8 8U +#define GPIOA_VBUS_FS 9U +#define GPIOA_OTG_FS_ID 10U +#define GPIOA_OTG_FS_DM 11U +#define GPIOA_OTG_FS_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_SWO 3U +#define GPIOB_PIN4 4U +#define GPIOB_PIN5 5U +#define GPIOB_UART1_TX 6U +#define GPIOB_UART1_RX 7U +#define GPIOB_I2C1_SCL 8U +#define GPIOB_I2C1_SDA 9U +#define GPIOB_I2C2_SCL 10U +#define GPIOB_I2C2_SDA 11U +#define GPIOB_PIN12 12U +#define GPIOB_PIN13 13U +#define GPIOB_PIN14 14U +#define GPIOB_PIN15 15U + +#define GPIOC_ADC2_IN10 0U +#define GPIOC_ADC2_IN11 1U +#define GPIOC_ADC3_IN12 2U +#define GPIOC_ADC3_IN13 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_PIN7 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_PIN14 14U +#define GPIOC_PIN15 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_RESET 4U +#define GPIOD_OVER_CURRENT 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_LED4 12U +#define GPIOD_LED3 13U +#define GPIOD_LED5 14U +#define GPIOD_LED6 15U + +#define GPIOE_INT1 0U +#define GPIOE_INT2 1U +#define GPIOE_PIN2 2U +#define GPIOE_CS_SPI 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_PIN0 0U +#define GPIOF_PIN1 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +#define GPIOJ_PIN0 0U +#define GPIOJ_PIN1 1U +#define GPIOJ_PIN2 2U +#define GPIOJ_PIN3 3U +#define GPIOJ_PIN4 4U +#define GPIOJ_PIN5 5U +#define GPIOJ_PIN6 6U +#define GPIOJ_PIN7 7U +#define GPIOJ_PIN8 8U +#define GPIOJ_PIN9 9U +#define GPIOJ_PIN10 10U +#define GPIOJ_PIN11 11U +#define GPIOJ_PIN12 12U +#define GPIOJ_PIN13 13U +#define GPIOJ_PIN14 14U +#define GPIOJ_PIN15 15U + +#define GPIOK_PIN0 0U +#define GPIOK_PIN1 1U +#define GPIOK_PIN2 2U +#define GPIOK_PIN3 3U +#define GPIOK_PIN4 4U +#define GPIOK_PIN5 5U +#define GPIOK_PIN6 6U +#define GPIOK_PIN7 7U +#define GPIOK_PIN8 8U +#define GPIOK_PIN9 9U +#define GPIOK_PIN10 10U +#define GPIOK_PIN11 11U +#define GPIOK_PIN12 12U +#define GPIOK_PIN13 13U +#define GPIOK_PIN14 14U +#define GPIOK_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_BUTTON PAL_LINE(GPIOA, 0U) +#define LINE_LRCK PAL_LINE(GPIOA, 4U) +#define LINE_SPC PAL_LINE(GPIOA, 5U) +#define LINE_SDO PAL_LINE(GPIOA, 6U) +#define LINE_SDI PAL_LINE(GPIOA, 7U) +#define LINE_VBUS_FS PAL_LINE(GPIOA, 9U) +#define LINE_OTG_FS_ID PAL_LINE(GPIOA, 10U) +#define LINE_OTG_FS_DM PAL_LINE(GPIOA, 11U) +#define LINE_OTG_FS_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) + +#define LINE_SWO PAL_LINE(GPIOB, 3U) +#define LINE_SCL PAL_LINE(GPIOB, 6U) +#define LINE_SDA PAL_LINE(GPIOB, 9U) +#define LINE_CLK_IN PAL_LINE(GPIOB, 10U) + +#define LINE_OTG_FS_POWER_ON PAL_LINE(GPIOC, 0U) +#define LINE_PDM_OUT PAL_LINE(GPIOC, 3U) +#define LINE_MCLK PAL_LINE(GPIOC, 7U) +#define LINE_SCLK PAL_LINE(GPIOC, 10U) +#define LINE_SDIN PAL_LINE(GPIOC, 12U) + +#define LINE_RESET PAL_LINE(GPIOD, 4U) +#define LINE_OVER_CURRENT PAL_LINE(GPIOD, 5U) +#define LINE_LED4 PAL_LINE(GPIOD, 12U) +#define LINE_LED3 PAL_LINE(GPIOD, 13U) +#define LINE_LED5 PAL_LINE(GPIOD, 14U) +#define LINE_LED6 PAL_LINE(GPIOD, 15U) + +#define LINE_INT1 PAL_LINE(GPIOE, 0U) +#define LINE_INT2 PAL_LINE(GPIOE, 1U) +#define LINE_CS_SPI PAL_LINE(GPIOE, 3U) + + + +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - BUTTON (input floating). + * PA1 - PIN1 (input pullup). + * PA2 - PIN2 (input pullup). + * PA3 - PIN3 (input pullup). + * PA4 - LRCK (alternate 6). + * PA5 - SPC (alternate 5). + * PA6 - SDO (alternate 5). + * PA7 - SDI (alternate 5). + * PA8 - PIN8 (input pullup). + * PA9 - VBUS_FS (input floating). + * PA10 - OTG_FS_ID (alternate 10). + * PA11 - OTG_FS_DM (alternate 10). + * PA12 - OTG_FS_DP (alternate 10). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - PIN15 (input pullup). + */ +#define VAL_GPIOA_MODER (PIN_MODE_ALTERNATE(GPIOA_UART2_CTS) | \ + PIN_MODE_ALTERNATE(GPIOA_UART2_RTS) | \ + PIN_MODE_ALTERNATE(GPIOA_UART2_TX) | \ + PIN_MODE_ALTERNATE(GPIOA_UART2_RX) | \ + PIN_MODE_ALTERNATE(GPIOA_LRCK) | \ + PIN_MODE_ALTERNATE(GPIOA_SPC) | \ + PIN_MODE_ALTERNATE(GPIOA_SDO) | \ + PIN_MODE_ALTERNATE(GPIOA_SDI) | \ + PIN_MODE_INPUT(GPIOA_PIN8) | \ + PIN_MODE_INPUT(GPIOA_VBUS_FS) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_ID) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_UART2_CTS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_UART2_RTS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_UART2_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_UART2_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_LRCK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SPC) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SDO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SDI) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_VBUS_FS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_ID) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_MEDIUM(GPIOA_UART2_CTS) | \ + PIN_OSPEED_MEDIUM(GPIOA_UART2_RTS) | \ + PIN_OSPEED_MEDIUM(GPIOA_UART2_TX) | \ + PIN_OSPEED_MEDIUM(GPIOA_UART2_RX) | \ + PIN_OSPEED_HIGH(GPIOA_LRCK) | \ + PIN_OSPEED_MEDIUM(GPIOA_SPC) | \ + PIN_OSPEED_MEDIUM(GPIOA_SDO) | \ + PIN_OSPEED_MEDIUM(GPIOA_SDI) | \ + PIN_OSPEED_HIGH(GPIOA_PIN8) | \ + PIN_OSPEED_HIGH(GPIOA_VBUS_FS) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_ID) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_UART2_CTS) | \ + PIN_PUPDR_FLOATING(GPIOA_UART2_RTS) | \ + PIN_PUPDR_FLOATING(GPIOA_UART2_TX) | \ + PIN_PUPDR_FLOATING(GPIOA_UART2_RX) | \ + PIN_PUPDR_FLOATING(GPIOA_LRCK) | \ + PIN_PUPDR_FLOATING(GPIOA_SPC) | \ + PIN_PUPDR_FLOATING(GPIOA_SDO) | \ + PIN_PUPDR_FLOATING(GPIOA_SDI) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOA_VBUS_FS) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_ID) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | \ + PIN_PUPDR_FLOATING(GPIOA_SWDIO) | \ + PIN_PUPDR_FLOATING(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_UART2_CTS) | \ + PIN_ODR_HIGH(GPIOA_UART2_RTS) | \ + PIN_ODR_HIGH(GPIOA_UART2_TX) | \ + PIN_ODR_HIGH(GPIOA_UART2_RX) | \ + PIN_ODR_HIGH(GPIOA_LRCK) | \ + PIN_ODR_HIGH(GPIOA_SPC) | \ + PIN_ODR_HIGH(GPIOA_SDO) | \ + PIN_ODR_HIGH(GPIOA_SDI) | \ + PIN_ODR_HIGH(GPIOA_PIN8) | \ + PIN_ODR_HIGH(GPIOA_VBUS_FS) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_ID) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_UART2_CTS, 7U) | \ + PIN_AFIO_AF(GPIOA_UART2_RTS, 7U) | \ + PIN_AFIO_AF(GPIOA_UART2_TX, 7U) | \ + PIN_AFIO_AF(GPIOA_UART2_RX, 7U) | \ + PIN_AFIO_AF(GPIOA_LRCK, 0U) | \ + PIN_AFIO_AF(GPIOA_SPC, 5U) | \ + PIN_AFIO_AF(GPIOA_SDO, 5U) | \ + PIN_AFIO_AF(GPIOA_SDI, 5U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOA_VBUS_FS, 0U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_ID, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0U)) + +/* + * GPIOB setup: + * + * PB0 - PIN0 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - SWO (alternate 0). + * PB4 - PIN4 (input pullup). + * PB5 - PIN5 (input pullup). + * PB6 - SCL (alternate 4). + * PB7 - PIN7 (input pullup). + * PB8 - PIN8 (input pullup). + * PB9 - SDA (alternate 4). + * PB10 - CLK_IN (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - PIN13 (input pullup). + * PB14 - PIN14 (input pullup). + * PB15 - PIN15 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_SWO) | \ + PIN_MODE_INPUT(GPIOB_PIN4) | \ + PIN_MODE_OUTPUT(GPIOB_PIN5) | \ + PIN_MODE_ALTERNATE(GPIOB_UART1_TX) | \ + PIN_MODE_ALTERNATE(GPIOB_UART1_RX) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C2_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C2_SDA) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_INPUT(GPIOB_PIN13) | \ + PIN_MODE_INPUT(GPIOB_PIN14) | \ + PIN_MODE_INPUT(GPIOB_PIN15)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_UART1_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOB_UART1_RX) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C2_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C2_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_PIN0) | \ + PIN_OSPEED_HIGH(GPIOB_PIN1) | \ + PIN_OSPEED_HIGH(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_SWO) | \ + PIN_OSPEED_HIGH(GPIOB_PIN4) | \ + PIN_OSPEED_HIGH(GPIOB_PIN5) | \ + PIN_OSPEED_MEDIUM(GPIOB_UART1_TX) | \ + PIN_OSPEED_MEDIUM(GPIOB_UART1_RX) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_I2C2_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C2_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_PIN12) | \ + PIN_OSPEED_HIGH(GPIOB_PIN13) | \ + PIN_OSPEED_HIGH(GPIOB_PIN14) | \ + PIN_OSPEED_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOB_SWO) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOB_UART1_TX) | \ + PIN_PUPDR_FLOATING(GPIOB_UART1_RX) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C2_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C2_SDA) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN15)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_SWO) | \ + PIN_ODR_HIGH(GPIOB_PIN4) | \ + PIN_ODR_LOW(GPIOB_PIN5) | \ + PIN_ODR_HIGH(GPIOB_UART1_TX) | \ + PIN_ODR_HIGH(GPIOB_UART1_RX) | \ + PIN_ODR_HIGH(GPIOB_I2C1_SCL) | \ + PIN_ODR_HIGH(GPIOB_I2C1_SDA) | \ + PIN_ODR_HIGH(GPIOB_I2C2_SCL) | \ + PIN_ODR_HIGH(GPIOB_I2C2_SDA) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_HIGH(GPIOB_PIN13) | \ + PIN_ODR_HIGH(GPIOB_PIN14) | \ + PIN_ODR_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOB_SWO, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOB_UART1_TX, 7U) | \ + PIN_AFIO_AF(GPIOB_UART1_RX, 7U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C2_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C2_SDA, 4U) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN15, 0U)) + +/* + * GPIOC setup: + * + * PC0 - GPIOC_ADC2_IN10 (analog input). + * PC1 - GPIOC_ADC2_IN11 (analog input). + * PC2 - GPIOC_ADC3_IN12 (analog input). + * PC3 - GPIOC_ADC1_IN13 (analog input). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - MCLK (alternate 6). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - SCLK (alternate 6). + * PC11 - PIN11 (input pullup). + * PC12 - SDIN (alternate 6). + * PC13 - PIN13 (input pullup). + * PC14 - PIN14 (input pullup). + * PC15 - PIN15 (input pullup). + */ +#define VAL_GPIOC_MODER (PIN_MODE_ANALOG(GPIOC_ADC2_IN10) |\ + PIN_MODE_ANALOG(GPIOC_ADC2_IN11) | \ + PIN_MODE_ANALOG(GPIOC_ADC3_IN12) | \ + PIN_MODE_ANALOG(GPIOC_ADC3_IN13) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_PIN7) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_PIN14) | \ + PIN_MODE_INPUT(GPIOC_PIN15)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ADC2_IN10) |\ + PIN_OTYPE_PUSHPULL(GPIOC_ADC2_IN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ADC3_IN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ADC3_IN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ADC2_IN10) |\ + PIN_OSPEED_HIGH(GPIOC_ADC2_IN11) | \ + PIN_OSPEED_HIGH(GPIOC_ADC3_IN12) | \ + PIN_OSPEED_HIGH(GPIOC_ADC3_IN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN5) | \ + PIN_OSPEED_HIGH(GPIOC_PIN6) | \ + PIN_OSPEED_HIGH(GPIOC_PIN7) | \ + PIN_OSPEED_HIGH(GPIOC_PIN8) | \ + PIN_OSPEED_HIGH(GPIOC_PIN9) | \ + PIN_OSPEED_HIGH(GPIOC_PIN10) | \ + PIN_OSPEED_HIGH(GPIOC_PIN11) | \ + PIN_OSPEED_HIGH(GPIOC_PIN12) | \ + PIN_OSPEED_HIGH(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN14) | \ + PIN_OSPEED_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_ADC2_IN10) |\ + PIN_PUPDR_FLOATING(GPIOC_ADC2_IN11) | \ + PIN_PUPDR_FLOATING(GPIOC_ADC3_IN12) | \ + PIN_PUPDR_FLOATING(GPIOC_ADC3_IN13) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN15)) +#define VAL_GPIOC_ODR (PIN_ODR_LOW(GPIOC_ADC2_IN10) | \ + PIN_ODR_LOW(GPIOC_ADC2_IN11) | \ + PIN_ODR_LOW(GPIOC_ADC3_IN12) | \ + PIN_ODR_LOW(GPIOC_ADC3_IN13) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_PIN7) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_PIN14) | \ + PIN_ODR_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ADC2_IN10, 0U) |\ + PIN_AFIO_AF(GPIOC_ADC2_IN11, 0U) | \ + PIN_AFIO_AF(GPIOC_ADC3_IN12, 0U) | \ + PIN_AFIO_AF(GPIOC_ADC3_IN13, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN7, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN15, 0U)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - RESET (output pushpull maximum). + * PD5 - OVER_CURRENT (input floating). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD10 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - LED4 (output pushpull maximum). + * PD13 - LED3 (output pushpull maximum). + * PD14 - LED5 (output pushpull maximum). + * PD15 - LED6 (output pushpull maximum). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_RESET) | \ + PIN_MODE_INPUT(GPIOD_OVER_CURRENT) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_LED4) | \ + PIN_MODE_INPUT(GPIOD_LED3) | \ + PIN_MODE_INPUT(GPIOD_LED5) | \ + PIN_MODE_INPUT(GPIOD_LED6)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_RESET) | \ + PIN_OTYPE_PUSHPULL(GPIOD_OVER_CURRENT) |\ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_LED4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_LED3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_LED5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_LED6)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \ + PIN_OSPEED_HIGH(GPIOD_PIN1) | \ + PIN_OSPEED_HIGH(GPIOD_PIN2) | \ + PIN_OSPEED_HIGH(GPIOD_PIN3) | \ + PIN_OSPEED_HIGH(GPIOD_RESET) | \ + PIN_OSPEED_HIGH(GPIOD_OVER_CURRENT) | \ + PIN_OSPEED_HIGH(GPIOD_PIN6) | \ + PIN_OSPEED_HIGH(GPIOD_PIN7) | \ + PIN_OSPEED_HIGH(GPIOD_PIN8) | \ + PIN_OSPEED_HIGH(GPIOD_PIN9) | \ + PIN_OSPEED_HIGH(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_PIN11) | \ + PIN_OSPEED_HIGH(GPIOD_LED4) | \ + PIN_OSPEED_HIGH(GPIOD_LED3) | \ + PIN_OSPEED_HIGH(GPIOD_LED5) | \ + PIN_OSPEED_HIGH(GPIOD_LED6)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_RESET) | \ + PIN_PUPDR_PULLUP(GPIOD_OVER_CURRENT) |\ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_LED4) | \ + PIN_PUPDR_PULLUP(GPIOD_LED3) | \ + PIN_PUPDR_PULLUP(GPIOD_LED5) | \ + PIN_PUPDR_PULLUP(GPIOD_LED6)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_RESET) | \ + PIN_ODR_HIGH(GPIOD_OVER_CURRENT) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_LED4) | \ + PIN_ODR_HIGH(GPIOD_LED3) | \ + PIN_ODR_HIGH(GPIOD_LED5) | \ + PIN_ODR_HIGH(GPIOD_LED6)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOD_RESET, 0U) | \ + PIN_AFIO_AF(GPIOD_OVER_CURRENT, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOD_LED4, 0U) | \ + PIN_AFIO_AF(GPIOD_LED3, 0U) | \ + PIN_AFIO_AF(GPIOD_LED5, 0U) | \ + PIN_AFIO_AF(GPIOD_LED6, 0U)) + +/* + * GPIOE setup: + * + * PE0 - INT1 (input floating). + * PE1 - INT2 (input floating). + * PE2 - PIN2 (input floating). + * PE3 - CS_SPI (output pushpull maximum). + * PE4 - PIN4 (input floating). + * PE5 - PIN5 (input floating). + * PE6 - PIN6 (input floating). + * PE7 - PIN7 (input floating). + * PE8 - PIN8 (input floating). + * PE9 - PIN9 (input floating). + * PE10 - PIN10 (input floating). + * PE11 - PIN11 (input floating). + * PE12 - PIN12 (input floating). + * PE13 - PIN13 (input floating). + * PE14 - PIN14 (input floating). + * PE15 - PIN15 (input floating). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_INT1) | \ + PIN_MODE_INPUT(GPIOE_INT2) | \ + PIN_MODE_INPUT(GPIOE_PIN2) | \ + PIN_MODE_INPUT(GPIOE_CS_SPI) | \ + PIN_MODE_INPUT(GPIOE_PIN4) | \ + PIN_MODE_INPUT(GPIOE_PIN5) | \ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_INPUT(GPIOE_PIN8) | \ + PIN_MODE_INPUT(GPIOE_PIN9) | \ + PIN_MODE_INPUT(GPIOE_PIN10) | \ + PIN_MODE_INPUT(GPIOE_PIN11) | \ + PIN_MODE_INPUT(GPIOE_PIN12) | \ + PIN_MODE_INPUT(GPIOE_PIN13) | \ + PIN_MODE_INPUT(GPIOE_PIN14) | \ + PIN_MODE_INPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_INT1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_INT2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_CS_SPI) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_INT1) | \ + PIN_OSPEED_HIGH(GPIOE_INT2) | \ + PIN_OSPEED_HIGH(GPIOE_PIN2) | \ + PIN_OSPEED_HIGH(GPIOE_CS_SPI) | \ + PIN_OSPEED_HIGH(GPIOE_PIN4) | \ + PIN_OSPEED_HIGH(GPIOE_PIN5) | \ + PIN_OSPEED_HIGH(GPIOE_PIN6) | \ + PIN_OSPEED_HIGH(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_INT1) | \ + PIN_PUPDR_FLOATING(GPIOE_INT2) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOE_CS_SPI) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_INT1) | \ + PIN_ODR_HIGH(GPIOE_INT2) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_CS_SPI) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_HIGH(GPIOE_PIN8) | \ + PIN_ODR_HIGH(GPIOE_PIN9) | \ + PIN_ODR_HIGH(GPIOE_PIN10) | \ + PIN_ODR_HIGH(GPIOE_PIN11) | \ + PIN_ODR_HIGH(GPIOE_PIN12) | \ + PIN_ODR_HIGH(GPIOE_PIN13) | \ + PIN_ODR_HIGH(GPIOE_PIN14) | \ + PIN_ODR_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_INT1, 0U) | \ + PIN_AFIO_AF(GPIOE_INT2, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOE_CS_SPI, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0U)) + +/* + * GPIOF setup: + * + * PF0 - PIN0 (input floating). + * PF1 - PIN1 (input floating). + * PF2 - PIN2 (input floating). + * PF3 - PIN3 (input floating). + * PF4 - PIN4 (input floating). + * PF5 - PIN5 (input floating). + * PF6 - PIN6 (input floating). + * PF7 - PIN7 (input floating). + * PF8 - PIN8 (input floating). + * PF9 - PIN9 (input floating). + * PF10 - PIN10 (input floating). + * PF11 - PIN11 (input floating). + * PF12 - PIN12 (input floating). + * PF13 - PIN13 (input floating). + * PF14 - PIN14 (input floating). + * PF15 - PIN15 (input floating). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \ + PIN_MODE_INPUT(GPIOF_PIN1) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_PIN0) | \ + PIN_OSPEED_HIGH(GPIOF_PIN1) | \ + PIN_OSPEED_HIGH(GPIOF_PIN2) | \ + PIN_OSPEED_HIGH(GPIOF_PIN3) | \ + PIN_OSPEED_HIGH(GPIOF_PIN4) | \ + PIN_OSPEED_HIGH(GPIOF_PIN5) | \ + PIN_OSPEED_HIGH(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_PIN7) | \ + PIN_OSPEED_HIGH(GPIOF_PIN8) | \ + PIN_OSPEED_HIGH(GPIOF_PIN9) | \ + PIN_OSPEED_HIGH(GPIOF_PIN10) | \ + PIN_OSPEED_HIGH(GPIOF_PIN11) | \ + PIN_OSPEED_HIGH(GPIOF_PIN12) | \ + PIN_OSPEED_HIGH(GPIOF_PIN13) | \ + PIN_OSPEED_HIGH(GPIOF_PIN14) | \ + PIN_OSPEED_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \ + PIN_ODR_HIGH(GPIOF_PIN1) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0U)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input floating). + * PG1 - PIN1 (input floating). + * PG2 - PIN2 (input floating). + * PG3 - PIN3 (input floating). + * PG4 - PIN4 (input floating). + * PG5 - PIN5 (input floating). + * PG6 - PIN6 (input floating). + * PG7 - PIN7 (input floating). + * PG8 - PIN8 (input floating). + * PG9 - PIN9 (input floating). + * PG10 - PIN10 (input floating). + * PG11 - PIN11 (input floating). + * PG12 - PIN12 (input floating). + * PG13 - PIN13 (input floating). + * PG14 - PIN14 (input floating). + * PG15 - PIN15 (input floating). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_HIGH(GPIOG_PIN0) | \ + PIN_OSPEED_HIGH(GPIOG_PIN1) | \ + PIN_OSPEED_HIGH(GPIOG_PIN2) | \ + PIN_OSPEED_HIGH(GPIOG_PIN3) | \ + PIN_OSPEED_HIGH(GPIOG_PIN4) | \ + PIN_OSPEED_HIGH(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_PIN6) | \ + PIN_OSPEED_HIGH(GPIOG_PIN7) | \ + PIN_OSPEED_HIGH(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_PIN9) | \ + PIN_OSPEED_HIGH(GPIOG_PIN10) | \ + PIN_OSPEED_HIGH(GPIOG_PIN11) | \ + PIN_OSPEED_HIGH(GPIOG_PIN12) | \ + PIN_OSPEED_HIGH(GPIOG_PIN13) | \ + PIN_OSPEED_HIGH(GPIOG_PIN14) | \ + PIN_OSPEED_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_FLOATING(GPIOG_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input floating). + * PH3 - PIN3 (input floating). + * PH4 - PIN4 (input floating). + * PH5 - PIN5 (input floating). + * PH6 - PIN6 (input floating). + * PH7 - PIN7 (input floating). + * PH8 - PIN8 (input floating). + * PH9 - PIN9 (input floating). + * PH10 - PIN10 (input floating). + * PH11 - PIN11 (input floating). + * PH12 - PIN12 (input floating). + * PH13 - PIN13 (input floating). + * PH14 - PIN14 (input floating). + * PH15 - PIN15 (input floating). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_HIGH(GPIOH_PIN2) | \ + PIN_OSPEED_HIGH(GPIOH_PIN3) | \ + PIN_OSPEED_HIGH(GPIOH_PIN4) | \ + PIN_OSPEED_HIGH(GPIOH_PIN5) | \ + PIN_OSPEED_HIGH(GPIOH_PIN6) | \ + PIN_OSPEED_HIGH(GPIOH_PIN7) | \ + PIN_OSPEED_HIGH(GPIOH_PIN8) | \ + PIN_OSPEED_HIGH(GPIOH_PIN9) | \ + PIN_OSPEED_HIGH(GPIOH_PIN10) | \ + PIN_OSPEED_HIGH(GPIOH_PIN11) | \ + PIN_OSPEED_HIGH(GPIOH_PIN12) | \ + PIN_OSPEED_HIGH(GPIOH_PIN13) | \ + PIN_OSPEED_HIGH(GPIOH_PIN14) | \ + PIN_OSPEED_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input floating). + * PI1 - PIN1 (input floating). + * PI2 - PIN2 (input floating). + * PI3 - PIN3 (input floating). + * PI4 - PIN4 (input floating). + * PI5 - PIN5 (input floating). + * PI6 - PIN6 (input floating). + * PI7 - PIN7 (input floating). + * PI8 - PIN8 (input floating). + * PI9 - PIN9 (input floating). + * PI10 - PIN10 (input floating). + * PI11 - PIN11 (input floating). + * PI12 - PIN12 (input floating). + * PI13 - PIN13 (input floating). + * PI14 - PIN14 (input floating). + * PI15 - PIN15 (input floating). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_HIGH(GPIOI_PIN0) | \ + PIN_OSPEED_HIGH(GPIOI_PIN1) | \ + PIN_OSPEED_HIGH(GPIOI_PIN2) | \ + PIN_OSPEED_HIGH(GPIOI_PIN3) | \ + PIN_OSPEED_HIGH(GPIOI_PIN4) | \ + PIN_OSPEED_HIGH(GPIOI_PIN5) | \ + PIN_OSPEED_HIGH(GPIOI_PIN6) | \ + PIN_OSPEED_HIGH(GPIOI_PIN7) | \ + PIN_OSPEED_HIGH(GPIOI_PIN8) | \ + PIN_OSPEED_HIGH(GPIOI_PIN9) | \ + PIN_OSPEED_HIGH(GPIOI_PIN10) | \ + PIN_OSPEED_HIGH(GPIOI_PIN11) | \ + PIN_OSPEED_HIGH(GPIOI_PIN12) | \ + PIN_OSPEED_HIGH(GPIOI_PIN13) | \ + PIN_OSPEED_HIGH(GPIOI_PIN14) | \ + PIN_OSPEED_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_FLOATING(GPIOI_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + +/* + * GPIOJ setup: + * + * PJ0 - PIN0 (input floating). + * PJ1 - PIN1 (input floating). + * PJ2 - PIN2 (input floating). + * PJ3 - PIN3 (input floating). + * PJ4 - PIN4 (input floating). + * PJ5 - PIN5 (input floating). + * PJ6 - PIN6 (input floating). + * PJ7 - PIN7 (input floating). + * PJ8 - PIN8 (input floating). + * PJ9 - PIN9 (input floating). + * PJ10 - PIN10 (input floating). + * PJ11 - PIN11 (input floating). + * PJ12 - PIN12 (input floating). + * PJ13 - PIN13 (input floating). + * PJ14 - PIN14 (input floating). + * PJ15 - PIN15 (input floating). + */ +#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \ + PIN_MODE_INPUT(GPIOJ_PIN1) | \ + PIN_MODE_INPUT(GPIOJ_PIN2) | \ + PIN_MODE_INPUT(GPIOJ_PIN3) | \ + PIN_MODE_INPUT(GPIOJ_PIN4) | \ + PIN_MODE_INPUT(GPIOJ_PIN5) | \ + PIN_MODE_INPUT(GPIOJ_PIN6) | \ + PIN_MODE_INPUT(GPIOJ_PIN7) | \ + PIN_MODE_INPUT(GPIOJ_PIN8) | \ + PIN_MODE_INPUT(GPIOJ_PIN9) | \ + PIN_MODE_INPUT(GPIOJ_PIN10) | \ + PIN_MODE_INPUT(GPIOJ_PIN11) | \ + PIN_MODE_INPUT(GPIOJ_PIN12) | \ + PIN_MODE_INPUT(GPIOJ_PIN13) | \ + PIN_MODE_INPUT(GPIOJ_PIN14) | \ + PIN_MODE_INPUT(GPIOJ_PIN15)) +#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN15)) +#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_HIGH(GPIOJ_PIN0) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN1) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN2) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN3) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN4) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN5) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN6) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN7) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN8) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN9) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN10) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN11) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN12) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN13) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN14) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_PUPDR (PIN_PUPDR_FLOATING(GPIOJ_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN15)) +#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \ + PIN_ODR_HIGH(GPIOJ_PIN1) | \ + PIN_ODR_HIGH(GPIOJ_PIN2) | \ + PIN_ODR_HIGH(GPIOJ_PIN3) | \ + PIN_ODR_HIGH(GPIOJ_PIN4) | \ + PIN_ODR_HIGH(GPIOJ_PIN5) | \ + PIN_ODR_HIGH(GPIOJ_PIN6) | \ + PIN_ODR_HIGH(GPIOJ_PIN7) | \ + PIN_ODR_HIGH(GPIOJ_PIN8) | \ + PIN_ODR_HIGH(GPIOJ_PIN9) | \ + PIN_ODR_HIGH(GPIOJ_PIN10) | \ + PIN_ODR_HIGH(GPIOJ_PIN11) | \ + PIN_ODR_HIGH(GPIOJ_PIN12) | \ + PIN_ODR_HIGH(GPIOJ_PIN13) | \ + PIN_ODR_HIGH(GPIOJ_PIN14) | \ + PIN_ODR_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN7, 0U)) +#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN15, 0U)) + +/* + * GPIOK setup: + * + * PK0 - PIN0 (input floating). + * PK1 - PIN1 (input floating). + * PK2 - PIN2 (input floating). + * PK3 - PIN3 (input floating). + * PK4 - PIN4 (input floating). + * PK5 - PIN5 (input floating). + * PK6 - PIN6 (input floating). + * PK7 - PIN7 (input floating). + * PK8 - PIN8 (input floating). + * PK9 - PIN9 (input floating). + * PK10 - PIN10 (input floating). + * PK11 - PIN11 (input floating). + * PK12 - PIN12 (input floating). + * PK13 - PIN13 (input floating). + * PK14 - PIN14 (input floating). + * PK15 - PIN15 (input floating). + */ +#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \ + PIN_MODE_INPUT(GPIOK_PIN1) | \ + PIN_MODE_INPUT(GPIOK_PIN2) | \ + PIN_MODE_INPUT(GPIOK_PIN3) | \ + PIN_MODE_INPUT(GPIOK_PIN4) | \ + PIN_MODE_INPUT(GPIOK_PIN5) | \ + PIN_MODE_INPUT(GPIOK_PIN6) | \ + PIN_MODE_INPUT(GPIOK_PIN7) | \ + PIN_MODE_INPUT(GPIOK_PIN8) | \ + PIN_MODE_INPUT(GPIOK_PIN9) | \ + PIN_MODE_INPUT(GPIOK_PIN10) | \ + PIN_MODE_INPUT(GPIOK_PIN11) | \ + PIN_MODE_INPUT(GPIOK_PIN12) | \ + PIN_MODE_INPUT(GPIOK_PIN13) | \ + PIN_MODE_INPUT(GPIOK_PIN14) | \ + PIN_MODE_INPUT(GPIOK_PIN15)) +#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN15)) +#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_HIGH(GPIOK_PIN0) | \ + PIN_OSPEED_HIGH(GPIOK_PIN1) | \ + PIN_OSPEED_HIGH(GPIOK_PIN2) | \ + PIN_OSPEED_HIGH(GPIOK_PIN3) | \ + PIN_OSPEED_HIGH(GPIOK_PIN4) | \ + PIN_OSPEED_HIGH(GPIOK_PIN5) | \ + PIN_OSPEED_HIGH(GPIOK_PIN6) | \ + PIN_OSPEED_HIGH(GPIOK_PIN7) | \ + PIN_OSPEED_HIGH(GPIOK_PIN8) | \ + PIN_OSPEED_HIGH(GPIOK_PIN9) | \ + PIN_OSPEED_HIGH(GPIOK_PIN10) | \ + PIN_OSPEED_HIGH(GPIOK_PIN11) | \ + PIN_OSPEED_HIGH(GPIOK_PIN12) | \ + PIN_OSPEED_HIGH(GPIOK_PIN13) | \ + PIN_OSPEED_HIGH(GPIOK_PIN14) | \ + PIN_OSPEED_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_PUPDR (PIN_PUPDR_FLOATING(GPIOK_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN15)) +#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \ + PIN_ODR_HIGH(GPIOK_PIN1) | \ + PIN_ODR_HIGH(GPIOK_PIN2) | \ + PIN_ODR_HIGH(GPIOK_PIN3) | \ + PIN_ODR_HIGH(GPIOK_PIN4) | \ + PIN_ODR_HIGH(GPIOK_PIN5) | \ + PIN_ODR_HIGH(GPIOK_PIN6) | \ + PIN_ODR_HIGH(GPIOK_PIN7) | \ + PIN_ODR_HIGH(GPIOK_PIN8) | \ + PIN_ODR_HIGH(GPIOK_PIN9) | \ + PIN_ODR_HIGH(GPIOK_PIN10) | \ + PIN_ODR_HIGH(GPIOK_PIN11) | \ + PIN_ODR_HIGH(GPIOK_PIN12) | \ + PIN_ODR_HIGH(GPIOK_PIN13) | \ + PIN_ODR_HIGH(GPIOK_PIN14) | \ + PIN_ODR_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN7, 0U)) +#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN15, 0U)) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/CMakeLists.txt new file mode 100644 index 00000000..aa7f1d54 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..c0759ead --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,94 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 08008000 nanoCLR +}; + +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage.c new file mode 100644 index 00000000..b05efe0e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/Device_BlockStorage.c @@ -0,0 +1,94 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 08004000 nanoCLR +}; + +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.c new file mode 100644 index 00000000..a048c76f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.c @@ -0,0 +1,435 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD1. + */ +#define USBD1_DATA_REQUEST_EP 1 +#define USBD1_DATA_AVAILABLE_EP 1 +#define USBD1_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"STMicroelectronics" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"nanoFramework Virtual COM Port" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[18] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[67] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(67, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + sduRequestsHook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD1_DATA_REQUEST_EP, + USBD1_DATA_AVAILABLE_EP, + USBD1_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.h new file mode 100644 index 00000000..167e1df8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/common/usbcfg.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Adc.cs new file mode 100644 index 00000000..f73100be --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Adc.cs @@ -0,0 +1,48 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.Community.GHI_FEZ_CERB40_NF +{ + /// + /// Enumeration of ADC channels available in the community board GHI_FEZ_CERB40_NF + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed on PC0, connected to PC0 (ADC2 - IN10) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed on PA1, connected to PA1 (ADC2 - IN11) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed on PA4, connected to PA4 (ADC3 - IN12) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, exposed on PC3, connected to PC3 (ADC3 - IN13) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 4; + + /// + /// Channel 5, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 5; + + /// + /// Channel 6, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 6; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Gpio.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Gpio.cs new file mode 100644 index 00000000..d10d066e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/GHI_FEZ_CERB40_NF.Gpio.cs @@ -0,0 +1,55 @@ +using System; + +namespace nanoFramework.Targets.Community.GHI_FEZ_CERB40_NF +{ + public static class Gpio + { + /// + /// + /// + public const int PA0 = 0; + public const int PA1 = 1; + public const int PA2 = 2; + public const int PA3 = 3; + public const int PA4 = 4; + public const int PA5 = 5; + public const int PA6 = 6; + public const int PA7 = 7; + public const int PA8 = 8; + public const int PA9 = 9; + public const int PA10 = 10; + public const int PA11 = 11; + public const int PA12 = 12; + public const int PA13 = 13; + public const int PA14 = 14; + public const int PA15 = 15; + + /// + /// + /// + public const int PB0 = 16; + public const int PB1 = 17; + public const int PB2 = 18; + public const int PB3 = 19; + public const int PB4 = 20; + public const int PB5 = 21; + public const int PB6 = 22; + public const int PB7 = 23; + public const int PB8 = 24; + public const int PB9 = 25; + public const int PB10 = 26; + public const int PB11 = 27; + public const int PB12 = 28; + public const int PB13 = 29; + public const int PB14 = 30; + public const int PB15 = 31; + + /// + /// + /// + public const int PC0 = 32; + public const int PC1 = 33; + public const int PC2 = 34; + public const int PC3 = 35; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/README.md new file mode 100644 index 00000000..a749a3ce --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/managed_helpers/README.md @@ -0,0 +1,6 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](GHI_FEZ_CERB40_NF.Adc.cs) +* [Gpio](GHI_FEZ_CERB40_NF.Gpio.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter-DEBUG.ld new file mode 100644 index 00000000..740054ed --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F405xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08008000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter.ld new file mode 100644 index 00000000..f79d8294 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/STM32F405xG_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F405xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08004000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/chconf.h new file mode 100644 index 00000000..335e3fa4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf.h new file mode 100644 index 00000000..b970c22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/main.c new file mode 100644 index 00000000..521b0f7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/main.c @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + osDelay(20); // Let init stabilize + + // check for valid CLR image + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOB, GPIOB_PIN5); + osDelay(500); + palClearPad(GPIOB, GPIOB_PIN5); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf.h new file mode 100644 index 00000000..5ed72f99 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf.h @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F405_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED FALSE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 6 +#define STM32_PLLN_VALUE 168 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR-DEBUG.ld new file mode 100644 index 00000000..d3630a67 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F405xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 1M - 32k - 768k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 768k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR.ld new file mode 100644 index 00000000..a9114720 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/STM32F405xG_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F405xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 1M - 16k - 768k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 768k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/chconf.h new file mode 100644 index 00000000..390ce3a6 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf.h new file mode 100644 index 00000000..a1e2b875 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf.h @@ -0,0 +1,525 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..6e46ee50 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/halconf_nf.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +// enables STM32 Can driver +#if !defined(HAL_USE_STM32_CAN) +#define HAL_USE_STM32_CAN FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/main.c new file mode 100644 index 00000000..b6e22be3 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/main.c @@ -0,0 +1,74 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf.h new file mode 100644 index 00000000..7365203d --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf.h @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F405_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 6 +#define STM32_PLLN_VALUE 168 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 TRUE +#define STM32_ADC_USE_ADC3 TRUE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 TRUE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 TRUE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/resources/cerb40-top.PNG b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/resources/cerb40-top.PNG new file mode 100644 index 0000000000000000000000000000000000000000..e0f346c7e8fbfa16affb9ab063dba31bf1c613ff GIT binary patch literal 499810 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

;Z4MLoSdYD!-M;9~Rn5bc~NH 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

8XQCA*jj3wOGYcQmb)CfF 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 literal 0 HcmV?d00001 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.c new file mode 100644 index 00000000..c70f5865 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.c @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" +#include + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; + +// this target uses DFU for updates +uint32_t GetTargetCapabilities() +{ + return TargetCapabilities_DfuUpdate; +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.h.in new file mode 100644 index 00000000..89d68da4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00020000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00100000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..cd9ed56a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_adc_config.cpp @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC2 + {2, GPIOC, 0, ADC_CHANNEL_IN10}, + {2, GPIOC, 1, ADC_CHANNEL_IN11}, + + // ADC3 + {3, GPIOC, 2, ADC_CHANNEL_IN12}, + {3, GPIOC, 3, ADC_CHANNEL_IN13}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..534f821a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_i2c_config.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) + +////////// +// I2C2 // +////////// + +// pin configuration for I2C2 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_10 +// SDA pin: is GPIOB_11 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(2, GPIOB, GPIOB, 10, 11, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..fe9517a6 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART1 // +/////////// + +// pin configuration for UART1 +// port: GPIOB +// TX pin: is GPIOB_6 +// RX pin: is GPIOB_7 +// GPIO alternate pin function is 7 (see "Table 9. Alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +UART_CONFIG_PINS(1, GPIOB, GPIOB, 6, 7, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_TxBuffer[UART1_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_RxBuffer[UART1_RX_SIZE]; + +// initialization for UART1 +UART_INIT(1, UART1_TX_SIZE, UART1_RX_SIZE) + +// un-initialization for UART1 +UART_UNINIT(1) + +/////////// +// UART2 // +/////////// + +// pin configuration for UART2 +// port: GPIOA +// TX pin: is GPIOA_2 +// RX pin: is GPIOA_3 +// GPIO alternate pin function is 7 (see "Table 9. Alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +UART_CONFIG_PINS(2, GPIOA, GPIOA, 2, 3, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// initialization for UART2 +UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// un-initialization for UART2 +UART_UNINIT(2) + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..dc1de238 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +/////////// +// UART1 // +/////////// + +// enable USART1 +#define NF_SERIAL_COMM_STM32_UART_USE_USART1 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART1_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART1_RX_SIZE 256 + + +/////////// +// UART2 // +/////////// + +// enable USART2 +#define NF_SERIAL_COMM_STM32_UART_USE_USART2 TRUE + +// buffers size +// tx buffer size: 1024 bytes +#define UART2_TX_SIZE 1024 +// rx buffer size: 1024 bytes +#define UART2_RX_SIZE 1024 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..ef2d3a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/CMakeLists.txt new file mode 100644 index 00000000..513bffbe --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/CMakeLists.txt @@ -0,0 +1,212 @@ +# +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker file +nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F411xE_booter.ld) +nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F411xE_CLR.ld) + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x1000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x2800") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) + +# if HEX2DFU tool is available pack the binaries into a DFU package +if(HEX2DFU_TOOL_AVAILABLE) + + #################################################################################################### + ## when changing the linker file make sure to update the new addresses for the image files bellow ## + ## DO NOT use the leading 0x notation, just the address in plain hexadecimal formating ## + #################################################################################################### + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08008000 + ${PROJECT_SOURCE_DIR}/build/nanoframework-4-electron.dfu + ) + +endif() diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/README.md new file mode 100644 index 00000000..b3735442 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/README.md @@ -0,0 +1,17 @@ + + +## Electron community board ## + +The board used in this community contribution is a STM32F411CEU6 based board from IngenuityMicro called Electron. The board has only 12 pins of which 3 are already used for 3.3V, 5V and GND, leaving use of only 9 pins. + +These pins can be used for: + +- 1 x TX/RX +- 4 x PWM +- 4 X ADC +- 1 x I2C +- 1 x SPI + +In addition, the board has two on-board LEDs connected to PA1 and PA8 and are tested for use as GPIO, PWM. + +Further information can be found on http://www.ingenuitymicro.com/products/electron/ where firmware, board layout and schema can be found. diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.c new file mode 100644 index 00000000..6f55c3bf --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.c @@ -0,0 +1,265 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.h new file mode 100644 index 00000000..5d7f0d7c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/board.h @@ -0,0 +1,1607 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This is the a board made by IngenuityMicro based upon MCU from ST + * the STM32F411CEU6. The board is equipped with both LSE and HSE. + * Details can be found on + * + * http://www.ingenuitymicro.com/products/electron/ + * + * for various firmware, board layout and schematic. + */ + +#ifndef BOARD_H +#define BOARD_H + +/* + * Setup for the IngenuityMicro Electron board based upon an STM32F411CEU6. + */ + +/* + * Board identifier. + */ +#define BOARD_I2M_ELECTRON_NF +#define BOARD_NAME "IngenuityMicro Electron" + +/* + * USB OTG Force + */ +#define BOARD_OTG_NOVBUSSENS + +/* + * Completely wacko definition of a flash sector here + */ +#define FLASH_SECTOR_11 ((uint32_t)11U) + +/* + * Board oscillators-related settings. + * NOTE: LSE is fitted and is of course 32768. + * NOTE: HSE is fitted and set to a 12 MHz one. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 12000000U +#endif + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F411xE + +/* + * IO pins assignments. + */ +#define GPIOA_PIN0 0U +#define GPIOA_LED_GREEN 1U +#define GPIOA_PIN2 2U +#define GPIOA_PIN3 3U +#define GPIOA_ADC1_4 4U +#define GPIOA_ADC1_5 5U +#define GPIOA_PIN6 6U +#define GPIOA_PIN7 7U +#define GPIOA_LED_BLUE 8U +#define GPIOA_PIN9 9U +#define GPIOA_PIN10 10U +#define GPIOA_OTG_FS_DM 11U +#define GPIOA_OTG_FS_DP 12U +#define GPIOA_PIN13 13U +#define GPIOA_PIN14 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_SPI1_CLK 3U +#define GPIOB_SPI1_MISO 4U +#define GPIOB_SPI1_MOSI 5U +#define GPIOB_I2C1_SCL 6U +#define GPIOB_I2C1_SDA 7U +#define GPIOB_PIN8 8U +#define GPIOB_PIN9 9U +#define GPIOB_PIN10 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_PIN13 13U +#define GPIOB_PIN14 14U +#define GPIOB_PIN15 15U + +#define GPIOC_PIN0 0U +#define GPIOC_PIN1 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_PIN7 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_PIN14 14U +#define GPIOC_PIN15 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_PIN0 0U +#define GPIOF_PIN1 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +#define GPIOJ_PIN0 0U +#define GPIOJ_PIN1 1U +#define GPIOJ_PIN2 2U +#define GPIOJ_PIN3 3U +#define GPIOJ_PIN4 4U +#define GPIOJ_PIN5 5U +#define GPIOJ_PIN6 6U +#define GPIOJ_PIN7 7U +#define GPIOJ_PIN8 8U +#define GPIOJ_PIN9 9U +#define GPIOJ_PIN10 10U +#define GPIOJ_PIN11 11U +#define GPIOJ_PIN12 12U +#define GPIOJ_PIN13 13U +#define GPIOJ_PIN14 14U +#define GPIOJ_PIN15 15U + +#define GPIOK_PIN0 0U +#define GPIOK_PIN1 1U +#define GPIOK_PIN2 2U +#define GPIOK_PIN3 3U +#define GPIOK_PIN4 4U +#define GPIOK_PIN5 5U +#define GPIOK_PIN6 6U +#define GPIOK_PIN7 7U +#define GPIOK_PIN8 8U +#define GPIOK_PIN9 9U +#define GPIOK_PIN10 10U +#define GPIOK_PIN11 11U +#define GPIOK_PIN12 12U +#define GPIOK_PIN13 13U +#define GPIOK_PIN14 14U +#define GPIOK_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_LED_GREEN PAL_LINE(GPIOA, 1U) +#define LINE_PIN2 PAL_LINE(GPIOA, 2U) +#define LINE_PIN3 PAL_LINE(GPIOA, 3U) +#define LINE_PIN4 PAL_LINE(GPIOA, 4U) +#define LINE_LED_BLUE PAL_LINE(GPIOA, 8U) +#define LINE_OTG_FS_DM PAL_LINE(GPIOA, 11U) +#define LINE_OTG_FS_DP PAL_LINE(GPIOA, 12U) + +#define LINE_SPI1_CLK PAL_LINE(GPIOB, 3U) +#define LINE_SPI1_MISO PAL_LINE(GPIOB, 4U) +#define LINE_SPI1_MOSI PAL_LINE(GPIOB, 5U) +#define LINE_I2C1_SCL PAL_LINE(GPIOB, 6U) +#define LINE_I2C1_SDA PAL_LINE(GPIOB, 7U) + +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) + +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - PIN0 (input pullup). + * PA1 - LED_GREEN (output pushpull high). + * PA2 - USART_TX (alternate 7). + * PA3 - USART_RX (alternate 7). + * PA4 - ADC1_4 (input analog). + * PA5 - ADC1_5 (input analog). + * PA6 - PIN6 (input pullup). + * PA7 - PIN7 (input pullup). + * PA8 - LED_BLUE (output pushpull high). + * PA9 - PIN9 (input pullup). + * PA10 - PIN10 (input pullup). + * PA11 - OTG_FS_DM (alternate 10). + * PA12 - OTG_FS_DP (alternate 10). + * PA13 - PIN13 (input pullup). + * PA14 - PIN14 (input pullup). + * PA15 - PIN15 (input pullup). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ + PIN_MODE_OUTPUT(GPIOA_LED_GREEN) | \ + PIN_MODE_ALTERNATE(GPIOA_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOA_PIN3) | \ + PIN_MODE_ANALOG(GPIOA_ADC1_4) | \ + PIN_MODE_ANALOG(GPIOA_ADC1_5) | \ + PIN_MODE_INPUT(GPIOA_PIN6) | \ + PIN_MODE_INPUT(GPIOA_PIN7) | \ + PIN_MODE_OUTPUT(GPIOA_LED_BLUE) | \ + PIN_MODE_INPUT(GPIOA_PIN9) | \ + PIN_MODE_INPUT(GPIOA_PIN10) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DP) | \ + PIN_MODE_INPUT(GPIOA_PIN13) | \ + PIN_MODE_INPUT(GPIOA_PIN14) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_LED_GREEN) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ADC1_4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ADC1_5) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_LED_BLUE) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_PIN0) | \ + PIN_OSPEED_MEDIUM(GPIOA_LED_GREEN) | \ + PIN_OSPEED_HIGH(GPIOA_PIN2) | \ + PIN_OSPEED_HIGH(GPIOA_PIN3) | \ + PIN_OSPEED_HIGH(GPIOA_ADC1_4) | \ + PIN_OSPEED_HIGH(GPIOA_ADC1_5) | \ + PIN_OSPEED_HIGH(GPIOA_PIN6) | \ + PIN_OSPEED_HIGH(GPIOA_PIN7) | \ + PIN_OSPEED_MEDIUM(GPIOA_LED_BLUE) | \ + PIN_OSPEED_HIGH(GPIOA_PIN9) | \ + PIN_OSPEED_HIGH(GPIOA_PIN10) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_OSPEED_HIGH(GPIOA_PIN13) | \ + PIN_OSPEED_HIGH(GPIOA_PIN14) | \ + PIN_OSPEED_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOA_LED_GREEN) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOA_ADC1_4) | \ + PIN_PUPDR_FLOATING(GPIOA_ADC1_5) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOA_LED_BLUE) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \ + PIN_ODR_LOW(GPIOA_LED_GREEN) | \ + PIN_ODR_LOW(GPIOA_PIN2) | \ + PIN_ODR_LOW(GPIOA_PIN3) | \ + PIN_ODR_LOW(GPIOA_ADC1_4) | \ + PIN_ODR_LOW(GPIOA_ADC1_5) | \ + PIN_ODR_HIGH(GPIOA_PIN6) | \ + PIN_ODR_HIGH(GPIOA_PIN7) | \ + PIN_ODR_LOW(GPIOA_LED_BLUE) | \ + PIN_ODR_HIGH(GPIOA_PIN9) | \ + PIN_ODR_HIGH(GPIOA_PIN10) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_ODR_HIGH(GPIOA_PIN13) | \ + PIN_ODR_HIGH(GPIOA_PIN14) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOA_LED_GREEN, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN2, 7U) | \ + PIN_AFIO_AF(GPIOA_PIN3, 7U) | \ + PIN_AFIO_AF(GPIOA_ADC1_4, 0U) | \ + PIN_AFIO_AF(GPIOA_ADC1_5, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN7, 0U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_LED_BLUE, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0U)) + +/* + * GPIOB setup: + * + * PB0 - PIN0 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - SPI1_CLK (alternate 5). + * PB4 - SPI1_MISO (alternate 5). + * PB5 - SPI1_MOSI (alternate 5). + * PB6 - I2C1_SCL (alternate 4). + * PB7 - I2C1_SDA (alternate 4). + * PB8 - PIN8 (input pullup). + * PB9 - PIN9 (input pullup). + * PB10 - PIN10 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - PIN13 (input pullup). + * PB14 - PIN14 (input pullup). + * PB15 - PIN15 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI1_CLK) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI1_MISO) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI1_MOSI) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_INPUT(GPIOB_PIN8) | \ + PIN_MODE_INPUT(GPIOB_PIN9) | \ + PIN_MODE_INPUT(GPIOB_PIN10) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_INPUT(GPIOB_PIN13) | \ + PIN_MODE_INPUT(GPIOB_PIN14) | \ + PIN_MODE_INPUT(GPIOB_PIN15)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI1_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI1_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI1_MOSI) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_PIN0) | \ + PIN_OSPEED_HIGH(GPIOB_PIN1) | \ + PIN_OSPEED_HIGH(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_SPI1_CLK) | \ + PIN_OSPEED_HIGH(GPIOB_SPI1_MISO) | \ + PIN_OSPEED_HIGH(GPIOB_SPI1_MOSI) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_PIN8) | \ + PIN_OSPEED_HIGH(GPIOB_PIN9) | \ + PIN_OSPEED_HIGH(GPIOB_PIN10) | \ + PIN_OSPEED_HIGH(GPIOB_PIN11) | \ + PIN_OSPEED_HIGH(GPIOB_PIN12) | \ + PIN_OSPEED_HIGH(GPIOB_PIN13) | \ + PIN_OSPEED_HIGH(GPIOB_PIN14) | \ + PIN_OSPEED_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI1_CLK) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI1_MISO) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI1_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN15)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_LOW(GPIOB_SPI1_CLK) | \ + PIN_ODR_LOW(GPIOB_SPI1_MISO) | \ + PIN_ODR_LOW(GPIOB_SPI1_MOSI) | \ + PIN_ODR_LOW(GPIOB_I2C1_SCL) | \ + PIN_ODR_LOW(GPIOB_I2C1_SDA) | \ + PIN_ODR_HIGH(GPIOB_PIN8) | \ + PIN_ODR_HIGH(GPIOB_PIN9) | \ + PIN_ODR_HIGH(GPIOB_PIN10) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_HIGH(GPIOB_PIN13) | \ + PIN_ODR_HIGH(GPIOB_PIN14) | \ + PIN_ODR_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOB_SPI1_CLK, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI1_MISO, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI1_MOSI, 5U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN15, 0U)) + +/* + * GPIOC setup: + * + * PC0 - PIN0 (input pullup). + * PC1 - PIN1 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - PIN7 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - PIN10 (input pullup). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - PIN13 (input pullup). + * PC14 - PIN14 (input pullup). + * PC15 - PIN15 (input pullup). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ + PIN_MODE_INPUT(GPIOC_PIN1) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_PIN7) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_PIN14) | \ + PIN_MODE_INPUT(GPIOC_PIN15)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_PIN0) | \ + PIN_OSPEED_HIGH(GPIOC_PIN1) | \ + PIN_OSPEED_HIGH(GPIOC_PIN2) | \ + PIN_OSPEED_HIGH(GPIOC_PIN3) | \ + PIN_OSPEED_HIGH(GPIOC_PIN4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN5) | \ + PIN_OSPEED_HIGH(GPIOC_PIN6) | \ + PIN_OSPEED_HIGH(GPIOC_PIN7) | \ + PIN_OSPEED_HIGH(GPIOC_PIN8) | \ + PIN_OSPEED_HIGH(GPIOC_PIN9) | \ + PIN_OSPEED_HIGH(GPIOC_PIN10) | \ + PIN_OSPEED_HIGH(GPIOC_PIN11) | \ + PIN_OSPEED_HIGH(GPIOC_PIN12) | \ + PIN_OSPEED_HIGH(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN14) | \ + PIN_OSPEED_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN15)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ + PIN_ODR_HIGH(GPIOC_PIN1) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_PIN7) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_PIN14) | \ + PIN_ODR_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN7, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN15, 0U)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD10 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \ + PIN_OSPEED_HIGH(GPIOD_PIN1) | \ + PIN_OSPEED_HIGH(GPIOD_PIN2) | \ + PIN_OSPEED_HIGH(GPIOD_PIN3) | \ + PIN_OSPEED_HIGH(GPIOD_PIN4) | \ + PIN_OSPEED_HIGH(GPIOD_PIN5) | \ + PIN_OSPEED_HIGH(GPIOD_PIN6) | \ + PIN_OSPEED_HIGH(GPIOD_PIN7) | \ + PIN_OSPEED_HIGH(GPIOD_PIN8) | \ + PIN_OSPEED_HIGH(GPIOD_PIN9) | \ + PIN_OSPEED_HIGH(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_PIN11) | \ + PIN_OSPEED_HIGH(GPIOD_PIN12) | \ + PIN_OSPEED_HIGH(GPIOD_PIN13) | \ + PIN_OSPEED_HIGH(GPIOD_PIN14) | \ + PIN_OSPEED_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0U)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 (input pullup). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (input pullup). + * PE9 - PIN9 (input pullup). + * PE10 - PIN10 (input pullup). + * PE11 - PIN11 (input pullup). + * PE12 - PIN12 (input pullup). + * PE13 - PIN13 (input pullup). + * PE14 - PIN14 (input pullup). + * PE15 - PIN15 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) | \ + PIN_MODE_INPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) | \ + PIN_MODE_INPUT(GPIOE_PIN5) | \ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_INPUT(GPIOE_PIN8) | \ + PIN_MODE_INPUT(GPIOE_PIN9) | \ + PIN_MODE_INPUT(GPIOE_PIN10) | \ + PIN_MODE_INPUT(GPIOE_PIN11) | \ + PIN_MODE_INPUT(GPIOE_PIN12) | \ + PIN_MODE_INPUT(GPIOE_PIN13) | \ + PIN_MODE_INPUT(GPIOE_PIN14) | \ + PIN_MODE_INPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \ + PIN_OSPEED_HIGH(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_PIN2) | \ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_HIGH(GPIOE_PIN4) | \ + PIN_OSPEED_HIGH(GPIOE_PIN5) | \ + PIN_OSPEED_HIGH(GPIOE_PIN6) | \ + PIN_OSPEED_HIGH(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_HIGH(GPIOE_PIN8) | \ + PIN_ODR_HIGH(GPIOE_PIN9) | \ + PIN_ODR_HIGH(GPIOE_PIN10) | \ + PIN_ODR_HIGH(GPIOE_PIN11) | \ + PIN_ODR_HIGH(GPIOE_PIN12) | \ + PIN_ODR_HIGH(GPIOE_PIN13) | \ + PIN_ODR_HIGH(GPIOE_PIN14) | \ + PIN_ODR_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0U)) + +/* + * GPIOF setup: + * + * PF0 - PIN0 (input pullup). + * PF1 - PIN1 (input pullup). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \ + PIN_MODE_INPUT(GPIOF_PIN1) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_PIN0) | \ + PIN_OSPEED_HIGH(GPIOF_PIN1) | \ + PIN_OSPEED_HIGH(GPIOF_PIN2) | \ + PIN_OSPEED_HIGH(GPIOF_PIN3) | \ + PIN_OSPEED_HIGH(GPIOF_PIN4) | \ + PIN_OSPEED_HIGH(GPIOF_PIN5) | \ + PIN_OSPEED_HIGH(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_PIN7) | \ + PIN_OSPEED_HIGH(GPIOF_PIN8) | \ + PIN_OSPEED_HIGH(GPIOF_PIN9) | \ + PIN_OSPEED_HIGH(GPIOF_PIN10) | \ + PIN_OSPEED_HIGH(GPIOF_PIN11) | \ + PIN_OSPEED_HIGH(GPIOF_PIN12) | \ + PIN_OSPEED_HIGH(GPIOF_PIN13) | \ + PIN_OSPEED_HIGH(GPIOF_PIN14) | \ + PIN_OSPEED_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \ + PIN_ODR_HIGH(GPIOF_PIN1) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0U)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_HIGH(GPIOG_PIN0) | \ + PIN_OSPEED_HIGH(GPIOG_PIN1) | \ + PIN_OSPEED_HIGH(GPIOG_PIN2) | \ + PIN_OSPEED_HIGH(GPIOG_PIN3) | \ + PIN_OSPEED_HIGH(GPIOG_PIN4) | \ + PIN_OSPEED_HIGH(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_PIN6) | \ + PIN_OSPEED_HIGH(GPIOG_PIN7) | \ + PIN_OSPEED_HIGH(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_PIN9) | \ + PIN_OSPEED_HIGH(GPIOG_PIN10) | \ + PIN_OSPEED_HIGH(GPIOG_PIN11) | \ + PIN_OSPEED_HIGH(GPIOG_PIN12) | \ + PIN_OSPEED_HIGH(GPIOG_PIN13) | \ + PIN_OSPEED_HIGH(GPIOG_PIN14) | \ + PIN_OSPEED_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_HIGH(GPIOH_PIN2) | \ + PIN_OSPEED_HIGH(GPIOH_PIN3) | \ + PIN_OSPEED_HIGH(GPIOH_PIN4) | \ + PIN_OSPEED_HIGH(GPIOH_PIN5) | \ + PIN_OSPEED_HIGH(GPIOH_PIN6) | \ + PIN_OSPEED_HIGH(GPIOH_PIN7) | \ + PIN_OSPEED_HIGH(GPIOH_PIN8) | \ + PIN_OSPEED_HIGH(GPIOH_PIN9) | \ + PIN_OSPEED_HIGH(GPIOH_PIN10) | \ + PIN_OSPEED_HIGH(GPIOH_PIN11) | \ + PIN_OSPEED_HIGH(GPIOH_PIN12) | \ + PIN_OSPEED_HIGH(GPIOH_PIN13) | \ + PIN_OSPEED_HIGH(GPIOH_PIN14) | \ + PIN_OSPEED_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input pullup). + * PI1 - PIN1 (input pullup). + * PI2 - PIN2 (input pullup). + * PI3 - PIN3 (input pullup). + * PI4 - PIN4 (input pullup). + * PI5 - PIN5 (input pullup). + * PI6 - PIN6 (input pullup). + * PI7 - PIN7 (input pullup). + * PI8 - PIN8 (input pullup). + * PI9 - PIN9 (input pullup). + * PI10 - PIN10 (input pullup). + * PI11 - PIN11 (input pullup). + * PI12 - PIN12 (input pullup). + * PI13 - PIN13 (input pullup). + * PI14 - PIN14 (input pullup). + * PI15 - PIN15 (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_HIGH(GPIOI_PIN0) | \ + PIN_OSPEED_HIGH(GPIOI_PIN1) | \ + PIN_OSPEED_HIGH(GPIOI_PIN2) | \ + PIN_OSPEED_HIGH(GPIOI_PIN3) | \ + PIN_OSPEED_HIGH(GPIOI_PIN4) | \ + PIN_OSPEED_HIGH(GPIOI_PIN5) | \ + PIN_OSPEED_HIGH(GPIOI_PIN6) | \ + PIN_OSPEED_HIGH(GPIOI_PIN7) | \ + PIN_OSPEED_HIGH(GPIOI_PIN8) | \ + PIN_OSPEED_HIGH(GPIOI_PIN9) | \ + PIN_OSPEED_HIGH(GPIOI_PIN10) | \ + PIN_OSPEED_HIGH(GPIOI_PIN11) | \ + PIN_OSPEED_HIGH(GPIOI_PIN12) | \ + PIN_OSPEED_HIGH(GPIOI_PIN13) | \ + PIN_OSPEED_HIGH(GPIOI_PIN14) | \ + PIN_OSPEED_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + +/* + * GPIOJ setup: + * + * PJ0 - PIN0 (input floating). + * PJ1 - PIN1 (input floating). + * PJ2 - PIN2 (input floating). + * PJ3 - PIN3 (input floating). + * PJ4 - PIN4 (input floating). + * PJ5 - PIN5 (input floating). + * PJ6 - PIN6 (input floating). + * PJ7 - PIN7 (input floating). + * PJ8 - PIN8 (input floating). + * PJ9 - PIN9 (input floating). + * PJ10 - PIN10 (input floating). + * PJ11 - PIN11 (input floating). + * PJ12 - PIN12 (input floating). + * PJ13 - PIN13 (input floating). + * PJ14 - PIN14 (input floating). + * PJ15 - PIN15 (input floating). + */ +#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \ + PIN_MODE_INPUT(GPIOJ_PIN1) | \ + PIN_MODE_INPUT(GPIOJ_PIN2) | \ + PIN_MODE_INPUT(GPIOJ_PIN3) | \ + PIN_MODE_INPUT(GPIOJ_PIN4) | \ + PIN_MODE_INPUT(GPIOJ_PIN5) | \ + PIN_MODE_INPUT(GPIOJ_PIN6) | \ + PIN_MODE_INPUT(GPIOJ_PIN7) | \ + PIN_MODE_INPUT(GPIOJ_PIN8) | \ + PIN_MODE_INPUT(GPIOJ_PIN9) | \ + PIN_MODE_INPUT(GPIOJ_PIN10) | \ + PIN_MODE_INPUT(GPIOJ_PIN11) | \ + PIN_MODE_INPUT(GPIOJ_PIN12) | \ + PIN_MODE_INPUT(GPIOJ_PIN13) | \ + PIN_MODE_INPUT(GPIOJ_PIN14) | \ + PIN_MODE_INPUT(GPIOJ_PIN15)) +#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN15)) +#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_HIGH(GPIOJ_PIN0) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN1) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN2) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN3) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN4) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN5) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN6) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN7) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN8) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN9) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN10) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN11) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN12) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN13) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN14) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_PUPDR (PIN_PUPDR_FLOATING(GPIOJ_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN15)) +#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \ + PIN_ODR_HIGH(GPIOJ_PIN1) | \ + PIN_ODR_HIGH(GPIOJ_PIN2) | \ + PIN_ODR_HIGH(GPIOJ_PIN3) | \ + PIN_ODR_HIGH(GPIOJ_PIN4) | \ + PIN_ODR_HIGH(GPIOJ_PIN5) | \ + PIN_ODR_HIGH(GPIOJ_PIN6) | \ + PIN_ODR_HIGH(GPIOJ_PIN7) | \ + PIN_ODR_HIGH(GPIOJ_PIN8) | \ + PIN_ODR_HIGH(GPIOJ_PIN9) | \ + PIN_ODR_HIGH(GPIOJ_PIN10) | \ + PIN_ODR_HIGH(GPIOJ_PIN11) | \ + PIN_ODR_HIGH(GPIOJ_PIN12) | \ + PIN_ODR_HIGH(GPIOJ_PIN13) | \ + PIN_ODR_HIGH(GPIOJ_PIN14) | \ + PIN_ODR_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN7, 0U)) +#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN15, 0U)) + +/* + * GPIOK setup: + * + * PK0 - PIN0 (input floating). + * PK1 - PIN1 (input floating). + * PK2 - PIN2 (input floating). + * PK3 - PIN3 (input floating). + * PK4 - PIN4 (input floating). + * PK5 - PIN5 (input floating). + * PK6 - PIN6 (input floating). + * PK7 - PIN7 (input floating). + * PK8 - PIN8 (input floating). + * PK9 - PIN9 (input floating). + * PK10 - PIN10 (input floating). + * PK11 - PIN11 (input floating). + * PK12 - PIN12 (input floating). + * PK13 - PIN13 (input floating). + * PK14 - PIN14 (input floating). + * PK15 - PIN15 (input floating). + */ +#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \ + PIN_MODE_INPUT(GPIOK_PIN1) | \ + PIN_MODE_INPUT(GPIOK_PIN2) | \ + PIN_MODE_INPUT(GPIOK_PIN3) | \ + PIN_MODE_INPUT(GPIOK_PIN4) | \ + PIN_MODE_INPUT(GPIOK_PIN5) | \ + PIN_MODE_INPUT(GPIOK_PIN6) | \ + PIN_MODE_INPUT(GPIOK_PIN7) | \ + PIN_MODE_INPUT(GPIOK_PIN8) | \ + PIN_MODE_INPUT(GPIOK_PIN9) | \ + PIN_MODE_INPUT(GPIOK_PIN10) | \ + PIN_MODE_INPUT(GPIOK_PIN11) | \ + PIN_MODE_INPUT(GPIOK_PIN12) | \ + PIN_MODE_INPUT(GPIOK_PIN13) | \ + PIN_MODE_INPUT(GPIOK_PIN14) | \ + PIN_MODE_INPUT(GPIOK_PIN15)) +#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN15)) +#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_HIGH(GPIOK_PIN0) | \ + PIN_OSPEED_HIGH(GPIOK_PIN1) | \ + PIN_OSPEED_HIGH(GPIOK_PIN2) | \ + PIN_OSPEED_HIGH(GPIOK_PIN3) | \ + PIN_OSPEED_HIGH(GPIOK_PIN4) | \ + PIN_OSPEED_HIGH(GPIOK_PIN5) | \ + PIN_OSPEED_HIGH(GPIOK_PIN6) | \ + PIN_OSPEED_HIGH(GPIOK_PIN7) | \ + PIN_OSPEED_HIGH(GPIOK_PIN8) | \ + PIN_OSPEED_HIGH(GPIOK_PIN9) | \ + PIN_OSPEED_HIGH(GPIOK_PIN10) | \ + PIN_OSPEED_HIGH(GPIOK_PIN11) | \ + PIN_OSPEED_HIGH(GPIOK_PIN12) | \ + PIN_OSPEED_HIGH(GPIOK_PIN13) | \ + PIN_OSPEED_HIGH(GPIOK_PIN14) | \ + PIN_OSPEED_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_PUPDR (PIN_PUPDR_FLOATING(GPIOK_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN15)) +#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \ + PIN_ODR_HIGH(GPIOK_PIN1) | \ + PIN_ODR_HIGH(GPIOK_PIN2) | \ + PIN_ODR_HIGH(GPIOK_PIN3) | \ + PIN_ODR_HIGH(GPIOK_PIN4) | \ + PIN_ODR_HIGH(GPIOK_PIN5) | \ + PIN_ODR_HIGH(GPIOK_PIN6) | \ + PIN_ODR_HIGH(GPIOK_PIN7) | \ + PIN_ODR_HIGH(GPIOK_PIN8) | \ + PIN_ODR_HIGH(GPIOK_PIN9) | \ + PIN_ODR_HIGH(GPIOK_PIN10) | \ + PIN_ODR_HIGH(GPIOK_PIN11) | \ + PIN_ODR_HIGH(GPIOK_PIN12) | \ + PIN_ODR_HIGH(GPIOK_PIN13) | \ + PIN_ODR_HIGH(GPIOK_PIN14) | \ + PIN_ODR_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN7, 0U)) +#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN15, 0U)) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/CMakeLists.txt new file mode 100644 index 00000000..db80e7ce --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/Device_BlockStorage.c new file mode 100644 index 00000000..b4ccd595 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/Device_BlockStorage.c @@ -0,0 +1,94 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 08008000 nanoCLR +}; + +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 5 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 6, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00080000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.c new file mode 100644 index 00000000..a048c76f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.c @@ -0,0 +1,435 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD1. + */ +#define USBD1_DATA_REQUEST_EP 1 +#define USBD1_DATA_AVAILABLE_EP 1 +#define USBD1_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"STMicroelectronics" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"nanoFramework Virtual COM Port" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[18] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[67] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(67, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + sduRequestsHook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD1_DATA_REQUEST_EP, + USBD1_DATA_AVAILABLE_EP, + USBD1_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.h new file mode 100644 index 00000000..167e1df8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/common/usbcfg.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Adc.cs new file mode 100644 index 00000000..94e54b13 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Adc.cs @@ -0,0 +1,38 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.Community.I2M_ELECTRON_NF +{ + ///

+ /// Enumeration of ADC channels available in the community board I2M_ELECTRON_NF + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed on PA4, connected to PA4 (ADC1 - IN4) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed on PA5, connected to PA5 (ADC1 - IN5) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 2; + + /// + /// Channel 3, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 3; + + /// + /// Channel 4, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 4; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Gpio.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Gpio.cs new file mode 100644 index 00000000..8f4ec298 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/I2M_ELECTRON_NF.Gpio.cs @@ -0,0 +1,57 @@ +using System; + +namespace nanoFramework.Targets.Community.I2M_ELECTRON_NF +{ + public static class Gpio + { + /// + /// Output pin connected to the on-board Green LED + /// + public const int GreenLed = PA1; + + /// + /// Output pin connected to the on-board Blue LED + /// + public const int BlueLed = PA8; + + /// + /// + /// + public const int PA0 = 0; + public const int PA1 = 1; + public const int PA2 = 2; + public const int PA3 = 3; + public const int PA4 = 4; + public const int PA5 = 5; + public const int PA6 = 6; + public const int PA7 = 7; + public const int PA8 = 8; + public const int PA9 = 9; + public const int PA10 = 10; + public const int PA11 = 11; + public const int PA12 = 12; + public const int PA13 = 13; + public const int PA14 = 14; + public const int PA15 = 15; + + /// + /// + /// + public const int PB0 = 16; + public const int PB1 = 17; + public const int PB2 = 18; + public const int PB3 = 19; + public const int PB4 = 20; + public const int PB5 = 21; + public const int PB6 = 22; + public const int PB7 = 23; + public const int PB8 = 24; + public const int PB9 = 25; + public const int PB10 = 26; + public const int PB11 = 27; + public const int PB12 = 28; + public const int PB13 = 29; + public const int PB14 = 30; + public const int PB15 = 31; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/README.md new file mode 100644 index 00000000..0820b7ed --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/managed_helpers/README.md @@ -0,0 +1,6 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](I2M_ELECTRON_NF.Adc.cs) +* [Gpio](I2M_ELECTRON_NF.Gpio.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/STM32F411xE_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/STM32F411xE_booter.ld new file mode 100644 index 00000000..ef8cbbab --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/STM32F411xE_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08008000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/chconf.h new file mode 100644 index 00000000..335e3fa4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf.h new file mode 100644 index 00000000..b970c22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/main.c new file mode 100644 index 00000000..b7890058 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/main.c @@ -0,0 +1,75 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + osDelay(20); // Let init stabilize + + // check for valid CLR image + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + palClearPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf.h new file mode 100644 index 00000000..318fae15 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf.h @@ -0,0 +1,338 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F411_MCUCONF + +/* + * HAL driver system settings. + */ + +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED FALSE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 12 +#define STM32_PLLN_VALUE 192 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 4 + +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/STM32F411xE_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/STM32F411xE_CLR.ld new file mode 100644 index 00000000..f1f0afc1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/STM32F411xE_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 512k - 32k - 256k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/chconf.h new file mode 100644 index 00000000..390ce3a6 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf.h new file mode 100644 index 00000000..85b9b4e6 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf.h @@ -0,0 +1,532 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/main.c new file mode 100644 index 00000000..83f74065 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/main.c @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // Start Watchdog + Watchdog_Init(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // EXT driver needs to be started from main + #if (HAL_USE_EXT == TRUE) + extStart(&EXTD1, &extInterruptsConfiguration); + #endif + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf.h new file mode 100644 index 00000000..af4fd4d7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf.h @@ -0,0 +1,338 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F411_MCUCONF + +/* + * HAL driver system settings. + */ + +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 12 +#define STM32_PLLN_VALUE 192 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 4 + +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 TRUE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/IngenuityMicro_Logo.svg b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/IngenuityMicro_Logo.svg new file mode 100644 index 00000000..4ffae142 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/IngenuityMicro_Logo.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + I + + + 2 + + + M + + + IngenuityMicro + + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/electron.pdf b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/electron.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8792a0e7d2caab0bb3263021c94ad38fc71e14df GIT binary patch literal 337442 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 z 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

K7YAc#^!G4uJ(8?hd(H8#e4oj# z-STlA#?bgFFi=45$KV2l1}MXm^`W*=)@O}CGN0VXgDb$~TiqCw-c5|j{lFN@@EnEB zvOW~+ifkZtsL#pwL~!+(>>DvAePeb-nU6a$meC^=z<7HKDOWp@#>Sti>B@V;QEMmuzWe_`#2;Jw_?dmq4o5PsK$`d4M zMK6(W@;(o@k@>wJ=96oX_s>0*vh)(7X~`35uY z_kK`lsrkg1?8PxAccNkpC*z(jICW6C(jO1+A$O@@EVDjbk|*=Qr+7KQjb}dBjQQ|U zV81?`l?$B_N(r5@Z4^4grwE;qHk0+C99`&w`g?^Tb%NHxt82z|0t4q7G9Q|ty)M|j ztFmVFcnS^hokF20!Zoj}cF&#QhLpa}hYW|Oy?#FhY(tnN&*36N8Oz8du6B_1!88fa zwe}ov<&JZ^2GZx7FqV-?TpuC$F3}|G*NmfleNMg)0T`11!!rnz_mD#)4{a3;dY&8T1YO(|d(z^n~E^TnSfRZugIYd%nsGmkANNK8l zR7eQQeV`cAy%kQ6R1VN?AZyWYZDBsSYYk)Sr%|S$vI`d~^urYzItG>V^h2ML&>8y_ zeNMj1h--S~?g@+`K_oDwo*Kpv1vUOTy{ie&Nu3+UGCarLMd*y8F~JQz?m8y-kK^_d z-TR@$P;o#Xt@I{M+@CeNSvKEkD$Mn1h-Asxb z_9Vhf?H$3^RP%7y)v64^SIAnhC($vf55re(rNwDbCr2 zrh50Cb*AZ>(N-z^)jkotE4^tLlRFG><-FW4g)zCC0AuPGGWU7lIn8s~JsqCENEHZ= zpn{^)*ddBNMfs%IFocAn)5xNWPNSSZ14GYY5iy9(ww5!`OQbg>7l|~w zmxZqpM!H1$s4yn?zhJDEytjP2)a**MzP`M@}DhpaEq$K%Mhi~QkKS9pYo#@F^BjU@MPAdRGZVwh~%4?@!93=RD= zItD@TI*ns-T??83J*~hE$*yJPB)lWM+s7aM`qv+SbaQ)lefz`p=GDg^S=M8^`1qrL{Kw<3PCowV Fe*=EP8EOCk literal 0 HcmV?d00001 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/electronpins.png b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/resources/electronpins.png new file mode 100644 index 0000000000000000000000000000000000000000..1d7d4e9980bb13e2353cd66438a4d8dd6c0c0352 GIT binary patch literal 549881 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�Mb@HLx;jM&AAm87KJYSo;q!%Lu1dWhtV{ zrY#?=v67S41v(0(^2~X|3nMAZAr5{A%TxF)bu=MLhcF<>r}ip3WyBz=w^ty;`;oo4 zw6wRZsy(+|v}twD#8YApMFdEosU5T5d^yUqT&lDmm;yx1e$weIzfNE)9JNTm8#k|k zJl7QmJPPyVScJQx^sqiSUM-wrrPochIun>p-z_a$^~R`KDvgrM(Ptn@bO_k|sA|pT z*$pAgH#L~yUVM0eJu9)`714ZCDE8y8+fZKeoZl;CS=sFabnbSiB}Kb{xhX`ry0f-a z1FG7XW$v*UX9R{Ly^i;Tva`0a!JKr9O#h7nW4AUsXe+0MAR2Y0`HqlS$VFmdUfP;z zZo|`fZ*-BAINF%434+&=w(Ag8o?0g`))%+pI8F1Dk&(&07J{@tu3B1T?*4ui;#f2# z^w3ayU3MJ8ac#Fa@L5zh#jwm83}2};-2-A8hsIMG=drhKnuRmNhFWUQA|>}P)G4B9-&Td{j`jLwPkh#n(k{{fp=40UksNf<&EpG>K1 z*p;2lP3aYcbBFY@GK=*~0KILzQ1YFH4nhYs&N{g$=q2XnX^_U;PIe0u2=iEo_{~nR z?)LlL)b|my=mxCtnLJA@>COaaX0l(ku4S5S>s-%&b*QM%KpLa$>urkJ`vEORN#4Xz zxfCtzau?z2qg9nx-oO)01O$k#EEwaj8k-HOgaoRXH_<^bwme~$iO|4S)ID@-4LSw) zA~-A_Y{ky!@3vhJNfMa0E43JS-q)S2H3#Ld_a}d8-p<3LGC4})0ohLEQhI0m7E-s< zpNFc`v(to5otC&@&1&;Kl5+J932#*mn-8`>+j+z)sw*gFj51`~M$LW}CJJHoJqWc=>vHf#%8e{yPDqOLK6=T7 zTpy>)_Suov8YPLG1p2(WE5hP$=94Z2Q`I$pl?-9h{|8_c9Bt49f_gtQ_Y4 z_?s(Yj=%$p$Wh~@bHaLJ7ErE-T0A;ck02~8xP9{}9ed<;khsuUIr+Dxpyl+C0AGm= zkLrq&w%}_boz+&QoKZZ^Z+3PTWpwHb2AAu3lS+0_c(myXy&wY4;Iz@^Lc`fH7G5pO zkVF3TCh5W$Pxrm4t6*rH$+#L(^i`cW_NwEFTqFuR>f=!{4eARvkxB-_At4H$e3)+i zK!s8lvYdCRARAlxVFghgn=+$3w!#wo?n7$|cAq>wS}B)XfrWnoJWNW-{Yeznf!^^@ zHih+SDaN(+ryrB4v_~!yBovlo=KFF4h+dH!5-hj)&Uq@Go1~0hz5`|yUC!^tXO(ib zC_tMg?hY3bL21DtsOh}(%Di!W=-B6aolWgjo$YT)AvZiF{0QH(VgEenzo?*V+}{*h$V2V_}(5b z=q={u|HxoR;sAN%;4opFGTx8_iDZQ>ZXl-*WPHu9e(lH8(i;u`u0LJke*xEzPuj(N3Wst}ZD7mZV_xx#rXLzfT6Vp+!vWlN4YP*Ad}n}&u7OWUEN zEzlw&uM~4jPj(1s?-EUhrL$96YK@LZre&&CmC^5FW<*@3Ar+z7@9o`<07m6cqiL>F{Udaxy!K$6Pte^N=w?fvjsIh*V{xS*Op=q5$asly zqmKsltzOx0aLdfb<%AbM61R9pnUk5LpjDD2Fcb?S#K{Z%uKaOjYy1mCWD7w?p={%C z?`Ru=cezvpZuop_zFn+Qc~hr7tVzHF_zS< zNB@}rT&NAxG&fX;ud6O0()Xb1~+i`0iY(afwSnMX8JintQefK7a@hERGB}&K)>mc^8 zI{uwKDJ6XOzQ=|edc$FpXy~33Mp=@KC&k!EBUAClpFht2#f`=12_Su#CAo}h)Nq?N zT+&}T?RSM1IvOzZXdn=rzKZ4Z?10N$1jmNWYPDIu;WC54I4sr#H@!~g)V*qx512V& z+c{sfwcKWe|1(6@3aBBYtV8rUOf@Yy8<)5T0uXxfgR%WZ@w}N1ulw}x4kwy#2C?cv zzx(|>QgMQ{u8pLM(thb@qV$$^hJrYxSd);!a^@#>W-_3zVGeJx8muy!fF!?othdXJ z=EZLcL{u;Tt1eN;T$Y;nUNaP>l1wR%ECq4Z_2qMtaXaA$G$&#kzSlXyHPPF>OzPIV ztvA^Qt1k3dO?C6NuwHjM2B?h`5v`^_}jR&BLc3FNGw+U z;h6ZDmJYZ!R#~C7cdH9`L|0i(jhw`*7!v3$TfbXvJF-QH)jXEt&|?P^7WL&WQ+(KyE%u#+ez3SuzC)g3TSpTA&F=>vANW8{ecHNh?)vNIY_vnUiTI@% z3C4K(0)i-Rj!iI*3p!RZdoL)qAQ}5lE2-pch&VczcZhFqY9=zCN#w*loP3~L02TDP zxGrFyz<{RTJpsH?i#dP6aRj(9hA13h6-zC6g>By`4lR*RWz$`UgRBy{ca5b~R(5^qP@ys;x zina!Hhhw(sS-uIk);tpIJYqA%gE!8KEK4|McmDREXNj&bb=ex_^H*1{sw$t=Rx1oe zAZyJr^Jt&Ffly84yjQ2`zYc`=ahS~H&ZN4!oE3xGMm;!USLT)Q#wRP4bkLnA=oyJs zj%_$3?kD&F%|I>GuV1%`GFDLzvSWDO(u8gpXP2UnKgWUVz2f#Rt+V7mXKNF0Z|}47 z^K%tHzHaZEVYAYbk`j#?17T;!aRn=Jx7!i4`IUX&&pV9KF=DI=m(H}s=arP9&dl1H zl5&s+XRB(Zm39y?e~j0M=`%;+Hl7-{ad1KGTC`ECQ9c^&O{p1bKQ;%SL?RuFlT4;0-Q`GFIm7DenW1p?duLLQ7JbsbYc4%rKdMi-d`g*&o@?@aUo_D%EjU2ZIfclHd=Gbq~!)Hb46f z=cOIsi~7uqG7Aww5e%bhto3OodEd_K@&iqUot>FUq|l?Mcuno)9<-@jwH6Ki>U2UQ zI1sa543wcyrbEAxD2S&KD2PE#lkhJU-zWdR$F7Etl^^r@CBC6FSt3E?MF?d+K61d0eksUrr2EXIEq+m$# zrQ)}SQBgckh%q}FuOW)~+$XWp>}X2qIaZWWRtom(ZqU2h+S=PhhH(p?6Aj#i_M9-A zrTL{L)kfrAI>dYW0$>H98^;v}#?Z=p^B;ZVWH#3MyX=+{keE9W%x!~fMG-hqzb zxu`GdT6|H=-f7TUKcz4*ZmS&y9gXL>cpqCiWT{NGnS5Z~&kuNB9o0y|)Rb0y6BW&VX^)N1(L-BdcUM!dNdT`x58=|vVnXMbym-m}f?F9XD1c1EeLm=R1OvAeBUZ}(p38_sP2gQha9Wp;B zj=?npXsmf?-nt}j?r3?_YmXh!nT#@$CK0I~CLoh1O z_~{-MW*JN@k;Ws~s8h7}BQ>lp)Cxlj)&&F;NACysAC=V8w#>`KDc30L1Sx4?3}H7G zvkHh#oc0S><XrA7*%}QVhpySuKZ%#Pno^rXT|-g^Fg%PP24 z%u{_j0CcgVwYh;&cwSw^+co5 zKpy8uOkLJL+HyZ4eEtB@a{3%8wq^x)Z`%wy3?%g4wlqdTb)(Pq1%*AY(LlM|+x=H; zUX4^X6VvBKd2h{EwRqQ^t0zP+?zqb4qRf<2-U-sO!oTi4m#Nm~(y`|q3&9%za>j=5 zAUP8#6bK^VC?|nkkGQcGhClZAW{2n(b*T45H#||w`w-7B@!!J6I|&i|Qi)oKVwQ%* z973466pWHSX8i#R_u{mghIU#}bJ*ccB+!rj!f_#KLbY>g5wqDHUIQYX>ID)D&juXY z@$NKtRz9S>`KEGp_GA-hvcNk_!t zb36n|ZNDU2{!g2DbUs4fmDPa`&!?y~szU~rB290TRG)!^sdI3PC)AD=QJm-=EB`4QzH2@~o*nzdLm&WgX=-{W#HO%faCy~Hsa17U5=uTv zs$clDkj#pi6Ks}u-Mc0UEpd^u@vP{>N9-ZBLVNrY$8i%O!S(d7GzTxYx4q4f7*y;yU6T{`XX25&I#A!=ZpgTHCaapVGG6{r^ zZLv?VARJ9-CWo(z?0ge@Uoi;~B_pwxSFuS#6UkR$EIMGKd7ivhq|$1)^FPN;t6r(u zs0KK9TFqwqKR*V#jK@@*^ZsFjF+53Esi7LVLH@cet~LK>B*W%LhzW{u+C3ShZC&jo zDZ2JYJlaKbx?)4dO=xKjxA96|{CGWrV&Bw8n5nU~1iN)&^y+W>W8U=s6EJ@o7nhZV z^9~Y0risxl+Ed1hxnQ>E%x1SU3MBt|v8qQ5##n)Q5^LVGix!bek0%a!Xr=46hGtuv z%gGES^tQ)$B0)zK8zA}hB?=y^ZV0gq`9w5urWP##)w`(kaoJ{T4~QoW*PA^J8mpz7 zoNoxDxytLaB=xTI7V{yGtdt|vo*IxOlW7JfGdUFrY-{^6c)T%nybp}WGKt1x`zky% zTOAH4tTxg*i7^BmTt`M($o=W0a)jxZiCU+Hi`;c%LXGHuhg}#OyB%FL&9^$e-wf?_ zgTh5Hg4__IerUG2P?JP_k@~!vC(YuSBmN@<$2U3PzQ7bg@-PhwqC3Ig_mnZZpt`~~ zP_dR|mcYGAc#89@)j-fdOkFa>(7N%elB>O738* zo)Th!a&7hBNtZ1(?5Pe6&F?nWsq|2(+zQc*^!NhA!I{1|n;WI?=1ZOQPauqiA6LFQ zN}Ifv*p~#a0SGw@v6w`Pn(O}x|L0`b?HI`VOQN>@cV@!5e|3E{0_@mCe^wM$RNA^> zj3O%*uEyNDLCzKr%Ak*a8TkGYQwdmguvq{dVNhG+M(AXPD{Edtti1ezsJ4ve{H)Bg z-R#h5T0C&*>|!zdSyHo0OA)U+STTSdgaP8@2;pd4ZUqwcc0HkWpalvAc&MJr%#o+t z#|hTC8UX9QKbb=#&GK@X?UMxuwv~cZb=)y{KkgMB!*3x3jWi5qa)p;0JXuvLwL<^G za{L5L1Olhfd|E;eyMZwyYDvcv1qi1L^^oGCIhf60+lydC)^0(*SZf-JBMwi~%;2R` zsn7@q{H7p_vOJiQKJHOGoNfqcn_iNk&sR3J>?;j@SiCk#CTNAG>vJz>a$vomYG@Wx z%514Y{mN|s8IsV3se|v^MKl@Z8p5v4lE(6Xh5bLF`cn^axOOw}GYY4{XL6T&1;0br z!K&3CyVhGQ{2IdZWwOxB`lj1Q;P!n&7B&2MwoqeZS2U$vqDI{wha(sKO>Zp8+U;&) zWV>=PWWm;=KE#tMP~t5oE;BJPv=0t1C<3}p(hw65!CR(l;g!#&fvl35>NDtjY&rP; zGde0I$0!wFzNJXHN?owrC&2)YL6?ad-E{F^CECE|!CTw?VSNjqG`b~7)VcE;+u$a1 z#&dV`F#W;>Cr^xVvH;$)GGv~7LVBKDjRxBd4HNNtM~>c>!F(BrptH4k2l%-2yaSC8vepzi>Qi#1SjDl6-&{ zA4HRu&oAfIh^*m@Qv1w5Rjk$t9{vs`HS+ok2AiVW!G(zFw?7%wv~w*z z@=sn{jy^F2gP`RrIurv_sQ)M;^GuP-%aS47LAQd~M*JXYM-0ha zSODvKYO^1J-{raBSS&;rI^;M@&$4ulbJ;rYS&D9S6vSeY+lLV;hTf?D#iJ;suL>N~ z0W7e(Lv8ZG2GP*apztN+Bv^qXcqyxJ&=&G^$F@<^Y{W;^j%-q_qu0J(j>KYg?We9@^UwXz{9znm zm7_Q>+o6C>foODV3T=7Dr)fn%bLDx7fkuG8qxp@rL@ea)+~}lTAp*;lRmbCmcwv-{ zkD!Nq1~Mh@XcM^l-I5pBp6ByT==RXBHx za~iQWtp~P?frROuf#~{vIJ;f894R-=TTL8RBNEYf$bd1`0d_5jU7xFE&s+UpC6Z17 zv)H>%dg;~sZY?jdi0wHkr^Mc>)yL3Z%sE`J;z)p7`I( zCP*A*o}cdA&MJ;#f={v^B>DVv2P*k8!romZ(kVP6B_Cc#b`Gj1<|D|&rq@JPZWp{w zq`ii4;0T<`5N!Nl4c?_~SO2Hh{8xMsga5aDqe8C17wfGwo6XoZzZ`nre7;rXxW2p%Z(lko)8&wHv{C!typxY;nsSIpsu?s6WyuOHgbMv&GH6}hDADcF&Y5EjI2fH^%q{YUS2c6;=u>Jqui143<~`Jkv$ zMY@nwT#Kbi`#;eDvscNG7MFrp05&XFuLCd2bfGAeegg*-4k9WlN&Ck5*l`8P5kw~L za@yLFbyFNrYp&-%TV&c(aC1$+A&e?ZW+icr+-mTmT|+2I(z@u%$jJ28a`MN^&f!Va zH^#`-Wio4SHXHs4*1Qum>-v!!pOr0uLvMiU#J~Q`{zltm0DU?~GmakeuhX)!<(Dk? z173#vp?c{j9k&FUzr^3Ep9Vo)Umpxq>g{UD6M2V7Q)bVJ-NKS z5&!2B{jUcR+KwCe??T-nu&##94TM+_b?o)kGj)S3)y#rC9Z_DQ{S^GYB30v`)?4$_ z$a!e(>kZyk+Dn&vNoz6fhKSmBNytrUX_!2Tpr0>&OSZ;Jo0$Wqee*MfP39maYsWGO zG!xCBS`&)2(SwB0b!qLI#rmhGEK@)g5`!fgL7tELvgdc7?WYEmW3FqC$yAJd<9$@3 zd*`+0Y~we>-c+(el}8Hv$l89=hNIYC=!&rno&BzX0b+FKQ!;0GpWFSX=`z);=^T>O z_O64&bb8ZCtA)Klsw^s6S6@n5t!ny!Nso~$QUmHGIo+-7xcW_KxXVsY>`5NZ+6Nzo zo<-8myGc&Izx?N`9b<7W1}_J1LSpg%;O1|kYa-4mhk*SY3=DAQ-MXnxJ{y~J zOKlMOr>MW){#1qgH|C4U zUP#>Zb+~&Gj-pzvM%u73poz(xz%eMK!B3?cr3~lG*P34?HqfdI6lKnA+xCaL9%q~~ z*dLCC96^IqFgHF&XQ74qB{qjFoEfSZ%5=GO4)2hO|0>B(1y^~LvkS}+s;3hVz;z5^ zKm7+O(Kg%axzvQMKmmEx%wld2oR=IdN;$kkpI8I?G+yTzY>{{C!59N_VK`Kw+FM7ms?Bl3b7E2 z#FJ*|V_w$>RDhjTOWPsurw#vJSRDCy$9xN%bWKZL(ivehIa$j2dTu|*zFpt`*qP8+38L+?V#zU$^&4gQbM_n~v_WGo~TN zhCb-AH7x9Q(AuEkWQP0o+ea*3?O}zXil)i{61u4+BqVsSyrO5GX!IbC>$+bAG%YNb z*|%DAT4Gux$CJ(c{Ek8|(6mKv{0SC4B1Xsn(zL%IVSIw@W-;o+*B-Jk1pPeCXLPfY z0)U^2veLQ&pqMC&WTBa>UFL|v^tY3h^BE~#rswM9;UH}DC&@85P<+wjAx%u!Dl8PS z+Gv!9c?Tksg=}PCY1)qoG5}8v$dPlfLz~y4ER!98Zd8f({rYfKN=QEYyFDrR?uDZ~ zQ=ZafN#Jf+7@g7|r7tfc9j--hMO@Vg?CAaTz8xXGi6T%1qOt8Z-H*yFBZ36mJ=}|C zP0F?)}>ILc;TXkDVng?^jXwEw*qr*GOBdD1_+% zSwdkm&C`!P;cG-FLX3dv&uubkPI6R=i4PyR+C9kYTI+v9j16}kgJ!^ae6Lf_PVZ$0 z8(nS3F|)D?LH88|bsWm_g5y0QLhH~8Yv*G3ZH9I!`&{nzIj{L2&1-IczEEejsuclF zn8)5Zzur>i20HI2Z}VxXB)!A4{%ESyb7^5G(gYqnmt3IO(-3OaYw~Y73j{u4TRidUvuIU{;(THmOUYj;`CkZ+bQZ}ZfR-LLU%JpnNskeQs1?(GfFTd@HFBvzW)lNmgmF36v@r4B`NKiUEU=rJNtrWfJc#SqzR*c!ba|LU8Y+x+zk zLV9r&wJ2k>Ou%#6=i@<@neK4)Fnq0rPNR(b*EnmhUHv_DsvJJ`;Kc2AZQ^q5sb3}r<7cJ(sMABKvRbPXIg8DDK;_$| zrCJ`)^ro@_BBET0DwKkP0zgIkq`Z^b_EDl(R03VUHxBd*0BKOp40#0lNc znJsQ^2!xUS4aW2Nd9m7{IE8`&BTxO?5QLB%SRpMt9+^6&p9@c#GiNv^ngAa!wmhi?%De_M(Vgg6D| z8kp|+tctA7cXv+TO4BuS{!OKFW4UfQCu8~tr&OU3M$RYrOC!p!(SK+wsi>GlOO|_5 z(I!5JxJAMnen*{BMc+xcrbpQX$(h0R@%04z9xHy36j5F-a*#fd*B~k&X<{9`&>m6K z#b&q7w{G_VE zqnFovDbMwZ&1fxl!U|Q;NQ~ye;=^g?HRFGQF}=Q$3mEO3m2B;NJn;^sF`w-`cua6c z!v0=3`!Vwtq;y<_(ZO6XG0RD5Mg83Mae>%y_5VY40DwT+{l5T$M)zVj=TU~Ea@j&C z(pG=1@y^D~=ud9Bhl?g&g0bXC#wiYzkGCgb>&Kr5k0SevD4?+bQU*#G(*lQiCz6f* zalO)(wVM}RsJAq^Ar6^d;XVw0LEHIk3qY)*Qd2VjxG(_Gn{*iVM4*vIOyMdfGs;ex zzQ>*11t)k5Ojoy{B_S`e_HanD7i=)OVrR^-GRw1RIk`p5z@c8wE2~(feJ&1KC%xa4vCn`Nb=2&50^&ykf9QqUKyrRyTnwMgs6bM=%f?Jz1>oUWR86jZ{_9z_TGEgi3#Kjpz>diy4 z{TmWNVIEcJ3p*IAF&Ow2nF4&qECp9}ls4%o5E@L5DBI{ymj>@xVL*SQ5E}AIE}anr zIcb+P&<-6+cQ-DBiLfxiHUt6z&8MwR-TZHP3(wz1gJhnGg$b~d9RN&C!2#C;V@jvT zEW{EV$J#<F#EO>eVkp9i0?rgtU4hT-`(1PIbaGjq; zah(%Ry#u+w0G;IV&9w)0FfHPj%+1{gAja%FQ@&SS5y6@4^gE4JW>hUv^mI|rN9>7! zJ!O?Myp(g^9dONHAmvF#zEGu^8<&MlKKO`<6I<~2i9;<3p?J2F64~h z|8NWx#)P2%)dJ*W{U4?gCP~vG^s@YDxZ5APs%OcxeTa+?Uf21mkS^?dnKi|i#nT~| z`9$jG-*C-b`7I~3Wqtz-VfZ{EsC|db67vt9&ojal&s~~D2{EisSReAta>6zLE^u4! z0jv2vKojKGXx-Q1<}wIH%M}gO)L;4>;`_M;gklczsot2iSZJiNR4%iAVrdwekAsN0 za~(BiMdP;c-6OBm{f-1Lh?=E{eq!GSQfAo#>SxQ^!3?1!lH%1dd~aTkp1)@i4pX&6 zAn0Po0ZFwbVk$-|sfKy4ali4aNa)O`1M zf{nEi2&PFwQou~*Qs#T3KzsO{q{Zf6kqFQN=VVR_-~AQ481OeD>y#jgoEiIbZ>e`c zLk`+8$n9fP!!&qPxL&jqGk7fK$?nfwI|bdWP9h7d6)rL0XW?_$x;{N9T3s$M88O_> zYlceWDJ(557D6cy5QNh;G+rrBu`pwk-&m1hcrb{T|BSy9pCVFEf(ZO#>QLzvcvo6% zaO%gqZd4WD9aIq|fd5HmT>Y)8iw6?WFEvOtBD8YV+HniXfcX(DnabsVs;j+VeOl;`WE~F-uTCqjhxz#BT6f6=*+4vG;{bbaZSKm} z*RSakM^UAH-2j$Eq}YXKhpH@Xys_o>Q(bQ2nCXc36(UP1S#fi zMoj$ah7c8@3UKL9SC9|732ZBB=;bi|m-J+EAHr~@NWarf5onmqpm9(D>*?!6SLSC(6;?=v*iPX^WrMR_D_qBf~Rx3HlU>C(O!Ft@vXL+Jy-bL{#8WIAKcr>7l z08+ItYY_$ped_%vSxwv+r}ISN{6`{5@D?5nvfNJPojXcy-|5MUy&zU#!mE!EA@spR za#<;6clfo_>tv^!ph`<3t{1`SNJ!TLA-; zJ#<3z-+E6h%8qFr8+=ieOXa_S+}@5rUAx5(X7QDeSS7EF?ud0wkk4#%aJ zOX`n!2U|0#vG!}kxpty9MVC>W*5HFVOam?}?WOllq5e2|Y?4s374T;r7O@!Ya~>Pk z&KqHR&~+iD9W1)?g!W@@nl|`LIg!2X-g6cha}?*?S+eDz6E@_5JbuwYie9^BoSy|{ zHjJ;6d^aa}?k*X6js1YW6PvwxSqEh$t$lc_VIxMR_wn4(6EB-**ri5=SBZ801ZdC% zgoTZ@yte>*ZvEM|tKH^3k-Wx65e*UnDqX`4n={Xz7)8&hh7SO_@7bd1M7@&oK-i=? zB4{E&>P*vxf58%SvkaZ^94`q&X+-n-C2j~;dM6{KsDsch(G6I|4Si{Qa6?}qAvRNi z6idbm>T3L10OeCl<2%--IG8U{MDu#TDH?pTFW1}ZqtX9=z&Jpd%KRU7%7X1UPVe>+ z$!d3#Lce1R&1r@YSN{39#-QaoQQ>yWySH;^oKw1R^3%g1R+E)eT;Zyv*v1#*yZXjW z7b}V3Y#ZKMrK5u=+g~&BM|ug2&po`a5Y0wF-@FG1-iHPwu?ROUVIu}`HgE&ES6bOp zlX6`?kgMe1m^G8cDd9Du4j`W4vn6JJf!@k{L^MKWBMAv{OrIsQ{eL{2Ra9Newnd|8 zg1fsr1ef6M?!n#N6Ck+D#@!t@?!nzQ?(P=c;jMGuJ-0q-jgN#{RW-*PqfZ*krWH(r z0_4ls1=k;OP!uU-aaxdVVpUq97t9{gZf4?sSg!>wO|Bu@f-Ei8t}j_I10pRVUoIuL zot(RazSD4o>N{fz}FYgYwJ8 z$59aXzuA4t zfJ%dWhx8Ekn>( zT%Zf;2h7xcMg%lOS~%AsIkpfoB_ktJ5TpKY9=lG$#uZn5ATkDT=@g|rZ3v5_8?hT!nWzZXA_vk^nJj8R#u;USm&U*=FfY0utaqPXtIZzXNTqP~)MvhZ@6#<|cY zazB`0v@?A`yi7guEuw!Y0odDa(1{=N?#XMU zt|f|;ZA;kX*l99(7MdU$aozXncd|K&j1w}9VU1iAjtd)* zGxyw0bIMxyJcFF&M*cq`f2aH3dRFL1Wh<7!C=#N<=v*`3?Sc`r?Fyg!V@gpCKxEr2 zb;*`%6Uqq6S7qu37)AVgzK61aV>xT8(avsW_seJ8pMw=?=(Q1EEFV%bCMS=u?tNbV zE|uABk1%$2%~hB{_%6SPGLxaG-UE^h7em`$Apohx%JA@yBm(>d`=1FX(31B=^#KLu zIw)uO8y_XSNJ8;VQ-$4;EXq~xzZShG>-BijMJXYTMd5V}7tM3-6vh*ItjT0YA#y;O zguabD7=7<`g>4xPAx5FKLB%mW(OSind|yMKtz|(CwTt0a(`Ae9 zyT(?F6p@K`T_wWqb1q|9EaD!7-P%EBWb%!|BDbn1Ec9#w^Jua9h^cXl&?F^2tNWxL zc+lnt3{X-mx!)ass#Re>g5@F|+X=G>?*=E2Ti1y2V30ZO zX;5c=%J`yIwu*$sYh$O*1({+bKNZ58D2jXNvQ|po=u5=7%g|lGAzOfI_Ff8iD>U5# z2L*dm4eJZZ5FQ4uCI_M0y(6f`RFHKsWrTvY=xR&wI*Ol6>rpSK&LCP4d12q_*^c7P zI9n_eu`d}(D?!Sw^?8Z>(>fAP^k|mvr^@Rhn{4KaJ+(xoRWJB6)q{AvYC8hY{g_6! z?4^h6yzjk_rwYe7qCkCf&nVGu=WCIN(?unf!BqhAtHCM>%P={dzRN0#^N!Y#a%pJuAh8ZnzbjIlaa*Gf=doOSUL;P{41smbL zy!Olven3$9dnrv*!=-uFzlW5{z<33m90cwTD54p?tJF!(E4QbM0sLTQBZmGiXhJ;U zC7Eh|jhN;}*HFX%ZgElgpZ~st1G`N7o#2hcX8OY-BECHDwp}SGD+e^LWrmoHfXGEF z?K&R_I?CzNJ#I@5*8Tiu_V5sJ%)dVrE*?w<5z$V!h|R7AT+#@9NYRa%HYIcY{IoeT zl(hwTEc?z@(ItuTY7@Nq?pBY2sX3SGk1DQ6in%H=Q{4Q#zVlKsB`XH{dNz^;z zPt`^7eJLqvF=;&W%FKyar88$nCOE{|Ej6B5b~--$UW8VfloBAv=K z?SBHe^#A@s`9C$WYBg_8dN}mdwTu|sRq#hWuf{lPEN7)82+w1Jn|ci<>=k8GSWe#- zTM^uw!;W6YI`ou@18FkIh;p-GBoa%Ve-SCgBPpc%fB5xNDG|X?NKz;=`)9Taatr}k z;AIhIPJZ0l+Q_lperMz8XiBq_+xgjYQXBNuZc?M$c?Qq^Xo}-`rrr1#NXjR`ogIAM ziw(XJ)R=7fR9`@DZu0_H;Ei5NBYinnPub1dGaTfqGUo?R3o$v6_$n;CjMVl#T-NmZ z=uk64J1x;oHmjzuAHC|fjt@AXZld9THC|r_!lIIhIC!@bN6mZ_Bx@=tp63_x%LpUe zjJroV6^SL$!9|t8P+R*RjRb#gY+Oz(=SlFY%z+}#cgO>oVz``hRyaH)7%WXEJ|)I` z)IpQO#8iGKWLo^m6Swds*eXlqT~W$lIV^FHGr7dGRx%|?ND^i`>RX8d1IaTRlM-c+ z&Kn~9a`-)20*Yq+PvMoSW0~EHzY%d|NmG>N5}9E$n~*6wN%{+2+BAqD12*l+Sn_P8 zPGvjou(*rruG)5!wF}93+zJx+uy8X8U%ZysfFS`WHuwRaMLKZ;0^ba7iC{q|3pZa| zX$sCnbwynj_f?NGuTAhtQuHe2Z5o_bV#k^{*HZLKrR$gEAm9F6VKu(n%;^!9upy#n zu4ajiyh*2)Lc|SuHJ;08s(egs%U&wL$;@7gM(9ekG#Q#&Z>9-cn-8__H<|Lc3VdQY z?ny9+$4rzz0y_GW^jhm%fqK!yQJ&g?AhByitwvXoW#VtNNi5lqnAnsS9yb?J8sTXk zTC{YIR3@m}w!j?7gXtoIG}{(Q5X+5TLL&X`(3V7Nq@?_GNPt{sf0KjX(2jDDFalQ{ zQTKwj#ZX$rp=_ql`KlWon2nsp?;u}&={7NQy0ATXZ_jjQHmcjrmGhGmj)3skPnJ3k z`uE2gQ5`qUw+raq*w~cSpxlTXDl-?coIGbHZe3+@0ZwZ+9R+Ur7EF^YI85 z^ZBjVTh4YA^IAy9sb~NYOgy|Fck57A2sNF^Je|M7(6&~bd_nl{T755$!NUnGw6AN3 z_I89@*sP}6g@yfZS&VXACV}$Y`d+8sH0sP1t+{vQ$p}7{$^Ds@e;Ih|oSoC&0FN+! z(7r>eE3ZYskoWuIau{9X@a>~C$6m#8YH)jbhDFrvINEUOqtTwfs)pT${LilAY!??) zJwFdPz%(2b_^`iLyHGX_pfJ&aytkKu=-`jFHjh_=KIJ00NXu+d;lmb5GX#?mcbpOg zyQ@s8uc9xy zHniE8D&AuEvJ&ZqE-BGmv!o5HXVI~GcpGFjbOmwwvGlElt%zjI#t3($Wv88(YgBtE zK@D9Mb1Jd{dD``QT8&+`B;X$ew6cT4WrwAPKMm+{iCDT0F0 zYTaRqLYzF_)eel5fOv$Ix|! zH~q!4sG7H0`6e>+y2|8gAbP)co!r+0lUn+)-F?*;m^6EGC99|5pT;vviK37G5@n+D z;kigAn(jfS@|0-`PbK8lk{pQ36>4f2Hi&uRSwD4MANVmCbbbvGXopncT3W3Ot#_=U zjBU=r$Pns|779K!)S0;NfwXNeD8~rgRv6*5;yi(j+SU2fE~8&)RYxk}aP=VkvUpQw z3-eytkl`BZUqBk}BYd@|fAv1jsvc+W>4HM|bN%LpRS;>nxeNf#th9ns(_{PlM?&2R zs++D?-)A&|%rxK*rVG>U?L34Sk3%;;vJ+pjg(bvTr&U#Dl0cl35P zcPPLH{+&2;o&nHLPcoP-UcwEFAp$g`7HS@Aggj z1`G`csi*w$Fzh<2qY+K~^o*cgKH^g}1nkxpcbXk&JM!@YFaUGD*4`d3CtM$?>k96FCmXF;V+ z;&Y_+>gO$CKbm8RJ-NW1Jg8}_rBeWAfXW@HeG$ovM5`&CS6|y5qfyQ?CmBF?9Y{^> zVk?~#AYm4}+e(z&DGCvDWT$X=Cb!bUnEz?*3O1&bUxu)rN))yDHFL#Wbi2v*kU#c{w;L5Mh6~cy1U`potN=KwC^?Pir2Xh z=VstGajx>gn!95b1H+y_{Fb7ddh)n)4dV>CQ57I@aRJzABs`a$S95H8hGD5C#a3ey z4NsRf?y9fe%vIQjkAy$|fSwF%Wu+$R9CiS&T@OI;D+OkNc zu&urJnx#7gb?&$m{{`vr9QL9z*`48aMoP5jPbV&~#&A7XuYcJ$VHB5(?%c&N(ww4d z?yq;wB}Ud~*fc%RHx~>W4y{^hYoIITq;y1zh@qAiPzd}C4|3ZhmdqCa3MFnCssi>V zdmxRHg$oERKuO`oXb3|ogrUTRA^B;wPdd^pl&H(uzk9hN#2&t8H(W~?Fv!|jCeNA+ z8X`}okAR-l<(^P|ow^kYGdtKHftA9u2wo!%WIpGLgR=e*TX1B2S;6n!3UHWE za9foQjw9lF-BFtF4kjhoc#-HSj}BLzMhs-MFG5$JsINzGd-0uwv_UHP7FBV?q9@Za z#W)r_q!2j{{wE(H_d)5vUR+G2^9^(ZX`iJBoje}Xcj~z`CJ+nz!dBhGMDAoX}$S+ z=S(4hygAs@64y(I`9e#FJEnYa-oEbfHsnr3DHV9CB9aMpROFoklSh_PTs1lONb}h_ z)QVz6aq8~}8eEWBR6{s>lwQQ^%UkHu5{I`}xGQed3`=BnN;M(GSjMCmq(Cdk3zXfj zmlHriEV{<+@!&Dl_jW&!mvVQezd0>mG;%v3Vgx&Y&OO)V-XWf3c78qZhnAs}V0KoO zbK_6D!)2(r!G6|iP=Bgp+r>Tkf~|5;*YOrt%jBl-(|e{bLKxZ(l~jDenfI`<0%f#%9bx~bP2{)SjG7>*z_J9HR0}^FkPAVqdO*_*%teEN}2yAVeZ2h=Sl{C=oBtxP|$Qr1h)$rX` zHcKJhK~9ntrcwf~UH@{hd539e%8-rF;Pv^6g&wEAnkn^A9GxuIRV>0Rh~#MPzFp9% zRFdQ!HFlA{xXh}Cmcksn^s<3>Yve*;nsId;WfNnDGsiIUN2huqW~dalHE_}w-$#PE zL(Jj$Wrs#nhc$y&J``4$KBbX@y_{C?-RD482_BY~ET`6~*~2T;b_T zEt4xvG>NXAieyulCVR%0>1yT&WXNM0v(XRuP@JO$W90kPszeajE^}IFku37a-^W8} zIg*hB&iK0+*!hml%nIS5@N~RTMPL;l2wz24F(|hO%VgW~19AnCh5R-S^b|h0gf^po zLG)X*P%7G{FwHe}F|_c?wLQ;5@z7H_VHK)Anqs$$9U0-*bNPXjNqzh1=5-_T|sN z8{7&#iq6#@SO@Ixy&E49pV14*snb~uje#pA@WK~}mjJTC_U-ZjZLXp%5_LLTuK^XZ zOTq$^*{#l7=RVa%IxIPLP+k=Or?l(!kEe;+dHFB22^_K`+INO|H6^GcYU)NCdr!IE zFYJF?&Nmb1*9L+K<+@gyuP%mZm7kpQnu5U0 zGnUV&lyZLnI-?vO`^+ge&d& zhuNaAPGU;peS5mUF43B)+>nK+wK-i_Ar8mzUg9B*9-8%R$=@}vyx?+#eXn*50f0X+gx7G zd3x(SAAT*SpUms~o%ZiS+5lU4iZO8~4DMp57Vqz;4A?sGCd0g<37v)-Xp+4W?JP=q zBw0I^buq+2lY=s+@#fU9+M;XUX9)3~>W1t#`8M|!;*^qZdQI9FDAA}O@~LuBTspP& zYem=0pyBBsD|vUqc{Xtua#6ax)^~x5X1!3{&{9tvv6KwViUgI3%EjY>86N|Jj^e!% z=A?qKx_fxJYBFdTry`H!PDqdBu1VAAMd?$JrwaL0(|(cp+?>|;Fw(`~S_B8_THrDr zpC5P1D@B#FS3`CC+gb5t&?I(g`CDRC9cqxXoGU|jEVRk50rV|p7G6XZM&oyJHi?o z)DH5TSbRtu5}*a&9xpncw(j-uq5>RE5?+XLc~mbU0z?0#jy|F52< zp#MI!TF_a|#(OhRDY6?X*VcQQz+jfDC%)j9ngN1v5Xe*purK|?)amBAdU}6`3_;}o zD?!BCXMd0b{Ucu1Rb29^Z4|bCWnuX9TksJCYDOh-C()1pFGVk-*4&;r^8D8oDD?V( z$uI=ABCAQAdfGzYM-r_yFMPm=&%5Sz9>D7u#r;;>RYqGiE*6FJ`z!kb)48Mj{rcP5 zpH(;cZoqLMqX)+CNcsE04(hhzyUUZfgbN)z3@S`CC);^>-}_9oI&pi?I24*bp+6T$ zmC11^VPUzxX7J?7$p=`DeVI{6QbXk5qs3HMRAML^^%y@;ZAJG-9!^fAztF4$P zg^3XLMm}Tam8wS3J0!e|MtRxuY5okSd12EvBiLAE>%Vf^Uk=}zZoZh{4N>OQwfJu5 zrDHYCoSf_BN=wCdMvetBui~Mut@Dcu=kGqDa=1A4UBLl$ZU_o`NH*Jyk3=|I z3!cc%;)vb1lyXF72Z_XQ8HQS#Aygq9L~qJIU$m#<4VyhG!8p zH8R=zP56~>4YH_h*Z#Sq{;+?+^3OXqRR%Hb8&4`~NrQ`%#;K-D+L?LPAAh;)J(5TX zN42Zrc6}PYzr3@{wG=y7`IcJhHgNz9$ZbdtdbnEutFG+%Sn@W=E&b$Tz>li(hBR^& zK4kFgrI*OKqvz92(?F)z7G@_Wfxv>tzW?wA;Qrjm34V=wqFhI0PN6=i)$CXPPZLrh3~l6GckY#ymGRh3;xT>cusJFBrOtZZwaD=jN?+OZn|3?e@-wg)zWOYUPfNlt=TuSEr+ zxhfWYM#=;S;(M+c+(9?5(>{x{Q}V_s&y?G_M-(Y7GvO0rb1?y>4_(1 z0Zc5m3ZGHq_}Fw86e_%krr9*JLwJN;-K&}^(TXnfUTCoubE5JTftm2>%G!<#bORpO z>BAgynX;~JW82OXRn`q)$OJHxVplIwF=OnxxsDuW2yKWjeC4|u4LYEtj{8ZSg|Lu2 zh*1)UpI%axZ<^Q69FkQ45p%*37{ zX$8aP6C}#u2?jdFp8lhwmG|;9e*SXxygU@CDg^(WcvTjI^}*rqUp5f^zVV_V z!P(~uilBSRX4}T>@op=BZ?vJWU=7|*yOs;FgnTLc-dJ(Nmz((s?PI>XC3y5i^pv}| z#QTkxJJh(oM^2g}h_|20X~rh7qjwoo+K(#*{xC)f!0q06<&>Nw`6U)NPp8!wE8@<{ z&l+TWou9ol*I>t`FH6cR1*7>K(-s)&&`71a@2zZ^lqoLzDJQ5e`Js;M-k@6^cSb`x zTA#QZ>+84MEzX~e)^y{~23pTMsuE%2=nCU{IR_=VBz2)EbGVCtCdtFCFZz1@laac= zZS2HXr`Kfmy0zxLzU$nM;;~IiEEqJbq)$5C`2RJD`meO(FNhy-y%4+!t<&!L4e-8) zhN4m$-mTt!2L{}%T>{^lv7f~eZB^Tc5fHt!JEm%&VDxPGozSWuaEQF=x-Jf_4@hTQ zueMjyTs6~NJ*{b@RNAe3o_17$c%#7mZw9qrYm=(lNh728*>YLOYA$Y{awq=$u&BMg zMWEB~`0yVtZ94v`IDr_ z%DT~GZg~HXrMgBs6l*2omtN*(F&{1~r1s$Sm&czF60KS7=ksfk+cRPb++8Y_)nD35 zM-Ph!k(}7K{ZecV$bveZe@LNYbuRra2Ph6jjB)V9!QR_RsVc@|*XiWn9!5I@Jq5

d^!20;`XYsqZKY5pZzf)z!zsV0wkkHTPAFnu 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%0AF}%W7u?qM`c}|t(v1+Kk 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

F)0M%V`3;V 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%0D?GC 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

r@EHn94A1UZs=-?+ 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 literal 0 HcmV?d00001 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.c new file mode 100644 index 00000000..c70f5865 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.c @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" +#include + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; + +// this target uses DFU for updates +uint32_t GetTargetCapabilities() +{ + return TargetCapabilities_DfuUpdate; +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.h.in new file mode 100644 index 00000000..419f9f35 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00020000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00080000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..5d78d470 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_adc_config.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 4, ADC_CHANNEL_IN4}, + {1, GPIOA, 5, ADC_CHANNEL_IN5}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2a60a22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..cbd0a365 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART2 // +/////////// + +// pin configuration for UART2 +// port: GPIOA +// TX pin: is GPIOA_2 +// RX pin: is GPIOA_3 +// GPIO alternate pin function is 7 (see "Table 9. Alternate function mapping" in STM32F411xC and STM32F411xE datasheet) +UART_CONFIG_PINS(2, GPIOA, GPIOA, 2, 3, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// initialization for UART2 +UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// un-initialization for UART2 +UART_UNINIT(2) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..68578e71 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +/////////// +// UART2 // +/////////// + +// enable USART2 +#define NF_SERIAL_COMM_STM32_UART_USE_USART2 TRUE + +// buffers size +// tx buffer size: 1024 bytes +#define UART2_TX_SIZE 1024 +// rx buffer size: 1024 bytes +#define UART2_RX_SIZE 1024 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..ef2d3a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_ELECTRON_NF/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/CMakeLists.txt new file mode 100644 index 00000000..52a69f81 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/CMakeLists.txt @@ -0,0 +1,225 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F411xE_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F411xE_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F411xE_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F411xE_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x1000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x2800") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) + +# if HEX2DFU tool is available pack the binaries into a DFU package +if(HEX2DFU_TOOL_AVAILABLE) + + #################################################################################################### + ## when changing the linker file make sure to update the new addresses for the image files bellow ## + ## DO NOT use the leading 0x notation, just the address in plain hexadecimal formating ## + #################################################################################################### + if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08008000 + ${PROJECT_SOURCE_DIR}/build/nanoframework-4-oxygen.dfu + ) + else() + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08004000 + ${PROJECT_SOURCE_DIR}/build/nanoframework-4-oxygen.dfu + ) + endif() + +endif() diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/README.md new file mode 100644 index 00000000..e1c16b7f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/README.md @@ -0,0 +1,9 @@ +## Oxygen community board ## + +The board used in this community contribution is a STM32F411CEU6 based board from IngenuityMicro called Oxygen. The board has 20 pins for your use. The pins on the opposite side of the USB connector can be used for several add-on boards for f.e. BLE, WiFi (ESP8266). + +The pins can be used for several purposes, GPIO, PWM, I2C, SPI, SERIAL, etc. + +Further details how the pin out is supposed to work can be found in the resources folder, of course since we know now what MCU pins go to what PCB pins we can change the board.h depending on what you want to achieve with the board. + +For more information you nay want to have a look at https://github.com/piwi1263/Molecules diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.c new file mode 100644 index 00000000..5e13690c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.c @@ -0,0 +1,265 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.h new file mode 100644 index 00000000..92f959c7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/board.h @@ -0,0 +1,1633 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This is the a board made by IngenuityMicro based upon MCU from ST + * the STM32F411CEU6. The board is equipped with both LSE and HSE. + */ + +#ifndef BOARD_H +#define BOARD_H + +/* + * Setup for IngenuityMicro Oxygen board based upon an STM32F411CEU6.. + */ + +/* + * Board identifier. + */ +#define BOARD_I2M_OXYGEN_NF +#define BOARD_NAME "IngenuityMicro Oxygen board based upon STM32F411CEU6 for nanoFramework" + +/* + * USB OTG Force + */ +#define BOARD_OTG_NOVBUSSENS + +/* + * Completely wacko definition of a flash sector here + */ +#define FLASH_SECTOR_11 ((uint32_t)11U) + +/* + * Board oscillators-related settings. + * NOTE: LSE is fitted and is of course 32768. + * NOTE: HSE is fitted and set to a 12 MHz one. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 12000000U +#endif + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F411xE + +/* + * IO pins assignments. + */ +#define GPIOA_ADC1_IN0 0U +#define GPIOA_USART2_CTS 0U +#define GPIOA_ADC1_IN1 1U +#define GPIOA_USART2_RTS 1U +#define GPIOA_USART2_TX 2U +#define GPIOA_USART2_RX 3U +#define GPIOA_ADC1_IN4 4U +#define GPIOA_SPI1_SCLK 5U +#define GPIOA_SPI1_MISO 6U +#define GPIOA_SPI1_MOSI 7U +#define GPIOA_PIN8 8U +#define GPIOA_USART1_TX 9U +#define GPIOA_USART1_RX 10U +#define GPIOA_OTG_FS_DM 11U +#define GPIOA_OTG_FS_DP 12U +#define GPIOA_USER_LED 13U +#define GPIOA_PIN14 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_PIN3 3U +#define GPIOB_PIN4 4U +#define GPIOB_PIN5 5U +#define GPIOB_PIN6 6U +#define GPIOB_PIN7 7U +#define GPIOB_I2C1_SCL 8U +#define GPIOB_I2C1_SDA 9U +#define GPIOB_PIN10 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_SPI2_SCLK 13U +#define GPIOB_SPI2_MISO 14U +#define GPIOB_SPI2_MOSI 15U + +#define GPIOC_PIN0 0U +#define GPIOC_PIN1 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_USART6_TX 6U +#define GPIOC_USART6_RX 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_PIN0 0U +#define GPIOF_PIN1 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +#define GPIOJ_PIN0 0U +#define GPIOJ_PIN1 1U +#define GPIOJ_PIN2 2U +#define GPIOJ_PIN3 3U +#define GPIOJ_PIN4 4U +#define GPIOJ_PIN5 5U +#define GPIOJ_PIN6 6U +#define GPIOJ_PIN7 7U +#define GPIOJ_PIN8 8U +#define GPIOJ_PIN9 9U +#define GPIOJ_PIN10 10U +#define GPIOJ_PIN11 11U +#define GPIOJ_PIN12 12U +#define GPIOJ_PIN13 13U +#define GPIOJ_PIN14 14U +#define GPIOJ_PIN15 15U + +#define GPIOK_PIN0 0U +#define GPIOK_PIN1 1U +#define GPIOK_PIN2 2U +#define GPIOK_PIN3 3U +#define GPIOK_PIN4 4U +#define GPIOK_PIN5 5U +#define GPIOK_PIN6 6U +#define GPIOK_PIN7 7U +#define GPIOK_PIN8 8U +#define GPIOK_PIN9 9U +#define GPIOK_PIN10 10U +#define GPIOK_PIN11 11U +#define GPIOK_PIN12 12U +#define GPIOK_PIN13 13U +#define GPIOK_PIN14 14U +#define GPIOK_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U) +#define LINE_ADC1_IN0 PAL_LINE(GPIOA, 0U) +#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U) +#define LINE_ADC1_IN1 PAL_LINE(GPIOA, 1U) +#define LINE_ARD_D1 PAL_LINE(GPIOA, 2U) +#define LINE_USART2_TX PAL_LINE(GPIOA, 2U) +#define LINE_ARD_D0 PAL_LINE(GPIOA, 3U) +#define LINE_USART2_RX PAL_LINE(GPIOA, 3U) +#define LINE_ARD_A2 PAL_LINE(GPIOA, 4U) +#define LINE_ADC1_IN4 PAL_LINE(GPIOA, 4U) +#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U) +#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U) +#define LINE_ARD_D7 PAL_LINE(GPIOA, 8U) +#define LINE_ARD_D8 PAL_LINE(GPIOA, 9U) +#define LINE_ARD_D2 PAL_LINE(GPIOA, 10U) +#define LINE_OTG_FS_DM PAL_LINE(GPIOA, 11U) +#define LINE_OTG_FS_DP PAL_LINE(GPIOA, 12U) +#define LINE_USER_LED PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) + +#define LINE_ARD_A3 PAL_LINE(GPIOB, 0U) +#define LINE_ADC1_IN8 PAL_LINE(GPIOB, 0U) +#define LINE_SWO PAL_LINE(GPIOB, 3U) +#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U) +#define LINE_ARD_D5 PAL_LINE(GPIOB, 4U) +#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U) +#define LINE_ARD_D10 PAL_LINE(GPIOB, 6U) +#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U) +#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U) +#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U) + +#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U) +#define LINE_ADC1_IN10 PAL_LINE(GPIOC, 0U) +#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U) +#define LINE_ADC1_IN11 PAL_LINE(GPIOC, 1U) +#define LINE_ARD_D9 PAL_LINE(GPIOC, 7U) +#define LINE_BUTTON PAL_LINE(GPIOC, 13U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) + + + + + +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - ADC1_IN0 (input pullup). + * PA1 - ADC1_IN1 (input pullup). + * PA2 - USART2_TX (alternate 7). + * PA3 - USART2_RX (alternate 7). + * PA4 - ADC1_IN4 (input pullup). + * PA5 - SPI1_SCLK (alternate 5). + * PA6 - SPI1_MISO (alternate 5). + * PA7 - SPI1_MOSI (alternate 5). + * PA8 - PIN8 (input pullup). + * PA9 - USART1_TX (alternate 7). + * PA10 - USART1_RX (alternate 7). + * PA11 - OTG_FS_DM (alternate 10). + * PA12 - OTG_FS_DP (alternate 10). + * PA13 - USER_LED (output pushpull high). + * PA14 - PIN14 (alternate 0). + * PA15 - PIN15 (input pullup). + */ +#define VAL_GPIOA_MODER (PIN_MODE_ANALOG(GPIOA_ADC1_IN0) | \ + PIN_MODE_ANALOG(GPIOA_ADC1_IN1) | \ + PIN_MODE_ALTERNATE(GPIOA_USART2_TX) | \ + PIN_MODE_ALTERNATE(GPIOA_USART2_RX) | \ + PIN_MODE_ANALOG(GPIOA_ADC1_IN4) | \ + PIN_MODE_ALTERNATE(GPIOA_SPI1_SCLK) | \ + PIN_MODE_ALTERNATE(GPIOA_SPI1_MISO) | \ + PIN_MODE_ALTERNATE(GPIOA_SPI1_MOSI) | \ + PIN_MODE_INPUT(GPIOA_PIN8) | \ + PIN_MODE_ALTERNATE(GPIOA_USART1_TX) | \ + PIN_MODE_ALTERNATE(GPIOA_USART1_RX) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DP) | \ + PIN_MODE_OUTPUT(GPIOA_USER_LED) | \ + PIN_MODE_INPUT(GPIOA_PIN14) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ADC1_IN0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ADC1_IN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USART2_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USART2_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ADC1_IN4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SPI1_SCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SPI1_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SPI1_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USART1_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USART1_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USER_LED) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ADC1_IN0) | \ + PIN_OSPEED_HIGH(GPIOA_ADC1_IN1) | \ + PIN_OSPEED_HIGH(GPIOA_USART2_TX) | \ + PIN_OSPEED_HIGH(GPIOA_USART2_RX) | \ + PIN_OSPEED_HIGH(GPIOA_ADC1_IN4) | \ + PIN_OSPEED_HIGH(GPIOA_SPI1_SCLK) | \ + PIN_OSPEED_HIGH(GPIOA_SPI1_MISO) | \ + PIN_OSPEED_HIGH(GPIOA_SPI1_MOSI) | \ + PIN_OSPEED_HIGH(GPIOA_PIN8) | \ + PIN_OSPEED_HIGH(GPIOA_USART1_TX) | \ + PIN_OSPEED_HIGH(GPIOA_USART1_RX) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_OSPEED_HIGH(GPIOA_USER_LED) | \ + PIN_OSPEED_HIGH(GPIOA_PIN14) | \ + PIN_OSPEED_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_ADC1_IN0) | \ + PIN_PUPDR_FLOATING(GPIOA_ADC1_IN1) | \ + PIN_PUPDR_FLOATING(GPIOA_USART2_TX) | \ + PIN_PUPDR_FLOATING(GPIOA_USART2_RX) | \ + PIN_PUPDR_FLOATING(GPIOA_ADC1_IN4) | \ + PIN_PUPDR_FLOATING(GPIOA_SPI1_SCLK) | \ + PIN_PUPDR_FLOATING(GPIOA_SPI1_MISO) | \ + PIN_PUPDR_FLOATING(GPIOA_SPI1_MOSI) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOA_USART1_TX) | \ + PIN_PUPDR_FLOATING(GPIOA_USART1_RX) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | \ + PIN_PUPDR_FLOATING(GPIOA_USER_LED) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_LOW(GPIOA_ADC1_IN0) | \ + PIN_ODR_LOW(GPIOA_ADC1_IN1) | \ + PIN_ODR_LOW(GPIOA_USART2_TX) | \ + PIN_ODR_LOW(GPIOA_USART2_RX) | \ + PIN_ODR_LOW(GPIOA_ADC1_IN4) | \ + PIN_ODR_LOW(GPIOA_SPI1_SCLK) | \ + PIN_ODR_LOW(GPIOA_SPI1_MISO) | \ + PIN_ODR_LOW(GPIOA_SPI1_MOSI) | \ + PIN_ODR_HIGH(GPIOA_PIN8) | \ + PIN_ODR_LOW(GPIOA_USART1_TX) | \ + PIN_ODR_LOW(GPIOA_USART1_RX) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_ODR_LOW(GPIOA_USER_LED) | \ + PIN_ODR_HIGH(GPIOA_PIN14) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ADC1_IN0, 0U) | \ + PIN_AFIO_AF(GPIOA_ADC1_IN1, 0U) | \ + PIN_AFIO_AF(GPIOA_USART2_TX, 7U) | \ + PIN_AFIO_AF(GPIOA_USART2_RX, 7U) | \ + PIN_AFIO_AF(GPIOA_ADC1_IN4, 0U) | \ + PIN_AFIO_AF(GPIOA_SPI1_SCLK, 5U) | \ + PIN_AFIO_AF(GPIOA_SPI1_MISO, 5U) | \ + PIN_AFIO_AF(GPIOA_SPI1_MOSI, 5U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOA_USART1_TX, 7U) | \ + PIN_AFIO_AF(GPIOA_USART1_RX, 7U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_USER_LED, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0U)) + +/* + * GPIOB setup: + * + * PB0 - PIN0 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - PIN3 (input pullup). + * PB4 - PIN4 (input pullup). + * PB5 - PIN5 (input pullup). + * PB6 - PIN6 (input pullup). + * PB7 - PIN7 (input pullup). + * PB8 - I2C1_SCL (alternate 4). + * PB9 - I2C1_SDA (alternate 4). + * PB10 - ARD_D6 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - SPI2_SCLK (alternate 5). + * PB14 - SPI2_MISO (alternate 5). + * PB15 - SPI2_MOSI (alternate 5). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_INPUT(GPIOB_PIN3) | \ + PIN_MODE_INPUT(GPIOB_PIN4) | \ + PIN_MODE_INPUT(GPIOB_PIN5) | \ + PIN_MODE_INPUT(GPIOB_PIN6) | \ + PIN_MODE_INPUT(GPIOB_PIN7) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_INPUT(GPIOB_PIN10) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_SCLK) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_MISO) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_SCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_PIN0) | \ + PIN_OSPEED_HIGH(GPIOB_PIN1) | \ + PIN_OSPEED_HIGH(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_PIN3) | \ + PIN_OSPEED_HIGH(GPIOB_PIN4) | \ + PIN_OSPEED_HIGH(GPIOB_PIN5) | \ + PIN_OSPEED_HIGH(GPIOB_PIN6) | \ + PIN_OSPEED_HIGH(GPIOB_PIN7) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_PIN10) | \ + PIN_OSPEED_HIGH(GPIOB_PIN11) | \ + PIN_OSPEED_HIGH(GPIOB_PIN12) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_SCLK) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_MISO) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_SCLK) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_MISO) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_PIN0) | \ + PIN_ODR_LOW(GPIOB_PIN1) | \ + PIN_ODR_LOW(GPIOB_PIN2) | \ + PIN_ODR_LOW(GPIOB_PIN3) | \ + PIN_ODR_LOW(GPIOB_PIN4) | \ + PIN_ODR_LOW(GPIOB_PIN5) | \ + PIN_ODR_LOW(GPIOB_PIN6) | \ + PIN_ODR_LOW(GPIOB_PIN7) | \ + PIN_ODR_LOW(GPIOB_I2C1_SCL) | \ + PIN_ODR_LOW(GPIOB_I2C1_SDA) | \ + PIN_ODR_LOW(GPIOB_PIN10) | \ + PIN_ODR_LOW(GPIOB_PIN11) | \ + PIN_ODR_LOW(GPIOB_PIN12) | \ + PIN_ODR_LOW(GPIOB_SPI2_SCLK) | \ + PIN_ODR_LOW(GPIOB_SPI2_MISO) | \ + PIN_ODR_LOW(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U) | \ + PIN_AFIO_AF(GPIOB_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOB_SPI2_SCLK, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI2_MISO, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI2_MOSI, 5U)) + +/* + * GPIOC setup: + * + * PC0 - ARD_A5 ADC1_IN10 (input pullup). + * PC1 - ARD_A4 ADC1_IN11 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 = TX6 (Alternate8 floating). + * PC7 - PIN7 = RX6 (Alternate8 floating). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - PIN10 (input pullup). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - BUTTON (input floating). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ + PIN_MODE_INPUT(GPIOC_PIN1) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_ALTERNATE(GPIOC_USART6_TX) | \ + PIN_MODE_ALTERNATE(GPIOC_USART6_RX) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_OSC32_IN) | \ + PIN_MODE_INPUT(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_USART6_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOC_USART6_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_PIN0) | \ + PIN_OSPEED_HIGH(GPIOC_PIN1) | \ + PIN_OSPEED_HIGH(GPIOC_PIN2) | \ + PIN_OSPEED_HIGH(GPIOC_PIN3) | \ + PIN_OSPEED_HIGH(GPIOC_PIN4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN5) | \ + PIN_OSPEED_MEDIUM(GPIOC_USART6_TX) | \ + PIN_OSPEED_MEDIUM(GPIOC_USART6_RX) | \ + PIN_OSPEED_HIGH(GPIOC_PIN8) | \ + PIN_OSPEED_HIGH(GPIOC_PIN9) | \ + PIN_OSPEED_HIGH(GPIOC_PIN10) | \ + PIN_OSPEED_HIGH(GPIOC_PIN11) | \ + PIN_OSPEED_HIGH(GPIOC_PIN12) | \ + PIN_OSPEED_HIGH(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOC_USART6_TX) | \ + PIN_PUPDR_FLOATING(GPIOC_USART6_RX) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ + PIN_ODR_HIGH(GPIOC_PIN1) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_USART6_TX) | \ + PIN_ODR_HIGH(GPIOC_USART6_RX) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_OSC32_IN) | \ + PIN_ODR_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOC_USART6_TX, 8U) | \ + PIN_AFIO_AF(GPIOC_USART6_RX, 8U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD10 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \ + PIN_OSPEED_HIGH(GPIOD_PIN1) | \ + PIN_OSPEED_HIGH(GPIOD_PIN2) | \ + PIN_OSPEED_HIGH(GPIOD_PIN3) | \ + PIN_OSPEED_HIGH(GPIOD_PIN4) | \ + PIN_OSPEED_HIGH(GPIOD_PIN5) | \ + PIN_OSPEED_HIGH(GPIOD_PIN6) | \ + PIN_OSPEED_HIGH(GPIOD_PIN7) | \ + PIN_OSPEED_HIGH(GPIOD_PIN8) | \ + PIN_OSPEED_HIGH(GPIOD_PIN9) | \ + PIN_OSPEED_HIGH(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_PIN11) | \ + PIN_OSPEED_HIGH(GPIOD_PIN12) | \ + PIN_OSPEED_HIGH(GPIOD_PIN13) | \ + PIN_OSPEED_HIGH(GPIOD_PIN14) | \ + PIN_OSPEED_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0U)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 (input pullup). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (input pullup). + * PE9 - PIN9 (input pullup). + * PE10 - PIN10 (input pullup). + * PE11 - PIN11 (input pullup). + * PE12 - PIN12 (input pullup). + * PE13 - PIN13 (input pullup). + * PE14 - PIN14 (input pullup). + * PE15 - PIN15 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) | \ + PIN_MODE_INPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) | \ + PIN_MODE_INPUT(GPIOE_PIN5) | \ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_INPUT(GPIOE_PIN8) | \ + PIN_MODE_INPUT(GPIOE_PIN9) | \ + PIN_MODE_INPUT(GPIOE_PIN10) | \ + PIN_MODE_INPUT(GPIOE_PIN11) | \ + PIN_MODE_INPUT(GPIOE_PIN12) | \ + PIN_MODE_INPUT(GPIOE_PIN13) | \ + PIN_MODE_INPUT(GPIOE_PIN14) | \ + PIN_MODE_INPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \ + PIN_OSPEED_HIGH(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_PIN2) | \ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_HIGH(GPIOE_PIN4) | \ + PIN_OSPEED_HIGH(GPIOE_PIN5) | \ + PIN_OSPEED_HIGH(GPIOE_PIN6) | \ + PIN_OSPEED_HIGH(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_HIGH(GPIOE_PIN8) | \ + PIN_ODR_HIGH(GPIOE_PIN9) | \ + PIN_ODR_HIGH(GPIOE_PIN10) | \ + PIN_ODR_HIGH(GPIOE_PIN11) | \ + PIN_ODR_HIGH(GPIOE_PIN12) | \ + PIN_ODR_HIGH(GPIOE_PIN13) | \ + PIN_ODR_HIGH(GPIOE_PIN14) | \ + PIN_ODR_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0U)) + +/* + * GPIOF setup: + * + * PF0 - PIN0 (input pullup). + * PF1 - PIN1 (input pullup). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \ + PIN_MODE_INPUT(GPIOF_PIN1) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_PIN0) | \ + PIN_OSPEED_HIGH(GPIOF_PIN1) | \ + PIN_OSPEED_HIGH(GPIOF_PIN2) | \ + PIN_OSPEED_HIGH(GPIOF_PIN3) | \ + PIN_OSPEED_HIGH(GPIOF_PIN4) | \ + PIN_OSPEED_HIGH(GPIOF_PIN5) | \ + PIN_OSPEED_HIGH(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_PIN7) | \ + PIN_OSPEED_HIGH(GPIOF_PIN8) | \ + PIN_OSPEED_HIGH(GPIOF_PIN9) | \ + PIN_OSPEED_HIGH(GPIOF_PIN10) | \ + PIN_OSPEED_HIGH(GPIOF_PIN11) | \ + PIN_OSPEED_HIGH(GPIOF_PIN12) | \ + PIN_OSPEED_HIGH(GPIOF_PIN13) | \ + PIN_OSPEED_HIGH(GPIOF_PIN14) | \ + PIN_OSPEED_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \ + PIN_ODR_HIGH(GPIOF_PIN1) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0U)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_HIGH(GPIOG_PIN0) | \ + PIN_OSPEED_HIGH(GPIOG_PIN1) | \ + PIN_OSPEED_HIGH(GPIOG_PIN2) | \ + PIN_OSPEED_HIGH(GPIOG_PIN3) | \ + PIN_OSPEED_HIGH(GPIOG_PIN4) | \ + PIN_OSPEED_HIGH(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_PIN6) | \ + PIN_OSPEED_HIGH(GPIOG_PIN7) | \ + PIN_OSPEED_HIGH(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_PIN9) | \ + PIN_OSPEED_HIGH(GPIOG_PIN10) | \ + PIN_OSPEED_HIGH(GPIOG_PIN11) | \ + PIN_OSPEED_HIGH(GPIOG_PIN12) | \ + PIN_OSPEED_HIGH(GPIOG_PIN13) | \ + PIN_OSPEED_HIGH(GPIOG_PIN14) | \ + PIN_OSPEED_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_HIGH(GPIOH_PIN2) | \ + PIN_OSPEED_HIGH(GPIOH_PIN3) | \ + PIN_OSPEED_HIGH(GPIOH_PIN4) | \ + PIN_OSPEED_HIGH(GPIOH_PIN5) | \ + PIN_OSPEED_HIGH(GPIOH_PIN6) | \ + PIN_OSPEED_HIGH(GPIOH_PIN7) | \ + PIN_OSPEED_HIGH(GPIOH_PIN8) | \ + PIN_OSPEED_HIGH(GPIOH_PIN9) | \ + PIN_OSPEED_HIGH(GPIOH_PIN10) | \ + PIN_OSPEED_HIGH(GPIOH_PIN11) | \ + PIN_OSPEED_HIGH(GPIOH_PIN12) | \ + PIN_OSPEED_HIGH(GPIOH_PIN13) | \ + PIN_OSPEED_HIGH(GPIOH_PIN14) | \ + PIN_OSPEED_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input pullup). + * PI1 - PIN1 (input pullup). + * PI2 - PIN2 (input pullup). + * PI3 - PIN3 (input pullup). + * PI4 - PIN4 (input pullup). + * PI5 - PIN5 (input pullup). + * PI6 - PIN6 (input pullup). + * PI7 - PIN7 (input pullup). + * PI8 - PIN8 (input pullup). + * PI9 - PIN9 (input pullup). + * PI10 - PIN10 (input pullup). + * PI11 - PIN11 (input pullup). + * PI12 - PIN12 (input pullup). + * PI13 - PIN13 (input pullup). + * PI14 - PIN14 (input pullup). + * PI15 - PIN15 (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_HIGH(GPIOI_PIN0) | \ + PIN_OSPEED_HIGH(GPIOI_PIN1) | \ + PIN_OSPEED_HIGH(GPIOI_PIN2) | \ + PIN_OSPEED_HIGH(GPIOI_PIN3) | \ + PIN_OSPEED_HIGH(GPIOI_PIN4) | \ + PIN_OSPEED_HIGH(GPIOI_PIN5) | \ + PIN_OSPEED_HIGH(GPIOI_PIN6) | \ + PIN_OSPEED_HIGH(GPIOI_PIN7) | \ + PIN_OSPEED_HIGH(GPIOI_PIN8) | \ + PIN_OSPEED_HIGH(GPIOI_PIN9) | \ + PIN_OSPEED_HIGH(GPIOI_PIN10) | \ + PIN_OSPEED_HIGH(GPIOI_PIN11) | \ + PIN_OSPEED_HIGH(GPIOI_PIN12) | \ + PIN_OSPEED_HIGH(GPIOI_PIN13) | \ + PIN_OSPEED_HIGH(GPIOI_PIN14) | \ + PIN_OSPEED_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + +/* + * GPIOJ setup: + * + * PJ0 - PIN0 (input floating). + * PJ1 - PIN1 (input floating). + * PJ2 - PIN2 (input floating). + * PJ3 - PIN3 (input floating). + * PJ4 - PIN4 (input floating). + * PJ5 - PIN5 (input floating). + * PJ6 - PIN6 (input floating). + * PJ7 - PIN7 (input floating). + * PJ8 - PIN8 (input floating). + * PJ9 - PIN9 (input floating). + * PJ10 - PIN10 (input floating). + * PJ11 - PIN11 (input floating). + * PJ12 - PIN12 (input floating). + * PJ13 - PIN13 (input floating). + * PJ14 - PIN14 (input floating). + * PJ15 - PIN15 (input floating). + */ +#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \ + PIN_MODE_INPUT(GPIOJ_PIN1) | \ + PIN_MODE_INPUT(GPIOJ_PIN2) | \ + PIN_MODE_INPUT(GPIOJ_PIN3) | \ + PIN_MODE_INPUT(GPIOJ_PIN4) | \ + PIN_MODE_INPUT(GPIOJ_PIN5) | \ + PIN_MODE_INPUT(GPIOJ_PIN6) | \ + PIN_MODE_INPUT(GPIOJ_PIN7) | \ + PIN_MODE_INPUT(GPIOJ_PIN8) | \ + PIN_MODE_INPUT(GPIOJ_PIN9) | \ + PIN_MODE_INPUT(GPIOJ_PIN10) | \ + PIN_MODE_INPUT(GPIOJ_PIN11) | \ + PIN_MODE_INPUT(GPIOJ_PIN12) | \ + PIN_MODE_INPUT(GPIOJ_PIN13) | \ + PIN_MODE_INPUT(GPIOJ_PIN14) | \ + PIN_MODE_INPUT(GPIOJ_PIN15)) +#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN15)) +#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_HIGH(GPIOJ_PIN0) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN1) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN2) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN3) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN4) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN5) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN6) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN7) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN8) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN9) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN10) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN11) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN12) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN13) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN14) | \ + PIN_OSPEED_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_PUPDR (PIN_PUPDR_FLOATING(GPIOJ_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN15)) +#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \ + PIN_ODR_HIGH(GPIOJ_PIN1) | \ + PIN_ODR_HIGH(GPIOJ_PIN2) | \ + PIN_ODR_HIGH(GPIOJ_PIN3) | \ + PIN_ODR_HIGH(GPIOJ_PIN4) | \ + PIN_ODR_HIGH(GPIOJ_PIN5) | \ + PIN_ODR_HIGH(GPIOJ_PIN6) | \ + PIN_ODR_HIGH(GPIOJ_PIN7) | \ + PIN_ODR_HIGH(GPIOJ_PIN8) | \ + PIN_ODR_HIGH(GPIOJ_PIN9) | \ + PIN_ODR_HIGH(GPIOJ_PIN10) | \ + PIN_ODR_HIGH(GPIOJ_PIN11) | \ + PIN_ODR_HIGH(GPIOJ_PIN12) | \ + PIN_ODR_HIGH(GPIOJ_PIN13) | \ + PIN_ODR_HIGH(GPIOJ_PIN14) | \ + PIN_ODR_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN7, 0U)) +#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN15, 0U)) + +/* + * GPIOK setup: + * + * PK0 - PIN0 (input floating). + * PK1 - PIN1 (input floating). + * PK2 - PIN2 (input floating). + * PK3 - PIN3 (input floating). + * PK4 - PIN4 (input floating). + * PK5 - PIN5 (input floating). + * PK6 - PIN6 (input floating). + * PK7 - PIN7 (input floating). + * PK8 - PIN8 (input floating). + * PK9 - PIN9 (input floating). + * PK10 - PIN10 (input floating). + * PK11 - PIN11 (input floating). + * PK12 - PIN12 (input floating). + * PK13 - PIN13 (input floating). + * PK14 - PIN14 (input floating). + * PK15 - PIN15 (input floating). + */ +#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \ + PIN_MODE_INPUT(GPIOK_PIN1) | \ + PIN_MODE_INPUT(GPIOK_PIN2) | \ + PIN_MODE_INPUT(GPIOK_PIN3) | \ + PIN_MODE_INPUT(GPIOK_PIN4) | \ + PIN_MODE_INPUT(GPIOK_PIN5) | \ + PIN_MODE_INPUT(GPIOK_PIN6) | \ + PIN_MODE_INPUT(GPIOK_PIN7) | \ + PIN_MODE_INPUT(GPIOK_PIN8) | \ + PIN_MODE_INPUT(GPIOK_PIN9) | \ + PIN_MODE_INPUT(GPIOK_PIN10) | \ + PIN_MODE_INPUT(GPIOK_PIN11) | \ + PIN_MODE_INPUT(GPIOK_PIN12) | \ + PIN_MODE_INPUT(GPIOK_PIN13) | \ + PIN_MODE_INPUT(GPIOK_PIN14) | \ + PIN_MODE_INPUT(GPIOK_PIN15)) +#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN15)) +#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_HIGH(GPIOK_PIN0) | \ + PIN_OSPEED_HIGH(GPIOK_PIN1) | \ + PIN_OSPEED_HIGH(GPIOK_PIN2) | \ + PIN_OSPEED_HIGH(GPIOK_PIN3) | \ + PIN_OSPEED_HIGH(GPIOK_PIN4) | \ + PIN_OSPEED_HIGH(GPIOK_PIN5) | \ + PIN_OSPEED_HIGH(GPIOK_PIN6) | \ + PIN_OSPEED_HIGH(GPIOK_PIN7) | \ + PIN_OSPEED_HIGH(GPIOK_PIN8) | \ + PIN_OSPEED_HIGH(GPIOK_PIN9) | \ + PIN_OSPEED_HIGH(GPIOK_PIN10) | \ + PIN_OSPEED_HIGH(GPIOK_PIN11) | \ + PIN_OSPEED_HIGH(GPIOK_PIN12) | \ + PIN_OSPEED_HIGH(GPIOK_PIN13) | \ + PIN_OSPEED_HIGH(GPIOK_PIN14) | \ + PIN_OSPEED_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_PUPDR (PIN_PUPDR_FLOATING(GPIOK_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN15)) +#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \ + PIN_ODR_HIGH(GPIOK_PIN1) | \ + PIN_ODR_HIGH(GPIOK_PIN2) | \ + PIN_ODR_HIGH(GPIOK_PIN3) | \ + PIN_ODR_HIGH(GPIOK_PIN4) | \ + PIN_ODR_HIGH(GPIOK_PIN5) | \ + PIN_ODR_HIGH(GPIOK_PIN6) | \ + PIN_ODR_HIGH(GPIOK_PIN7) | \ + PIN_ODR_HIGH(GPIOK_PIN8) | \ + PIN_ODR_HIGH(GPIOK_PIN9) | \ + PIN_ODR_HIGH(GPIOK_PIN10) | \ + PIN_ODR_HIGH(GPIOK_PIN11) | \ + PIN_ODR_HIGH(GPIOK_PIN12) | \ + PIN_ODR_HIGH(GPIOK_PIN13) | \ + PIN_ODR_HIGH(GPIOK_PIN14) | \ + PIN_ODR_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN7, 0U)) +#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN15, 0U)) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/CMakeLists.txt new file mode 100644 index 00000000..aa7f1d54 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..0e822535 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 08008000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +//384kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 5 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 6, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00080000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage.c new file mode 100644 index 00000000..6e381213 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/Device_BlockStorage.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 08004000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +//384kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 5 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 6, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00080000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.c new file mode 100644 index 00000000..a048c76f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.c @@ -0,0 +1,435 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD1. + */ +#define USBD1_DATA_REQUEST_EP 1 +#define USBD1_DATA_AVAILABLE_EP 1 +#define USBD1_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"STMicroelectronics" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"nanoFramework Virtual COM Port" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[18] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[67] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(67, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + sduRequestsHook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD1_DATA_REQUEST_EP, + USBD1_DATA_AVAILABLE_EP, + USBD1_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.h new file mode 100644 index 00000000..167e1df8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/common/usbcfg.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Adc.cs new file mode 100644 index 00000000..16f88c5a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Adc.cs @@ -0,0 +1,43 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.Community.I2M_OXYGEN_NF +{ + ///

+ /// Enumeration of ADC channels available in the community board I2M_OXYGEN_NF + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed on PA0, connected to PA0 (ADC1 - IN0) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed on PA1, connected to PA1 (ADC1 - IN1) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed on PA4, connected to PA4 (ADC1 - IN4) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 3; + + /// + /// Channel 4, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 4; + + /// + /// Channel 5, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 5; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Gpio.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Gpio.cs new file mode 100644 index 00000000..204b455d --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/I2M_OXYGEN_NF.Gpio.cs @@ -0,0 +1,63 @@ +using System; + +namespace nanoFramework.Targets.Community.I2M_OXYGEN_NF +{ + public static class Gpio + { + /// + /// Output pin connected to the on-board user LED + /// + public const int UserLed = PA13; + + /// + /// Output pin used for controlling the power to the Rf sub-assembly + /// + public const int RfPower = PB3; + + /// + /// + /// + public const int PA0 = 0; + public const int PA1 = 1; + public const int PA2 = 2; + public const int PA3 = 3; + public const int PA4 = 4; + public const int PA5 = 5; + public const int PA6 = 6; + public const int PA7 = 7; + public const int PA8 = 8; + public const int PA9 = 9; + public const int PA10 = 10; + public const int PA11 = 11; + public const int PA12 = 12; + public const int PA13 = 13; + public const int PA14 = 14; + public const int PA15 = 15; + + /// + /// + /// + public const int PB0 = 16; + public const int PB1 = 17; + public const int PB2 = 18; + public const int PB3 = 19; + public const int PB4 = 20; + public const int PB5 = 21; + public const int PB6 = 22; + public const int PB7 = 23; + public const int PB8 = 24; + public const int PB9 = 25; + public const int PB10 = 26; + public const int PB11 = 27; + public const int PB12 = 28; + public const int PB13 = 29; + public const int PB14 = 30; + public const int PB15 = 31; + + /// + /// + /// + public const int PC0 = 32; + public const int PC1 = 33; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/README.md new file mode 100644 index 00000000..551569ac --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/managed_helpers/README.md @@ -0,0 +1,6 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](I2M_OXYGEN_NF.Adc.cs) +* [Gpio](I2M_OXYGEN_NF.Gpio.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld new file mode 100644 index 00000000..704cbf78 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08007FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter.ld new file mode 100644 index 00000000..93940298 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/STM32F411xE_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08003FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/chconf.h new file mode 100644 index 00000000..335e3fa4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf.h new file mode 100644 index 00000000..b970c22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/main.c new file mode 100644 index 00000000..404ff970 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/main.c @@ -0,0 +1,75 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + osDelay(20); // Let init stabilize + + // check for valid CLR image + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOA, GPIOA_USER_LED); + osDelay(500); + palClearPad(GPIOA, GPIOA_USER_LED); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf.h new file mode 100644 index 00000000..7138056a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf.h @@ -0,0 +1,338 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F411_MCUCONF + +/* + * HAL driver system settings. + */ + +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED FALSE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 12 +#define STM32_PLLN_VALUE 192 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 4 + +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 TRUE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld new file mode 100644 index 00000000..f1f0afc1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 512k - 32k - 256k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR.ld new file mode 100644 index 00000000..41fe4314 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/STM32F411xE_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 512k - 16k - 256k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/chconf.h new file mode 100644 index 00000000..3ce5c5aa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/chconf.h @@ -0,0 +1,621 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// address of vector table for nanoCLR +#define CORTEX_VTOR_INIT 0x08008000U +/////////////////////////////////////////////////////////////////////////////// + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf.h new file mode 100644 index 00000000..a1e2b875 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf.h @@ -0,0 +1,525 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/main.c new file mode 100644 index 00000000..83f74065 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/main.c @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // Start Watchdog + Watchdog_Init(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // EXT driver needs to be started from main + #if (HAL_USE_EXT == TRUE) + extStart(&EXTD1, &extInterruptsConfiguration); + #endif + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf.h new file mode 100644 index 00000000..8416bc6e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf.h @@ -0,0 +1,338 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F411_MCUCONF + +/* + * HAL driver system settings. + */ + + #define STM32_NO_INIT FALSE + #define STM32_HSI_ENABLED FALSE + #define STM32_LSI_ENABLED TRUE + #define STM32_HSE_ENABLED TRUE + #define STM32_LSE_ENABLED TRUE + #define STM32_CLOCK48_REQUIRED TRUE + #define STM32_SW STM32_SW_PLL + #define STM32_PLLSRC STM32_PLLSRC_HSE + #define STM32_PLLM_VALUE 12 + #define STM32_PLLN_VALUE 192 + #define STM32_PLLP_VALUE 2 + #define STM32_PLLQ_VALUE 4 + + #define STM32_HPRE STM32_HPRE_DIV1 + #define STM32_PPRE1 STM32_PPRE1_DIV4 + #define STM32_PPRE2 STM32_PPRE2_DIV2 + #define STM32_RTCSEL STM32_RTCSEL_LSE + #define STM32_RTCPRE_VALUE 8 + #define STM32_MCO1SEL STM32_MCO1SEL_HSE + #define STM32_MCO1PRE STM32_MCO1PRE_DIV1 + #define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK + #define STM32_MCO2PRE STM32_MCO2PRE_DIV5 + #define STM32_I2SSRC STM32_I2SSRC_CKIN + #define STM32_PLLI2SN_VALUE 192 + #define STM32_PLLI2SR_VALUE 5 + #define STM32_PVD_ENABLE FALSE + #define STM32_PLS STM32_PLS_LEV0 + #define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 TRUE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/resources/oxygen-pcb.jpeg b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/resources/oxygen-pcb.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..2cf5fbd60e70879d35e9da56f663c0cb44ecd09e GIT binary patch literal 114109 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

$>X*?lG`uuTQmU>+Bfq*qhIskn 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 AYybcN literal 0 HcmV?d00001 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/resources/oxygen.jpeg b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/resources/oxygen.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..71395c9fec3fa24bbf7a227873fdb8cfac83a379 GIT binary patch literal 189405 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

+ /// Enumeration of ADC channels available on board ST_NUCLEO144_F412ZG_NF + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed on CN9 Pin 1, connected to PA3 (ADC1 - IN3) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed on CN9 Pin 3, connected to PC0 (ADC1 - IN10) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed on CN9 Pin 5, connected to PC3 (ADC1 - IN13) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, exposed on CN9 Pin 7, connected to PC1 (ADC1 - IN11) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, exposed on CN9 Pin 9, connected to PC4 (ADC1 - IN14) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, exposed on CN9 Pin 11, connected to PC5 (ADC1 - IN15) + /// + public const int Channel_5 = 5; + + /// + /// Channel 6, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 6; + + /// + /// Channel 7, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 7; + + /// + /// Channel 8, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 8; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Gpio.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Gpio.cs new file mode 100644 index 00000000..aa09ba34 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Gpio.cs @@ -0,0 +1,72 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +using System; + +namespace nanoFramework.Targets.Community.ST_NUCLEO144_F412ZG_NF +{ + public static class Gpio + { + /// + /// + /// + public const int PA0 = 0; + public const int PA1 = 1; + public const int PA2 = 2; + public const int PA3 = 3; + public const int PA4 = 4; + public const int PA5 = 5; + public const int PA6 = 6; + public const int PA7 = 7; + public const int PA8 = 8; + public const int PA9 = 9; + public const int PA10 = 10; + public const int PA11 = 11; + public const int PA12 = 12; + public const int PA13 = 13; + public const int PA14 = 14; + public const int PA15 = 15; + + /// + /// + /// + public const int PB0 = 16; + public const int PB1 = 17; + public const int PB2 = 18; + public const int PB3 = 19; + public const int PB4 = 20; + public const int PB5 = 21; + public const int PB6 = 22; + public const int PB7 = 23; + public const int PB8 = 24; + public const int PB9 = 25; + public const int PB10 = 26; + public const int PB11 = 27; + public const int PB12 = 28; + public const int PB13 = 29; + public const int PB14 = 30; + public const int PB15 = 31; + + /// + /// + /// + public const int PC0 = 32; + public const int PC1 = 33; + public const int PC2 = 34; + public const int PC3 = 35; + public const int PC4 = 36; + public const int PC5 = 37; + public const int PC6 = 38; + public const int PC7 = 39; + public const int PC8 = 40; + public const int PC9 = 41; + public const int PC10 = 42; + public const int PC11 = 43; + public const int PC12 = 44; + public const int PC13 = 45; + public const int PC14 = 46; + public const int PC15 = 47; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.LEDs.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.LEDs.cs new file mode 100644 index 00000000..ef9cb0dc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.LEDs.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.Community.ST_NUCLEO144_F412ZG_NF +{ + public enum OnBoardLeds + { + /// + /// Output pin connected to the on-board green user LED + /// + GreenLed = Gpio.PB0, + + /// + /// Output pin connected to the on-board blue user LED + /// + BlueLed = Gpio.PB7, + + /// + /// Output pin connected to the on-board red user LED + /// + RedLed = Gpio.PB14 + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..f0e921f7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") + +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter-DEBUG.ld new file mode 100644 index 00000000..f9ee71b8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F412xG memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08007FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 256k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter.ld new file mode 100644 index 00000000..f71d39bd --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/STM32F412xG_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F412xG memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08007FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 256k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/chconf.h new file mode 100644 index 00000000..90665754 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/chconf.h @@ -0,0 +1,618 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 2000 // this is 2 milliseconds + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#define CORTEX_VTOR_INIT 0x00200000U + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf.h new file mode 100644 index 00000000..fee2feb7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/main.c new file mode 100644 index 00000000..11c74236 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/main.c @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + // the user button in this board has a pull-up resistor so the check has to be inverted + if (!palReadPad(GPIOC, GPIOC_BUTTON)) + { + // check for valid CLR image + // we are checking for a valid image right after the configuration block + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOB, GPIOB_LED1); + palSetPad(GPIOB, GPIOB_LED2); + palSetPad(GPIOB, GPIOB_LED3); + osDelay(250); + palClearPad(GPIOB, GPIOB_LED1); + palClearPad(GPIOB, GPIOB_LED2); + palClearPad(GPIOB, GPIOB_LED3); + osDelay(250); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf.h new file mode 100644 index 00000000..bf26e0f7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf.h @@ -0,0 +1,343 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 4 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_PLLI2SSRC STM32_PLLI2SSRC_PLLSRC +#define STM32_I2SCKIN_VALUE 0 +#define STM32_PLLI2SM_VALUE 8 +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 4 +#define STM32_PLLI2SQ_VALUE 4 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_USE_I2C4 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C4_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_I2C4_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR-DEBUG.ld new file mode 100644 index 00000000..36c75241 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F412xG memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 1M - 32k - 768k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 768k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 256k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR.ld new file mode 100644 index 00000000..265d2745 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/STM32F412xG_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 1M - 32k - 768k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 768k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 256k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/chconf.h new file mode 100644 index 00000000..4e161afa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/chconf.h @@ -0,0 +1,621 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// address of vector table for nanoCLR +#define CORTEX_VTOR_INIT 0x08008000U +/////////////////////////////////////////////////////////////////////////////// + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf.h new file mode 100644 index 00000000..ba392052 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf.h @@ -0,0 +1,524 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC FALSE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM FALSE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ + +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..5ac68c7c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/halconf_nf.h @@ -0,0 +1,14 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/main.c new file mode 100644 index 00000000..d1126c73 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/main.c @@ -0,0 +1,71 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf.h new file mode 100644 index 00000000..b80b4e23 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf.h @@ -0,0 +1,349 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ + + #define STM32_NO_INIT FALSE + #define STM32_HSI_ENABLED TRUE + #define STM32_LSI_ENABLED TRUE + #define STM32_HSE_ENABLED TRUE + #define STM32_LSE_ENABLED TRUE + #define STM32_CLOCK48_REQUIRED TRUE + #define STM32_SW STM32_SW_PLL + #define STM32_PLLSRC STM32_PLLSRC_HSE + #define STM32_PLLM_VALUE 8 + #define STM32_PLLN_VALUE 336 + #define STM32_PLLP_VALUE 4 + #define STM32_PLLQ_VALUE 7 + #define STM32_HPRE STM32_HPRE_DIV1 + #define STM32_PPRE1 STM32_PPRE1_DIV4 + #define STM32_PPRE2 STM32_PPRE2_DIV2 + #define STM32_RTCSEL STM32_RTCSEL_LSE + #define STM32_RTCPRE_VALUE 8 + #define STM32_MCO1SEL STM32_MCO1SEL_HSE + #define STM32_MCO1PRE STM32_MCO1PRE_DIV1 + #define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK + #define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_PLLI2SSRC STM32_PLLI2SSRC_PLLSRC +#define STM32_I2SCKIN_VALUE 0 +#define STM32_PLLI2SM_VALUE 8 +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 4 +#define STM32_PLLI2SQ_VALUE 4 + #define STM32_PVD_ENABLE FALSE + #define STM32_PLS STM32_PLS_LEV0 + #define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 TRUE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 TRUE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 TRUE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 TRUE +#define STM32_SPI_USE_SPI4 TRUE +#define STM32_SPI_USE_SPI5 TRUE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.h.in new file mode 100644 index 00000000..a247c865 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x200000C0) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00040000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00100000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..0a92a44a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_adc_config.cpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 3, ADC_CHANNEL_IN3}, + {1, GPIOC, 0, ADC_CHANNEL_IN10}, + {1, GPIOC, 3, ADC_CHANNEL_IN13}, + {1, GPIOC, 1, ADC_CHANNEL_IN11}, + {1, GPIOC, 4, ADC_CHANNEL_IN14}, + {1, GPIOC, 5, ADC_CHANNEL_IN15}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..534f821a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_i2c_config.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) + +////////// +// I2C2 // +////////// + +// pin configuration for I2C2 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_10 +// SDA pin: is GPIOB_11 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(2, GPIOB, GPIOB, 10, 11, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..945efe88 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART2 // +/////////// + +// pin configuration for UART2 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOD +// TX pin: is GPIOD_5 +// RX pin: is GPIOD_6 +// GPIO alternate pin function is 7 (see "Table 10. STM32F412xE/G alternate function mapping" in datasheet) +UART_CONFIG_PINS(2, GPIOD, GPIOD, 5, 6, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// initialization for UART2 +UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// un-initialization for UART2 +UART_UNINIT(2) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..8320132b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +/////////// +// UART2 // +/////////// + +// enable USART2 +#define NF_SERIAL_COMM_STM32_UART_USE_USART2 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART2_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART2_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..ef2d3a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/CMakeLists.txt new file mode 100644 index 00000000..4d858847 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/CMakeLists.txt @@ -0,0 +1,245 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) + find_package(NF_NETWORKING REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +# security provider is mbedTLS +if(USE_SECURITY_MBEDTLS_OPTION) + find_package(mbedTLS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for ChibiOS FatFS + ${CHIBIOS_FATFS_SOURCES} + + # sources for nanoFramework Network LWIP, Sockets and TLS + "${CHIBIOS_LWIP_SOURCES}" + ${NF_Networking_SOURCES} + "${mbedTLS_SOURCES}" + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# add dependencies from CHIBIOS_NETWORK_COMPONENTS (this is required to make sure that ChibiOS network components are unzip at the proper locations before the build starts) +# only required if networking in ON +if(USE_NETWORKING_OPTION) + add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf CHIBIOS_NETWORK_COMPONENTS) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf CHIBIOS_NETWORK_COMPONENTS) + + # add dependency for security provider mbedTLS + if(USE_SECURITY_MBEDTLS_OPTION) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf mbedTLS) + endif() +endif() + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS FatFS + ${CHIBIOS_FATFS_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} + + # incudes for Networking and TLS + ${NF_Networking_INCLUDE_DIRS} + ${mbedTLS_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# mbed TLS requires a config file +if(USE_SECURITY_MBEDTLS_OPTION) + # this seems to be only option to properly set a compiler define through the command line that needs to be a string literal + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h>\"") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h>\"") +endif() + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F439xI_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F439xI_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F439xI_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F439xI_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x10000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x10000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/README.md new file mode 100644 index 00000000..34a6b2ce --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/README.md @@ -0,0 +1,31 @@ +## STM NUCLEO144 F439ZI board + +![STM NUCLEO144 F439ZI board](nucleo144-f439zi.jpg) + +The board used in this community contribution is the NUCLEO144 F439ZI board from STM. The board can be purchased from various sources and should be about 23 euros. Further information on this board and links for the user and programming manuals can be found at the product page in ST [website](http://www.st.com/en/evaluation-tools/nucleo-f439zi.html). + +Some basic information abstracted from ST: +- STM32 microcontroller in LQFP144 package +- External SMPS to generate Vcore logic supply (only available on '-P' suffixed boards) +- Ethernet compliant with IEEE-802.3-2002 (depending on STM32 support) +- USB OTG or full-speed device (depending on STM32 support) +- 3 user LEDs +- User and reset push-buttons +- 32.768 kHz crystal oscillator +- Board connectors: + - USB with Micro-AB + - SWD + - Ethernet RJ45 (depending on STM32 support) + - ST Zio connector including Arduino™ Uno V3 + - ST morpho +- Flexible power-supply options: ST-LINK USB VBUS or external sources +- On-board ST-LINK/V2-1 debugger/programmer with USB re-enumeration capability: mass storage, virtual COM port and debug port + +### Flashing and debugging + +This board has two micro USB connectors. One is exposing the embedded ST-Link interface that is used for flashing the nanoFramework firmware and for performing debugging on the nanoCLR code. The second is used to connect the device with Visual Studio allowing to deploy and debug your C# managed applications. + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.c new file mode 100644 index 00000000..90f2ece9 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + + return !palReadLine(LINE_SD_DETECT); +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.h new file mode 100644 index 00000000..1b558faf --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/board.h @@ -0,0 +1,1837 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef BOARD_H +#define BOARD_H + +/* + * Setup for STMicroelectronics STM32 Nucleo144-F439ZI board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_NUCLEO144_F439ZI +#define BOARD_NAME "STMicroelectronics STM32 Nucleo144-F439ZI" + +/* + * Ethernet PHY type. + */ +#define BOARD_PHY_ID MII_LAN8742A_ID +#define BOARD_PHY_RMII + +/* + * Board oscillators-related settings. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +#define STM32_HSE_BYPASS + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F439xx + +/* + * IO pins assignments. + */ +#define GPIOA_ZIO_D32 0U +#define GPIOA_TIM2_CH1 0U +#define GPIOA_RMII_REF_CLK 1U +#define GPIOA_RMII_MDIO 2U +#define GPIOA_ARD_A0 3U +#define GPIOA_ADC123_IN3 3U +#define GPIOA_ZIO_D24 4U +#define GPIOA_SPI3_NSS 4U +#define GPIOA_ARD_D13 5U +#define GPIOA_SPI1_SCK 5U +#define GPIOA_ARD_D12 6U +#define GPIOA_SPI1_MISO 6U +#define GPIOA_ARD_D11 7U +#define GPIOA_SPI1_MOSI 7U +#define GPIOA_ZIO_D71 7U +#define GPIOA_RMII_RX_DV 7U +#define GPIOA_USB_SOF 8U +#define GPIOA_USB_VBUS 9U +#define GPIOA_USB_ID 10U +#define GPIOA_USB_DM 11U +#define GPIOA_USB_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_ZIO_D20 15U +#define GPIOA_I2S3_WS 15U + +#define GPIOB_ZIO_D33 0U +#define GPIOB_TIM3_CH3 0U +#define GPIOB_LED1 0U +#define GPIOB_ZIO_A6 1U +#define GPIOB_ADC12_IN9 1U +#define GPIOB_ZIO_D27 2U +#define GPIOB_ZIO_D23 3U +#define GPIOB_I2S3_CK 3U +#define GPIOB_SWO 3U +#define GPIOB_ZIO_D25 4U +#define GPIOB_SPI3_MISO 4U +#define GPIOB_ZIO_D22 5U +#define GPIOB_I2S3_SD 5U +#define GPIOB_ZIO_D26 6U +#define GPIOB_LED2 7U +#define GPIOB_ARD_D15 8U +#define GPIOB_I2C1_SCL 8U +#define GPIOB_ARD_D14 9U +#define GPIOB_I2C1_SDA 9U +#define GPIOB_ZIO_D36 10U +#define GPIOB_TIM2_CH3 10U +#define GPIOB_ZIO_D35 11U +#define GPIOB_TIM2_CH4 11U +#define GPIOB_ZIO_D19 12U +#define GPIOB_I2S2_WS 12U +#define GPIOB_ZIO_D18 13U +#define GPIOB_I2S2_CK 13U +#define GPIOB_RMII_TXD1 13U +#define GPIOB_LED3 14U +#define GPIOB_ZIO_D17 15U +#define GPIOB_I2S2_SD 15U + +#define GPIOC_ARD_A1 0U +#define GPIOC_ADC123_IN10 0U +#define GPIOC_RMII_MDC 1U +#define GPIOC_ZIO_A7 2U +#define GPIOC_ADC123_IN12 2U +#define GPIOC_ARD_A2 3U +#define GPIOC_ADC123_IN13 3U +#define GPIOC_RMII_RXD0 4U +#define GPIOC_RMII_RXD1 5U +#define GPIOC_ZIO_D16 6U +#define GPIOC_I2S2_MCK 6U +#define GPIOC_ZIO_D21 7U +#define GPIOC_I2S3_MCK 7U +#define GPIOC_ZIO_D43 8U +#define GPIOC_SDMMC_D0 8U +#define GPIOC_ZIO_D44 9U +#define GPIOC_SDMMC_D1 9U +#define GPIOC_ZIO_D45 10U +#define GPIOC_SDMMC_D2 10U +#define GPIOC_ZIO_D46 11U +#define GPIOC_SDMMC_D3 11U +#define GPIOC_ZIO_D47 12U +#define GPIOC_SDMMC_CK 12U +#define GPIOC_BUTTON 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_ZIO_D67 0U +#define GPIOD_CAN1_RX 0U +#define GPIOD_ZIO_D66 1U +#define GPIOD_CAN1_TX 1U +#define GPIOD_ZIO_D48 2U +#define GPIOD_SDMMC_CMD 2U +#define GPIOD_ZIO_D55 3U +#define GPIOD_USART2_CTS 3U +#define GPIOD_ZIO_D54 4U +#define GPIOD_USART2_RTS 4U +#define GPIOD_ZIO_D53 5U +#define GPIOD_USART2_TX 5U +#define GPIOD_ZIO_D52 6U +#define GPIOD_USART2_RX 6U +#define GPIOD_ZIO_D51 7U +#define GPIOD_USART2_SCLK 7U +#define GPIOD_USART3_TX 8U +#define GPIOD_STLK_TX 8U +#define GPIOD_USART3_RX 9U +#define GPIOD_STLK_RX 9U +#define GPIOD_PIN10 10U +#define GPIOD_ZIO_D30 11U +#define GPIOD_ZIO_D29 12U +#define GPIOD_ZIO_D28 13U +#define GPIOD_ARD_D10 14U +#define GPIOD_SPI1_NSS 14U +#define GPIOD_ARD_D9 15U +#define GPIOD_TIM4_CH4 15U + +#define GPIOE_ZIO_D34 0U +#define GPIOE_TIM4_ETR 0U +#define GPIOE_PIN1 1U +#define GPIOE_ZIO_D31 2U +#define GPIOE_ZIO_D56 2U +#define GPIOE_SAI1_MCLK_A 2U +#define GPIOE_ZIO_D60 3U +#define GPIOE_SAI1_SD_B 3U +#define GPIOE_ZIO_D57 4U +#define GPIOE_SAI1_FS_A 4U +#define GPIOE_ZIO_D58 5U +#define GPIOE_SAI1_SCK_A 5U +#define GPIOE_ZIO_D59 6U +#define GPIOE_SAI1_SD_A 6U +#define GPIOE_ZIO_D41 7U +#define GPIOE_TIM1_ETR 7U +#define GPIOE_ZIO_D42 8U +#define GPIOE_TIM1_CH1N 8U +#define GPIOE_ARD_D6 9U +#define GPIOE_TIM1_CH1 9U +#define GPIOE_ZIO_D40 10U +#define GPIOE_TIM1_CH2N 10U +#define GPIOE_ARD_D5 11U +#define GPIOE_TIM1_CH2 11U +#define GPIOE_ZIO_D39 12U +#define GPIOE_TIM1_CH3N 12U +#define GPIOE_ARD_D3 13U +#define GPIOE_TIM1_CH3 13U +#define GPIOE_ZIO_D38 14U +#define GPIOE_ZIO_D37 15U +#define GPIOE_TIM1_BKIN1 15U + +#define GPIOF_ZIO_D68 0U +#define GPIOF_I2C2_SDA 0U +#define GPIOF_ZIO_D69 1U +#define GPIOF_I2C2_SCL 1U +#define GPIOF_ZIO_D70 2U +#define GPIOF_I2C2_SMBA 2U +#define GPIOF_ARD_A3 3U +#define GPIOF_ADC3_IN9 3U +#define GPIOF_ZIO_A8 4U +#define GPIOF_ADC3_IN14 4U +#define GPIOF_ARD_A4 5U +#define GPIOF_ADC3_IN15 5U +#define GPIOF_PIN6 6U +#define GPIOF_ZIO_D62 7U +#define GPIOF_SAI1_MCLK_B 7U +#define GPIOF_SPI5_SCK 7U +#define GPIOF_ZIO_D61 8U +#define GPIOF_SAI1_SCK_B 8U +#define GPIOF_SPI5_MISO 8U +#define GPIOF_ZIO_D63 9U +#define GPIOF_SAI1_FS_B 9U +#define GPIOF_SPI5_MOSI 9U +#define GPIOF_ARD_A5 10U +#define GPIOF_ADC3_IN8 10U +#define GPIOF_PIN11 11U +#define GPIOF_ARD_D8 12U +#define GPIOF_ARD_D7 13U +#define GPIOF_ARD_D4 14U +#define GPIOF_ARD_D2 15U + +#define GPIOG_ZIO_D65 0U +#define GPIOG_ZIO_D64 1U +#define GPIOG_ZIO_D49 2U +#define GPIOG_ZIO_D50 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_USB_GPIO_OUT 6U +#define GPIOG_USB_GPIO_IN 7U +#define GPIOG_PIN8 8U +#define GPIOG_ARD_D0 9U +#define GPIOG_USART6_RX 9U +#define GPIOG_PIN10 10U +#define GPIOG_RMII_TX_EN 11U +#define GPIOG_PIN12 12U +#define GPIOG_RMII_TXD0 13U +#define GPIOG_ARD_D1 14U +#define GPIOG_USART6_TX 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +#define GPIOJ_PIN0 0U +#define GPIOJ_PIN1 1U +#define GPIOJ_PIN2 2U +#define GPIOJ_PIN3 3U +#define GPIOJ_PIN4 4U +#define GPIOJ_PIN5 5U +#define GPIOJ_PIN6 6U +#define GPIOJ_PIN7 7U +#define GPIOJ_PIN8 8U +#define GPIOJ_PIN9 9U +#define GPIOJ_PIN10 10U +#define GPIOJ_PIN11 11U +#define GPIOJ_PIN12 12U +#define GPIOJ_PIN13 13U +#define GPIOJ_PIN14 14U +#define GPIOJ_PIN15 15U + +#define GPIOK_PIN0 0U +#define GPIOK_PIN1 1U +#define GPIOK_PIN2 2U +#define GPIOK_PIN3 3U +#define GPIOK_PIN4 4U +#define GPIOK_PIN5 5U +#define GPIOK_PIN6 6U +#define GPIOK_PIN7 7U +#define GPIOK_PIN8 8U +#define GPIOK_PIN9 9U +#define GPIOK_PIN10 10U +#define GPIOK_PIN11 11U +#define GPIOK_PIN12 12U +#define GPIOK_PIN13 13U +#define GPIOK_PIN14 14U +#define GPIOK_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_ZIO_D32 PAL_LINE(GPIOA, 0U) +#define LINE_TIM2_CH1 PAL_LINE(GPIOA, 0U) +#define LINE_RMII_REF_CLK PAL_LINE(GPIOA, 1U) +#define LINE_RMII_MDIO PAL_LINE(GPIOA, 2U) +#define LINE_ARD_A0 PAL_LINE(GPIOA, 3U) +#define LINE_ADC123_IN3 PAL_LINE(GPIOA, 3U) +#define LINE_ZIO_D24 PAL_LINE(GPIOA, 4U) +#define LINE_SPI3_NSS PAL_LINE(GPIOA, 4U) +#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U) +#define LINE_SPI1_SCK PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U) +#define LINE_SPI1_MISO PAL_LINE(GPIOA, 6U) +#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U) +#define LINE_SPI1_MOSI PAL_LINE(GPIOA, 7U) +#define LINE_ZIO_D71 PAL_LINE(GPIOA, 7U) +#define LINE_RMII_RX_DV PAL_LINE(GPIOA, 7U) +#define LINE_USB_SOF PAL_LINE(GPIOA, 8U) +#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U) +#define LINE_USB_ID PAL_LINE(GPIOA, 10U) +#define LINE_USB_DM PAL_LINE(GPIOA, 11U) +#define LINE_USB_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) +#define LINE_ZIO_D20 PAL_LINE(GPIOA, 15U) +#define LINE_I2S3_WS PAL_LINE(GPIOA, 15U) +#define LINE_ZIO_D33 PAL_LINE(GPIOB, 0U) +#define LINE_TIM3_CH3 PAL_LINE(GPIOB, 0U) +#define LINE_LED1 PAL_LINE(GPIOB, 0U) +#define LINE_ZIO_A6 PAL_LINE(GPIOB, 1U) +#define LINE_ADC12_IN9 PAL_LINE(GPIOB, 1U) +#define LINE_ZIO_D27 PAL_LINE(GPIOB, 2U) +#define LINE_ZIO_D23 PAL_LINE(GPIOB, 3U) +#define LINE_I2S3_CK PAL_LINE(GPIOB, 3U) +#define LINE_ZIO_D25 PAL_LINE(GPIOB, 4U) +#define LINE_SPI3_MISO PAL_LINE(GPIOB, 4U) +#define LINE_ZIO_D22 PAL_LINE(GPIOB, 5U) +#define LINE_I2S3_SD PAL_LINE(GPIOB, 5U) +#define LINE_ZIO_D26 PAL_LINE(GPIOB, 6U) +#define LINE_LED2 PAL_LINE(GPIOB, 7U) +#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U) +#define LINE_I2C1_SCL PAL_LINE(GPIOB, 8U) +#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U) +#define LINE_I2C1_SDA PAL_LINE(GPIOB, 9U) +#define LINE_ZIO_D36 PAL_LINE(GPIOB, 10U) +#define LINE_TIM2_CH3 PAL_LINE(GPIOB, 10U) +#define LINE_ZIO_D35 PAL_LINE(GPIOB, 11U) +#define LINE_TIM2_CH4 PAL_LINE(GPIOB, 11U) +#define LINE_ZIO_D19 PAL_LINE(GPIOB, 12U) +#define LINE_I2S2_WS PAL_LINE(GPIOB, 12U) +#define LINE_ZIO_D18 PAL_LINE(GPIOB, 13U) +#define LINE_I2S2_CK PAL_LINE(GPIOB, 13U) +#define LINE_RMII_TXD1 PAL_LINE(GPIOB, 13U) +#define LINE_LED3 PAL_LINE(GPIOB, 14U) +#define LINE_ZIO_D17 PAL_LINE(GPIOB, 15U) +#define LINE_I2S2_SD PAL_LINE(GPIOB, 15U) +#define LINE_ARD_A1 PAL_LINE(GPIOC, 0U) +#define LINE_ADC123_IN10 PAL_LINE(GPIOC, 0U) +#define LINE_RMII_MDC PAL_LINE(GPIOC, 1U) +#define LINE_ZIO_A7 PAL_LINE(GPIOC, 2U) +#define LINE_ADC123_IN12 PAL_LINE(GPIOC, 2U) +#define LINE_ARD_A2 PAL_LINE(GPIOC, 3U) +#define LINE_ADC123_IN13 PAL_LINE(GPIOC, 3U) +#define LINE_RMII_RXD0 PAL_LINE(GPIOC, 4U) +#define LINE_RMII_RXD1 PAL_LINE(GPIOC, 5U) +#define LINE_ZIO_D16 PAL_LINE(GPIOC, 6U) +#define LINE_I2S2_MCK PAL_LINE(GPIOC, 6U) +#define LINE_ZIO_D21 PAL_LINE(GPIOC, 7U) +#define LINE_I2S3_MCK PAL_LINE(GPIOC, 7U) +#define LINE_ZIO_D43 PAL_LINE(GPIOC, 8U) +#define LINE_SDMMC_D0 PAL_LINE(GPIOC, 8U) +#define LINE_ZIO_D44 PAL_LINE(GPIOC, 9U) +#define LINE_SDMMC_D1 PAL_LINE(GPIOC, 9U) +#define LINE_ZIO_D45 PAL_LINE(GPIOC, 10U) +#define LINE_SDMMC_D2 PAL_LINE(GPIOC, 10U) +#define LINE_ZIO_D46 PAL_LINE(GPIOC, 11U) +#define LINE_SDMMC_D3 PAL_LINE(GPIOC, 11U) +#define LINE_ZIO_D47 PAL_LINE(GPIOC, 12U) +#define LINE_SDMMC_CK PAL_LINE(GPIOC, 12U) +#define LINE_BUTTON PAL_LINE(GPIOC, 13U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) +#define LINE_ZIO_D67 PAL_LINE(GPIOD, 0U) +#define LINE_CAN1_RX PAL_LINE(GPIOD, 0U) +#define LINE_ZIO_D66 PAL_LINE(GPIOD, 1U) +#define LINE_CAN1_TX PAL_LINE(GPIOD, 1U) +#define LINE_ZIO_D48 PAL_LINE(GPIOD, 2U) +#define LINE_SDMMC_CMD PAL_LINE(GPIOD, 2U) +#define LINE_ZIO_D55 PAL_LINE(GPIOD, 3U) +#define LINE_USART2_CTS PAL_LINE(GPIOD, 3U) +#define LINE_ZIO_D54 PAL_LINE(GPIOD, 4U) +#define LINE_USART2_RTS PAL_LINE(GPIOD, 4U) +#define LINE_ZIO_D53 PAL_LINE(GPIOD, 5U) +#define LINE_USART2_TX PAL_LINE(GPIOD, 5U) +#define LINE_ZIO_D52 PAL_LINE(GPIOD, 6U) +#define LINE_USART2_RX PAL_LINE(GPIOD, 6U) +#define LINE_ZIO_D51 PAL_LINE(GPIOD, 7U) +#define LINE_USART2_SCLK PAL_LINE(GPIOD, 7U) +#define LINE_USART3_TX PAL_LINE(GPIOD, 8U) +#define LINE_STLK_TX PAL_LINE(GPIOD, 8U) +#define LINE_USART3_RX PAL_LINE(GPIOD, 9U) +#define LINE_STLK_RX PAL_LINE(GPIOD, 9U) +#define LINE_ZIO_D30 PAL_LINE(GPIOD, 11U) +#define LINE_ZIO_D29 PAL_LINE(GPIOD, 12U) +#define LINE_ZIO_D28 PAL_LINE(GPIOD, 13U) +#define LINE_ARD_D10 PAL_LINE(GPIOD, 14U) +#define LINE_SPI1_NSS PAL_LINE(GPIOD, 14U) +#define LINE_ARD_D9 PAL_LINE(GPIOD, 15U) +#define LINE_TIM4_CH4 PAL_LINE(GPIOD, 15U) +#define LINE_ZIO_D34 PAL_LINE(GPIOE, 0U) +#define LINE_TIM4_ETR PAL_LINE(GPIOE, 0U) +#define LINE_ZIO_D31 PAL_LINE(GPIOE, 2U) +#define LINE_ZIO_D56 PAL_LINE(GPIOE, 2U) +#define LINE_SAI1_MCLK_A PAL_LINE(GPIOE, 2U) +#define LINE_ZIO_D60 PAL_LINE(GPIOE, 3U) +#define LINE_SAI1_SD_B PAL_LINE(GPIOE, 3U) +#define LINE_ZIO_D57 PAL_LINE(GPIOE, 4U) +#define LINE_SAI1_FS_A PAL_LINE(GPIOE, 4U) +#define LINE_ZIO_D58 PAL_LINE(GPIOE, 5U) +#define LINE_SAI1_SCK_A PAL_LINE(GPIOE, 5U) +#define LINE_ZIO_D59 PAL_LINE(GPIOE, 6U) +#define LINE_SAI1_SD_A PAL_LINE(GPIOE, 6U) +#define LINE_ZIO_D41 PAL_LINE(GPIOE, 7U) +#define LINE_TIM1_ETR PAL_LINE(GPIOE, 7U) +#define LINE_ZIO_D42 PAL_LINE(GPIOE, 8U) +#define LINE_TIM1_CH1N PAL_LINE(GPIOE, 8U) +#define LINE_ARD_D6 PAL_LINE(GPIOE, 9U) +#define LINE_TIM1_CH1 PAL_LINE(GPIOE, 9U) +#define LINE_ZIO_D40 PAL_LINE(GPIOE, 10U) +#define LINE_TIM1_CH2N PAL_LINE(GPIOE, 10U) +#define LINE_ARD_D5 PAL_LINE(GPIOE, 11U) +#define LINE_TIM1_CH2 PAL_LINE(GPIOE, 11U) +#define LINE_ZIO_D39 PAL_LINE(GPIOE, 12U) +#define LINE_TIM1_CH3N PAL_LINE(GPIOE, 12U) +#define LINE_ARD_D3 PAL_LINE(GPIOE, 13U) +#define LINE_TIM1_CH3 PAL_LINE(GPIOE, 13U) +#define LINE_ZIO_D38 PAL_LINE(GPIOE, 14U) +#define LINE_ZIO_D37 PAL_LINE(GPIOE, 15U) +#define LINE_TIM1_BKIN1 PAL_LINE(GPIOE, 15U) +#define LINE_ZIO_D68 PAL_LINE(GPIOF, 0U) +#define LINE_I2C2_SDA PAL_LINE(GPIOF, 0U) +#define LINE_ZIO_D69 PAL_LINE(GPIOF, 1U) +#define LINE_I2C2_SCL PAL_LINE(GPIOF, 1U) +#define LINE_ZIO_D70 PAL_LINE(GPIOF, 2U) +#define LINE_I2C2_SMBA PAL_LINE(GPIOF, 2U) +#define LINE_ARD_A3 PAL_LINE(GPIOF, 3U) +#define LINE_ADC3_IN9 PAL_LINE(GPIOF, 3U) +#define LINE_ZIO_A8 PAL_LINE(GPIOF, 4U) +#define LINE_ADC3_IN14 PAL_LINE(GPIOF, 4U) +#define LINE_ARD_A4 PAL_LINE(GPIOF, 5U) +#define LINE_ADC3_IN15 PAL_LINE(GPIOF, 5U) +#define LINE_ZIO_D62 PAL_LINE(GPIOF, 7U) +#define LINE_SAI1_MCLK_B PAL_LINE(GPIOF, 7U) +#define LINE_ZIO_D61 PAL_LINE(GPIOF, 8U) +#define LINE_SAI1_SCK_B PAL_LINE(GPIOF, 8U) +#define LINE_ZIO_D63 PAL_LINE(GPIOF, 9U) +#define LINE_SAI1_FS_B PAL_LINE(GPIOF, 9U) +#define LINE_ARD_A5 PAL_LINE(GPIOF, 10U) +#define LINE_ADC3_IN8 PAL_LINE(GPIOF, 10U) +#define LINE_ARD_D8 PAL_LINE(GPIOF, 12U) +#define LINE_ARD_D7 PAL_LINE(GPIOF, 13U) +#define LINE_ARD_D4 PAL_LINE(GPIOF, 14U) +#define LINE_ARD_D2 PAL_LINE(GPIOF, 15U) +#define LINE_ZIO_D65 PAL_LINE(GPIOG, 0U) +#define LINE_ZIO_D64 PAL_LINE(GPIOG, 1U) +#define LINE_ZIO_D49 PAL_LINE(GPIOG, 2U) +#define LINE_ZIO_D50 PAL_LINE(GPIOG, 3U) +#define LINE_USB_GPIO_OUT PAL_LINE(GPIOG, 6U) +#define LINE_USB_GPIO_IN PAL_LINE(GPIOG, 7U) +#define LINE_ARD_D0 PAL_LINE(GPIOG, 9U) +#define LINE_USART6_RX PAL_LINE(GPIOG, 9U) +#define LINE_RMII_TX_EN PAL_LINE(GPIOG, 11U) +#define LINE_RMII_TXD0 PAL_LINE(GPIOG, 13U) +#define LINE_ARD_D1 PAL_LINE(GPIOG, 14U) +#define LINE_USART6_TX PAL_LINE(GPIOG, 14U) +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - ZIO_D32 TIM2_CH1 (input pullup). + * PA1 - RMII_REF_CLK (alternate 11). + * PA2 - RMII_MDIO (alternate 11). + * PA3 - ARD_A0 ADC123_IN3 (input pullup). + * PA4 - ZIO_D24 SPI3_NSS (input pullup). + * PA5 - ARD_D13 SPI1_SCK (input pullup). + * PA6 - ARD_D12 SPI1_MISO (input pullup). + * PA7 - ARD_D11 SPI1_MOSI ZIO_D71 RMII_RX_DV(alternate 11). + * PA8 - USB_SOF (alternate 10). + * PA9 - USB_VBUS (analog). + * PA10 - USB_ID (alternate 10). + * PA11 - USB_DM (alternate 10). + * PA12 - USB_DP (alternate 10). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - ZIO_D20 I2S3_WS (input pullup). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ZIO_D32) | \ + PIN_MODE_ALTERNATE(GPIOA_RMII_REF_CLK) |\ + PIN_MODE_ALTERNATE(GPIOA_RMII_MDIO) | \ + PIN_MODE_INPUT(GPIOA_ARD_A0) | \ + PIN_MODE_INPUT(GPIOA_ZIO_D24) | \ + PIN_MODE_INPUT(GPIOA_ARD_D13) | \ + PIN_MODE_INPUT(GPIOA_ARD_D12) | \ + PIN_MODE_ALTERNATE(GPIOA_ARD_D11) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_SOF) | \ + PIN_MODE_ANALOG(GPIOA_USB_VBUS) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_ID) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_ZIO_D20)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D32) | \ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_REF_CLK) |\ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_MDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D24) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D13) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_SOF) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_VBUS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_ID) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D20)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ZIO_D32) | \ + PIN_OSPEED_HIGH(GPIOA_RMII_REF_CLK) | \ + PIN_OSPEED_HIGH(GPIOA_RMII_MDIO) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \ + PIN_OSPEED_HIGH(GPIOA_ZIO_D24) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D13) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \ + PIN_OSPEED_HIGH(GPIOA_USB_SOF) | \ + PIN_OSPEED_HIGH(GPIOA_USB_VBUS) | \ + PIN_OSPEED_HIGH(GPIOA_USB_ID) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DM) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_HIGH(GPIOA_ZIO_D20)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ZIO_D32) | \ + PIN_PUPDR_FLOATING(GPIOA_RMII_REF_CLK) |\ + PIN_PUPDR_PULLUP(GPIOA_RMII_MDIO) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \ + PIN_PUPDR_PULLUP(GPIOA_ZIO_D24) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D13) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D12) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D11) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_SOF) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_VBUS) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_ID) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ + PIN_PUPDR_FLOATING(GPIOA_SWDIO) | \ + PIN_PUPDR_FLOATING(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_ZIO_D20)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ZIO_D32) | \ + PIN_ODR_HIGH(GPIOA_RMII_REF_CLK) | \ + PIN_ODR_HIGH(GPIOA_RMII_MDIO) | \ + PIN_ODR_HIGH(GPIOA_ARD_A0) | \ + PIN_ODR_HIGH(GPIOA_ZIO_D24) | \ + PIN_ODR_HIGH(GPIOA_ARD_D13) | \ + PIN_ODR_HIGH(GPIOA_ARD_D12) | \ + PIN_ODR_HIGH(GPIOA_ARD_D11) | \ + PIN_ODR_HIGH(GPIOA_USB_SOF) | \ + PIN_ODR_HIGH(GPIOA_USB_VBUS) | \ + PIN_ODR_HIGH(GPIOA_USB_ID) | \ + PIN_ODR_HIGH(GPIOA_USB_DM) | \ + PIN_ODR_HIGH(GPIOA_USB_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_ZIO_D20)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ZIO_D32, 0U) | \ + PIN_AFIO_AF(GPIOA_RMII_REF_CLK, 11U) | \ + PIN_AFIO_AF(GPIOA_RMII_MDIO, 11U) | \ + PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \ + PIN_AFIO_AF(GPIOA_ZIO_D24, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D13, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D11, 11U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_USB_SOF, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_VBUS, 0U) | \ + PIN_AFIO_AF(GPIOA_USB_ID, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \ + PIN_AFIO_AF(GPIOA_ZIO_D20, 0U)) + +/* + * GPIOB setup: + * + * PB0 - ZIO_D33 TIM3_CH3 LED1 (output pushpull maximum). + * PB1 - ZIO_A6 ADC12_IN9 (input pullup). + * PB2 - ZIO_D27 (input pullup). + * PB3 - ZIO_D23 I2S3_CK SWO (alternate). + * PB4 - ZIO_D25 SPI3_MISO (input pullup). + * PB5 - ZIO_D22 I2S3_SD (input pullup). + * PB6 - ZIO_D26 (input pullup). + * PB7 - LED2 (output pushpull maximum). + * PB8 - ARD_D15 I2C1_SCL (input pullup). + * PB9 - ARD_D14 I2C1_SDA (input pullup). + * PB10 - ZIO_D36 TIM2_CH3 (input pullup). + * PB11 - ZIO_D35 TIM2_CH4 (input pullup). + * PB12 - ZIO_D19 I2S2_WS (input pullup). + * PB13 - ZIO_D18 I2S2_CK RMII_TXD1 (alternate 11). + * PB14 - LED3 (output pushpull maximum). + * PB15 - ZIO_D17 I2S2_SD (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_OUTPUT(GPIOB_ZIO_D33) | \ + PIN_MODE_INPUT(GPIOB_ZIO_A6) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D27) | \ + PIN_MODE_ALTERNATE(GPIOB_SWO) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D25) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D22) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D26) | \ + PIN_MODE_OUTPUT(GPIOB_LED2) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D36) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D35) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D19) | \ + PIN_MODE_ALTERNATE(GPIOB_ZIO_D18) | \ + PIN_MODE_OUTPUT(GPIOB_LED3) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D17)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D33) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_A6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D27) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D25) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D22) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D26) | \ + PIN_OTYPE_PUSHPULL(GPIOB_LED2) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D36) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D35) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D19) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D18) | \ + PIN_OTYPE_PUSHPULL(GPIOB_LED3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D17)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ZIO_D33) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_A6) | \ + PIN_OSPEED_VERYLOW(GPIOB_ZIO_D27) | \ + PIN_OSPEED_HIGH(GPIOB_SWO) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D25) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D22) | \ + PIN_OSPEED_VERYLOW(GPIOB_ZIO_D26) | \ + PIN_OSPEED_HIGH(GPIOB_LED2) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D36) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D35) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D19) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D18) | \ + PIN_OSPEED_HIGH(GPIOB_LED3) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D17)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_ZIO_D33) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_A6) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D27) | \ + PIN_PUPDR_FLOATING(GPIOB_SWO) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D25) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D22) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D26) | \ + PIN_PUPDR_FLOATING(GPIOB_LED2) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D36) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D35) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D19) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D18) | \ + PIN_PUPDR_FLOATING(GPIOB_LED3) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D17)) +#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_ZIO_D33) | \ + PIN_ODR_HIGH(GPIOB_ZIO_A6) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D27) | \ + PIN_ODR_HIGH(GPIOB_SWO) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D25) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D22) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D26) | \ + PIN_ODR_LOW(GPIOB_LED2) | \ + PIN_ODR_LOW(GPIOB_I2C1_SCL) | \ + PIN_ODR_LOW(GPIOB_I2C1_SDA) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D36) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D35) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D19) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D18) | \ + PIN_ODR_LOW(GPIOB_LED3) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D17)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ZIO_D33, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_A6, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D27, 0U) | \ + PIN_AFIO_AF(GPIOB_SWO, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D25, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D22, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D26, 0U) | \ + PIN_AFIO_AF(GPIOB_LED2, 0U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D36, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D35, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D19, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D18, 11U) | \ + PIN_AFIO_AF(GPIOB_LED3, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D17, 0U)) + +/* + * GPIOC setup: + * + * PC0 - ARD_A1 ADC123_IN10 (input pullup). + * PC1 - RMII_MDC (alternate 11). + * PC2 - ZIO_A7 ADC123_IN12 (input pullup). + * PC3 - ARD_A2 ADC123_IN13 (input pullup). + * PC4 - RMII_RXD0 (alternate 11). + * PC5 - RMII_RXD1 (alternate 11). + * PC6 - ZIO_D16 I2S2_MCK (input pullup). + * PC7 - ZIO_D21 I2S3_MCK (input pullup). + * PC8 - ZIO_D43 SDMMC_D0 (input pullup). + * PC9 - ZIO_D44 SDMMC_D1 (input pullup). + * PC10 - ZIO_D45 SDMMC_D2 (input pullup). + * PC11 - ZIO_D46 SDMMC_D3 (input pullup). + * PC12 - ZIO_D47 SDMMC_CK (input pullup). + * PC13 - BUTTON (input floating). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ARD_A1) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_MDC) | \ + PIN_MODE_INPUT(GPIOC_ZIO_A7) | \ + PIN_MODE_INPUT(GPIOC_ARD_A2) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_RXD0) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_RXD1) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D16) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D21) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D43) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D44) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D45) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D46) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D47) | \ + PIN_MODE_INPUT(GPIOC_BUTTON) | \ + PIN_MODE_INPUT(GPIOC_OSC32_IN) | \ + PIN_MODE_INPUT(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_MDC) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_A7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D16) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D21) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D43) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D44) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D45) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D46) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D47) | \ + PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A1) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_MDC) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_A7) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_A2) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_RXD0) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_RXD1) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D16) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D21) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D43) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D44) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D45) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D46) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D47) | \ + PIN_OSPEED_HIGH(GPIOC_BUTTON) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A1) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_MDC) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_A7) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A2) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_RXD0) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_RXD1) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D16) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D21) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D43) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D44) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D45) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D46) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D47) | \ + PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A1) | \ + PIN_ODR_HIGH(GPIOC_RMII_MDC) | \ + PIN_ODR_HIGH(GPIOC_ZIO_A7) | \ + PIN_ODR_HIGH(GPIOC_ARD_A2) | \ + PIN_ODR_HIGH(GPIOC_RMII_RXD0) | \ + PIN_ODR_HIGH(GPIOC_RMII_RXD1) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D16) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D21) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D43) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D44) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D45) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D46) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D47) | \ + PIN_ODR_HIGH(GPIOC_BUTTON) | \ + PIN_ODR_HIGH(GPIOC_OSC32_IN) | \ + PIN_ODR_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A1, 0U) | \ + PIN_AFIO_AF(GPIOC_RMII_MDC, 11U) | \ + PIN_AFIO_AF(GPIOC_ZIO_A7, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A2, 0U) | \ + PIN_AFIO_AF(GPIOC_RMII_RXD0, 11U) | \ + PIN_AFIO_AF(GPIOC_RMII_RXD1, 11U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D16, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D21, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_ZIO_D43, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D44, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D45, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D46, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D47, 0U) | \ + PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - ZIO_D67 CAN1_RX (input pullup). + * PD1 - ZIO_D66 CAN1_TX (input pullup). + * PD2 - ZIO_D48 SDMMC_CMD (input pullup). + * PD3 - ZIO_D55 USART2_CTS (input pullup). + * PD4 - ZIO_D54 USART2_RTS (input pullup). + * PD5 - ZIO_D53 USART2_TX (input pullup). + * PD6 - ZIO_D52 USART2_RX (input pullup). + * PD7 - ZIO_D51 USART2_SCLK (input pullup). + * PD8 - USART3_TX STLK_TX (alternate 7). + * PD9 - USART3_RX STLK_RX (alternate 7). + * PD10 - PIN10 (input pullup). + * PD11 - ZIO_D30 (input pullup). + * PD12 - ZIO_D29 (input pullup). + * PD13 - ZIO_D28 (input pullup). + * PD14 - ARD_D10 SPI1_NSS (input pullup). + * PD15 - ARD_D9 TIM4_CH4 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_ZIO_D67) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D66) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D48) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D55) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D54) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D53) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D52) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D51) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_TX) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_RX) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D30) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D29) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D28) | \ + PIN_MODE_INPUT(GPIOD_ARD_D10) | \ + PIN_MODE_INPUT(GPIOD_ARD_D9)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D67) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D66) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D48) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D55) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D54) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D53) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D52) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D51) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D30) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D29) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D28) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ARD_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ARD_D9)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_ZIO_D67) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D66) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D48) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D55) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D54) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D53) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D52) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D51) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_TX) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_RX) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOD_ZIO_D30) | \ + PIN_OSPEED_VERYLOW(GPIOD_ZIO_D29) | \ + PIN_OSPEED_VERYLOW(GPIOD_ZIO_D28) | \ + PIN_OSPEED_HIGH(GPIOD_ARD_D10) | \ + PIN_OSPEED_HIGH(GPIOD_ARD_D9)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_ZIO_D67) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D66) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D48) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D55) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D54) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D53) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D52) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D51) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_TX) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_RX) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D30) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D29) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D28) | \ + PIN_PUPDR_PULLUP(GPIOD_ARD_D10) | \ + PIN_PUPDR_PULLUP(GPIOD_ARD_D9)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_ZIO_D67) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D66) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D48) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D55) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D54) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D53) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D52) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D51) | \ + PIN_ODR_HIGH(GPIOD_USART3_TX) | \ + PIN_ODR_HIGH(GPIOD_USART3_RX) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D30) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D29) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D28) | \ + PIN_ODR_HIGH(GPIOD_ARD_D10) | \ + PIN_ODR_HIGH(GPIOD_ARD_D9)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_ZIO_D67, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D66, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D48, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D55, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D54, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D53, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D52, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D51, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_USART3_TX, 7U) | \ + PIN_AFIO_AF(GPIOD_USART3_RX, 7U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D30, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D29, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D28, 0U) | \ + PIN_AFIO_AF(GPIOD_ARD_D10, 0U) | \ + PIN_AFIO_AF(GPIOD_ARD_D9, 0U)) + +/* + * GPIOE setup: + * + * PE0 - ZIO_D34 TIM4_ETR (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - ZIO_D31 ZIO_D56 SAI1_MCLK_A(input pullup). + * PE3 - ZIO_D60 SAI1_SD_B (input pullup). + * PE4 - ZIO_D57 SAI1_FS_A (input pullup). + * PE5 - ZIO_D58 SAI1_SCK_A (input pullup). + * PE6 - ZIO_D59 SAI1_SD_A (input pullup). + * PE7 - ZIO_D41 TIM1_ETR (input pullup). + * PE8 - ZIO_D42 TIM1_CH1N (input pullup). + * PE9 - ARD_D6 TIM1_CH1 (input pullup). + * PE10 - ZIO_D40 TIM1_CH2N (input pullup). + * PE11 - ARD_D5 TIM1_CH2 (input pullup). + * PE12 - ZIO_D39 TIM1_CH3N (input pullup). + * PE13 - ARD_D3 TIM1_CH3 (input pullup). + * PE14 - ZIO_D38 (input pullup). + * PE15 - ZIO_D37 TIM1_BKIN1 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_ZIO_D34) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D31) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D60) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D57) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D58) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D59) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D41) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D42) | \ + PIN_MODE_INPUT(GPIOE_ARD_D6) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D40) | \ + PIN_MODE_INPUT(GPIOE_ARD_D5) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D39) | \ + PIN_MODE_INPUT(GPIOE_ARD_D3) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D38) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D37)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D34) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D31) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D60) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D57) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D58) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D59) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D41) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D42) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D40) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D39) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D38) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D37)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_ZIO_D34) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D31) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D60) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D57) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D58) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D59) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D41) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D42) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D6) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D40) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D5) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D39) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D3) | \ + PIN_OSPEED_VERYLOW(GPIOE_ZIO_D38) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D37)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_ZIO_D34) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D31) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D60) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D57) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D58) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D59) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D41) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D42) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D6) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D40) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D5) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D39) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D3) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D38) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D37)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_ZIO_D34) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D31) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D60) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D57) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D58) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D59) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D41) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D42) | \ + PIN_ODR_HIGH(GPIOE_ARD_D6) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D40) | \ + PIN_ODR_HIGH(GPIOE_ARD_D5) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D39) | \ + PIN_ODR_HIGH(GPIOE_ARD_D3) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D38) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D37)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_ZIO_D34, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D31, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D60, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D57, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D58, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D59, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D41, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_ZIO_D42, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D6, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D40, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D5, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D39, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D3, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D38, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D37, 0U)) + +/* + * GPIOF setup: + * + * PF0 - ZIO_D68 I2C2_SDA (input pullup). + * PF1 - ZIO_D69 I2C2_SCL (input pullup). + * PF2 - ZIO_D70 I2C2_SMBA (input pullup). + * PF3 - ARD_A3 ADC3_IN9 (input pullup). + * PF4 - ZIO_A8 ADC3_IN14 (input pullup). + * PF5 - ARD_A4 ADC3_IN15 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - SPI5_SCK (Alternate 5). + * PF8 - SPI5_MISO (Alternate 5). + * PF9 - SPI5_MOSI (Alternate 5). + * PF10 - ARD_A5 ADC3_IN8 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - ARD_D8 (input pullup). + * PF13 - ARD_D7 (input pullup). + * PF14 - ARD_D4 (input pullup). + * PF15 - ARD_D2 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_ZIO_D68) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D69) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D70) | \ + PIN_MODE_INPUT(GPIOF_ARD_A3) | \ + PIN_MODE_INPUT(GPIOF_ZIO_A8) | \ + PIN_MODE_INPUT(GPIOF_ARD_A4) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_ALTERNATE(GPIOF_SPI5_SCK) | \ + PIN_MODE_ALTERNATE(GPIOF_SPI5_MISO) | \ + PIN_MODE_ALTERNATE(GPIOF_SPI5_MOSI) | \ + PIN_MODE_INPUT(GPIOF_ARD_A5) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_ARD_D8) | \ + PIN_MODE_INPUT(GPIOF_ARD_D7) | \ + PIN_MODE_INPUT(GPIOF_ARD_D4) | \ + PIN_MODE_INPUT(GPIOF_ARD_D2)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D68) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D69) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D70) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_A8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_SPI5_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOF_SPI5_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOF_SPI5_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D2)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_ZIO_D68) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D69) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D70) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A3) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_A8) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A4) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_SPI5_SCK) | \ + PIN_OSPEED_HIGH(GPIOF_SPI5_MISO) | \ + PIN_OSPEED_HIGH(GPIOF_SPI5_MOSI) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A5) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D8) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D7) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D4) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D2)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_ZIO_D68) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D69) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D70) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A3) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_A8) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOF_SPI5_SCK) | \ + PIN_PUPDR_FLOATING(GPIOF_SPI5_MISO) | \ + PIN_PUPDR_FLOATING(GPIOF_SPI5_MOSI) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D8) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D7) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D4) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D2)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_ZIO_D68) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D69) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D70) | \ + PIN_ODR_HIGH(GPIOF_ARD_A3) | \ + PIN_ODR_HIGH(GPIOF_ZIO_A8) | \ + PIN_ODR_HIGH(GPIOF_ARD_A4) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_SPI5_SCK) | \ + PIN_ODR_HIGH(GPIOF_SPI5_MISO) | \ + PIN_ODR_HIGH(GPIOF_SPI5_MOSI) | \ + PIN_ODR_HIGH(GPIOF_ARD_A5) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_ARD_D8) | \ + PIN_ODR_HIGH(GPIOF_ARD_D7) | \ + PIN_ODR_HIGH(GPIOF_ARD_D4) | \ + PIN_ODR_HIGH(GPIOF_ARD_D2)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_ZIO_D68, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D69, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D70, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_A3, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_A8, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_A4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_SPI5_SCK, 5U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_SPI5_MISO, 5U) | \ + PIN_AFIO_AF(GPIOF_SPI5_MOSI, 5U) | \ + PIN_AFIO_AF(GPIOF_ARD_A5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D8, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D7, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D4, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D2, 0U)) + +/* + * GPIOG setup: + * + * PG0 - ZIO_D65 (input pullup). + * PG1 - ZIO_D64 (input pullup). + * PG2 - ZIO_D49 (input pullup). + * PG3 - ZIO_D50 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - USB_GPIO_OUT (input pullup). + * PG7 - USB_GPIO_IN (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - ARD_D0 USART6_RX (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - RMII_TX_EN (alternate 11). + * PG12 - PIN12 (input pullup). + * PG13 - RMII_TXD0 (alternate 11). + * PG14 - ARD_D1 USART6_TX (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_ZIO_D65) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D64) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D49) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D50) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_USB_GPIO_OUT) | \ + PIN_MODE_INPUT(GPIOG_USB_GPIO_IN) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_ALTERNATE(GPIOG_USART6_RX) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_ALTERNATE(GPIOG_RMII_TX_EN) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_ALTERNATE(GPIOG_RMII_TXD0) | \ + PIN_MODE_ALTERNATE(GPIOG_USART6_TX) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D65) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D64) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D49) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D50) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_USB_GPIO_OUT) |\ + PIN_OTYPE_PUSHPULL(GPIOG_USB_GPIO_IN) |\ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_USART6_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_RMII_TX_EN) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_RMII_TXD0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_USART6_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_ZIO_D65) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D64) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D49) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D50) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_USB_GPIO_OUT) | \ + PIN_OSPEED_HIGH(GPIOG_USB_GPIO_IN) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_USART6_RX) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \ + PIN_OSPEED_HIGH(GPIOG_RMII_TX_EN) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \ + PIN_OSPEED_HIGH(GPIOG_RMII_TXD0) | \ + PIN_OSPEED_HIGH(GPIOG_USART6_TX) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_ZIO_D65) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D64) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D49) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D50) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_USB_GPIO_OUT) | \ + PIN_PUPDR_PULLUP(GPIOG_USB_GPIO_IN) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOG_USART6_RX) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOG_RMII_TX_EN) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOG_RMII_TXD0) | \ + PIN_PUPDR_FLOATING(GPIOG_USART6_TX) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_ZIO_D65) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D64) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D49) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D50) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_USB_GPIO_OUT) | \ + PIN_ODR_HIGH(GPIOG_USB_GPIO_IN) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_USART6_RX) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_RMII_TX_EN) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_RMII_TXD0) | \ + PIN_ODR_HIGH(GPIOG_USART6_TX) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_ZIO_D65, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D64, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D49, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D50, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_USB_GPIO_OUT, 0U) | \ + PIN_AFIO_AF(GPIOG_USB_GPIO_IN, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_USART6_RX, 8U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_RMII_TX_EN, 11U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_RMII_TXD0, 11U) | \ + PIN_AFIO_AF(GPIOG_USART6_TX, 8U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input pullup). + * PI1 - PIN1 (input pullup). + * PI2 - PIN2 (input pullup). + * PI3 - PIN3 (input pullup). + * PI4 - PIN4 (input pullup). + * PI5 - PIN5 (input pullup). + * PI6 - PIN6 (input pullup). + * PI7 - PIN7 (input pullup). + * PI8 - PIN8 (input pullup). + * PI9 - PIN9 (input pullup). + * PI10 - PIN10 (input pullup). + * PI11 - PIN11 (input pullup). + * PI12 - PIN12 (input pullup). + * PI13 - PIN13 (input pullup). + * PI14 - PIN14 (input pullup). + * PI15 - PIN15 (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOI_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + +/* + * GPIOJ setup: + * + * PJ0 - PIN0 (input pullup). + * PJ1 - PIN1 (input pullup). + * PJ2 - PIN2 (input pullup). + * PJ3 - PIN3 (input pullup). + * PJ4 - PIN4 (input pullup). + * PJ5 - PIN5 (input pullup). + * PJ6 - PIN6 (input pullup). + * PJ7 - PIN7 (input pullup). + * PJ8 - PIN8 (input pullup). + * PJ9 - PIN9 (input pullup). + * PJ10 - PIN10 (input pullup). + * PJ11 - PIN11 (input pullup). + * PJ12 - PIN12 (input pullup). + * PJ13 - PIN13 (input pullup). + * PJ14 - PIN14 (input pullup). + * PJ15 - PIN15 (input pullup). + */ +#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \ + PIN_MODE_INPUT(GPIOJ_PIN1) | \ + PIN_MODE_INPUT(GPIOJ_PIN2) | \ + PIN_MODE_INPUT(GPIOJ_PIN3) | \ + PIN_MODE_INPUT(GPIOJ_PIN4) | \ + PIN_MODE_INPUT(GPIOJ_PIN5) | \ + PIN_MODE_INPUT(GPIOJ_PIN6) | \ + PIN_MODE_INPUT(GPIOJ_PIN7) | \ + PIN_MODE_INPUT(GPIOJ_PIN8) | \ + PIN_MODE_INPUT(GPIOJ_PIN9) | \ + PIN_MODE_INPUT(GPIOJ_PIN10) | \ + PIN_MODE_INPUT(GPIOJ_PIN11) | \ + PIN_MODE_INPUT(GPIOJ_PIN12) | \ + PIN_MODE_INPUT(GPIOJ_PIN13) | \ + PIN_MODE_INPUT(GPIOJ_PIN14) | \ + PIN_MODE_INPUT(GPIOJ_PIN15)) +#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN15)) +#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOJ_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN15)) +#define VAL_GPIOJ_PUPDR (PIN_PUPDR_PULLUP(GPIOJ_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN15)) +#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \ + PIN_ODR_HIGH(GPIOJ_PIN1) | \ + PIN_ODR_HIGH(GPIOJ_PIN2) | \ + PIN_ODR_HIGH(GPIOJ_PIN3) | \ + PIN_ODR_HIGH(GPIOJ_PIN4) | \ + PIN_ODR_HIGH(GPIOJ_PIN5) | \ + PIN_ODR_HIGH(GPIOJ_PIN6) | \ + PIN_ODR_HIGH(GPIOJ_PIN7) | \ + PIN_ODR_HIGH(GPIOJ_PIN8) | \ + PIN_ODR_HIGH(GPIOJ_PIN9) | \ + PIN_ODR_HIGH(GPIOJ_PIN10) | \ + PIN_ODR_HIGH(GPIOJ_PIN11) | \ + PIN_ODR_HIGH(GPIOJ_PIN12) | \ + PIN_ODR_HIGH(GPIOJ_PIN13) | \ + PIN_ODR_HIGH(GPIOJ_PIN14) | \ + PIN_ODR_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN7, 0U)) +#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN15, 0U)) + +/* + * GPIOK setup: + * + * PK0 - PIN0 (input pullup). + * PK1 - PIN1 (input pullup). + * PK2 - PIN2 (input pullup). + * PK3 - PIN3 (input pullup). + * PK4 - PIN4 (input pullup). + * PK5 - PIN5 (input pullup). + * PK6 - PIN6 (input pullup). + * PK7 - PIN7 (input pullup). + * PK8 - PIN8 (input pullup). + * PK9 - PIN9 (input pullup). + * PK10 - PIN10 (input pullup). + * PK11 - PIN11 (input pullup). + * PK12 - PIN12 (input pullup). + * PK13 - PIN13 (input pullup). + * PK14 - PIN14 (input pullup). + * PK15 - PIN15 (input pullup). + */ +#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \ + PIN_MODE_INPUT(GPIOK_PIN1) | \ + PIN_MODE_INPUT(GPIOK_PIN2) | \ + PIN_MODE_INPUT(GPIOK_PIN3) | \ + PIN_MODE_INPUT(GPIOK_PIN4) | \ + PIN_MODE_INPUT(GPIOK_PIN5) | \ + PIN_MODE_INPUT(GPIOK_PIN6) | \ + PIN_MODE_INPUT(GPIOK_PIN7) | \ + PIN_MODE_INPUT(GPIOK_PIN8) | \ + PIN_MODE_INPUT(GPIOK_PIN9) | \ + PIN_MODE_INPUT(GPIOK_PIN10) | \ + PIN_MODE_INPUT(GPIOK_PIN11) | \ + PIN_MODE_INPUT(GPIOK_PIN12) | \ + PIN_MODE_INPUT(GPIOK_PIN13) | \ + PIN_MODE_INPUT(GPIOK_PIN14) | \ + PIN_MODE_INPUT(GPIOK_PIN15)) +#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN15)) +#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOK_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN15)) +#define VAL_GPIOK_PUPDR (PIN_PUPDR_PULLUP(GPIOK_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN15)) +#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \ + PIN_ODR_HIGH(GPIOK_PIN1) | \ + PIN_ODR_HIGH(GPIOK_PIN2) | \ + PIN_ODR_HIGH(GPIOK_PIN3) | \ + PIN_ODR_HIGH(GPIOK_PIN4) | \ + PIN_ODR_HIGH(GPIOK_PIN5) | \ + PIN_ODR_HIGH(GPIOK_PIN6) | \ + PIN_ODR_HIGH(GPIOK_PIN7) | \ + PIN_ODR_HIGH(GPIOK_PIN8) | \ + PIN_ODR_HIGH(GPIOK_PIN9) | \ + PIN_ODR_HIGH(GPIOK_PIN10) | \ + PIN_ODR_HIGH(GPIOK_PIN11) | \ + PIN_ODR_HIGH(GPIOK_PIN12) | \ + PIN_ODR_HIGH(GPIOK_PIN13) | \ + PIN_ODR_HIGH(GPIOK_PIN14) | \ + PIN_ODR_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN7, 0U)) +#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN15, 0U)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/CMakeLists.txt new file mode 100644 index 00000000..27f8f458 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigurationManager.cpp") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..7651a37e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,135 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 16kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CONFIG , 2, 3 } // 0x08008000 nanoConfig +}; + +// 64kB blocks +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +// 128kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 3 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 4, 6 }, // 0x080A0000 deployment +}; + +// 16kB blocks +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +// 64kB blocks +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +// 128kB blocks +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage.c new file mode 100644 index 00000000..46f13500 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/Device_BlockStorage.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 16kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CONFIG , 2, 3 } // 0x08008000 nanoConfig +}; + +// 64kB blocks +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +// 128kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 3 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 4, 6 }, // 0x080A0000 deployment +}; + +// 16kB blocks +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +// 64kB blocks +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +// 128kB blocks +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + (0), // no attributes for this region + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + (0), // no attributes for this region + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + (0), // no attributes for this region + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/serialcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/serialcfg.h new file mode 100644 index 00000000..803da07a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/serialcfg.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef SERIALCFG_H +#define SERIALCFG_H + +// define which serial driver the Wire Protocol will be using +#define SERIAL_DRIVER SD3 + +#endif /* SERIALCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/targetHAL_ConfigurationManager.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/targetHAL_ConfigurationManager.cpp new file mode 100644 index 00000000..178f6aa7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/common/targetHAL_ConfigurationManager.cpp @@ -0,0 +1,35 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +// Default initialisation for Network interface config blocks +// strong implementation replacing ChibiOS 'weak' one +bool InitialiseNetworkDefaultConfig(HAL_Configuration_NetworkInterface * pconfig, uint32_t configurationIndex) +{ + (void)configurationIndex; + + // make sure the config block marker is set + memcpy(pconfig->Marker, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + pconfig->InterfaceType = NetworkInterfaceType_Ethernet; + pconfig->StartupAddressMode = AddressMode_DHCP; + pconfig->AutomaticDNS = 1; + pconfig->SpecificConfigId = 0; + + // set MAC address with ST provided MAC for development boards + // 00:80:E1:01:35:D1 + pconfig->MacAddress[0] = 0x00; + pconfig->MacAddress[1] = 0x80; + pconfig->MacAddress[2] = 0xE1; + pconfig->MacAddress[3] = 0x01; + pconfig->MacAddress[4] = 0x35; + pconfig->MacAddress[5] = 0xD1; + + return true; +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/ffconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/ffconf.h new file mode 100644 index 00000000..7ffb3957 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/ffconf.h @@ -0,0 +1,272 @@ +/* CHIBIOS FIX */ +#include "ch.h" + +/*---------------------------------------------------------------------------/ +/ FatFs - Configuration file +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 87030 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: All basic functions are enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_STRFUNC 0 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 0 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 850 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 3 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added +/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255. +/ It should be set 255 to support full featured LFN operations. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree(), must be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16, +/ when LFN is enabled. Also behavior of string I/O functions will be affected by +/ this option. When LFN is not enabled, this option has no effect. +*/ + + +#define FF_STRF_ENCODE 3 +/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(), +/ f_putc(), f_puts and f_printf() convert the character encoding in it. +/ This option selects assumption of character encoding ON THE FILE to be +/ read/written via those functions. +/ +/ 0: ANSI/OEM +/ 1: UTF-16LE +/ 2: UTF-16BE +/ 3: UTF-8 +*/ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 1 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches string support for volume ID. +/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each +/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for +/ the drive ID strings are: A-Z and 0-9. */ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 0 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ When enable exFAT, also LFN needs to be enabled. +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 1 +#define FF_NORTC_MON 8 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2018 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT TIME_MS2I(1000) +#define FF_SYNC_t semaphore_t* +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +/* #include // O/S definitions */ + + + +/*--- End of configuration options ---*/ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/lwipopts.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/lwipopts.h new file mode 100644 index 00000000..3e12c25e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/lwipopts.h @@ -0,0 +1,2167 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science, All Rights Reserved +// See LICENSE file in the project root for full license information. +// +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIPOPT_H__ +#define __LWIPOPT_H__ + + +#define _REENT_ONLY +#define set_errno(err) +#include +#include +#include + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 1 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +// empty on purpose +#define LWIP_TCPIP_THREAD_ALIVE() + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 1 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 1 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 4 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE (16 * 1024) +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#define LWIP_IPV6 0 + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 15 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 +#endif + +#define LWIP_RAND rand + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 1 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +#define LWIP_DHCP_CHECK_LINK_UP 1 + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 1 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 1480 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 1 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 1 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 1 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 1 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 1024 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE MEMP_NUM_PBUF +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 1024 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 1024 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 1024 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 4 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 4 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 40 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 4 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 1 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 +#endif + +/** + * LWIP_SO_LINGER==1: Enable linger option for sockets/netconns + */ +#define LWIP_SO_LINGER 1 + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 1 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 1 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 1 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 0 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +// in order to enable the lwIP debug output the bellow has to be uncomment and +// the options above changed to LWIP_DBG_ON for the features that are to output debug information +//#define LWIP_DEBUG 1 + +// enable full duplex comms on multiple threads +// this requires adding an extra field in ChibiOS thread_t (see comment on platform_sys_arch.c) +//#define LWIP_NETCONN_FULLDUPLEX 1 + +#endif /* __LWIPOPT_H__ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/Adc.cs new file mode 100644 index 00000000..8fe3c75b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/Adc.cs @@ -0,0 +1,73 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.ST_NUCLEO144_F439ZI +{ + /// + /// Enumeration of ADC channels available on ST_NUCLEO144_F439ZI + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed as A0, connected to pin 1 on CN9 = PA3 (ADC1 - IN3) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed as A1, connected to pin 3 on CN9 = PC0 (ADC1 - IN10) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed as A2, connected to pin 5 on CN9 = PC3 (ADC1 - IN13) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, exposed as A3, connected to pin 7 on CN9 = PF3 (ADC3 - IN9) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, exposed as A4, connected to pin 9 on CN9 = PF5 (ADC3 - IN15) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, exposed on A5, connected to pin 11 on CN9 = PF10 (ADC3 - IN8) + /// + public const int Channel_5 = 5; + + /// + /// Channel 6, exposed on PB1, connected to CN10 Pin 7 (ADC2 - IN9) + /// + public const int Channel_6 = 6; + + /// + /// Channel 7, exposed on PC2, connected to CN10 Pin 9 (ADC2 - IN12) + /// + public const int Channel_7 = 7; + + /// + /// Channel 8, exposed on PF4, connected to CN10 Pin 11 (ADC3 - IN14) + /// + public const int Channel_8 = 8; + + /// + /// Channel 9, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 9; + + /// + /// Channel 10, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 10; + + /// + /// Channel 11, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 11; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/README.md new file mode 100644 index 00000000..e73c9643 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](Adc.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/mbedtls_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/mbedtls_config.h new file mode 100644 index 00000000..9877ca77 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/mbedtls_config.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// See LICENSE file in the project root for full license information. +// + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* For test certificates */ +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_PEM_PARSE_C + +// #define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +// #define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +// #define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +// #define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +// #define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +// #define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET + +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +// #define MBEDTLS_SSL_DEBUG_ALL +// #define MBEDTLS_VERSION_FEATURES +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_ERROR_C +// #define MBEDTLS_VERSION_C + +// uncomment the defines below to enable static memory allocation feature +#if 0 +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_MEMORY +#endif + +#ifdef USE_LCD +#include "lcd_log.h" +#define MBEDTLS_PLATFORM_PRINTF_MACRO LCD_UsrLog +#endif + +// uncomment the defines bellow to generate debug output +// set below the threshold level for debug messages +// check mbed TLS mbedtls/debug.h header for details. +// Debug levels: +// 0 No debug +// 1 Error +// 2 State change +// 3 Informational +// 4 Verbose + +// #define MBEDTLS_DEBUG_C +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +// #define MBEDTLS_DEBUG_THRESHOLD 2 + +#endif // MBEDTLS_CONFIG_H diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..f0e921f7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") + +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter-DEBUG.ld new file mode 100644 index 00000000..455ac681 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter-DEBUG.ld @@ -0,0 +1,97 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F439xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08008000)*/ + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram0); + +SECTIONS +{ + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter.ld new file mode 100644 index 00000000..d76bca04 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/STM32F439xI_booter.ld @@ -0,0 +1,97 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F439xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08007FFF)*/ + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram0); + +SECTIONS +{ + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/chconf.h new file mode 100644 index 00000000..ef98a914 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf.h new file mode 100644 index 00000000..32253663 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf.h @@ -0,0 +1,519 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..c710062b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/halconf_nf.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// Enables the ChibiOS community overlay. +#if !defined(HAL_USE_COMMUNITY) +#define HAL_USE_COMMUNITY TRUE +#endif + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/main.c new file mode 100644 index 00000000..01d95f38 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/main.c @@ -0,0 +1,81 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + // the user button in this board has a pull-up resistor so the check has to be inverted + if (!palReadLine(LINE_BUTTON)) + { + // check for valid CLR image + // we are checking for a valid image right after the configuration block + if(CheckValidCLRImage((uint32_t)&__nanoConfig_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoConfig_end__); + } + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // initialize configuration manager + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it here to have access to network configuration blocks + ConfigurationManager_Initialize(); + + // Normal main() thread + while (true) { + palToggleLine(LINE_LED1); + palToggleLine(LINE_LED2); + palToggleLine(LINE_LED3); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf.h new file mode 100644 index 00000000..6a6ca336 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf.h @@ -0,0 +1,355 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F439_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI +#define STM32_PLLM_VALUE 16 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 TRUE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_USE_SPI5 FALSE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR-DEBUG.ld new file mode 100644 index 00000000..f364f36c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR-DEBUG.ld @@ -0,0 +1,102 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F439xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08010000, len = 2M - 32k - 32k - 1408k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x080A0000, len = 1408k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules_stacks.ld + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram0); + +SECTIONS +{ + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR.ld new file mode 100644 index 00000000..f364f36c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/STM32F439xI_CLR.ld @@ -0,0 +1,102 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F439xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08010000, len = 2M - 32k - 32k - 1408k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x080A0000, len = 1408k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules_stacks.ld + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram0); + +SECTIONS +{ + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/chconf.h new file mode 100644 index 00000000..ef39575e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf.h new file mode 100644 index 00000000..aa4d7607 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf.h @@ -0,0 +1,541 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC FALSE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM FALSE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ + +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..7b316d22 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ 1 + +// Enables the ChibiOS community overlay. +#if !defined(HAL_USE_COMMUNITY) +#define HAL_USE_COMMUNITY TRUE +#endif + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/main.c new file mode 100644 index 00000000..3d00c498 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/main.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf.h new file mode 100644 index 00000000..2bc22f18 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf.h @@ -0,0 +1,355 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F439_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI +#define STM32_PLLM_VALUE 16 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 TRUE +#define STM32_ADC_USE_ADC3 TRUE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 TRUE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 TRUE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 TRUE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 TRUE +#define STM32_SPI_USE_SPI4 TRUE +#define STM32_SPI_USE_SPI5 TRUE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/target_board.h.in new file mode 100644 index 00000000..5b4698cf --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nucleo144-f439zi.jpg b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/nucleo144-f439zi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9af10bd8352009ec4beb71eede2fb5f78b228415 GIT binary patch literal 35572 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 literal 0 HcmV?d00001 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.h.in new file mode 100644 index 00000000..cc944913 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00040000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00200000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_lwip_sntp_opts.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_lwip_sntp_opts.h new file mode 100644 index 00000000..c115cd67 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_lwip_sntp_opts.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#define SNTP_SERVER_DEFAULT_ADDRESS "0.pool.ntp.org" + +// update delay (default 1 hour) +// (value in milliseconds) +#define SNTP_UPDATE_DELAY 3600000 + +// better have a startup delay because we can have DHCP enabled (default 30 seconds) +// value in milliseconds +#define SNTP_STARTUP_DELAY 30000 + +// retry timeout (15 minutes) +// value in milliseconds +#define SNTP_RETRY_TIMEOUT 900000 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..7d5ccdeb --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_adc_config.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 3, ADC_CHANNEL_IN3}, + {1, GPIOC, 0, ADC_CHANNEL_IN10}, + {1, GPIOC, 3, ADC_CHANNEL_IN13}, + + // ADC3 + {3, GPIOF, 3, ADC_CHANNEL_IN9}, + {3, GPIOF, 5, ADC_CHANNEL_IN15}, + {3, GPIOF, 10, ADC_CHANNEL_IN8}, + + // ADC2/ADC3 + // Fill up with rest of set ADC pins + {2, GPIOB, 1, ADC_CHANNEL_IN9}, + {2, GPIOC, 2, ADC_CHANNEL_IN12}, + {3, GPIOF, 4, ADC_CHANNEL_IN14}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..70d9d9a8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_i2c_config.cpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) + +////////// +// I2C2 // +////////// + +// pin configuration for I2C2 +// port for SCL pin is: GPIOF +// port for SDA pin is: GPIOF +// SCL pin: is GPIOF_0 +// SDA pin: is GPIOF_1 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(2, GPIOF, GPIOF, 0, 1, 4) + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..219210fa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART1 // +/////////// + +// pin configuration for UART1 +// port for TX pin is: GPIOA +// port for RX pin is: GPIOA +// TX pin: is GPIOA_9 +// RX pin: is GPIOA_10 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(1, GPIOA, GPIOA, 9, 10, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_TxBuffer[UART1_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_RxBuffer[UART1_RX_SIZE]; + +// initialization for UART1 +UART_INIT(1, UART1_TX_SIZE, UART1_RX_SIZE) + +// un-initialization for UART1 +UART_UNINIT(1) + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port for TX pin is: GPIOG +// port for RX pin is: GPIOG +// TX pin: is GPIOG_14 +// RX pin: is GPIOG_9 +// GPIO alternate pin function is 8 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(6, GPIOG, GPIOG, 14, 9, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; + +// initialization for UART6 +UART_INIT(6, UART6_TX_SIZE, UART6_RX_SIZE) + +// un-initialization for UART6 +UART_UNINIT(6) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..66671f10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART1 // +/////////// + +// enable USART1 +#define NF_SERIAL_COMM_STM32_UART_USE_USART1 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART1_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART1_RX_SIZE 256 + + +/////////// +// UART6 // +/////////// + +// enable USART6 +#define NF_SERIAL_COMM_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART6_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART6_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..f08c5650 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native_target.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/CMakeLists.txt new file mode 100644 index 00000000..eaaf8443 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/CMakeLists.txt @@ -0,0 +1,239 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) + find_package(NF_NETWORKING REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +# security provider is mbedTLS +if(USE_SECURITY_MBEDTLS_OPTION) + find_package(mbedTLS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework Network LWIP, Sockets and TLS + "${CHIBIOS_LWIP_SOURCES}" + ${NF_Networking_SOURCES} + "${mbedTLS_SOURCES}" + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# add dependencies from CHIBIOS_NETWORK_COMPONENTS (this is required to make sure that ChibiOS network components are unzip at the proper locations before the build starts) +# only required if networking in ON +if(USE_NETWORKING_OPTION) + add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf CHIBIOS_NETWORK_COMPONENTS) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf CHIBIOS_NETWORK_COMPONENTS) + + # add dependency for security provider mbedTLS + if(USE_SECURITY_MBEDTLS_OPTION) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf mbedTLS) + endif() +endif() + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} + + # incudes for Networking and TLS + ${NF_Networking_INCLUDE_DIRS} + ${mbedTLS_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# mbed TLS requires a config file +if(USE_SECURITY_MBEDTLS_OPTION) + # this seems to be only option to properly set a compiler define through the command line that needs to be a string literal + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h>\"") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h>\"") +endif() + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F746xG_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F746xG_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F746xG_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F746xG_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x1000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x21000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/README.md new file mode 100644 index 00000000..04fa8212 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/README.md @@ -0,0 +1,31 @@ +## STM NUCLEO144 F746ZG board + +![STM NUCLEO144 F746ZG board](nucleo144-f746zg.jpg) + +The board used in this community contribution is the NUCLEO144 F746ZG board from STM. The board can be purchased from various sources and should be about 23 euros. Further information on this board and links for the user and programming manuals can be found at the product page in ST [website](http://www.st.com/en/evaluation-tools/nucleo-f746zg.html). + +Some basic information abstracted from ST: +- STM32 microcontroller in LQFP144 package +- External SMPS to generate Vcore logic supply (only available on '-P' suffixed boards) +- Ethernet compliant with IEEE-802.3-2002 (depending on STM32 support) +- USB OTG or full-speed device (depending on STM32 support) +- 3 user LEDs +-2 user and reset push-buttons +- 32.768 kHz crystal oscillator +- Board connectors: + - USB with Micro-AB + - SWD + - Ethernet RJ45 (depending on STM32 support) + - ST Zio connector including Arduino™ Uno V3 + - ST morpho +- Flexible power-supply options: ST-LINK USB VBUS or external sources +- On-board ST-LINK/V2-1 debugger/programmer with USB re-enumeration capability: mass storage, virtual COM port and debug port + +### Flashing and debugging + +This board has two micro USB connectors. One is exposing the embedded ST-Link interface that is used for flashing the nanoFramework firmware and for performing debugging on the nanoCLR code. The second is used to connect the device with Visual Studio allowing to deploy and debug your C# managed applications. + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.c new file mode 100644 index 00000000..90f2ece9 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + + return !palReadLine(LINE_SD_DETECT); +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.h new file mode 100644 index 00000000..6f8dd55f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/board.h @@ -0,0 +1,1833 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef BOARD_H +#define BOARD_H + +/* + * Setup for STMicroelectronics STM32 Nucleo144-F746ZG board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_NUCLEO144_F746ZG +#define BOARD_NAME "STMicroelectronics STM32 Nucleo144-F746ZG" + +/* + * Ethernet PHY type. + */ +#define BOARD_PHY_ID MII_LAN8742A_ID +#define BOARD_PHY_RMII + +/* + * Board oscillators-related settings. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +#define STM32_HSE_BYPASS + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F746xx + +/* + * IO pins assignments. + */ +#define GPIOA_ZIO_D32 0U +#define GPIOA_TIM2_CH1 0U +#define GPIOA_RMII_REF_CLK 1U +#define GPIOA_RMII_MDIO 2U +#define GPIOA_ARD_A0 3U +#define GPIOA_ADC123_IN3 3U +#define GPIOA_ZIO_D24 4U +#define GPIOA_SPI3_NSS 4U +#define GPIOA_ARD_D13 5U +#define GPIOA_SPI1_SCK 5U +#define GPIOA_ARD_D12 6U +#define GPIOA_SPI1_MISO 6U +#define GPIOA_RMII_CRS_DV 7U +#define GPIOA_SPI1_MOSI 7U +#define GPIOA_ZIO_D71 7U +#define GPIOA_RMII_RX_DV 7U +#define GPIOA_USB_SOF 8U +#define GPIOA_USB_VBUS 9U +#define GPIOA_USB_ID 10U +#define GPIOA_USB_DM 11U +#define GPIOA_USB_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_ZIO_D20 15U +#define GPIOA_I2S3_WS 15U + +#define GPIOB_ZIO_D33 0U +#define GPIOB_TIM3_CH3 0U +#define GPIOB_LED1 0U +#define GPIOB_ZIO_A6 1U +#define GPIOB_ADC12_IN9 1U +#define GPIOB_ZIO_D27 2U +#define GPIOB_QSPI_CLK 2U +#define GPIOB_ZIO_D23 3U +#define GPIOB_I2S3_CK 3U +#define GPIOB_ZIO_D25 4U +#define GPIOB_SPI3_MISO 4U +#define GPIOB_ZIO_D22 5U +#define GPIOB_I2S3_SD 5U +#define GPIOB_ZIO_D26 6U +#define GPIOB_QSPI_BK1_NCS 6U +#define GPIOB_LED2 7U +#define GPIOB_ARD_D15 8U +#define GPIOB_I2C1_SCL 8U +#define GPIOB_ARD_D14 9U +#define GPIOB_I2C1_SDA 9U +#define GPIOB_ZIO_D36 10U +#define GPIOB_TIM2_CH3 10U +#define GPIOB_ZIO_D35 11U +#define GPIOB_TIM2_CH4 11U +#define GPIOB_ZIO_D19 12U +#define GPIOB_I2S2_WS 12U +#define GPIOB_ZIO_D18 13U +#define GPIOB_I2S2_CK 13U +#define GPIOB_RMII_TXD1 13U +#define GPIOB_LED3 14U +#define GPIOB_ZIO_D17 15U +#define GPIOB_I2S2_SD 15U + +#define GPIOC_ARD_A1 0U +#define GPIOC_ADC123_IN10 0U +#define GPIOC_RMII_MDC 1U +#define GPIOC_ZIO_A7 2U +#define GPIOC_ADC123_IN12 2U +#define GPIOC_ARD_A2 3U +#define GPIOC_ADC123_IN13 3U +#define GPIOC_RMII_RXD0 4U +#define GPIOC_RMII_RXD1 5U +#define GPIOC_ZIO_D16 6U +#define GPIOC_I2S2_MCK 6U +#define GPIOC_ZIO_D21 7U +#define GPIOC_I2S3_MCK 7U +#define GPIOC_ZIO_D43 8U +#define GPIOC_SDMMC_D0 8U +#define GPIOC_ZIO_D44 9U +#define GPIOC_SDMMC_D1 9U +#define GPIOC_ZIO_D45 10U +#define GPIOC_SDMMC_D2 10U +#define GPIOC_ZIO_D46 11U +#define GPIOC_SDMMC_D3 11U +#define GPIOC_ZIO_D47 12U +#define GPIOC_SDMMC_CK 12U +#define GPIOC_BUTTON 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_ZIO_D67 0U +#define GPIOD_CAN1_RX 0U +#define GPIOD_ZIO_D66 1U +#define GPIOD_CAN1_TX 1U +#define GPIOD_ZIO_D48 2U +#define GPIOD_SDMMC_CMD 2U +#define GPIOD_ZIO_D55 3U +#define GPIOD_USART2_CTS 3U +#define GPIOD_ZIO_D54 4U +#define GPIOD_USART2_RTS 4U +#define GPIOD_ZIO_D53 5U +#define GPIOD_USART2_TX 5U +#define GPIOD_ZIO_D52 6U +#define GPIOD_USART2_RX 6U +#define GPIOD_ZIO_D51 7U +#define GPIOD_USART2_SCLK 7U +#define GPIOD_USART3_RX 8U +#define GPIOD_STLK_RX 8U +#define GPIOD_USART3_TX 9U +#define GPIOD_STLK_TX 9U +#define GPIOD_PIN10 10U +#define GPIOD_ZIO_D30 11U +#define GPIOD_QSPI_BK1_IO0 11U +#define GPIOD_ZIO_D29 12U +#define GPIOD_QSPI_BK1_IO1 12U +#define GPIOD_ZIO_D28 13U +#define GPIOD_QSPI_BK1_IO3 13U +#define GPIOD_ARD_D10 14U +#define GPIOD_SPI1_NSS 14U +#define GPIOD_ARD_D9 15U +#define GPIOD_TIM4_CH4 15U + +#define GPIOE_ZIO_D34 0U +#define GPIOE_TIM4_ETR 0U +#define GPIOE_PIN1 1U +#define GPIOE_ZIO_D31 2U +#define GPIOE_ZIO_D56 2U +#define GPIOE_SAI1_MCLK_A 2U +#define GPIOE_ZIO_D60 3U +#define GPIOE_SAI1_SD_B 3U +#define GPIOE_ZIO_D57 4U +#define GPIOE_SAI1_FS_A 4U +#define GPIOE_ZIO_D58 5U +#define GPIOE_SAI1_SCK_A 5U +#define GPIOE_ZIO_D59 6U +#define GPIOE_SAI1_SD_A 6U +#define GPIOE_ZIO_D41 7U +#define GPIOE_TIM1_ETR 7U +#define GPIOE_ZIO_D42 8U +#define GPIOE_TIM1_CH1N 8U +#define GPIOE_ARD_D6 9U +#define GPIOE_TIM1_CH1 9U +#define GPIOE_ZIO_D40 10U +#define GPIOE_TIM1_CH2N 10U +#define GPIOE_ARD_D5 11U +#define GPIOE_TIM1_CH2 11U +#define GPIOE_ZIO_D39 12U +#define GPIOE_TIM1_CH3N 12U +#define GPIOE_ARD_D3 13U +#define GPIOE_TIM1_CH3 13U +#define GPIOE_ZIO_D38 14U +#define GPIOE_ZIO_D37 15U +#define GPIOE_TIM1_BKIN1 15U + +#define GPIOF_ZIO_D68 0U +#define GPIOF_I2C2_SDA 0U +#define GPIOF_ZIO_D69 1U +#define GPIOF_I2C2_SCL 1U +#define GPIOF_ZIO_D70 2U +#define GPIOF_I2C2_SMBA 2U +#define GPIOF_ARD_A3 3U +#define GPIOF_ADC3_IN9 3U +#define GPIOF_ZIO_A8 4U +#define GPIOF_ADC3_IN14 4U +#define GPIOF_ARD_A4 5U +#define GPIOF_ADC3_IN15 5U +#define GPIOF_PIN6 6U +#define GPIOF_ZIO_D62 7U +#define GPIOF_SPI5_SCK 7U +#define GPIOF_SPI5_MISO 8U +#define GPIOF_SAI1_SCK_B 8U +#define GPIOF_SPI5_MOSI 9U +#define GPIOF_SAI1_FS_B 9U +#define GPIOF_ARD_A5 10U +#define GPIOF_ADC3_IN8 10U +#define GPIOF_PIN11 11U +#define GPIOF_ARD_D8 12U +#define GPIOF_ARD_D7 13U +#define GPIOF_ARD_D4 14U +#define GPIOF_ARD_D2 15U + +#define GPIOG_ZIO_D65 0U +#define GPIOG_ZIO_D64 1U +#define GPIOG_ZIO_D49 2U +#define GPIOG_ZIO_D50 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_USB_GPIO_OUT 6U +#define GPIOG_USB_GPIO_IN 7U +#define GPIOG_PIN8 8U +#define GPIOG_ARD_D0 9U +#define GPIOG_USART6_RX 9U +#define GPIOG_PIN10 10U +#define GPIOG_RMII_TX_EN 11U +#define GPIOG_PIN12 12U +#define GPIOG_RMII_TXD0 13U +#define GPIOG_ARD_D1 14U +#define GPIOG_USART6_TX 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +#define GPIOJ_PIN0 0U +#define GPIOJ_PIN1 1U +#define GPIOJ_PIN2 2U +#define GPIOJ_PIN3 3U +#define GPIOJ_PIN4 4U +#define GPIOJ_PIN5 5U +#define GPIOJ_PIN6 6U +#define GPIOJ_PIN7 7U +#define GPIOJ_PIN8 8U +#define GPIOJ_PIN9 9U +#define GPIOJ_PIN10 10U +#define GPIOJ_PIN11 11U +#define GPIOJ_PIN12 12U +#define GPIOJ_PIN13 13U +#define GPIOJ_PIN14 14U +#define GPIOJ_PIN15 15U + +#define GPIOK_PIN0 0U +#define GPIOK_PIN1 1U +#define GPIOK_PIN2 2U +#define GPIOK_PIN3 3U +#define GPIOK_PIN4 4U +#define GPIOK_PIN5 5U +#define GPIOK_PIN6 6U +#define GPIOK_PIN7 7U +#define GPIOK_PIN8 8U +#define GPIOK_PIN9 9U +#define GPIOK_PIN10 10U +#define GPIOK_PIN11 11U +#define GPIOK_PIN12 12U +#define GPIOK_PIN13 13U +#define GPIOK_PIN14 14U +#define GPIOK_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_ZIO_D32 PAL_LINE(GPIOA, 0U) +#define LINE_TIM2_CH1 PAL_LINE(GPIOA, 0U) +#define LINE_RMII_REF_CLK PAL_LINE(GPIOA, 1U) +#define LINE_RMII_MDIO PAL_LINE(GPIOA, 2U) +#define LINE_ARD_A0 PAL_LINE(GPIOA, 3U) +#define LINE_ADC123_IN3 PAL_LINE(GPIOA, 3U) +#define LINE_ZIO_D24 PAL_LINE(GPIOA, 4U) +#define LINE_SPI3_NSS PAL_LINE(GPIOA, 4U) +#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U) +#define LINE_SPI1_SCK PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U) +#define LINE_SPI1_MISO PAL_LINE(GPIOA, 6U) +#define LINE_RMII_CRS_DV PAL_LINE(GPIOA, 7U) +#define LINE_SPI1_MOSI PAL_LINE(GPIOA, 7U) +#define LINE_ZIO_D71 PAL_LINE(GPIOA, 7U) +#define LINE_USB_SOF PAL_LINE(GPIOA, 8U) +#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U) +#define LINE_USB_ID PAL_LINE(GPIOA, 10U) +#define LINE_USB_DM PAL_LINE(GPIOA, 11U) +#define LINE_USB_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) +#define LINE_ZIO_D20 PAL_LINE(GPIOA, 15U) +#define LINE_I2S3_WS PAL_LINE(GPIOA, 15U) + +#define LINE_ZIO_D33 PAL_LINE(GPIOB, 0U) +#define LINE_TIM3_CH3 PAL_LINE(GPIOB, 0U) +#define LINE_LED1 PAL_LINE(GPIOB, 0U) +#define LINE_ZIO_A6 PAL_LINE(GPIOB, 1U) +#define LINE_ADC12_IN9 PAL_LINE(GPIOB, 1U) +#define LINE_ZIO_D27 PAL_LINE(GPIOB, 2U) +#define LINE_QSPI_CLK PAL_LINE(GPIOB, 2U) +#define LINE_ZIO_D23 PAL_LINE(GPIOB, 3U) +#define LINE_I2S3_CK PAL_LINE(GPIOB, 3U) +#define LINE_ZIO_D25 PAL_LINE(GPIOB, 4U) +#define LINE_SPI3_MISO PAL_LINE(GPIOB, 4U) +#define LINE_ZIO_D22 PAL_LINE(GPIOB, 5U) +#define LINE_I2S3_SD PAL_LINE(GPIOB, 5U) +#define LINE_ZIO_D26 PAL_LINE(GPIOB, 6U) +#define LINE_QSPI_BK1_NCS PAL_LINE(GPIOB, 6U) +#define LINE_LED2 PAL_LINE(GPIOB, 7U) +#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U) +#define LINE_I2C1_SCL PAL_LINE(GPIOB, 8U) +#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U) +#define LINE_I2C1_SDA PAL_LINE(GPIOB, 9U) +#define LINE_ZIO_D36 PAL_LINE(GPIOB, 10U) +#define LINE_TIM2_CH3 PAL_LINE(GPIOB, 10U) +#define LINE_ZIO_D35 PAL_LINE(GPIOB, 11U) +#define LINE_TIM2_CH4 PAL_LINE(GPIOB, 11U) +#define LINE_ZIO_D19 PAL_LINE(GPIOB, 12U) +#define LINE_I2S2_WS PAL_LINE(GPIOB, 12U) +#define LINE_ZIO_D18 PAL_LINE(GPIOB, 13U) +#define LINE_I2S2_CK PAL_LINE(GPIOB, 13U) +#define LINE_RMII_TXD1 PAL_LINE(GPIOB, 13U) +#define LINE_LED3 PAL_LINE(GPIOB, 14U) +#define LINE_ZIO_D17 PAL_LINE(GPIOB, 15U) +#define LINE_I2S2_SD PAL_LINE(GPIOB, 15U) + +#define LINE_ARD_A1 PAL_LINE(GPIOC, 0U) +#define LINE_ADC123_IN10 PAL_LINE(GPIOC, 0U) +#define LINE_RMII_MDC PAL_LINE(GPIOC, 1U) +#define LINE_ZIO_A7 PAL_LINE(GPIOC, 2U) +#define LINE_ADC123_IN12 PAL_LINE(GPIOC, 2U) +#define LINE_ARD_A2 PAL_LINE(GPIOC, 3U) +#define LINE_ADC123_IN13 PAL_LINE(GPIOC, 3U) +#define LINE_RMII_RXD0 PAL_LINE(GPIOC, 4U) +#define LINE_RMII_RXD1 PAL_LINE(GPIOC, 5U) +#define LINE_ZIO_D16 PAL_LINE(GPIOC, 6U) +#define LINE_I2S2_MCK PAL_LINE(GPIOC, 6U) +#define LINE_ZIO_D21 PAL_LINE(GPIOC, 7U) +#define LINE_I2S3_MCK PAL_LINE(GPIOC, 7U) +#define LINE_ZIO_D43 PAL_LINE(GPIOC, 8U) +#define LINE_SDMMC_D0 PAL_LINE(GPIOC, 8U) +#define LINE_ZIO_D44 PAL_LINE(GPIOC, 9U) +#define LINE_SDMMC_D1 PAL_LINE(GPIOC, 9U) +#define LINE_ZIO_D45 PAL_LINE(GPIOC, 10U) +#define LINE_SDMMC_D2 PAL_LINE(GPIOC, 10U) +#define LINE_ZIO_D46 PAL_LINE(GPIOC, 11U) +#define LINE_SDMMC_D3 PAL_LINE(GPIOC, 11U) +#define LINE_ZIO_D47 PAL_LINE(GPIOC, 12U) +#define LINE_SDMMC_CK PAL_LINE(GPIOC, 12U) +#define LINE_BUTTON PAL_LINE(GPIOC, 13U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) + +#define LINE_ZIO_D67 PAL_LINE(GPIOD, 0U) +#define LINE_CAN1_RX PAL_LINE(GPIOD, 0U) +#define LINE_ZIO_D66 PAL_LINE(GPIOD, 1U) +#define LINE_CAN1_TX PAL_LINE(GPIOD, 1U) +#define LINE_ZIO_D48 PAL_LINE(GPIOD, 2U) +#define LINE_SDMMC_CMD PAL_LINE(GPIOD, 2U) +#define LINE_ZIO_D55 PAL_LINE(GPIOD, 3U) +#define LINE_USART2_CTS PAL_LINE(GPIOD, 3U) +#define LINE_ZIO_D54 PAL_LINE(GPIOD, 4U) +#define LINE_USART2_RTS PAL_LINE(GPIOD, 4U) +#define LINE_ZIO_D53 PAL_LINE(GPIOD, 5U) +#define LINE_USART2_TX PAL_LINE(GPIOD, 5U) +#define LINE_ZIO_D52 PAL_LINE(GPIOD, 6U) +#define LINE_USART2_RX PAL_LINE(GPIOD, 6U) +#define LINE_ZIO_D51 PAL_LINE(GPIOD, 7U) +#define LINE_USART2_SCLK PAL_LINE(GPIOD, 7U) +#define LINE_USART3_RX PAL_LINE(GPIOD, 8U) +#define LINE_STLK_RX PAL_LINE(GPIOD, 8U) +#define LINE_USART3_TX PAL_LINE(GPIOD, 9U) +#define LINE_STLK_TX PAL_LINE(GPIOD, 9U) +#define LINE_ZIO_D30 PAL_LINE(GPIOD, 11U) +#define LINE_QSPI_BK1_IO0 PAL_LINE(GPIOD, 11U) +#define LINE_ZIO_D29 PAL_LINE(GPIOD, 12U) +#define LINE_QSPI_BK1_IO1 PAL_LINE(GPIOD, 12U) +#define LINE_ZIO_D28 PAL_LINE(GPIOD, 13U) +#define LINE_QSPI_BK1_IO3 PAL_LINE(GPIOD, 13U) +#define LINE_ARD_D10 PAL_LINE(GPIOD, 14U) +#define LINE_SPI1_NSS PAL_LINE(GPIOD, 14U) +#define LINE_ARD_D9 PAL_LINE(GPIOD, 15U) +#define LINE_TIM4_CH4 PAL_LINE(GPIOD, 15U) + +#define LINE_ZIO_D34 PAL_LINE(GPIOE, 0U) +#define LINE_TIM4_ETR PAL_LINE(GPIOE, 0U) +#define LINE_ZIO_D31 PAL_LINE(GPIOE, 2U) +#define LINE_ZIO_D56 PAL_LINE(GPIOE, 2U) +#define LINE_SAI1_MCLK_A PAL_LINE(GPIOE, 2U) +#define LINE_ZIO_D60 PAL_LINE(GPIOE, 3U) +#define LINE_SAI1_SD_B PAL_LINE(GPIOE, 3U) +#define LINE_ZIO_D57 PAL_LINE(GPIOE, 4U) +#define LINE_SAI1_FS_A PAL_LINE(GPIOE, 4U) +#define LINE_ZIO_D58 PAL_LINE(GPIOE, 5U) +#define LINE_SAI1_SCK_A PAL_LINE(GPIOE, 5U) +#define LINE_ZIO_D59 PAL_LINE(GPIOE, 6U) +#define LINE_SAI1_SD_A PAL_LINE(GPIOE, 6U) +#define LINE_ZIO_D41 PAL_LINE(GPIOE, 7U) +#define LINE_TIM1_ETR PAL_LINE(GPIOE, 7U) +#define LINE_ZIO_D42 PAL_LINE(GPIOE, 8U) +#define LINE_TIM1_CH1N PAL_LINE(GPIOE, 8U) +#define LINE_ARD_D6 PAL_LINE(GPIOE, 9U) +#define LINE_TIM1_CH1 PAL_LINE(GPIOE, 9U) +#define LINE_ZIO_D40 PAL_LINE(GPIOE, 10U) +#define LINE_TIM1_CH2N PAL_LINE(GPIOE, 10U) +#define LINE_ARD_D5 PAL_LINE(GPIOE, 11U) +#define LINE_TIM1_CH2 PAL_LINE(GPIOE, 11U) +#define LINE_ZIO_D39 PAL_LINE(GPIOE, 12U) +#define LINE_TIM1_CH3N PAL_LINE(GPIOE, 12U) +#define LINE_ARD_D3 PAL_LINE(GPIOE, 13U) +#define LINE_TIM1_CH3 PAL_LINE(GPIOE, 13U) +#define LINE_ZIO_D38 PAL_LINE(GPIOE, 14U) +#define LINE_ZIO_D37 PAL_LINE(GPIOE, 15U) +#define LINE_TIM1_BKIN1 PAL_LINE(GPIOE, 15U) + +#define LINE_ZIO_D68 PAL_LINE(GPIOF, 0U) +#define LINE_I2C2_SDA PAL_LINE(GPIOF, 0U) +#define LINE_ZIO_D69 PAL_LINE(GPIOF, 1U) +#define LINE_I2C2_SCL PAL_LINE(GPIOF, 1U) +#define LINE_ZIO_D70 PAL_LINE(GPIOF, 2U) +#define LINE_I2C2_SMBA PAL_LINE(GPIOF, 2U) +#define LINE_ARD_A3 PAL_LINE(GPIOF, 3U) +#define LINE_ADC3_IN9 PAL_LINE(GPIOF, 3U) +#define LINE_ZIO_A8 PAL_LINE(GPIOF, 4U) +#define LINE_ADC3_IN14 PAL_LINE(GPIOF, 4U) +#define LINE_ARD_A4 PAL_LINE(GPIOF, 5U) +#define LINE_ADC3_IN15 PAL_LINE(GPIOF, 5U) +#define LINE_ZIO_D62 PAL_LINE(GPIOF, 7U) +#define LINE_SAI1_MCLK_B PAL_LINE(GPIOF, 7U) +#define LINE_ZIO_D61 PAL_LINE(GPIOF, 8U) +#define LINE_SAI1_SCK_B PAL_LINE(GPIOF, 8U) +#define LINE_ZIO_D63 PAL_LINE(GPIOF, 9U) +#define LINE_SAI1_FS_B PAL_LINE(GPIOF, 9U) +#define LINE_ARD_A5 PAL_LINE(GPIOF, 10U) +#define LINE_ADC3_IN8 PAL_LINE(GPIOF, 10U) +#define LINE_ARD_D8 PAL_LINE(GPIOF, 12U) +#define LINE_ARD_D7 PAL_LINE(GPIOF, 13U) +#define LINE_ARD_D4 PAL_LINE(GPIOF, 14U) +#define LINE_ARD_D2 PAL_LINE(GPIOF, 15U) + +#define LINE_ZIO_D65 PAL_LINE(GPIOG, 0U) +#define LINE_ZIO_D64 PAL_LINE(GPIOG, 1U) +#define LINE_ZIO_D49 PAL_LINE(GPIOG, 2U) +#define LINE_ZIO_D50 PAL_LINE(GPIOG, 3U) +#define LINE_USB_GPIO_OUT PAL_LINE(GPIOG, 6U) +#define LINE_USB_GPIO_IN PAL_LINE(GPIOG, 7U) +#define LINE_ARD_D0 PAL_LINE(GPIOG, 9U) +#define LINE_USART6_RX PAL_LINE(GPIOG, 9U) +#define LINE_RMII_TX_EN PAL_LINE(GPIOG, 11U) +#define LINE_RMII_TXD0 PAL_LINE(GPIOG, 13U) +#define LINE_ARD_D1 PAL_LINE(GPIOG, 14U) +#define LINE_USART6_TX PAL_LINE(GPIOG, 14U) + +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + + + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - ZIO_D32 TIM2_CH1 (input pullup). + * PA1 - RMII_REF_CLK (alternate 11). + * PA2 - RMII_MDIO (alternate 11). + * PA3 - ARD_A0 ADC123_IN3 (input pullup). + * PA4 - ZIO_D24 SPI3_NSS (input pullup). + * PA5 - ARD_D13 (input pullup). + * PA6 - ARD_D12 (input pullup). + * PA7 - RMII_CRS_DV (alternate 11). + * PA8 - USB_SOF (alternate 10). + * PA9 - USB_VBUS (analog). + * PA10 - USB_ID (alternate 10). + * PA11 - USB_DM (alternate 10). + * PA12 - USB_DP (alternate 10). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - ZIO_D20 I2S3_WS (input pullup). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ZIO_D32) | \ + PIN_MODE_ALTERNATE(GPIOA_RMII_REF_CLK) |\ + PIN_MODE_ALTERNATE(GPIOA_RMII_MDIO) | \ + PIN_MODE_INPUT(GPIOA_ARD_A0) | \ + PIN_MODE_INPUT(GPIOA_ZIO_D24) | \ + PIN_MODE_INPUT(GPIOA_ARD_D13) | \ + PIN_MODE_INPUT(GPIOA_ARD_D12) | \ + PIN_MODE_ALTERNATE(GPIOA_RMII_CRS_DV) |\ + PIN_MODE_ALTERNATE(GPIOA_USB_SOF) | \ + PIN_MODE_ANALOG(GPIOA_USB_VBUS) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_ID) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_ZIO_D20)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D32) | \ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_REF_CLK) |\ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_MDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D24) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D13) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_CRS_DV) |\ + PIN_OTYPE_PUSHPULL(GPIOA_USB_SOF) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_VBUS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_ID) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D20)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ZIO_D32) | \ + PIN_OSPEED_HIGH(GPIOA_RMII_REF_CLK) | \ + PIN_OSPEED_HIGH(GPIOA_RMII_MDIO) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \ + PIN_OSPEED_HIGH(GPIOA_ZIO_D24) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D13) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \ + PIN_OSPEED_VERYLOW(GPIOA_RMII_CRS_DV) |\ + PIN_OSPEED_HIGH(GPIOA_USB_SOF) | \ + PIN_OSPEED_HIGH(GPIOA_USB_VBUS) | \ + PIN_OSPEED_HIGH(GPIOA_USB_ID) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DM) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_HIGH(GPIOA_ZIO_D20)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ZIO_D32) | \ + PIN_PUPDR_FLOATING(GPIOA_RMII_REF_CLK) |\ + PIN_PUPDR_PULLUP(GPIOA_RMII_MDIO) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \ + PIN_PUPDR_PULLUP(GPIOA_ZIO_D24) | \ + PIN_PUPDR_FLOATING(GPIOA_ARD_D13) | \ + PIN_PUPDR_FLOATING(GPIOA_ARD_D12) | \ + PIN_PUPDR_FLOATING(GPIOA_RMII_CRS_DV) |\ + PIN_PUPDR_FLOATING(GPIOA_USB_SOF) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_VBUS) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_ID) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ + PIN_PUPDR_FLOATING(GPIOA_SWDIO) | \ + PIN_PUPDR_FLOATING(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_ZIO_D20)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ZIO_D32) | \ + PIN_ODR_HIGH(GPIOA_RMII_REF_CLK) | \ + PIN_ODR_HIGH(GPIOA_RMII_MDIO) | \ + PIN_ODR_HIGH(GPIOA_ARD_A0) | \ + PIN_ODR_HIGH(GPIOA_ZIO_D24) | \ + PIN_ODR_HIGH(GPIOA_ARD_D13) | \ + PIN_ODR_HIGH(GPIOA_ARD_D12) | \ + PIN_ODR_HIGH(GPIOA_RMII_CRS_DV) | \ + PIN_ODR_HIGH(GPIOA_USB_SOF) | \ + PIN_ODR_HIGH(GPIOA_USB_VBUS) | \ + PIN_ODR_HIGH(GPIOA_USB_ID) | \ + PIN_ODR_HIGH(GPIOA_USB_DM) | \ + PIN_ODR_HIGH(GPIOA_USB_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_ZIO_D20)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ZIO_D32, 0U) | \ + PIN_AFIO_AF(GPIOA_RMII_REF_CLK, 11U) | \ + PIN_AFIO_AF(GPIOA_RMII_MDIO, 11U) | \ + PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \ + PIN_AFIO_AF(GPIOA_ZIO_D24, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D13, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \ + PIN_AFIO_AF(GPIOA_RMII_CRS_DV, 11U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_USB_SOF, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_VBUS, 0U) | \ + PIN_AFIO_AF(GPIOA_USB_ID, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \ + PIN_AFIO_AF(GPIOA_ZIO_D20, 0U)) + +/* + * GPIOB setup: + * + * PB0 - ZIO_D33 TIM3_CH3 LED1 (output pushpull maximum). + * PB1 - ZIO_A6 ADC12_IN9 (input pullup). + * PB2 - ZIO_D27 QSPI_CLK (input pullup). + * PB3 - ZIO_D23 I2S3_CK (input pullup). + * PB4 - ZIO_D25 SPI3_MISO (input pullup). + * PB5 - ZIO_D22 I2S3_SD (input pullup). + * PB6 - ZIO_D26 QSPI_BK1_NCS (input pullup). + * PB7 - LED2 (output pushpull maximum). + * PB8 - ARD_D15 I2C1_SCL (input pullup). + * PB9 - ARD_D14 I2C1_SDA (input pullup). + * PB10 - ZIO_D36 TIM2_CH3 (input pullup). + * PB11 - ZIO_D35 TIM2_CH4 (input pullup). + * PB12 - ZIO_D19 I2S2_WS (input pullup). + * PB13 - ZIO_D18 I2S2_CK RMII_TXD1 (alternate 11). + * PB14 - LED3 (output pushpull maximum). + * PB15 - ZIO_D17 I2S2_SD (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_OUTPUT(GPIOB_ZIO_D33) | \ + PIN_MODE_INPUT(GPIOB_ZIO_A6) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D27) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D23) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D25) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D22) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D26) | \ + PIN_MODE_OUTPUT(GPIOB_LED2) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D36) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D35) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D19) | \ + PIN_MODE_ALTERNATE(GPIOB_RMII_TXD1) | \ + PIN_MODE_OUTPUT(GPIOB_LED3) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D17)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D33) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_A6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D27) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D23) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D25) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D22) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D26) | \ + PIN_OTYPE_PUSHPULL(GPIOB_LED2) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D36) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D35) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D19) | \ + PIN_OTYPE_PUSHPULL(GPIOB_RMII_TXD1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_LED3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D17)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ZIO_D33) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_A6) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D27) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D23) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D25) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D22) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D26) | \ + PIN_OSPEED_HIGH(GPIOB_LED2) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D36) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D35) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D19) | \ + PIN_OSPEED_HIGH(GPIOB_RMII_TXD1) | \ + PIN_OSPEED_HIGH(GPIOB_LED3) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D17)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_ZIO_D33) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_A6) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D27) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D23) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D25) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D22) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D26) | \ + PIN_PUPDR_FLOATING(GPIOB_LED2) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D36) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D35) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D19) | \ + PIN_PUPDR_FLOATING(GPIOB_RMII_TXD1) | \ + PIN_PUPDR_FLOATING(GPIOB_LED3) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D17)) +#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_ZIO_D33) | \ + PIN_ODR_HIGH(GPIOB_ZIO_A6) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D27) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D23) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D25) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D22) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D26) | \ + PIN_ODR_LOW(GPIOB_LED2) | \ + PIN_ODR_LOW(GPIOB_I2C1_SCL) | \ + PIN_ODR_LOW(GPIOB_I2C1_SDA) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D36) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D35) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D19) | \ + PIN_ODR_HIGH(GPIOB_RMII_TXD1) | \ + PIN_ODR_LOW(GPIOB_LED3) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D17)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ZIO_D33, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_A6, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D27, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D23, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D25, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D22, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D26, 0U) | \ + PIN_AFIO_AF(GPIOB_LED2, 0U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D36, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D35, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D19, 0U) | \ + PIN_AFIO_AF(GPIOB_RMII_TXD1, 11U) | \ + PIN_AFIO_AF(GPIOB_LED3, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D17, 0U)) + +/* + * GPIOC setup: + * + * PC0 - ARD_A1 ADC123_IN10 (input pullup). + * PC1 - RMII_MDC (alternate 11). + * PC2 - ZIO_A7 ADC123_IN12 (input pullup). + * PC3 - ARD_A2 ADC123_IN13 (input pullup). + * PC4 - RMII_RXD0 (alternate 11). + * PC5 - RMII_RXD1 (alternate 11). + * PC6 - ZIO_D16 I2S2_MCK (input pullup). + * PC7 - ZIO_D21 I2S3_MCK (input pullup). + * PC8 - ZIO_D43 SDMMC_D0 (input pullup). + * PC9 - ZIO_D44 SDMMC_D1 (input pullup). + * PC10 - ZIO_D45 SDMMC_D2 (input pullup). + * PC11 - ZIO_D46 SDMMC_D3 (input pullup). + * PC12 - ZIO_D47 SDMMC_CK (input pullup). + * PC13 - BUTTON (input floating). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ARD_A1) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_MDC) | \ + PIN_MODE_INPUT(GPIOC_ZIO_A7) | \ + PIN_MODE_INPUT(GPIOC_ARD_A2) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_RXD0) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_RXD1) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D16) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D21) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D43) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D44) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D45) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D46) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D47) | \ + PIN_MODE_INPUT(GPIOC_BUTTON) | \ + PIN_MODE_INPUT(GPIOC_OSC32_IN) | \ + PIN_MODE_INPUT(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_MDC) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_A7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D16) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D21) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D43) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D44) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D45) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D46) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D47) | \ + PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A1) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_MDC) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_A7) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_A2) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_RXD0) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_RXD1) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D16) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D21) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D43) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D44) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D45) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D46) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D47) | \ + PIN_OSPEED_HIGH(GPIOC_BUTTON) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A1) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_MDC) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_A7) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A2) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_RXD0) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_RXD1) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D16) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D21) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D43) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D44) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D45) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D46) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D47) | \ + PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A1) | \ + PIN_ODR_HIGH(GPIOC_RMII_MDC) | \ + PIN_ODR_HIGH(GPIOC_ZIO_A7) | \ + PIN_ODR_HIGH(GPIOC_ARD_A2) | \ + PIN_ODR_HIGH(GPIOC_RMII_RXD0) | \ + PIN_ODR_HIGH(GPIOC_RMII_RXD1) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D16) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D21) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D43) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D44) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D45) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D46) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D47) | \ + PIN_ODR_HIGH(GPIOC_BUTTON) | \ + PIN_ODR_HIGH(GPIOC_OSC32_IN) | \ + PIN_ODR_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A1, 0U) | \ + PIN_AFIO_AF(GPIOC_RMII_MDC, 11U) | \ + PIN_AFIO_AF(GPIOC_ZIO_A7, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A2, 0U) | \ + PIN_AFIO_AF(GPIOC_RMII_RXD0, 11U) | \ + PIN_AFIO_AF(GPIOC_RMII_RXD1, 11U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D16, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D21, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_ZIO_D43, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D44, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D45, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D46, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D47, 0U) | \ + PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - ZIO_D67 CAN1_RX (input pullup). + * PD1 - ZIO_D66 CAN1_TX (input pullup). + * PD2 - ZIO_D48 SDMMC_CMD (input pullup). + * PD3 - ZIO_D55 USART2_CTS (input pullup). + * PD4 - ZIO_D54 USART2_RTS (input pullup). + * PD5 - ZIO_D53 USART2_TX (input pullup). + * PD6 - ZIO_D52 USART2_RX (input pullup). + * PD7 - ZIO_D51 USART2_SCLK (input pullup). + * PD8 - USART3_RX STLK_RX (alternate 7). + * PD9 - USART3_TX STLK_TX (alternate 7). + * PD10 - PIN10 (input pullup). + * PD11 - ZIO_D30 QSPI_BK1_IO0 (input pullup). + * PD12 - ZIO_D29 QSPI_BK1_IO1 (input pullup). + * PD13 - ZIO_D28 QSPI_BK1_IO3 (input pullup). + * PD14 - ARD_D10 SPI1_NSS (input pullup). + * PD15 - ARD_D9 TIM4_CH4 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_ZIO_D67) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D66) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D48) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D55) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D54) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D53) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D52) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D51) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_RX) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_TX) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D30) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D29) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D28) | \ + PIN_MODE_INPUT(GPIOD_ARD_D10) | \ + PIN_MODE_INPUT(GPIOD_ARD_D9)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D67) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D66) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D48) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D55) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D54) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D53) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D52) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D51) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D30) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D29) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D28) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ARD_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ARD_D9)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_ZIO_D67) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D66) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D48) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D55) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D54) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D53) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D52) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D51) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_RX) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_TX) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D30) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D29) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D28) | \ + PIN_OSPEED_HIGH(GPIOD_ARD_D10) | \ + PIN_OSPEED_HIGH(GPIOD_ARD_D9)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_ZIO_D67) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D66) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D48) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D55) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D54) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D53) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D52) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D51) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_RX) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_TX) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D30) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D29) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D28) | \ + PIN_PUPDR_PULLUP(GPIOD_ARD_D10) | \ + PIN_PUPDR_PULLUP(GPIOD_ARD_D9)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_ZIO_D67) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D66) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D48) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D55) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D54) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D53) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D52) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D51) | \ + PIN_ODR_HIGH(GPIOD_USART3_RX) | \ + PIN_ODR_HIGH(GPIOD_USART3_TX) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D30) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D29) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D28) | \ + PIN_ODR_HIGH(GPIOD_ARD_D10) | \ + PIN_ODR_HIGH(GPIOD_ARD_D9)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_ZIO_D67, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D66, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D48, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D55, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D54, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D53, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D52, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D51, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_USART3_RX, 7U) | \ + PIN_AFIO_AF(GPIOD_USART3_TX, 7U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D30, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D29, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D28, 0U) | \ + PIN_AFIO_AF(GPIOD_ARD_D10, 0U) | \ + PIN_AFIO_AF(GPIOD_ARD_D9, 0U)) + +/* + * GPIOE setup: + * + * PE0 - ZIO_D34 TIM4_ETR (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - ZIO_D31 ZIO_D56 SAI1_MCLK_A(input pullup). + * PE3 - ZIO_D60 SAI1_SD_B (input pullup). + * PE4 - ZIO_D57 SAI1_FS_A (input pullup). + * PE5 - ZIO_D58 SAI1_SCK_A (input pullup). + * PE6 - ZIO_D59 SAI1_SD_A (input pullup). + * PE7 - ZIO_D41 TIM1_ETR (input pullup). + * PE8 - ZIO_D42 TIM1_CH1N (input pullup). + * PE9 - ARD_D6 TIM1_CH1 (input pullup). + * PE10 - ZIO_D40 TIM1_CH2N (input pullup). + * PE11 - ARD_D5 TIM1_CH2 (input pullup). + * PE12 - ZIO_D39 TIM1_CH3N (input pullup). + * PE13 - ARD_D3 TIM1_CH3 (input pullup). + * PE14 - ZIO_D38 (input pullup). + * PE15 - ZIO_D37 TIM1_BKIN1 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_ZIO_D34) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D31) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D60) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D57) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D58) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D59) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D41) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D42) | \ + PIN_MODE_INPUT(GPIOE_ARD_D6) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D40) | \ + PIN_MODE_INPUT(GPIOE_ARD_D5) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D39) | \ + PIN_MODE_INPUT(GPIOE_ARD_D3) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D38) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D37)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D34) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D31) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D60) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D57) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D58) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D59) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D41) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D42) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D40) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D39) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D38) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D37)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_ZIO_D34) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D31) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D60) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D57) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D58) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D59) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D41) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D42) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D6) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D40) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D5) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D39) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D3) | \ + PIN_OSPEED_VERYLOW(GPIOE_ZIO_D38) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D37)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_ZIO_D34) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D31) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D60) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D57) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D58) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D59) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D41) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D42) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D6) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D40) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D5) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D39) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D3) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D38) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D37)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_ZIO_D34) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D31) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D60) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D57) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D58) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D59) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D41) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D42) | \ + PIN_ODR_HIGH(GPIOE_ARD_D6) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D40) | \ + PIN_ODR_HIGH(GPIOE_ARD_D5) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D39) | \ + PIN_ODR_HIGH(GPIOE_ARD_D3) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D38) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D37)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_ZIO_D34, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D31, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D60, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D57, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D58, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D59, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D41, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_ZIO_D42, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D6, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D40, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D5, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D39, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D3, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D38, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D37, 0U)) + +/* + * GPIOF setup: + * + * PF0 - ZIO_D68 I2C2_SDA (input pullup). + * PF1 - ZIO_D69 I2C2_SCL (input pullup). + * PF2 - ZIO_D70 I2C2_SMBA (input pullup). + * PF3 - ARD_A3 ADC3_IN9 (input pullup). + * PF4 - ZIO_A8 ADC3_IN14 (input pullup). + * PF5 - ARD_A4 ADC3_IN15 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - SPI5_SCK (Alternate 5). + * PF8 - SPI5_MISO (Alternate 5). + * PF9 - SPI5_MOSI (Alternate 5). + * PF10 - ARD_A5 ADC3_IN8 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - ARD_D8 (input pullup). + * PF13 - ARD_D7 (input pullup). + * PF14 - ARD_D4 (input pullup). + * PF15 - ARD_D2 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_ZIO_D68) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D69) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D70) | \ + PIN_MODE_INPUT(GPIOF_ARD_A3) | \ + PIN_MODE_INPUT(GPIOF_ZIO_A8) | \ + PIN_MODE_INPUT(GPIOF_ARD_A4) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_ALTERNATE(GPIOF_SPI5_SCK) | \ + PIN_MODE_ALTERNATE(GPIOF_SPI5_MISO) | \ + PIN_MODE_ALTERNATE(GPIOF_SPI5_MOSI) | \ + PIN_MODE_INPUT(GPIOF_ARD_A5) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_ARD_D8) | \ + PIN_MODE_INPUT(GPIOF_ARD_D7) | \ + PIN_MODE_INPUT(GPIOF_ARD_D4) | \ + PIN_MODE_INPUT(GPIOF_ARD_D2)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D68) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D69) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D70) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_A8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_SPI5_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOF_SPI5_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOF_SPI5_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D2)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_ZIO_D68) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D69) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D70) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A3) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_A8) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A4) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_SPI5_SCK) | \ + PIN_OSPEED_HIGH(GPIOF_SPI5_MISO) | \ + PIN_OSPEED_HIGH(GPIOF_SPI5_MOSI) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A5) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D8) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D7) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D4) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D2)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_ZIO_D68) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D69) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D70) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A3) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_A8) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOF_SPI5_SCK) | \ + PIN_PUPDR_FLOATING(GPIOF_SPI5_MISO) | \ + PIN_PUPDR_FLOATING(GPIOF_SPI5_MOSI) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D8) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D7) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D4) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D2)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_ZIO_D68) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D69) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D70) | \ + PIN_ODR_HIGH(GPIOF_ARD_A3) | \ + PIN_ODR_HIGH(GPIOF_ZIO_A8) | \ + PIN_ODR_HIGH(GPIOF_ARD_A4) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_SPI5_SCK) | \ + PIN_ODR_HIGH(GPIOF_SPI5_MISO) | \ + PIN_ODR_HIGH(GPIOF_SPI5_MOSI) | \ + PIN_ODR_HIGH(GPIOF_ARD_A5) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_ARD_D8) | \ + PIN_ODR_HIGH(GPIOF_ARD_D7) | \ + PIN_ODR_HIGH(GPIOF_ARD_D4) | \ + PIN_ODR_HIGH(GPIOF_ARD_D2)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_ZIO_D68, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D69, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D70, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_A3, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_A8, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_A4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_SPI5_SCK, 5U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_SPI5_MISO, 5U) | \ + PIN_AFIO_AF(GPIOF_SPI5_MOSI, 5U) | \ + PIN_AFIO_AF(GPIOF_ARD_A5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D8, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D7, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D4, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D2, 0U)) + +/* + * GPIOG setup: + * + * PG0 - ZIO_D65 (input pullup). + * PG1 - ZIO_D64 (input pullup). + * PG2 - ZIO_D49 (input pullup). + * PG3 - ZIO_D50 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - USB_GPIO_OUT (input pullup). + * PG7 - USB_GPIO_IN (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - ARD_D0 USART6_RX (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - RMII_TX_EN (alternate 11). + * PG12 - PIN12 (input pullup). + * PG13 - RMII_TXD0 (alternate 11). + * PG14 - ARD_D1 USART6_TX (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_OUTPUT(GPIOG_ZIO_D65) | \ + PIN_MODE_OUTPUT(GPIOG_ZIO_D64) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D49) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D50) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_USB_GPIO_OUT) | \ + PIN_MODE_INPUT(GPIOG_USB_GPIO_IN) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_ARD_D0) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_ALTERNATE(GPIOG_RMII_TX_EN) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_ALTERNATE(GPIOG_RMII_TXD0) | \ + PIN_MODE_INPUT(GPIOG_ARD_D1) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D65) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D64) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D49) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D50) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_USB_GPIO_OUT) |\ + PIN_OTYPE_PUSHPULL(GPIOG_USB_GPIO_IN) |\ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ARD_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_RMII_TX_EN) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_RMII_TXD0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ARD_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_HIGH(GPIOG_ZIO_D65) | \ + PIN_OSPEED_HIGH(GPIOG_ZIO_D64) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D49) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D50) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_USB_GPIO_OUT) | \ + PIN_OSPEED_HIGH(GPIOG_USB_GPIO_IN) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_ARD_D0) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \ + PIN_OSPEED_HIGH(GPIOG_RMII_TX_EN) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \ + PIN_OSPEED_HIGH(GPIOG_RMII_TXD0) | \ + PIN_OSPEED_HIGH(GPIOG_ARD_D1) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_ZIO_D65) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D64) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D49) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D50) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_USB_GPIO_OUT) | \ + PIN_PUPDR_PULLUP(GPIOG_USB_GPIO_IN) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_ARD_D0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOG_RMII_TX_EN) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOG_RMII_TXD0) | \ + PIN_PUPDR_PULLUP(GPIOG_ARD_D1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_ZIO_D65) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D64) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D49) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D50) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_USB_GPIO_OUT) | \ + PIN_ODR_HIGH(GPIOG_USB_GPIO_IN) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_ARD_D0) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_RMII_TX_EN) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_RMII_TXD0) | \ + PIN_ODR_HIGH(GPIOG_ARD_D1) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_ZIO_D65, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D64, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D49, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D50, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_USB_GPIO_OUT, 0U) | \ + PIN_AFIO_AF(GPIOG_USB_GPIO_IN, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_ARD_D0, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_RMII_TX_EN, 11U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_RMII_TXD0, 11U) | \ + PIN_AFIO_AF(GPIOG_ARD_D1, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input pullup). + * PI1 - PIN1 (input pullup). + * PI2 - PIN2 (input pullup). + * PI3 - PIN3 (input pullup). + * PI4 - PIN4 (input pullup). + * PI5 - PIN5 (input pullup). + * PI6 - PIN6 (input pullup). + * PI7 - PIN7 (input pullup). + * PI8 - PIN8 (input pullup). + * PI9 - PIN9 (input pullup). + * PI10 - PIN10 (input pullup). + * PI11 - PIN11 (input pullup). + * PI12 - PIN12 (input pullup). + * PI13 - PIN13 (input pullup). + * PI14 - PIN14 (input pullup). + * PI15 - PIN15 (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOI_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + +/* + * GPIOJ setup: + * + * PJ0 - PIN0 (input pullup). + * PJ1 - PIN1 (input pullup). + * PJ2 - PIN2 (input pullup). + * PJ3 - PIN3 (input pullup). + * PJ4 - PIN4 (input pullup). + * PJ5 - PIN5 (input pullup). + * PJ6 - PIN6 (input pullup). + * PJ7 - PIN7 (input pullup). + * PJ8 - PIN8 (input pullup). + * PJ9 - PIN9 (input pullup). + * PJ10 - PIN10 (input pullup). + * PJ11 - PIN11 (input pullup). + * PJ12 - PIN12 (input pullup). + * PJ13 - PIN13 (input pullup). + * PJ14 - PIN14 (input pullup). + * PJ15 - PIN15 (input pullup). + */ +#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \ + PIN_MODE_INPUT(GPIOJ_PIN1) | \ + PIN_MODE_INPUT(GPIOJ_PIN2) | \ + PIN_MODE_INPUT(GPIOJ_PIN3) | \ + PIN_MODE_INPUT(GPIOJ_PIN4) | \ + PIN_MODE_INPUT(GPIOJ_PIN5) | \ + PIN_MODE_INPUT(GPIOJ_PIN6) | \ + PIN_MODE_INPUT(GPIOJ_PIN7) | \ + PIN_MODE_INPUT(GPIOJ_PIN8) | \ + PIN_MODE_INPUT(GPIOJ_PIN9) | \ + PIN_MODE_INPUT(GPIOJ_PIN10) | \ + PIN_MODE_INPUT(GPIOJ_PIN11) | \ + PIN_MODE_INPUT(GPIOJ_PIN12) | \ + PIN_MODE_INPUT(GPIOJ_PIN13) | \ + PIN_MODE_INPUT(GPIOJ_PIN14) | \ + PIN_MODE_INPUT(GPIOJ_PIN15)) +#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN15)) +#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOJ_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN15)) +#define VAL_GPIOJ_PUPDR (PIN_PUPDR_PULLUP(GPIOJ_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN15)) +#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \ + PIN_ODR_HIGH(GPIOJ_PIN1) | \ + PIN_ODR_HIGH(GPIOJ_PIN2) | \ + PIN_ODR_HIGH(GPIOJ_PIN3) | \ + PIN_ODR_HIGH(GPIOJ_PIN4) | \ + PIN_ODR_HIGH(GPIOJ_PIN5) | \ + PIN_ODR_HIGH(GPIOJ_PIN6) | \ + PIN_ODR_HIGH(GPIOJ_PIN7) | \ + PIN_ODR_HIGH(GPIOJ_PIN8) | \ + PIN_ODR_HIGH(GPIOJ_PIN9) | \ + PIN_ODR_HIGH(GPIOJ_PIN10) | \ + PIN_ODR_HIGH(GPIOJ_PIN11) | \ + PIN_ODR_HIGH(GPIOJ_PIN12) | \ + PIN_ODR_HIGH(GPIOJ_PIN13) | \ + PIN_ODR_HIGH(GPIOJ_PIN14) | \ + PIN_ODR_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN7, 0U)) +#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN15, 0U)) + +/* + * GPIOK setup: + * + * PK0 - PIN0 (input pullup). + * PK1 - PIN1 (input pullup). + * PK2 - PIN2 (input pullup). + * PK3 - PIN3 (input pullup). + * PK4 - PIN4 (input pullup). + * PK5 - PIN5 (input pullup). + * PK6 - PIN6 (input pullup). + * PK7 - PIN7 (input pullup). + * PK8 - PIN8 (input pullup). + * PK9 - PIN9 (input pullup). + * PK10 - PIN10 (input pullup). + * PK11 - PIN11 (input pullup). + * PK12 - PIN12 (input pullup). + * PK13 - PIN13 (input pullup). + * PK14 - PIN14 (input pullup). + * PK15 - PIN15 (input pullup). + */ +#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \ + PIN_MODE_INPUT(GPIOK_PIN1) | \ + PIN_MODE_INPUT(GPIOK_PIN2) | \ + PIN_MODE_INPUT(GPIOK_PIN3) | \ + PIN_MODE_INPUT(GPIOK_PIN4) | \ + PIN_MODE_INPUT(GPIOK_PIN5) | \ + PIN_MODE_INPUT(GPIOK_PIN6) | \ + PIN_MODE_INPUT(GPIOK_PIN7) | \ + PIN_MODE_INPUT(GPIOK_PIN8) | \ + PIN_MODE_INPUT(GPIOK_PIN9) | \ + PIN_MODE_INPUT(GPIOK_PIN10) | \ + PIN_MODE_INPUT(GPIOK_PIN11) | \ + PIN_MODE_INPUT(GPIOK_PIN12) | \ + PIN_MODE_INPUT(GPIOK_PIN13) | \ + PIN_MODE_INPUT(GPIOK_PIN14) | \ + PIN_MODE_INPUT(GPIOK_PIN15)) +#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN15)) +#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOK_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN15)) +#define VAL_GPIOK_PUPDR (PIN_PUPDR_PULLUP(GPIOK_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN15)) +#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \ + PIN_ODR_HIGH(GPIOK_PIN1) | \ + PIN_ODR_HIGH(GPIOK_PIN2) | \ + PIN_ODR_HIGH(GPIOK_PIN3) | \ + PIN_ODR_HIGH(GPIOK_PIN4) | \ + PIN_ODR_HIGH(GPIOK_PIN5) | \ + PIN_ODR_HIGH(GPIOK_PIN6) | \ + PIN_ODR_HIGH(GPIOK_PIN7) | \ + PIN_ODR_HIGH(GPIOK_PIN8) | \ + PIN_ODR_HIGH(GPIOK_PIN9) | \ + PIN_ODR_HIGH(GPIOK_PIN10) | \ + PIN_ODR_HIGH(GPIOK_PIN11) | \ + PIN_ODR_HIGH(GPIOK_PIN12) | \ + PIN_ODR_HIGH(GPIOK_PIN13) | \ + PIN_ODR_HIGH(GPIOK_PIN14) | \ + PIN_ODR_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN7, 0U)) +#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN15, 0U)) + + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/CMakeLists.txt new file mode 100644 index 00000000..7c21ff9b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigurationManager.cpp") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") + +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..b70530cd --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 32kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + + /////////////////////////////////////////////////////////////////////////////////////// + // because this target is using a configuration block need to add the + // configuration manager files to the CMake and call ConfigurationManager_Initialize() + // in nanoBooter so the configuration can be managed when in booter mode + /////////////////////////////////////////////////////////////////////////////////////// + { BlockRange_BLOCKTYPE_CONFIG , 1, 1 }, // 0x08008000 configuration block + /////////////////////////////////////////////////////////////////////////////////////// + + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08020000 nanoCLR +}; + +// 256kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE, 0, 1 }, // 0x08040000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 2 } // 0x080C0000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x8000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 1, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08040000, // start address for block region + 3, // total number of blocks in this region + 0x40000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage.c new file mode 100644 index 00000000..eae99f09 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/Device_BlockStorage.c @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 32kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + + /////////////////////////////////////////////////////////////////////////////////////// + // because this target is using a configuration block need to add the + // configuration manager files to the CMake and call ConfigurationManager_Initialize() + // in nanoBooter so the configuration can be managed when in booter mode + /////////////////////////////////////////////////////////////////////////////////////// + { BlockRange_BLOCKTYPE_CONFIG , 1, 1 }, // 0x08008000 configuration block + /////////////////////////////////////////////////////////////////////////////////////// + + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08020000 nanoCLR +}; + +// 256kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE, 0, 0 }, // 0x08040000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 2 } // 0x08080000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x8000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 1, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08040000, // start address for block region + 3, // total number of blocks in this region + 0x40000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/serialcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/serialcfg.h new file mode 100644 index 00000000..803da07a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/serialcfg.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef SERIALCFG_H +#define SERIALCFG_H + +// define which serial driver the Wire Protocol will be using +#define SERIAL_DRIVER SD3 + +#endif /* SERIALCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/targetHAL_ConfigurationManager.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/targetHAL_ConfigurationManager.cpp new file mode 100644 index 00000000..178f6aa7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/common/targetHAL_ConfigurationManager.cpp @@ -0,0 +1,35 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +// Default initialisation for Network interface config blocks +// strong implementation replacing ChibiOS 'weak' one +bool InitialiseNetworkDefaultConfig(HAL_Configuration_NetworkInterface * pconfig, uint32_t configurationIndex) +{ + (void)configurationIndex; + + // make sure the config block marker is set + memcpy(pconfig->Marker, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + pconfig->InterfaceType = NetworkInterfaceType_Ethernet; + pconfig->StartupAddressMode = AddressMode_DHCP; + pconfig->AutomaticDNS = 1; + pconfig->SpecificConfigId = 0; + + // set MAC address with ST provided MAC for development boards + // 00:80:E1:01:35:D1 + pconfig->MacAddress[0] = 0x00; + pconfig->MacAddress[1] = 0x80; + pconfig->MacAddress[2] = 0xE1; + pconfig->MacAddress[3] = 0x01; + pconfig->MacAddress[4] = 0x35; + pconfig->MacAddress[5] = 0xD1; + + return true; +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/lwipopts.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/lwipopts.h new file mode 100644 index 00000000..3e12c25e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/lwipopts.h @@ -0,0 +1,2167 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science, All Rights Reserved +// See LICENSE file in the project root for full license information. +// +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIPOPT_H__ +#define __LWIPOPT_H__ + + +#define _REENT_ONLY +#define set_errno(err) +#include +#include +#include + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 1 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +// empty on purpose +#define LWIP_TCPIP_THREAD_ALIVE() + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 1 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 1 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 4 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE (16 * 1024) +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#define LWIP_IPV6 0 + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 15 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 +#endif + +#define LWIP_RAND rand + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 1 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +#define LWIP_DHCP_CHECK_LINK_UP 1 + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 1 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 1480 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 1 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 1 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 1 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 1 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 1024 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE MEMP_NUM_PBUF +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 1024 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 1024 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 1024 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 4 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 4 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 40 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 4 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 1 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 +#endif + +/** + * LWIP_SO_LINGER==1: Enable linger option for sockets/netconns + */ +#define LWIP_SO_LINGER 1 + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 1 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 1 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 1 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 0 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +// in order to enable the lwIP debug output the bellow has to be uncomment and +// the options above changed to LWIP_DBG_ON for the features that are to output debug information +//#define LWIP_DEBUG 1 + +// enable full duplex comms on multiple threads +// this requires adding an extra field in ChibiOS thread_t (see comment on platform_sys_arch.c) +//#define LWIP_NETCONN_FULLDUPLEX 1 + +#endif /* __LWIPOPT_H__ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/README.md new file mode 100644 index 00000000..d745be69 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](ST_NUCLEO144_F746ZG.Adc.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/ST_NUCLEO144_F746ZG.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/ST_NUCLEO144_F746ZG.Adc.cs new file mode 100644 index 00000000..ca285084 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/managed_helpers/ST_NUCLEO144_F746ZG.Adc.cs @@ -0,0 +1,73 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.ST_NUCLEO144_F746ZG +{ + /// + /// Enumeration of ADC channels available on ST_NUCLEO144_F746ZG + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed as A0, connected to pin 1 on CN9 = PA3 (ADC1 - IN3) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed as A1, connected to pin 3 on CN9 = PC0 (ADC1 - IN10) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed as A2, connected to pin 5 on CN9 = PC3 (ADC1 - IN13) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, exposed as A3, connected to pin 7 on CN9 = PF3 (ADC3 - IN9) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, exposed as A4, connected to pin 9 on CN9 = PF5 (ADC3 - IN15) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, exposed on A5, connected to pin 11 on CN9 = PF10 (ADC3 - IN8) + /// + public const int Channel_5 = 5; + + /// + /// Channel 6, exposed on PB1, connected to CN10 Pin 7 (ADC2 - IN9) + /// + public const int Channel_6 = 6; + + /// + /// Channel 7, exposed on PC2, connected to CN10 Pin 9 (ADC2 - IN12) + /// + public const int Channel_7 = 7; + + /// + /// Channel 8, exposed on PF4, connected to CN10 Pin 11 (ADC3 - IN14) + /// + public const int Channel_8 = 8; + + /// + /// Channel 9, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 9; + + /// + /// Channel 10, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 10; + + /// + /// Channel 11, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 11; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/mbedtls_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/mbedtls_config.h new file mode 100644 index 00000000..9877ca77 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/mbedtls_config.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// See LICENSE file in the project root for full license information. +// + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* For test certificates */ +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_PEM_PARSE_C + +// #define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +// #define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +// #define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +// #define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +// #define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +// #define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET + +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +// #define MBEDTLS_SSL_DEBUG_ALL +// #define MBEDTLS_VERSION_FEATURES +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_ERROR_C +// #define MBEDTLS_VERSION_C + +// uncomment the defines below to enable static memory allocation feature +#if 0 +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_MEMORY +#endif + +#ifdef USE_LCD +#include "lcd_log.h" +#define MBEDTLS_PLATFORM_PRINTF_MACRO LCD_UsrLog +#endif + +// uncomment the defines bellow to generate debug output +// set below the threshold level for debug messages +// check mbed TLS mbedtls/debug.h header for details. +// Debug levels: +// 0 No debug +// 1 Error +// 2 State change +// 3 Informational +// 4 Verbose + +// #define MBEDTLS_DEBUG_C +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +// #define MBEDTLS_DEBUG_THRESHOLD 2 + +#endif // MBEDTLS_CONFIG_H diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..f0e921f7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") + +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter-DEBUG.ld new file mode 100644 index 00000000..b1b4c994 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter-DEBUG.ld @@ -0,0 +1,122 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F746xG generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08008000)*/ + flash_itcm : org = 0x00200000, len = 1M + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20010000, len = 240k /* SRAM1 */ + ram2 : org = 0x2004C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 64k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter.ld new file mode 100644 index 00000000..b1b4c994 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/STM32F746xG_booter.ld @@ -0,0 +1,122 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F746xG generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08008000)*/ + flash_itcm : org = 0x00200000, len = 1M + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20010000, len = 240k /* SRAM1 */ + ram2 : org = 0x2004C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 64k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/chconf.h new file mode 100644 index 00000000..de13f63d --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/chconf.h @@ -0,0 +1,707 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 10000 +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM FALSE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES FALSE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS FALSE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES FALSE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP TRUE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS TRUE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS TRUE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + // this field is required in case lwIP options has LWIP_NETCONN_SEM_PER_THREAD + // void* localStorage; + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#define CORTEX_VTOR_INIT 0x00200000U + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf.h new file mode 100644 index 00000000..1a2f5c78 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf.h @@ -0,0 +1,524 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +#if !defined(FATFS_HAL_DEVICE) || defined(__DOXYGEN__) +//this board requires SDCD2 not SDCD1 +#define FATFS_HAL_DEVICE SDCD2 +#endif + +//#define STM32_SDC_SDMMC_50MHZ TRUE + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +// header for nanoFramework overlay +#include "halconf_nf.h" +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/main.c new file mode 100644 index 00000000..ed61f944 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/main.c @@ -0,0 +1,84 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + osDelay(20); // Let init stabilize + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + // the user button in this board has a pull-up resistor so the check has to be inverted + if (!palReadLine(LINE_BUTTON)) + { + // check for valid CLR image + // we are checking for a valid image right after the configuration block + if(CheckValidCLRImage((uint32_t)&__nanoConfig_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoConfig_end__); + } + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // initialize configuration manager + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it here to have access to network configuration blocks + ConfigurationManager_Initialize(); + + // Normal main() thread + while (true) { + palToggleLine(LINE_LED1); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf.h new file mode 100644 index 00000000..9ea6775e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf.h @@ -0,0 +1,381 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F7xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F7xx_MCUCONF +#define STM32F746_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 4 +#define STM32_PLLN_VALUE 216 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 25 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_OFF +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SP_VALUE 2 +#define STM32_PLLI2SQ_VALUE 2 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PLLSAIN_VALUE 192 +#define STM32_PLLSAIP_VALUE 2 +#define STM32_PLLSAIQ_VALUE 2 +#define STM32_PLLSAIR_VALUE 2 +#define STM32_PLLSAIDIVQ_VALUE 2 +#define STM32_PLLSAIDIVR_VALUE 2 +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#define STM32_LCDTFT_REQUIRED FALSE +#define STM32_USART1SEL STM32_USART1SEL_PCLK2 +#define STM32_USART2SEL STM32_USART2SEL_PCLK1 +#define STM32_USART3SEL STM32_USART3SEL_PCLK1 +#define STM32_UART4SEL STM32_UART4SEL_PCLK1 +#define STM32_UART5SEL STM32_UART5SEL_PCLK1 +#define STM32_USART6SEL STM32_USART6SEL_PCLK2 +#define STM32_UART7SEL STM32_UART7SEL_PCLK1 +#define STM32_UART8SEL STM32_UART8SEL_PCLK1 +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_CECSEL STM32_CECSEL_HSIDIV488 +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#define STM32_SDMMCSEL STM32_SDMMCSEL_SYSCLK +#define STM32_SRAM2_NOCACHE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_USE_CAN3 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 +#define STM32_CAN_CAN3_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_USE_I2C4 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C4_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_I2C4_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_USE_SDMMC1 FALSE +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#define STM32_SDC_SDMMC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 +#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 TRUE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_USE_SPI5 FALSE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USE_UART7 FALSE +#define STM32_UART_USE_UART8 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_UART7_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART7_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_UART8_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_UART8_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_UART7_DMA_PRIORITY 0 +#define STM32_UART_UART8_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR-DEBUG.ld new file mode 100644 index 00000000..3b10b360 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR-DEBUG.ld @@ -0,0 +1,127 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F746xG generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08010000, len = 1M - 32k - 32k - 256k /* flash size less the space reserved for nanoBooter, configuration block and application deployment*/ + flash_itcm : org = 0x00210000, len = 1M - 32k - 32k - 256k + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x080C0000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20010000, len = 240k /* SRAM1 */ + ram2 : org = 0x2004C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 64k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR.ld new file mode 100644 index 00000000..dbaaf06f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/STM32F746xG_CLR.ld @@ -0,0 +1,127 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F746xG generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08010000, len = 1M - 32k - 32k - 512k /* flash size less the space reserved for nanoBooter, configuration block and application deployment*/ + flash_itcm : org = 0x00210000, len = 1M - 32k - 32k - 512k + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x08080000, len = 512k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20010000, len = 240k /* SRAM1 */ + ram2 : org = 0x2004C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 64k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/chconf.h new file mode 100644 index 00000000..214cbcd6 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/chconf.h @@ -0,0 +1,705 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 10000 +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM FALSE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES TRUE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS TRUE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES TRUE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP TRUE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS TRUE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS TRUE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + // this field is required in case lwIP options has LWIP_NETCONN_SEM_PER_THREAD + // void* localStorage; + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf.h new file mode 100644 index 00000000..32abfdc5 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf.h @@ -0,0 +1,535 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +#if !defined(FATFS_HAL_DEVICE) || defined(__DOXYGEN__) +//this board requires SDCD2 not SDCD1 +#define FATFS_HAL_DEVICE SDCD2 +#endif + +//#define STM32_SDC_SDMMC_50MHZ TRUE + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC FALSE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM FALSE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC TRUE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +// header for nanoFramework overlay +#include "halconf_nf.h" +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..c40fe9b1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/halconf_nf.h @@ -0,0 +1,14 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ 1 + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/main.c new file mode 100644 index 00000000..d244b913 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/main.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf.h new file mode 100644 index 00000000..eeede4ff --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf.h @@ -0,0 +1,384 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F7xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F7xx_MCUCONF +#define STM32F746_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 4 +#define STM32_PLLN_VALUE 216 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 25 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_OFF +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SP_VALUE 2 +#define STM32_PLLI2SQ_VALUE 2 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PLLSAIN_VALUE 192 +#define STM32_PLLSAIP_VALUE 2 +#define STM32_PLLSAIQ_VALUE 2 +#define STM32_PLLSAIR_VALUE 2 +#define STM32_PLLSAIDIVQ_VALUE 2 +#define STM32_PLLSAIDIVR_VALUE 2 +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#define STM32_LCDTFT_REQUIRED FALSE +#define STM32_USART1SEL STM32_USART1SEL_PCLK2 +#define STM32_USART2SEL STM32_USART2SEL_PCLK1 +#define STM32_USART3SEL STM32_USART3SEL_PCLK1 +#define STM32_UART4SEL STM32_UART4SEL_PCLK1 +#define STM32_UART5SEL STM32_UART5SEL_PCLK1 +#define STM32_USART6SEL STM32_USART6SEL_PCLK2 +#define STM32_UART7SEL STM32_UART7SEL_PCLK1 +#define STM32_UART8SEL STM32_UART8SEL_PCLK1 +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_CECSEL STM32_CECSEL_HSIDIV488 +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#define STM32_SDMMCSEL STM32_SDMMCSEL_SYSCLK +#define STM32_SRAM2_NOCACHE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 TRUE +#define STM32_ADC_USE_ADC3 TRUE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_USE_CAN3 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 +#define STM32_CAN_CAN3_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 TRUE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_USE_I2C4 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C4_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_I2C4_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 TRUE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_USE_SDMMC1 FALSE +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#define STM32_SDC_SDMMC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 +#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 TRUE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 TRUE +#define STM32_SPI_USE_SPI4 TRUE +#define STM32_SPI_USE_SPI5 TRUE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 TRUE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USE_UART7 FALSE +#define STM32_UART_USE_UART8 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_UART7_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART7_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_UART8_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_UART8_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_UART7_DMA_PRIORITY 0 +#define STM32_UART_UART8_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nucleo144-f746zg.jpg b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/nucleo144-f746zg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b59f8467f92e6130f9c0b15629c3ba200943238c GIT binary patch literal 57158 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 literal 0 HcmV?d00001 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.h.in new file mode 100644 index 00000000..3eddd436 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_common.h.in @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x200000C0) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00040000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00100000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F7" +/////////////////////////////////////////////// + +///////////////////////////////////// +#define PLATFORM_HAS_RNG TRUE +///////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_lwip_sntp_opts.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_lwip_sntp_opts.h new file mode 100644 index 00000000..ed534601 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_lwip_sntp_opts.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#define SNTP_SERVER_DEFAULT_ADDRESS "0.pool.ntp.org" + +// update delay (default 1 hour) +// (value in milliseconds) +#define SNTP_UPDATE_DELAY 3600000 + +// better have a startup delay because we can have DHCP enabled (default 30 seconds) +// value in milliseconds +#define SNTP_STARTUP_DELAY 5000 + +// retry timeout (2 minutes) +// value in milliseconds +#define SNTP_RETRY_TIMEOUT 2*6000 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..09f1420e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_nf_devices_onewire_config.h" +#include + +/////////// +// UART4 // +/////////// + +// pin configuration for UART4 +// port for TX pin is: GPIOC +// TX pin: is GPIOC_10 +// GPIO alternate pin function is 8 +UART_CONFIG_PINS(4, GPIOC, 10, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart4_TxBuffer[UART4_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart4_RxBuffer[UART4_RX_SIZE]; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..76f90a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_nf_devices_onewire_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART4 // +/////////// + +// enable USART4 +#define NF_ONEWIRE_STM32_UART_USE_USART4 TRUE + +// buffers size +// tx buffer size: 32 bytes +#define UART4_TX_SIZE 32 +// rx buffer size: 32 bytes +#define UART4_RX_SIZE 32 \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..7d5ccdeb --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_adc_config.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 3, ADC_CHANNEL_IN3}, + {1, GPIOC, 0, ADC_CHANNEL_IN10}, + {1, GPIOC, 3, ADC_CHANNEL_IN13}, + + // ADC3 + {3, GPIOF, 3, ADC_CHANNEL_IN9}, + {3, GPIOF, 5, ADC_CHANNEL_IN15}, + {3, GPIOF, 10, ADC_CHANNEL_IN8}, + + // ADC2/ADC3 + // Fill up with rest of set ADC pins + {2, GPIOB, 1, ADC_CHANNEL_IN9}, + {2, GPIOC, 2, ADC_CHANNEL_IN12}, + {3, GPIOF, 4, ADC_CHANNEL_IN14}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..16256ec8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_i2c_config.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) + +////////// +// I2C2 // +////////// + +// pin configuration for I2C2 +// port for SCL pin is: GPIOF +// port for SDA pin is: GPIOF +// SCL pin: is GPIOB_0 +// SDA pin: is GPIOB_1 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(2, GPIOF, GPIOF, 0, 1, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..92f732ec --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART2 // +/////////// + +// pin configuration for UART2 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOD +// TX pin: is GPIOD_5 +// RX pin: is GPIOD_6 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(2, GPIOD, GPIOD, 5, 6, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// initialization for UART2 +UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// un-initialization for UART2 +UART_UNINIT(2) + + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port for TX pin is: GPIOC +// port for RX pin is: GPIOC +// TX pin: is GPIOC_6 +// RX pin: is GPIOC_7 +// GPIO alternate pin function is 8 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(6, GPIOC, GPIOC, 6, 7, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; + +// initialization for UART6 +UART_INIT(6, UART6_TX_SIZE, UART6_RX_SIZE) + +// un-initialization for UART6 +UART_UNINIT(6) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..2c4f7c69 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART2 // +/////////// + +// enable USART2 +#define NF_SERIAL_COMM_STM32_UART_USE_USART2 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART2_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART2_RX_SIZE 256 + + +/////////// +// UART6 // +/////////// + +// enable USART6 +#define NF_SERIAL_COMM_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART6_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART6_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..f08c5650 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native_target.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/CMakeLists.txt new file mode 100644 index 00000000..8b8ab9b2 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/CMakeLists.txt @@ -0,0 +1,202 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F401xE_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F401xE_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F401xE_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F401xE_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x1000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x2800") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/README.md new file mode 100644 index 00000000..28532220 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/README.md @@ -0,0 +1,47 @@ +## ST of the shelve board ## + +The board used in this community contribution is the NUCLEO64_F401RE board from ST. The board can be purchased from various sources and should be about 20 euros. Further information on the Nucleo64 boards can be found in the user manual UM1724 on the ST side (www.st.com). The board used here is of revision c as can be found on the board's lower backside sticker. The board MB1136 C-02 is configured to use ST-LINK MCO as clock input for HSE so we have an HSE of 8 MHz. Plus X2 is mounted so we do have an LSE as well. This is reflected in the mcuconf.h in both nanoBooter and nanoCLR paths. If it is chosen to activate LSE as this is a for more accurate clock for RTC, the board.h file needs to be adjusted accordingly to use 32768 frequency for LSE. + +I prepared a custom made a 4-wire jumper to USB cable by cutting off one end (Type A part) and figuring out the required D+, D-, 5V and GND. These need to be connected as follows: + +USB V5 -> Can be ignored +USB GND -> GND on CN7 +USB D- -> PA11 on CN10 (outer row 7th pin from top) +USB D+ -> PA12 on CN10 (outer row 6th pin from top) + +Once these are connected and nanoFramework is flashed using the STM32 ST-LINK Utility the device should be visible in the Printf via SWO viewer function in the ST-LINK utility. Please set the frequency to match to what has been set in mcuconf.h (for the STM32F401RE it is 84MHz) and the Stimulus port to 0 and than hit start. If the board doesn't show then a reset (Black button on board) should do it. + +We can now fire up Visual Studio and view the Device explorer window the board should be visible there as well. Select the board (if not done already) and hit the device capabilities button. The board specifics can than be seen in the output window. + +Now you can start your adventure in the nanoFramework world and use one of the samples and adjust to the board specific features. Try to make a sample of yourself and publish it on f.e. www.hackster.io to show your achievement. + +For your convenience I've listed below the features and on what pins they can be found to help you out for an easy start. + +Arduino header pins: +==================== +D0 = COM2 RX +D1 = COM2 TX + +D2 - D9 can be used for an intermix of GPIO and PWM + +D14 = I2C1 SDA +D15 = I2C1 SCL + +A0 - A5 for Analog signal, please be aware the MCU has only one 12-bit ADC. + + +Connector CN7: +============== +1 = SPI3 SCK +2 = SPI3 MISO +3 = SPI3 MOSI + + +Connector CN10: +=============== +26 = SPI2 MOSI +28 = SPI2 MISO +30 = SPI2 SCK + + +**NOTE: This configuration was successfully tested on a NUCLEO64_F401RE board.** diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.c new file mode 100644 index 00000000..aece76d4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.h new file mode 100644 index 00000000..0ba7df63 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/board.h @@ -0,0 +1,1390 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#ifndef BOARD_H +#define BOARD_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* + * Setup for STMicroelectronics STM32 Nucleo64-F401RE board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_NUCLEO64_F401RE +#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-F401RE" + +/* + * USB OTG Force + */ +#define BOARD_OTG_NOVBUSSENS + +/* + * Completely wacko definition of a flash sector here + */ +#define FLASH_SECTOR_11 ((uint32_t)11U) + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +#define STM32_HSE_BYPASS + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F401xE + +/* + * IO pins assignments. + */ +#define GPIOA_ARD_A0 0U +#define GPIOA_ADC1_IN0 0U +#define GPIOA_ARD_A1 1U +#define GPIOA_ADC1_IN1 1U +#define GPIOA_ARD_D1 2U +#define GPIOA_USART2_TX 2U +#define GPIOA_ARD_D0 3U +#define GPIOA_USART2_RX 3U +#define GPIOA_ARD_A2 4U +#define GPIOA_ADC1_IN4 4U +#define GPIOA_LED_GREEN 5U +#define GPIOA_ARD_D13 5U +#define GPIOA_ARD_D12 6U +#define GPIOA_ARD_D11 7U +#define GPIOA_ARD_D7 8U +#define GPIOA_ARD_D8 9U +#define GPIOA_ARD_D2 10U +#define GPIOA_OTG_FS_DM 11U +#define GPIOA_OTG_FS_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_PIN15 15U + +#define GPIOB_ARD_A3 0U +#define GPIOB_ADC1_IN8 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_SWO 3U +#define GPIOB_ARD_D3 3U +#define GPIOB_ARD_D5 4U +#define GPIOB_ARD_D4 5U +#define GPIOB_ARD_D10 6U +#define GPIOB_PIN7 7U +#define GPIOB_ARD_D15 8U +#define GPIOB_ARD_D14 9U +#define GPIOB_ARD_D6 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_SPI2_SCK 13U +#define GPIOB_SPI2_MISO 14U +#define GPIOB_SPI2_MOSI 15U + +#define GPIOC_ARD_A5 0U +#define GPIOC_ADC1_IN10 0U +#define GPIOC_ARD_A4 1U +#define GPIOC_ADC1_IN11 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_ARD_D9 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_SPI3_SCK 10U +#define GPIOC_SPI3_MISO 11U +#define GPIOC_SPI3_MOSI 12U +#define GPIOC_BUTTON 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_PIN0 0U +#define GPIOF_PIN1 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U) +#define LINE_ADC1_IN0 PAL_LINE(GPIOA, 0U) +#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U) +#define LINE_ADC1_IN1 PAL_LINE(GPIOA, 1U) +#define LINE_ARD_D1 PAL_LINE(GPIOA, 2U) +#define LINE_USART2_TX PAL_LINE(GPIOA, 2U) +#define LINE_ARD_D0 PAL_LINE(GPIOA, 3U) +#define LINE_USART2_RX PAL_LINE(GPIOA, 3U) +#define LINE_ARD_A2 PAL_LINE(GPIOA, 4U) +#define LINE_ADC1_IN4 PAL_LINE(GPIOA, 4U) +#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U) +#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U) +#define LINE_ARD_D7 PAL_LINE(GPIOA, 8U) +#define LINE_ARD_D8 PAL_LINE(GPIOA, 9U) +#define LINE_ARD_D2 PAL_LINE(GPIOA, 10U) +#define LINE_OTG_FS_DM PAL_LINE(GPIOA, 11U) +#define LINE_OTG_FS_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) +#define LINE_ARD_A3 PAL_LINE(GPIOB, 0U) +#define LINE_ADC1_IN8 PAL_LINE(GPIOB, 0U) +#define LINE_SWO PAL_LINE(GPIOB, 3U) +#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U) +#define LINE_ARD_D5 PAL_LINE(GPIOB, 4U) +#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U) +#define LINE_ARD_D10 PAL_LINE(GPIOB, 6U) +#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U) +#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U) +#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U) +#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U) +#define LINE_ADC1_IN10 PAL_LINE(GPIOC, 0U) +#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U) +#define LINE_ADC1_IN11 PAL_LINE(GPIOC, 1U) +#define LINE_ARD_D9 PAL_LINE(GPIOC, 7U) +#define LINE_BUTTON PAL_LINE(GPIOC, 13U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - ARD_A0 ADC1_IN0 (input pullup). + * PA1 - ARD_A1 ADC1_IN1 (input pullup). + * PA2 - ARD_D1 USART2_TX (alternate 7). + * PA3 - ARD_D0 USART2_RX (alternate 7). + * PA4 - ARD_A2 ADC1_IN4 (input pullup). + * PA5 - LED_GREEN ARD_D13 (output pushpull high). + * PA6 - ARD_D12 (input pullup). + * PA7 - ARD_D11 (input pullup). + * PA8 - ARD_D7 (input pullup). + * PA9 - ARD_D8 (input pullup). + * PA10 - ARD_D2 (input pullup). + * PA11 - OTG_FS_DM (alternate 10). + * PA12 - OTG_FS_DP (alternate 10). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - PIN15 (input pullup). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ARD_A0) | \ + PIN_MODE_INPUT(GPIOA_ARD_A1) | \ + PIN_MODE_ALTERNATE(GPIOA_ARD_D1) | \ + PIN_MODE_ALTERNATE(GPIOA_ARD_D0) | \ + PIN_MODE_INPUT(GPIOA_ARD_A2) | \ + PIN_MODE_OUTPUT(GPIOA_LED_GREEN) | \ + PIN_MODE_INPUT(GPIOA_ARD_D12) | \ + PIN_MODE_INPUT(GPIOA_ARD_D11) | \ + PIN_MODE_INPUT(GPIOA_ARD_D7) | \ + PIN_MODE_INPUT(GPIOA_ARD_D8) | \ + PIN_MODE_INPUT(GPIOA_ARD_D2) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_LED_GREEN) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \ + PIN_OSPEED_MEDIUM(GPIOA_ARD_D1) | \ + PIN_OSPEED_MEDIUM(GPIOA_ARD_D0) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A2) | \ + PIN_OSPEED_MEDIUM(GPIOA_LED_GREEN) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D7) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D8) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D2) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A1) | \ + PIN_PUPDR_FLOATING(GPIOA_ARD_D1) | \ + PIN_PUPDR_FLOATING(GPIOA_ARD_D0) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A2) | \ + PIN_PUPDR_FLOATING(GPIOA_LED_GREEN) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D12) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D11) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D7) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D8) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D2) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | \ + PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \ + PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ARD_A0) | \ + PIN_ODR_HIGH(GPIOA_ARD_A1) | \ + PIN_ODR_HIGH(GPIOA_ARD_D1) | \ + PIN_ODR_HIGH(GPIOA_ARD_D0) | \ + PIN_ODR_HIGH(GPIOA_ARD_A2) | \ + PIN_ODR_LOW(GPIOA_LED_GREEN) | \ + PIN_ODR_HIGH(GPIOA_ARD_D12) | \ + PIN_ODR_HIGH(GPIOA_ARD_D11) | \ + PIN_ODR_HIGH(GPIOA_ARD_D7) | \ + PIN_ODR_HIGH(GPIOA_ARD_D8) | \ + PIN_ODR_HIGH(GPIOA_ARD_D2) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D1, 7U) | \ + PIN_AFIO_AF(GPIOA_ARD_D0, 7U) | \ + PIN_AFIO_AF(GPIOA_ARD_A2, 0U) | \ + PIN_AFIO_AF(GPIOA_LED_GREEN, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D11, 0U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_ARD_D7, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D8, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D2, 0U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0U)) + +/* + * GPIOB setup: + * + * PB0 - ARD_A3 ADC1_IN8 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - SWO ARD_D3 (alternate 0). + * PB4 - ARD_D5 (input pullup). + * PB5 - ARD_D4 (input pullup). + * PB6 - ARD_D10 (input pullup). + * PB7 - PIN7 (input pullup). + * PB8 - ARD_D15 (alternate 4). + * PB9 - ARD_D14 (alternate 4). + * PB10 - ARD_D6 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - SPI2_SCK (alternate 5). + * PB14 - SPI2_MISO (alternate 5). + * PB15 - SPI2_MOSI (alternate 5). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_ARD_A3) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_SWO) | \ + PIN_MODE_INPUT(GPIOB_ARD_D5) | \ + PIN_MODE_INPUT(GPIOB_ARD_D4) | \ + PIN_MODE_INPUT(GPIOB_ARD_D10) | \ + PIN_MODE_INPUT(GPIOB_PIN7) | \ + PIN_MODE_ALTERNATE(GPIOB_ARD_D15) | \ + PIN_MODE_ALTERNATE(GPIOB_ARD_D14) | \ + PIN_MODE_INPUT(GPIOB_ARD_D6) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_SCK) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_MISO) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ARD_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_ARD_D15) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_ARD_D14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ARD_A3) | \ + PIN_OSPEED_HIGH(GPIOB_PIN1) | \ + PIN_OSPEED_HIGH(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_SWO) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D5) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D4) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D10) | \ + PIN_OSPEED_HIGH(GPIOB_PIN7) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D15) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D14) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D6) | \ + PIN_OSPEED_HIGH(GPIOB_PIN11) | \ + PIN_OSPEED_HIGH(GPIOB_PIN12) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_SCK) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_MISO) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_ARD_A3) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOB_SWO) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D5) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D4) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOB_ARD_D15) | \ + PIN_PUPDR_FLOATING(GPIOB_ARD_D14) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D6) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_SCK) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_MISO) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_ARD_A3) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_SWO) | \ + PIN_ODR_HIGH(GPIOB_ARD_D5) | \ + PIN_ODR_HIGH(GPIOB_ARD_D4) | \ + PIN_ODR_HIGH(GPIOB_ARD_D10) | \ + PIN_ODR_HIGH(GPIOB_PIN7) | \ + PIN_ODR_LOW(GPIOB_ARD_D15) | \ + PIN_ODR_LOW(GPIOB_ARD_D14) | \ + PIN_ODR_HIGH(GPIOB_ARD_D6) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_LOW(GPIOB_SPI2_SCK) | \ + PIN_ODR_LOW(GPIOB_SPI2_MISO) | \ + PIN_ODR_LOW(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ARD_A3, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOB_SWO, 0U) | \ + PIN_AFIO_AF(GPIOB_ARD_D5, 0U) | \ + PIN_AFIO_AF(GPIOB_ARD_D4, 0U) | \ + PIN_AFIO_AF(GPIOB_ARD_D10, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 4U) | \ + PIN_AFIO_AF(GPIOB_ARD_D14, 4U) | \ + PIN_AFIO_AF(GPIOB_ARD_D6, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOB_SPI2_SCK, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI2_MISO, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI2_MOSI, 5U)) + +/* + * GPIOC setup: + * + * PC0 - ARD_A5 ADC1_IN10 (input pullup). + * PC1 - ARD_A4 ADC1_IN11 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - ARD_D9 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - SPI3_SCK (alternative 5). + * PC11 - SPI3_MISO (alternative 5). + * PC12 - SPI3_MOSI (alternative 5). + * PC13 - BUTTON (input floating). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ARD_A5) | \ + PIN_MODE_INPUT(GPIOC_ARD_A4) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_ARD_D9) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_SCK) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MISO) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MOSI) | \ + PIN_MODE_INPUT(GPIOC_BUTTON) | \ + PIN_MODE_INPUT(GPIOC_OSC32_IN) | \ + PIN_MODE_INPUT(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_D9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A5) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_A4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN2) | \ + PIN_OSPEED_HIGH(GPIOC_PIN3) | \ + PIN_OSPEED_HIGH(GPIOC_PIN4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN5) | \ + PIN_OSPEED_HIGH(GPIOC_PIN6) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_D9) | \ + PIN_OSPEED_HIGH(GPIOC_PIN8) | \ + PIN_OSPEED_HIGH(GPIOC_PIN9) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_SCK) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MISO) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MOSI) | \ + PIN_OSPEED_HIGH(GPIOC_BUTTON) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A5) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_D9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_SCK) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MISO) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A5) | \ + PIN_ODR_HIGH(GPIOC_ARD_A4) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_ARD_D9) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_LOW(GPIOC_SPI3_SCK) | \ + PIN_ODR_LOW(GPIOC_SPI3_MISO) | \ + PIN_ODR_LOW(GPIOC_SPI3_MOSI) | \ + PIN_ODR_HIGH(GPIOC_BUTTON) | \ + PIN_ODR_HIGH(GPIOC_OSC32_IN) | \ + PIN_ODR_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_D9, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOC_SPI3_SCK, 5U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MISO, 5U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MOSI, 5U) | \ + PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD10 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \ + PIN_OSPEED_HIGH(GPIOD_PIN1) | \ + PIN_OSPEED_HIGH(GPIOD_PIN2) | \ + PIN_OSPEED_HIGH(GPIOD_PIN3) | \ + PIN_OSPEED_HIGH(GPIOD_PIN4) | \ + PIN_OSPEED_HIGH(GPIOD_PIN5) | \ + PIN_OSPEED_HIGH(GPIOD_PIN6) | \ + PIN_OSPEED_HIGH(GPIOD_PIN7) | \ + PIN_OSPEED_HIGH(GPIOD_PIN8) | \ + PIN_OSPEED_HIGH(GPIOD_PIN9) | \ + PIN_OSPEED_HIGH(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_PIN11) | \ + PIN_OSPEED_HIGH(GPIOD_PIN12) | \ + PIN_OSPEED_HIGH(GPIOD_PIN13) | \ + PIN_OSPEED_HIGH(GPIOD_PIN14) | \ + PIN_OSPEED_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0U)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 (input pullup). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (input pullup). + * PE9 - PIN9 (input pullup). + * PE10 - PIN10 (input pullup). + * PE11 - PIN11 (input pullup). + * PE12 - PIN12 (input pullup). + * PE13 - PIN13 (input pullup). + * PE14 - PIN14 (input pullup). + * PE15 - PIN15 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) | \ + PIN_MODE_INPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) | \ + PIN_MODE_INPUT(GPIOE_PIN5) | \ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_INPUT(GPIOE_PIN8) | \ + PIN_MODE_INPUT(GPIOE_PIN9) | \ + PIN_MODE_INPUT(GPIOE_PIN10) | \ + PIN_MODE_INPUT(GPIOE_PIN11) | \ + PIN_MODE_INPUT(GPIOE_PIN12) | \ + PIN_MODE_INPUT(GPIOE_PIN13) | \ + PIN_MODE_INPUT(GPIOE_PIN14) | \ + PIN_MODE_INPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \ + PIN_OSPEED_HIGH(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_PIN2) | \ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_HIGH(GPIOE_PIN4) | \ + PIN_OSPEED_HIGH(GPIOE_PIN5) | \ + PIN_OSPEED_HIGH(GPIOE_PIN6) | \ + PIN_OSPEED_HIGH(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_HIGH(GPIOE_PIN8) | \ + PIN_ODR_HIGH(GPIOE_PIN9) | \ + PIN_ODR_HIGH(GPIOE_PIN10) | \ + PIN_ODR_HIGH(GPIOE_PIN11) | \ + PIN_ODR_HIGH(GPIOE_PIN12) | \ + PIN_ODR_HIGH(GPIOE_PIN13) | \ + PIN_ODR_HIGH(GPIOE_PIN14) | \ + PIN_ODR_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0U)) + +/* + * GPIOF setup: + * + * PF0 - PIN0 (input pullup). + * PF1 - PIN1 (input pullup). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \ + PIN_MODE_INPUT(GPIOF_PIN1) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_PIN0) | \ + PIN_OSPEED_HIGH(GPIOF_PIN1) | \ + PIN_OSPEED_HIGH(GPIOF_PIN2) | \ + PIN_OSPEED_HIGH(GPIOF_PIN3) | \ + PIN_OSPEED_HIGH(GPIOF_PIN4) | \ + PIN_OSPEED_HIGH(GPIOF_PIN5) | \ + PIN_OSPEED_HIGH(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_PIN7) | \ + PIN_OSPEED_HIGH(GPIOF_PIN8) | \ + PIN_OSPEED_HIGH(GPIOF_PIN9) | \ + PIN_OSPEED_HIGH(GPIOF_PIN10) | \ + PIN_OSPEED_HIGH(GPIOF_PIN11) | \ + PIN_OSPEED_HIGH(GPIOF_PIN12) | \ + PIN_OSPEED_HIGH(GPIOF_PIN13) | \ + PIN_OSPEED_HIGH(GPIOF_PIN14) | \ + PIN_OSPEED_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \ + PIN_ODR_HIGH(GPIOF_PIN1) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0U)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_HIGH(GPIOG_PIN0) | \ + PIN_OSPEED_HIGH(GPIOG_PIN1) | \ + PIN_OSPEED_HIGH(GPIOG_PIN2) | \ + PIN_OSPEED_HIGH(GPIOG_PIN3) | \ + PIN_OSPEED_HIGH(GPIOG_PIN4) | \ + PIN_OSPEED_HIGH(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_PIN6) | \ + PIN_OSPEED_HIGH(GPIOG_PIN7) | \ + PIN_OSPEED_HIGH(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_PIN9) | \ + PIN_OSPEED_HIGH(GPIOG_PIN10) | \ + PIN_OSPEED_HIGH(GPIOG_PIN11) | \ + PIN_OSPEED_HIGH(GPIOG_PIN12) | \ + PIN_OSPEED_HIGH(GPIOG_PIN13) | \ + PIN_OSPEED_HIGH(GPIOG_PIN14) | \ + PIN_OSPEED_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_HIGH(GPIOH_PIN2) | \ + PIN_OSPEED_HIGH(GPIOH_PIN3) | \ + PIN_OSPEED_HIGH(GPIOH_PIN4) | \ + PIN_OSPEED_HIGH(GPIOH_PIN5) | \ + PIN_OSPEED_HIGH(GPIOH_PIN6) | \ + PIN_OSPEED_HIGH(GPIOH_PIN7) | \ + PIN_OSPEED_HIGH(GPIOH_PIN8) | \ + PIN_OSPEED_HIGH(GPIOH_PIN9) | \ + PIN_OSPEED_HIGH(GPIOH_PIN10) | \ + PIN_OSPEED_HIGH(GPIOH_PIN11) | \ + PIN_OSPEED_HIGH(GPIOH_PIN12) | \ + PIN_OSPEED_HIGH(GPIOH_PIN13) | \ + PIN_OSPEED_HIGH(GPIOH_PIN14) | \ + PIN_OSPEED_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input pullup). + * PI1 - PIN1 (input pullup). + * PI2 - PIN2 (input pullup). + * PI3 - PIN3 (input pullup). + * PI4 - PIN4 (input pullup). + * PI5 - PIN5 (input pullup). + * PI6 - PIN6 (input pullup). + * PI7 - PIN7 (input pullup). + * PI8 - PIN8 (input pullup). + * PI9 - PIN9 (input pullup). + * PI10 - PIN10 (input pullup). + * PI11 - PIN11 (input pullup). + * PI12 - PIN12 (input pullup). + * PI13 - PIN13 (input pullup). + * PI14 - PIN14 (input pullup). + * PI15 - PIN15 (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_HIGH(GPIOI_PIN0) | \ + PIN_OSPEED_HIGH(GPIOI_PIN1) | \ + PIN_OSPEED_HIGH(GPIOI_PIN2) | \ + PIN_OSPEED_HIGH(GPIOI_PIN3) | \ + PIN_OSPEED_HIGH(GPIOI_PIN4) | \ + PIN_OSPEED_HIGH(GPIOI_PIN5) | \ + PIN_OSPEED_HIGH(GPIOI_PIN6) | \ + PIN_OSPEED_HIGH(GPIOI_PIN7) | \ + PIN_OSPEED_HIGH(GPIOI_PIN8) | \ + PIN_OSPEED_HIGH(GPIOI_PIN9) | \ + PIN_OSPEED_HIGH(GPIOI_PIN10) | \ + PIN_OSPEED_HIGH(GPIOI_PIN11) | \ + PIN_OSPEED_HIGH(GPIOI_PIN12) | \ + PIN_OSPEED_HIGH(GPIOI_PIN13) | \ + PIN_OSPEED_HIGH(GPIOI_PIN14) | \ + PIN_OSPEED_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/CMakeLists.txt new file mode 100644 index 00000000..42be0d5f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..0e822535 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 08008000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +//384kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 5 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 6, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00080000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage.c new file mode 100644 index 00000000..6e381213 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/Device_BlockStorage.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 08004000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +//384kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 5 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 6, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00080000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/serialcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/serialcfg.h new file mode 100644 index 00000000..bb32facc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/common/serialcfg.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef SERIALCFG_H +#define SERIALCFG_H + +// define which serial driver the Wire Protocol will be using +#define SERIAL_DRIVER SD2 + +#endif /* SERIALCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/README.md new file mode 100644 index 00000000..604b1bc1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](ST_NUCLEO64_F401RE.Adc.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/ST_NUCLEO64_F401RE.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/ST_NUCLEO64_F401RE.Adc.cs new file mode 100644 index 00000000..1ef0c990 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/managed_helpers/ST_NUCLEO64_F401RE.Adc.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.ST_NUCLEO64_F401RE +{ + /// + /// Enumeration of ADC channels available on ST_NUCLEO64_F401RE + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed as A0, connected to pin 1 on CN8 = PA0 (ADC1 - IN0) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed as A1, connected to pin 2 on CN8 = PA1 (ADC1 - IN1) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed as A2, connected to pin 3 on CN8 = PA4 (ADC1 - IN4) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, exposed as A3, connected to pin 4 on CN8 = PB0 (ADC1 - IN8) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, exposed as A4, connected to pin 5 on CN8 = PC1 (ADC1 - IN11) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, exposed on A5, connected to pin 6 on CN8 = PC0 (ADC1 - IN10) + /// + public const int Channel_5 = 5; + + /// + /// Channel 6, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 6; + + /// + /// Channel 7, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 7; + + /// + /// Channel 8, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 8; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter-DEBUG.ld new file mode 100644 index 00000000..d5010ba4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F401xE memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08007FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 96k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter.ld new file mode 100644 index 00000000..80074fed --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/STM32F401xE_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F401xE memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08003FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 96k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/chconf.h new file mode 100644 index 00000000..335e3fa4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf.h new file mode 100644 index 00000000..bb163e41 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/main.c new file mode 100644 index 00000000..78a16f43 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/main.c @@ -0,0 +1,73 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + if (palReadPad(GPIOC, GPIOC_BUTTON)) + { + // check for valid CLR image + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + palClearPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf.h new file mode 100644 index 00000000..1566db9f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf.h @@ -0,0 +1,338 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F401_MCUCONF + +/* + * HAL driver system settings. + */ + +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 4 +#define STM32_PLLQ_VALUE 7 + +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR-DEBUG.ld new file mode 100644 index 00000000..2223b481 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F401xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 512k - 32k - 256k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 96k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR.ld new file mode 100644 index 00000000..c93b2d95 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/STM32F401xE_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F401xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 512k - 16k - 256k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 96k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/chconf.h new file mode 100644 index 00000000..3ce5c5aa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/chconf.h @@ -0,0 +1,621 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// address of vector table for nanoCLR +#define CORTEX_VTOR_INIT 0x08008000U +/////////////////////////////////////////////////////////////////////////////// + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf.h new file mode 100644 index 00000000..cdf9edad --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf.h @@ -0,0 +1,525 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..c9800ae9 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/halconf_nf.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +// Disables the FSMC subsystem. +#if !defined(HAL_USE_FSMC) +#define HAL_USE_FSMC FALSE +#endif + +// STM32F401xx Does not support TRNG +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/main.c new file mode 100644 index 00000000..ca082290 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/main.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf.h new file mode 100644 index 00000000..3a2d2f88 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf.h @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F401_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 4 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 TRUE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.h.in new file mode 100644 index 00000000..99c1458e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00018000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00080000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..3f13d18c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_nf_devices_onewire_config.h" +#include + +/////////// +// UART1 // +/////////// + +// pin configuration for UART1 +// port for TX pin is: GPIOA_9 +// port for RX pin is: GPIOB_7 +// GPIO alternate pin function is 7 (see "Table 9. Alternate function mapping" in STM32F401RE datasheet) +UART_CONFIG_PINS(1, GPIOA, 9, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_TxBuffer[UART1_TX_SIZE]; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_RxBuffer[UART1_RX_SIZE]; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..1c16444d --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_nf_devices_onewire_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART1 // +/////////// + +// enable USART1 +#define NF_ONEWIRE_STM32_UART_USE_USART1 TRUE + +// buffers size +// tx buffer size: 32 bytes +#define UART1_TX_SIZE 32 +// rx buffer size: 32 bytes +#define UART1_RX_SIZE 32 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..0e68d91b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_adc_config.cpp @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 0, ADC_CHANNEL_IN0}, + {1, GPIOA, 1, ADC_CHANNEL_IN1}, + {1, GPIOA, 4, ADC_CHANNEL_IN4}, + {1, GPIOB, 0, ADC_CHANNEL_IN8}, + {1, GPIOC, 1, ADC_CHANNEL_IN11}, + {1, GPIOC, 0, ADC_CHANNEL_IN10}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2a60a22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..d117a945 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port: GPIOA +// TX pin: is GPIOA_11 +// RX pin: is GPIOA_12 +// GPIO alternate pin function is 8 (see "Table 9. Alternate function mapping" in STM32F401xC and STM32F401xE datasheet) +UART_CONFIG_PINS(6, GPIOA, GPIOA, 11, 12, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; + +// initialization for UART6 +UART_INIT(6, UART6_TX_SIZE, UART6_RX_SIZE) + +// un-initialization for UART6 +UART_UNINIT(6) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..d554e12c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +/////////// +// UART6 // +/////////// + +// enable USART6 +#define NF_SERIAL_COMM_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART6_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART6_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..ef2d3a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/CMakeLists.txt new file mode 100644 index 00000000..6668c291 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/CMakeLists.txt @@ -0,0 +1,202 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F411xE_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F411xE_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F411xE_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F411xE_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x1000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x2800") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/README.md new file mode 100644 index 00000000..cf99709d --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/README.md @@ -0,0 +1,45 @@ +## ST of the shelve board ## + +The board used in this community contribution is the NUCLEO64_F411RE board from ST. The board can be purchased from various sources and should be about 20 euros. Further information on the Nucleo64 boards can be found in the user manual UM1724 on the ST side (www.st.com). The board used here is of revision c as can be found on the board's lower backside sticker. The board MB1136 C-02 is configured to use ST-LINK MCO as clock input for HSE so we have an HSE of 8 MHz. Plus X2 is mounted we do have an LSE as well. This is reflected in the mcuconf.h in both nanoBooter and nanoCLR paths. If it is chosen to activate LSE as this is a for more accurate clock for RTC the board.h file needs to be adjusted accordingly to use 32768 frequency for LSE. + +I prepared a custom made a 4-wire jumper to USB cable by cutting off one end (Type A part) and figuring out the required D+, D-, 5V and GND. These need to be connected as follows: + +USB V5 -> Can be ignored +USB GND -> GND on CN7 +USB D- -> PA11 on CN10 (outer row 7th pin from top) +USB D+ -> PA12 on CN10 (outer row 6th pin from top) + +Once these are connected and nanoFramework is flashed using the STM32 ST-LINK Utility the device should be visible in the Printf via SWO viewer function in the ST-LINK utility. Please set the frequency to match to what has been set in mcuconf.h (mostly 96000000) and the Stimulus port to 0 and than hit start. If the board doesn't show then a reset (Black button on board) should do it. + +We can now fire up Visual Studio and view the Device explorer window the board should be visible there as well. Select the board (if not done already) and hit the device capabilities button. The board specifics can than be seen in the output window. + +Now you can start your adventure in the nanoFramework world and use one of the samples and adjust to the board specific features. Try to make a sample of yourself and publish it on f.e. www.hackster.io to show your achievement. + +For your convenience I've listed below the features and on what pins they can be found to help you out for an easy start. + +Arduino header pins: +==================== +D0 = COM2 RX +D1 = COM2 TX + +D2 - D9 can be used for an intermix of GPIO and PWM + +D14 = I2C1 SDA +D15 = I2C1 SCL + + +Connector CN7: +============== +1 = SPI3 SCK +2 = SPI3 MISO +3 = SPI3 MOSI + + +Connector CN10: +=============== +26 = SPI2 MOSI +28 = SPI2 MISO +30 = SPI2 SCK + + +**NOTE: This configuration was successfully tested on a NUCLEO64_F411RE board.** diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.c new file mode 100644 index 00000000..aece76d4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.h new file mode 100644 index 00000000..4f85a0e5 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/board.h @@ -0,0 +1,1375 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#ifndef BOARD_H +#define BOARD_H + +/* + * Setup for STMicroelectronics STM32 Nucleo64-F411RE board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_NUCLEO64_F411RE_NF +#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-F411RE for nanoFramework" + +/* + * USB OTG Force + */ +#define BOARD_OTG_NOVBUSSENS + +/* + * Completely wacko definition of a flash sector here + */ +#define FLASH_SECTOR_11 ((uint32_t)11U) + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +//#define STM32_HSE_BYPASS + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F411xE + +/* + * IO pins assignments. + */ +#define GPIOA_ARD_A0 0U +#define GPIOA_ADC1_IN0 0U +#define GPIOA_ARD_A1 1U +#define GPIOA_ADC1_IN1 1U +#define GPIOA_ARD_D1 2U +#define GPIOA_USART2_TX 2U +#define GPIOA_ARD_D0 3U +#define GPIOA_USART2_RX 3U +#define GPIOA_ARD_A2 4U +#define GPIOA_ADC1_IN4 4U +#define GPIOA_LED_GREEN 5U +#define GPIOA_ARD_D13 5U +#define GPIOA_ARD_D12 6U +#define GPIOA_ARD_D11 7U +#define GPIOA_ARD_D7 8U +#define GPIOA_ARD_D8 9U +#define GPIOA_ARD_D2 10U +#define GPIOA_OTG_FS_DM 11U +#define GPIOA_OTG_FS_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_PIN15 15U + +#define GPIOB_ARD_A3 0U +#define GPIOB_ADC1_IN8 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_SWO 3U +#define GPIOB_ARD_D3 3U +#define GPIOB_ARD_D5 4U +#define GPIOB_ARD_D4 5U +#define GPIOB_ARD_D10 6U +#define GPIOB_PIN7 7U +#define GPIOB_ARD_D15 8U +#define GPIOB_ARD_D14 9U +#define GPIOB_ARD_D6 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_SPI2_SCK 13U +#define GPIOB_SPI2_MISO 14U +#define GPIOB_SPI2_MOSI 15U + +#define GPIOC_ARD_A5 0U +#define GPIOC_ADC1_IN10 0U +#define GPIOC_ARD_A4 1U +#define GPIOC_ADC1_IN11 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_ARD_D9 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_SPI3_SCK 10U +#define GPIOC_SPI3_MISO 11U +#define GPIOC_SPI3_MOSI 12U +#define GPIOC_BUTTON 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_PIN0 0U +#define GPIOF_PIN1 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U) +#define LINE_ADC1_IN0 PAL_LINE(GPIOA, 0U) +#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U) +#define LINE_ADC1_IN1 PAL_LINE(GPIOA, 1U) +#define LINE_ARD_D1 PAL_LINE(GPIOA, 2U) +#define LINE_USART2_TX PAL_LINE(GPIOA, 2U) +#define LINE_ARD_D0 PAL_LINE(GPIOA, 3U) +#define LINE_USART2_RX PAL_LINE(GPIOA, 3U) +#define LINE_ARD_A2 PAL_LINE(GPIOA, 4U) +#define LINE_ADC1_IN4 PAL_LINE(GPIOA, 4U) +#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U) +#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U) +#define LINE_ARD_D7 PAL_LINE(GPIOA, 8U) +#define LINE_ARD_D8 PAL_LINE(GPIOA, 9U) +#define LINE_ARD_D2 PAL_LINE(GPIOA, 10U) +#define LINE_OTG_FS_DM PAL_LINE(GPIOA, 11U) +#define LINE_OTG_FS_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) + +#define LINE_ARD_A3 PAL_LINE(GPIOB, 0U) +#define LINE_ADC1_IN8 PAL_LINE(GPIOB, 0U) +#define LINE_SWO PAL_LINE(GPIOB, 3U) +#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U) +#define LINE_ARD_D5 PAL_LINE(GPIOB, 4U) +#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U) +#define LINE_ARD_D10 PAL_LINE(GPIOB, 6U) +#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U) +#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U) +#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U) + +#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U) +#define LINE_ADC1_IN10 PAL_LINE(GPIOC, 0U) +#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U) +#define LINE_ADC1_IN11 PAL_LINE(GPIOC, 1U) +#define LINE_ARD_D9 PAL_LINE(GPIOC, 7U) +#define LINE_BUTTON PAL_LINE(GPIOC, 13U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) + + + + + +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - ARD_A0 ADC1_IN0 (input pullup). + * PA1 - ARD_A1 ADC1_IN1 (input pullup). + * PA2 - ARD_D1 USART2_TX (alternate 7). + * PA3 - ARD_D0 USART2_RX (alternate 7). + * PA4 - ARD_A2 ADC1_IN4 (input pullup). + * PA5 - LED_GREEN ARD_D13 (output pushpull high). + * PA6 - ARD_D12 (input pullup). + * PA7 - ARD_D11 (input pullup). + * PA8 - ARD_D7 (input pullup). + * PA9 - ARD_D8 (input pullup). + * PA10 - ARD_D2 (input pullup). + * PA11 - OTG_FS_DM (alternate 10). + * PA12 - OTG_FS_DP (alternate 10). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - PIN15 (input pullup). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ARD_A0) | \ + PIN_MODE_INPUT(GPIOA_ARD_A1) | \ + PIN_MODE_ALTERNATE(GPIOA_ARD_D1) | \ + PIN_MODE_ALTERNATE(GPIOA_ARD_D0) | \ + PIN_MODE_INPUT(GPIOA_ARD_A2) | \ + PIN_MODE_OUTPUT(GPIOA_LED_GREEN) | \ + PIN_MODE_INPUT(GPIOA_ARD_D12) | \ + PIN_MODE_INPUT(GPIOA_ARD_D11) | \ + PIN_MODE_INPUT(GPIOA_ARD_D7) | \ + PIN_MODE_INPUT(GPIOA_ARD_D8) | \ + PIN_MODE_INPUT(GPIOA_ARD_D2) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_LED_GREEN) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \ + PIN_OSPEED_MEDIUM(GPIOA_ARD_D1) | \ + PIN_OSPEED_MEDIUM(GPIOA_ARD_D0) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A2) | \ + PIN_OSPEED_MEDIUM(GPIOA_LED_GREEN) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D7) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D8) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D2) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A1) | \ + PIN_PUPDR_FLOATING(GPIOA_ARD_D1) | \ + PIN_PUPDR_FLOATING(GPIOA_ARD_D0) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A2) | \ + PIN_PUPDR_FLOATING(GPIOA_LED_GREEN) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D12) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D11) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D7) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D8) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D2) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | \ + PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \ + PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ARD_A0) | \ + PIN_ODR_HIGH(GPIOA_ARD_A1) | \ + PIN_ODR_HIGH(GPIOA_ARD_D1) | \ + PIN_ODR_HIGH(GPIOA_ARD_D0) | \ + PIN_ODR_HIGH(GPIOA_ARD_A2) | \ + PIN_ODR_LOW(GPIOA_LED_GREEN) | \ + PIN_ODR_HIGH(GPIOA_ARD_D12) | \ + PIN_ODR_HIGH(GPIOA_ARD_D11) | \ + PIN_ODR_HIGH(GPIOA_ARD_D7) | \ + PIN_ODR_HIGH(GPIOA_ARD_D8) | \ + PIN_ODR_HIGH(GPIOA_ARD_D2) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D1, 7U) | \ + PIN_AFIO_AF(GPIOA_ARD_D0, 7U) | \ + PIN_AFIO_AF(GPIOA_ARD_A2, 0U) | \ + PIN_AFIO_AF(GPIOA_LED_GREEN, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D11, 0U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_ARD_D7, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D8, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D2, 0U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0U)) + +/* + * GPIOB setup: + * + * PB0 - ARD_A3 ADC1_IN8 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - SWO ARD_D3 (alternate 0). + * PB4 - ARD_D5 (input pullup). + * PB5 - ARD_D4 (input pullup). + * PB6 - ARD_D10 (input pullup). + * PB7 - PIN7 (input pullup). + * PB8 - ARD_D15 (alternate 4). + * PB9 - ARD_D14 (alternate 4). + * PB10 - ARD_D6 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - SPI2_SCK (alternate 5). + * PB14 - SPI2_MISO (alternate 5). + * PB15 - SPI2_MOSI (alternate 5). + */ +#define VAL_GPIOB_MODER (PIN_MODE_ANALOG(GPIOB_ARD_A3) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_SWO) | \ + PIN_MODE_INPUT(GPIOB_ARD_D5) | \ + PIN_MODE_INPUT(GPIOB_ARD_D4) | \ + PIN_MODE_INPUT(GPIOB_ARD_D10) | \ + PIN_MODE_INPUT(GPIOB_PIN7) | \ + PIN_MODE_ALTERNATE(GPIOB_ARD_D15) | \ + PIN_MODE_ALTERNATE(GPIOB_ARD_D14) | \ + PIN_MODE_INPUT(GPIOB_ARD_D6) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_SCK) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_MISO) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ARD_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_ARD_D15) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_ARD_D14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ARD_A3) | \ + PIN_OSPEED_HIGH(GPIOB_PIN1) | \ + PIN_OSPEED_HIGH(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_SWO) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D5) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D4) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D10) | \ + PIN_OSPEED_HIGH(GPIOB_PIN7) | \ + PIN_OSPEED_MEDIUM(GPIOB_ARD_D15) | \ + PIN_OSPEED_MEDIUM(GPIOB_ARD_D14) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D6) | \ + PIN_OSPEED_HIGH(GPIOB_PIN11) | \ + PIN_OSPEED_HIGH(GPIOB_PIN12) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_SCK) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_MISO) | \ + PIN_OSPEED_HIGH(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_ARD_A3) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOB_SWO) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D5) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D4) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOB_ARD_D15) | \ + PIN_PUPDR_FLOATING(GPIOB_ARD_D14) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D6) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_SCK) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_MISO) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_ARD_A3) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_SWO) | \ + PIN_ODR_HIGH(GPIOB_ARD_D5) | \ + PIN_ODR_HIGH(GPIOB_ARD_D4) | \ + PIN_ODR_HIGH(GPIOB_ARD_D10) | \ + PIN_ODR_HIGH(GPIOB_PIN7) | \ + PIN_ODR_HIGH(GPIOB_ARD_D15) | \ + PIN_ODR_HIGH(GPIOB_ARD_D14) | \ + PIN_ODR_HIGH(GPIOB_ARD_D6) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_LOW(GPIOB_SPI2_SCK) | \ + PIN_ODR_LOW(GPIOB_SPI2_MISO) | \ + PIN_ODR_LOW(GPIOB_SPI2_MOSI)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ARD_A3, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOB_SWO, 0U) | \ + PIN_AFIO_AF(GPIOB_ARD_D5, 0U) | \ + PIN_AFIO_AF(GPIOB_ARD_D4, 0U) | \ + PIN_AFIO_AF(GPIOB_ARD_D10, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 4U) | \ + PIN_AFIO_AF(GPIOB_ARD_D14, 4U) | \ + PIN_AFIO_AF(GPIOB_ARD_D6, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOB_SPI2_SCK, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI2_MISO, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI2_MOSI, 5U)) + +/* + * GPIOC setup: + * + * PC0 - ARD_A5 ADC1_IN10 (input pullup). + * PC1 - ARD_A4 ADC1_IN11 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - ARD_D9 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - SPI3_SCK (alternate 5). + * PC11 - SPI3_MISO (alternate 5). + * PC12 - SPI3_MOSI (alternate 5). + * PC13 - BUTTON (input floating). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_ANALOG(GPIOC_ARD_A5) | \ + PIN_MODE_ANALOG(GPIOC_ARD_A4) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_ARD_D9) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_SCK) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MISO) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MOSI) | \ + PIN_MODE_INPUT(GPIOC_BUTTON) | \ + PIN_MODE_INPUT(GPIOC_OSC32_IN) | \ + PIN_MODE_INPUT(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_D9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A5) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_A4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN2) | \ + PIN_OSPEED_HIGH(GPIOC_PIN3) | \ + PIN_OSPEED_HIGH(GPIOC_PIN4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN5) | \ + PIN_OSPEED_HIGH(GPIOC_PIN6) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_D9) | \ + PIN_OSPEED_HIGH(GPIOC_PIN8) | \ + PIN_OSPEED_HIGH(GPIOC_PIN9) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_SCK) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MISO) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MOSI) | \ + PIN_OSPEED_HIGH(GPIOC_BUTTON) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A5) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_D9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_SCK) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MISO) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A5) | \ + PIN_ODR_HIGH(GPIOC_ARD_A4) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_ARD_D9) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_LOW(GPIOC_SPI3_SCK) | \ + PIN_ODR_LOW(GPIOC_SPI3_MISO) | \ + PIN_ODR_LOW(GPIOC_SPI3_MOSI) | \ + PIN_ODR_HIGH(GPIOC_BUTTON) | \ + PIN_ODR_HIGH(GPIOC_OSC32_IN) | \ + PIN_ODR_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_D9, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOC_SPI3_SCK, 5U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MISO, 5U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MOSI, 5U) | \ + PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD10 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \ + PIN_OSPEED_HIGH(GPIOD_PIN1) | \ + PIN_OSPEED_HIGH(GPIOD_PIN2) | \ + PIN_OSPEED_HIGH(GPIOD_PIN3) | \ + PIN_OSPEED_HIGH(GPIOD_PIN4) | \ + PIN_OSPEED_HIGH(GPIOD_PIN5) | \ + PIN_OSPEED_HIGH(GPIOD_PIN6) | \ + PIN_OSPEED_HIGH(GPIOD_PIN7) | \ + PIN_OSPEED_HIGH(GPIOD_PIN8) | \ + PIN_OSPEED_HIGH(GPIOD_PIN9) | \ + PIN_OSPEED_HIGH(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_PIN11) | \ + PIN_OSPEED_HIGH(GPIOD_PIN12) | \ + PIN_OSPEED_HIGH(GPIOD_PIN13) | \ + PIN_OSPEED_HIGH(GPIOD_PIN14) | \ + PIN_OSPEED_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0U)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 (input pullup). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (input pullup). + * PE9 - PIN9 (input pullup). + * PE10 - PIN10 (input pullup). + * PE11 - PIN11 (input pullup). + * PE12 - PIN12 (input pullup). + * PE13 - PIN13 (input pullup). + * PE14 - PIN14 (input pullup). + * PE15 - PIN15 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) | \ + PIN_MODE_INPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) | \ + PIN_MODE_INPUT(GPIOE_PIN5) | \ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_INPUT(GPIOE_PIN8) | \ + PIN_MODE_INPUT(GPIOE_PIN9) | \ + PIN_MODE_INPUT(GPIOE_PIN10) | \ + PIN_MODE_INPUT(GPIOE_PIN11) | \ + PIN_MODE_INPUT(GPIOE_PIN12) | \ + PIN_MODE_INPUT(GPIOE_PIN13) | \ + PIN_MODE_INPUT(GPIOE_PIN14) | \ + PIN_MODE_INPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \ + PIN_OSPEED_HIGH(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_PIN2) | \ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_HIGH(GPIOE_PIN4) | \ + PIN_OSPEED_HIGH(GPIOE_PIN5) | \ + PIN_OSPEED_HIGH(GPIOE_PIN6) | \ + PIN_OSPEED_HIGH(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_HIGH(GPIOE_PIN8) | \ + PIN_ODR_HIGH(GPIOE_PIN9) | \ + PIN_ODR_HIGH(GPIOE_PIN10) | \ + PIN_ODR_HIGH(GPIOE_PIN11) | \ + PIN_ODR_HIGH(GPIOE_PIN12) | \ + PIN_ODR_HIGH(GPIOE_PIN13) | \ + PIN_ODR_HIGH(GPIOE_PIN14) | \ + PIN_ODR_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0U)) + +/* + * GPIOF setup: + * + * PF0 - PIN0 (input pullup). + * PF1 - PIN1 (input pullup). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \ + PIN_MODE_INPUT(GPIOF_PIN1) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_PIN0) | \ + PIN_OSPEED_HIGH(GPIOF_PIN1) | \ + PIN_OSPEED_HIGH(GPIOF_PIN2) | \ + PIN_OSPEED_HIGH(GPIOF_PIN3) | \ + PIN_OSPEED_HIGH(GPIOF_PIN4) | \ + PIN_OSPEED_HIGH(GPIOF_PIN5) | \ + PIN_OSPEED_HIGH(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_PIN7) | \ + PIN_OSPEED_HIGH(GPIOF_PIN8) | \ + PIN_OSPEED_HIGH(GPIOF_PIN9) | \ + PIN_OSPEED_HIGH(GPIOF_PIN10) | \ + PIN_OSPEED_HIGH(GPIOF_PIN11) | \ + PIN_OSPEED_HIGH(GPIOF_PIN12) | \ + PIN_OSPEED_HIGH(GPIOF_PIN13) | \ + PIN_OSPEED_HIGH(GPIOF_PIN14) | \ + PIN_OSPEED_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \ + PIN_ODR_HIGH(GPIOF_PIN1) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0U)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_HIGH(GPIOG_PIN0) | \ + PIN_OSPEED_HIGH(GPIOG_PIN1) | \ + PIN_OSPEED_HIGH(GPIOG_PIN2) | \ + PIN_OSPEED_HIGH(GPIOG_PIN3) | \ + PIN_OSPEED_HIGH(GPIOG_PIN4) | \ + PIN_OSPEED_HIGH(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_PIN6) | \ + PIN_OSPEED_HIGH(GPIOG_PIN7) | \ + PIN_OSPEED_HIGH(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_PIN9) | \ + PIN_OSPEED_HIGH(GPIOG_PIN10) | \ + PIN_OSPEED_HIGH(GPIOG_PIN11) | \ + PIN_OSPEED_HIGH(GPIOG_PIN12) | \ + PIN_OSPEED_HIGH(GPIOG_PIN13) | \ + PIN_OSPEED_HIGH(GPIOG_PIN14) | \ + PIN_OSPEED_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_HIGH(GPIOH_PIN2) | \ + PIN_OSPEED_HIGH(GPIOH_PIN3) | \ + PIN_OSPEED_HIGH(GPIOH_PIN4) | \ + PIN_OSPEED_HIGH(GPIOH_PIN5) | \ + PIN_OSPEED_HIGH(GPIOH_PIN6) | \ + PIN_OSPEED_HIGH(GPIOH_PIN7) | \ + PIN_OSPEED_HIGH(GPIOH_PIN8) | \ + PIN_OSPEED_HIGH(GPIOH_PIN9) | \ + PIN_OSPEED_HIGH(GPIOH_PIN10) | \ + PIN_OSPEED_HIGH(GPIOH_PIN11) | \ + PIN_OSPEED_HIGH(GPIOH_PIN12) | \ + PIN_OSPEED_HIGH(GPIOH_PIN13) | \ + PIN_OSPEED_HIGH(GPIOH_PIN14) | \ + PIN_OSPEED_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input pullup). + * PI1 - PIN1 (input pullup). + * PI2 - PIN2 (input pullup). + * PI3 - PIN3 (input pullup). + * PI4 - PIN4 (input pullup). + * PI5 - PIN5 (input pullup). + * PI6 - PIN6 (input pullup). + * PI7 - PIN7 (input pullup). + * PI8 - PIN8 (input pullup). + * PI9 - PIN9 (input pullup). + * PI10 - PIN10 (input pullup). + * PI11 - PIN11 (input pullup). + * PI12 - PIN12 (input pullup). + * PI13 - PIN13 (input pullup). + * PI14 - PIN14 (input pullup). + * PI15 - PIN15 (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_HIGH(GPIOI_PIN0) | \ + PIN_OSPEED_HIGH(GPIOI_PIN1) | \ + PIN_OSPEED_HIGH(GPIOI_PIN2) | \ + PIN_OSPEED_HIGH(GPIOI_PIN3) | \ + PIN_OSPEED_HIGH(GPIOI_PIN4) | \ + PIN_OSPEED_HIGH(GPIOI_PIN5) | \ + PIN_OSPEED_HIGH(GPIOI_PIN6) | \ + PIN_OSPEED_HIGH(GPIOI_PIN7) | \ + PIN_OSPEED_HIGH(GPIOI_PIN8) | \ + PIN_OSPEED_HIGH(GPIOI_PIN9) | \ + PIN_OSPEED_HIGH(GPIOI_PIN10) | \ + PIN_OSPEED_HIGH(GPIOI_PIN11) | \ + PIN_OSPEED_HIGH(GPIOI_PIN12) | \ + PIN_OSPEED_HIGH(GPIOI_PIN13) | \ + PIN_OSPEED_HIGH(GPIOI_PIN14) | \ + PIN_OSPEED_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/CMakeLists.txt new file mode 100644 index 00000000..42be0d5f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..0e822535 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 08008000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +//384kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 5 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 6, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00080000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage.c new file mode 100644 index 00000000..6e381213 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/Device_BlockStorage.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 08004000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08010000 nanoCLR +}; + +//384kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 5 } // 08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 6, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00080000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/serialcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/serialcfg.h new file mode 100644 index 00000000..bb32facc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/common/serialcfg.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef SERIALCFG_H +#define SERIALCFG_H + +// define which serial driver the Wire Protocol will be using +#define SERIAL_DRIVER SD2 + +#endif /* SERIALCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/README.md new file mode 100644 index 00000000..57c6e269 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](ST_NUCLEO64_F411RE_NF.Adc.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/ST_NUCLEO64_F411RE_NF.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/ST_NUCLEO64_F411RE_NF.Adc.cs new file mode 100644 index 00000000..f01b85ff --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/managed_helpers/ST_NUCLEO64_F411RE_NF.Adc.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.ST_NUCLEO64_F411RE_NF +{ + /// + /// Enumeration of ADC channels available on ST_NUCLEO64_F411RE_NF + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed as A0, connected to pin 1 on CN8 = PA0 (ADC1 - IN0) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed as A1, connected to pin 2 on CN8 = PA1 (ADC1 - IN1) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed as A2, connected to pin 3 on CN8 = PA4 (ADC1 - IN4) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, exposed as A3, connected to pin 4 on CN8 = PB0 (ADC1 - IN8) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, exposed as A4, connected to pin 5 on CN8 = PC1 (ADC1 - IN11) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, exposed on A5, connected to pin 6 on CN8 = PC0 (ADC1 - IN10) + /// + public const int Channel_5 = 5; + + /// + /// Channel 6, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 6; + + /// + /// Channel 7, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 7; + + /// + /// Channel 8, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 8; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld new file mode 100644 index 00000000..5c5bde44 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08008000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter.ld new file mode 100644 index 00000000..33f45204 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/STM32F411xE_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017..2019 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08004000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/chconf.h new file mode 100644 index 00000000..335e3fa4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf.h new file mode 100644 index 00000000..bb163e41 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/main.c new file mode 100644 index 00000000..2df0f094 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/main.c @@ -0,0 +1,73 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + if (palReadPad(GPIOC, GPIOC_BUTTON)) + { + // check for valid CLR image + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + palClearPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf.h new file mode 100644 index 00000000..692d8d1e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf.h @@ -0,0 +1,337 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F411_MCUCONF +/* + * HAL driver system settings. + */ + +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 192 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 4 + +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld new file mode 100644 index 00000000..674ee9b4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 512k - 32k - 256k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR.ld new file mode 100644 index 00000000..6b1d2747 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/STM32F411xE_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017..2019 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F411xE memory setup. + * Note: Only use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 512k - 16k - 256k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 256k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/chconf.h new file mode 100644 index 00000000..3ce5c5aa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/chconf.h @@ -0,0 +1,621 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +/////////////////////////////////////////////////////////////////////////////// +// address of vector table for nanoCLR +#define CORTEX_VTOR_INIT 0x08008000U +/////////////////////////////////////////////////////////////////////////////// + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf.h new file mode 100644 index 00000000..43e74c29 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf.h @@ -0,0 +1,525 @@ +// +// Copyright (c) 2017..2019 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..2cf04ece --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/halconf_nf.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +// Disables the FSMC subsystem. +#if !defined(HAL_USE_FSMC) +#define HAL_USE_FSMC FALSE +#endif + +// STM32F411xx Does not support TRNG +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/main.c new file mode 100644 index 00000000..58ebf66f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/main.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf.h new file mode 100644 index 00000000..1b4c6b57 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf.h @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F411_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 192 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 4 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 TRUE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.h.in new file mode 100644 index 00000000..419f9f35 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00020000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00080000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..8fddb9a0 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_adc_config.cpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 0, ADC_CHANNEL_IN0}, + {1, GPIOA, 1, ADC_CHANNEL_IN1}, + {1, GPIOA, 4, ADC_CHANNEL_IN4}, + {1, GPIOB, 0, ADC_CHANNEL_IN8}, + {1, GPIOC, 1, ADC_CHANNEL_IN11}, + {1, GPIOC, 0, ADC_CHANNEL_IN10}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2a60a22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..fbfef7b4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port: GPIOA +// TX pin: is GPIOA_11 +// RX pin: is GPIOA_12 +// GPIO alternate pin function is 7 (see "Table 9. Alternate function mapping" in STM32F411xC and STM32F411xE datasheet) +UART_CONFIG_PINS(6, GPIOA, GPIOA, 11, 12, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; + +// initialization for UART6 +UART_INIT(6, UART6_TX_SIZE, UART6_RX_SIZE) + +// un-initialization for UART6 +UART_UNINIT(6) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..408eb86b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +/////////// +// UART6 // +/////////// + +// enable USART6 +#define NF_SERIAL_COMM_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 1024 bytes +#define UART6_TX_SIZE 1024 +// rx buffer size: 1024 bytes +#define UART6_RX_SIZE 1024 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..f08c5650 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native_target.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/CMakeLists.txt new file mode 100644 index 00000000..0f13c959 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/CMakeLists.txt @@ -0,0 +1,205 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F407xG_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F407xG_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F407xG_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F407xG_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +############################################################################ +# CRT heap is assigned to RAM4 region @ CCM SRAM so we are OK to use it all +############################################################################ +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x10000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x10000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/README.md new file mode 100644 index 00000000..f0799610 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/README.md @@ -0,0 +1,57 @@ +## STM STM32F4DISCOVERY board + +![STM STM32F4DISCOVERY board](stm32f4_discovery.jpg) + +The board used in this community contribution is the STM32F4DISCOVERY board from STM. The board can be purchased from various sources and should be about 20 euros. Further information on this board and links for the user and programming manuals can be found at the product page in ST [website](https://www.st.com/en/evaluation-tools/stm32f4discovery.html). + +Some basic information abstracted from ST: + +- STM32F407VGT6 microcontroller featuring 32-bit ARM®Cortex®-M4 with FPU core, 1-Mbyte Flash memory, 192-kbyte RAM in an LQFP100 package +- On-board ST-LINK/V2 on STM32F4DISCOVERY (old reference) or ST-LINK/V2-A on STM32F407G-DISC1 (new order code) +- USB ST-LINK with re-enumeration capability and three different interfaces: + - Debug port + - Virtual Com port (with new order code only) + - Mass storage (with new order code only) +- Board power supply: through USB bus or from an external 5 V supply voltage +- External application power supply: 3 V and 5 V +- LIS302DL or LIS3DSH ST MEMS 3-axis accelerometer +- MP45DT02 ST-MEMS audio sensor omni-directional digital microphone +- CS43L22 audio DAC with integrated class D speaker driver +- Eight LEDs: + - LD1 (red/green) for USB communication + - LD2 (red) for 3.3 V power on + - Four user LEDs, LD3 (orange), LD4 (green), LD5 (red) and LD6 (blue) + - 2 USB OTG LEDs LD7 (green) VBUS and LD8 (red) over-current +- Two push-buttons (user and reset) +- USB OTG FS with micro-AB connector +- Extension header for all LQFP100 I/Os for quick connection to prototyping board and easy probing + +### Flashing and debugging + +This board has one mini USB connector exposing the embedded ST-Link interface that is used for flashing the nanoFramework firmware and for performing debugging on the nanoCLR code. +The second USB connector (a micro USB one) is used to connect the device with Visual Studio allowing to deploy and debug your C# managed applications. + +## ADC configurations + +The following ADC channels (and respective GPIO pins) are available to the managed API, in the respective index: + +- PC1, ADC1 IN11 +- PC2 ADC1 IN12 +- PA6 ADC2 IN6 +- PA7 ADC2 IN7 +- PB0 ADC2 IN8 +- Temp Sensor ADC1 +- VrefInt ADC1 +- Vbatt ADC1 + +## I2C configurations + +I2C buses available: +- I2C1 + - SCL pin: GPIOB_8 + - SDA pin: GPIOB_9 + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/CMakeLists.txt new file mode 100644 index 00000000..aa7f1d54 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..52e006a1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 0x08008000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 } // 0x08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage.c new file mode 100644 index 00000000..5989a2ce --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/Device_BlockStorage.c @@ -0,0 +1,97 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 0x08004000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 } // 0x08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.c new file mode 100644 index 00000000..225d046a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.c @@ -0,0 +1,454 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD2. + */ +#define USBD2_DATA_REQUEST_EP 1 +#define USBD2_DATA_AVAILABLE_EP 1 +#define USBD2_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"STMicroelectronics" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"nanoFramework Virtual COM Port" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[18] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[67] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(67, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + if (usbp->state == USB_ACTIVE) { + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD2_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD2_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + } + else if (usbp->state == USB_SELECTED) { + usbDisableEndpointsI(usbp); + } + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handling messages not implemented in the default handler nor in the + * SerialUSB handler. + */ +static bool requests_hook(USBDriver *usbp) { + + if (((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE) && + (usbp->setup[1] == USB_REQ_SET_INTERFACE)) { + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + } + return sduRequestsHook(usbp); +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + requests_hook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD2_DATA_REQUEST_EP, + USBD2_DATA_AVAILABLE_EP, + USBD2_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.h new file mode 100644 index 00000000..167e1df8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/common/usbcfg.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/README.md new file mode 100644 index 00000000..780b69ad --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](ST_STM32F4_DISCOVERY.Adc.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/ST_STM32F4_DISCOVERY.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/ST_STM32F4_DISCOVERY.Adc.cs new file mode 100644 index 00000000..a2395660 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/managed_helpers/ST_STM32F4_DISCOVERY.Adc.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.ST_STM32F4_DISCOVERY +{ + /// + /// Enumeration of ADC channels available on ST_STM32F4_DISCOVERY + /// + public static class AdcChannels + { + /// + /// Channel 0, connected to PC1 (ADC1 - IN11) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, connected to PC2 (ADC1 - IN12) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, connected to PA6 (ADC2 - IN6) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, connected to PA7 (ADC2 - IN7) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, connected to PB0 (ADC2 - IN8) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 5; + + /// + /// Channel 6, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 6; + + /// + /// Channel 7, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 7; + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter-DEBUG.ld new file mode 100644 index 00000000..60fd44dd --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F407xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08008000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter.ld new file mode 100644 index 00000000..eeaf96d0 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/STM32F407xG_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F407xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08008000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/chconf.h new file mode 100644 index 00000000..335e3fa4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf.h new file mode 100644 index 00000000..b970c22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/main.c new file mode 100644 index 00000000..c9085139 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/main.c @@ -0,0 +1,84 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + osDelay(20); // Let init stabilize + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + // the user button in this board has a pull-up resistor so the check has to be inverted + if (!palReadPad(GPIOA, GPIOA_BUTTON)) + { + // check for valid CLR image + // this target DOES NOT have configuration block, so we need to use the __nanoImage_end__ address here + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + } + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOD, GPIOD_LED3); + osDelay(500); + palClearPad(GPIOD, GPIOD_LED3); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf.h new file mode 100644 index 00000000..67f610b1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf.h @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F407_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 4 +#define STM32_PLLN_VALUE 168 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR-DEBUG.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR-DEBUG.ld new file mode 100644 index 00000000..0e092d71 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F407xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 1M - 32k - 768k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 768k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR.ld b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR.ld new file mode 100644 index 00000000..599abc4f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/STM32F407xG_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F407xG memory setup. + * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 1M - 16k - 768k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 768k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/chconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/chconf.h new file mode 100644 index 00000000..390ce3a6 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf.h new file mode 100644 index 00000000..a1e2b875 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf.h @@ -0,0 +1,525 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..215ec4a8 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/halconf_nf.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +// enables STM32 Can driver +#if !defined(HAL_USE_STM32_CAN) +#define HAL_USE_STM32_CAN TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/main.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/main.c new file mode 100644 index 00000000..a1738761 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/main.c @@ -0,0 +1,74 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf.h new file mode 100644 index 00000000..10039241 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf.h @@ -0,0 +1,336 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F407_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 4 +#define STM32_PLLN_VALUE 168 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 TRUE +#define STM32_CAN_USE_CAN2 TRUE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 TRUE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 TRUE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 TRUE +#define STM32_UART_USE_UART4 TRUE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/stm32f4_discovery.jpg b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/stm32f4_discovery.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a5d3ace079d1951eff8c1879709ad73b82a2f9ed GIT binary patch literal 105327 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

;ep4ce+*X1?|%P$1e4jwQ;;*6v1& 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

f4KVUU1Dyai3 z#W-wU{g&gDHB<^8u)9<~LjR;A7T#yhwi<&xo^_%g99-*aZnD=|o*QuF{xK=R-S-W@ z=pdmVe?l}8-cme8Y3U90nEyOfup@L4`t1I_ji-$?k+ya`d~z!)+pSoQBW{Dp32!{4 z#;gYKxy|T;b1y$tg(Z<>@f7iecN@QHN0}PQPjt)o87`|Mg^S<%_X$Z$4kzK;fU0E_ za+8z9m0E^2b#=LT1dO)$%2hW@db4-*bN;L!QmrU@nLz*UQnfsRSqgp1VU88i{8A`T z7}MwiPHk;2S>tv$W%gVlwb-UL7k$rsK^s6lU()Pq57wGP12vhtl(VDDO>>t(8rBHa z18V1BJJ4(!C)JtOP=y)kc$?JykR?(HjPG;!{<&Bm+~G0A=LzzK#DuH9KP6tb26NL>YY$j@bqL$vohT9cF;)9dur$NfdJo6>i z8c@pML)2lUf8EUI2a+M`pHX@Q*D19aO#886ZLnKMuGvWL|LDNl@q$V_Yb=dvMNFnU zVDpegB%aAH6k9}H4+WC2GdXx0UY1dTb@jX8%#&Bjp9=P{UYYQ+Own6)Y z5l>_~q}!V-lyw!2FKWVt3PEY)-|rZcU-{PHd~9+#5|$H&2)e;Vs7{~S)3)_!UUm%D zYWyq16^mr`FlTNRtmjiiPNc${EljkT#s~BDdIs~&>9DeBWp@*IV@{|<`RB)Ym@WS5 zXk9~Nu&3dhSE9mGmAjDBfj~t$FnQ+SXFGbm2v(4>dEDK!b%$58QV**@pLEjis>Am2Am-9h^FLXw3O!AO!?41h$Hc( z79#n*houdTKtRw(#F+pPe@>2W8E9H0FWrB{wqU@o=q%WS&hN#kD>Rl< zmP<<|h}7;9%xfk>g|vJU&wb2;ldZlGtMU;Mjn=2vMwhiFn9o&DYmfFCVD`k2lqt~d zmNLl)0#5ix)(h}*$<1S%nKv<@b6(W#lIy~0RU`mD6h6s^hvgn9a}`I4oU%xP^R5nB zMPQDx_f8)R0~I;NxV?@NI*3L0MueETP@=lw>y|@DTv=AUZsEd5{=d!r?RFideDBC6 z>U)zmq)(A-A3GpZmQ;DURCLv;4r+<(PP7yz9UzFPllv^Wjk4==EXyzDRg(7D0TYpv zF6lNy2OB3L;8;#SH`flNcW}^3N)0G7jj8MqDh_ zC!qp$eOWj_8px%l&F-ka2-bI?_)OyHkjIR1C}o|FiXoDJUD7oDPQ{SYy-U=GKrluf z9=EsMQ7Ygo37!&v|LHDrXn-&Q{}~+QMe+7c*8UOJ?+diBbktTTc)p?8GOCN``tUS( zwi_v;>3bEbKV*zyNA2owKV+tg-3pC|OrGAkJZzi6Jmi73fAN>21SFzly2ZzD{eG(I z%)az_x$fxMYViktYBPc{H{vzNiq3x|Ng7<>>24X>__kfA@;xQWO&93kN;MTX(q%tE z%srx4md^@=t6C>T+8B*k*)yh9lnomNyPe~9kPnbHN&1xL^iL0>9E^F*xLf-``*x=* z?2|>w@9DYPHZt753+FrK*UpJ(78)CW2g(t{1Rzv95}kvD+v}XCk6y^x1pp*^D;=6p z<{cENz4#pBZ%~wGmsdy;SAWC9?O>_8jdsc1~;d z#OF2P4HBpEECS$OIRD*tK^O>EdZD}K4U4N~1pI&%%9DXwT$cNb@9Aw9i-#O^%?a|= zKoe!@XWB~+_wO7;O0S7i;P_9xW;f5U@WpSe;W9j~17@Q51|uc9+Pt<$Ie6UB^_TgJ zx-J1Q54?EoXUYu1*|?WPi==QemACNp1FMMQ`c;u7f3*GIqo*A0_y- zz=jID)rI*gIsiD?3}SQl?eu%oSm1AkcZ43tlVqnOfX}n?sl%pEkszs(% zv>hM0PibNRA74Fh726&Aqw13br>Wl2`r-D)wn6B(e{LQ>iN5u&)u22Xz7+k+oIzDx zeSuBo3ALx8`$Z5*w|Oe*K&-{3`3s$q^f9!vj{L$CNNty*^hs-5RaPx(l8=vGy!_LB zEnhVyvA_dS%5+VZ?3ucZl(l3b!|<67BzOoLJ+xGr+wAZ&n>27#P>F2O(GcH9a&07b zrC{T&ttG$X!BD2V^cTPYs~A&}T~3umA#Ug7hjuUqUgG-MHE&yNH z*P##0MTs-}<7vN~h~((A=;MsM$q*FA!24e`R1$iWph~|?)?~XaGnR>Z)b^RzcZn&7 zUox|Hgfx1}yp6w1d`D%Y9HVA$ISAzoCL6Ywpl}XZt8FNNEuq-|2#MhsVosHiUS{;+s#i_|wZ%GL>4Y!lFNDtBa5;Rl-->nNe0?k@ObCm5_(p4aKtM>n5o-u2_|%0Ay?uhSkbCZ%%rc=m(HZPQc@Au+Ll@4 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 + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.h.in new file mode 100644 index 00000000..fd07d285 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x200000C0) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00020000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00100000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.cpp new file mode 100644 index 00000000..7dbe7ff1 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_nf_devices_can_config.h" +#include + +/////////// +// CAN1 // +/////////// + +// pin configuration for CAN1 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_09 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_08 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(1, GPIOB, GPIOB, 9, 8, 9) + +// buffer +CANRxFrame Can1_MsgBuffer[CAN1_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(1, CAN1_RX_BUFFER_SIZE) + +/////////// +// CAN2 // +/////////// + +// pin configuration for CAN2 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_06 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_05 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(2, GPIOB, GPIOB, 6, 5, 9) + +// buffer +CANRxFrame Can2_MsgBuffer[CAN2_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(2, CAN2_RX_BUFFER_SIZE) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.h new file mode 100644 index 00000000..adc8ace3 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_can_config.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +////////// +// CAN1 // +////////// + +// enable CAN1 +#define NF_CAN_STM32_CAN_USE_CAN1 TRUE + +// buffers size +#define CAN1_RX_BUFFER_SIZE 16 + +////////// +// CAN2 // +////////// + +// enable CAN2 +#define NF_CAN_STM32_CAN_USE_CAN2 TRUE + +// buffers size +#define CAN2_RX_BUFFER_SIZE 16 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..f56a636f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_nf_devices_onewire_config.h" +#include + +/////////// +// UART4 // +/////////// + +// pin configuration for UART4 +// port for TX pin is: GPIOC +// TX pin: is GPIOC_10 +// GPIO alternate pin function is 8 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +UART_CONFIG_PINS(4, GPIOC, 10, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart4_TxBuffer[UART4_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart4_RxBuffer[UART4_RX_SIZE]; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..76f90a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_nf_devices_onewire_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART4 // +/////////// + +// enable USART4 +#define NF_ONEWIRE_STM32_UART_USE_USART4 TRUE + +// buffers size +// tx buffer size: 32 bytes +#define UART4_TX_SIZE 32 +// rx buffer size: 32 bytes +#define UART4_RX_SIZE 32 \ No newline at end of file diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..e3a0eee9 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_system_devices_dac_config.cpp @@ -0,0 +1,17 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + + // DAC1, channel 2, GPIO port A, pin 5 + {1, 2, GPIOA, 5}, +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..a4bea18d --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_adc_config.cpp @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOC, 1, ADC_CHANNEL_IN11}, + {1, GPIOC, 2, ADC_CHANNEL_IN12}, + + // ADC2 + {2, GPIOA, 6, ADC_CHANNEL_IN6}, + {2, GPIOA, 7, ADC_CHANNEL_IN7}, + {2, GPIOB, 0, ADC_CHANNEL_IN8}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2a60a22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..309c05fb --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include + +/////////// +// UART2 // +/////////// + +// pin configuration for UART2 +// port for TX pin is: GPIOA +// port for RX pin is: GPIOA +// TX pin: is GPIOA_2 +// RX pin: is GPIOA_3 +// GPIO alternate pin function is 7 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +UART_CONFIG_PINS(2, GPIOA, GPIOA, 2, 3, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// initialization for UART2 +UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// un-initialization for UART2 +UART_UNINIT(2) + + +/////////// +// UART3 // +/////////// + +// pin configuration for UART3 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOD +// TX pin: is GPIOD_8 +// RX pin: is GPIOD_9 +// GPIO alternate pin function is 7 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +UART_CONFIG_PINS(3, GPIOD, GPIOD, 8, 9, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_TxBuffer[UART3_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_RxBuffer[UART3_RX_SIZE]; + +// initialization for UART3 +UART_INIT(3, UART3_TX_SIZE, UART3_RX_SIZE) + +// un-initialization for UART3 +UART_UNINIT(3) + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..d0dad6c0 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART2 // +/////////// + +// enable USART2 +#define NF_SERIAL_COMM_STM32_UART_USE_USART2 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART2_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART2_RX_SIZE 256 + + +/////////// +// UART3 // +/////////// + +// enable USART3 +#define NF_SERIAL_COMM_STM32_UART_USE_USART3 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART3_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART3_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..ef2d3a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/LICENSE b/source/native/nf-interpreter/targets-community/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/source/native/nf-interpreter/targets-community/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/source/native/nf-interpreter/targets-community/README.md b/source/native/nf-interpreter/targets-community/README.md new file mode 100644 index 00000000..86125a6b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/README.md @@ -0,0 +1,62 @@ +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Discord](https://img.shields.io/discord/478725473862549535.svg)](https://discord.gg/gCyBu8T) [![Build Status](https://dev.azure.com/nanoframework/Community-Targets/_apis/build/status/nanoframework.nf-Community-Targets)](https://dev.azure.com/nanoframework/Community-Targets/_build/latest?definitionId=4) + +![nanoFramework logo](https://github.com/nanoframework/Home/blob/master/resources/logo/nanoFramework-repo-logo.png) + +----- + +### Welcome to the **nanoFramework** community targets repository! + +This repository contains target boards for the **nanoFramework**, provided and maintained by community members. + +The provided boards are **NOT** supported by the **nanoFramework** team and any issues must be communicated with the contributor that _owns_ it. + +## Available community boards + +| Target name | Firmware Images | MCU | Frequency | FLASH | RAM | +|:-:|:-:|:-:|:-:|:-:|:-:| +| [GHI FEZ CERB40-I](CMSIS-OS/ChibiOS/GHI_FEZ_CERB40_NF) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/GHI_FEZ_CERB40_NF/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/GHI_FEZ_CERB40_NF/_latestVersion) | STM32F405RG | 168 MHz | 1024 KB | 192 KB | +| [IngenuityMicro Electron](CMSIS-OS/ChibiOS/I2M_ELECTRON_NF) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/I2M_ELECTRON_NF/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/I2M_ELECTRON_NF/_latestVersion) | STM32F411CE | 100 MHz | 512 KB | 128 KB | +| [IngenuityMicro Oxygen](CMSIS-OS/ChibiOS/I2M_OXYGEN_NF) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/I2M_OXYGEN_NF/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/I2M_OXYGEN_NF/_latestVersion) | STM32F411CE | 100 MHz | 512 KB | 128 KB | +| [ST Nucleo64 F401RE](CMSIS-OS/ChibiOS/ST_NUCLEO64_F401RE_NF) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/ST_NUCLEO64_F401RE_NF/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/ST_NUCLEO64_F401RE_NF/_latestVersion) | STM32F401RE | 84 MHz | 512 KB | 96 KB | +| [ST Nucleo64 F411RE](CMSIS-OS/ChibiOS/ST_NUCLEO64_F411RE_NF) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/ST_NUCLEO64_F411RE_NF/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/ST_NUCLEO64_F411RE_NF/_latestVersion) | STM32F411RE | 100 MHz | 512 KB | 128 KB | +| [ST Nucleo144 F412ZG](CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/ST_NUCLEO144_F412ZG_NF/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/ST_NUCLEO144_F412ZG_NF/_latestVersion) | STM32F412ZG | 100 MHz | 1024 KB | 256 KB | +| [ST Nucleo144 F746ZG](CMSIS-OS/ChibiOS/ST_NUCLEO144_F746ZG) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/ST_NUCLEO144_F746ZG/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/ST_NUCLEO144_F746ZG/_latestVersion) | STM32F746ZG | 216 MHz | 1024 KB | 320 KB | +| [ST STM32F4DISCO](CMSIS-OS/ChibiOS/ST_STM32F4_DISCOVERY) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/ST_STM32F4_DISCOVERY/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/ST_STM32F4_DISCOVERY/_latestVersion) | STM32F407VGT6 | 168 MHz | 1024 KB | 192 KB | +| [ST Nucleo144 F439ZI](CMSIS-OS/ChibiOS/ST_NUCLEO144_F439ZI) | [ ![Download](https://api.bintray.com/packages/nfbot/nanoframework-images-community-targets/ST_NUCLEO144_F439ZI/images/download.svg) ](https://bintray.com/nfbot/nanoframework-images-community-targets/ST_NUCLEO144_F439ZI/_latestVersion) | STM32F439ZI | 180 MHz | 2048 KB | 256 KB | + +The above firmware builds include support for the class libraries and features marked below. + +| Target | Gpio | Spi | I2c | Pwm | Adc | Serial | OneWire | CAN | Events | SWO | Networking | Large Heap | +|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| +| GHI FEZ CERB40-I | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |:heavy_check_mark: | | | :heavy_check_mark: | | | | +| IngenuityMicro Electron | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | | | | | +| IngenuityMicro Oxygen | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | | | | +| ST Nucleo64 F401RE | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | | +| ST Nucleo64 F411RE | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | | | +| ST Nucleo144 F412ZG | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | | | +| ST Nucleo144 F746ZG | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | +| ST STM32F4DISCO | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | +| ST Nucleo144 F439ZI | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | + +## Feedback and documentation + +For documentation, providing feedback, issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home). + +When you need to discuss something specific about a community target start by doing so in the _support:community-targets_ channel in our Discord community or reach out directly to the target _owner_. + +Join our Discord community [here](https://discord.gg/gCyBu8T). + +## Credits + +The list of contributors to this project can be found at [CONTRIBUTORS](https://github.com/nanoframework/Home/blob/master/CONTRIBUTORS.md). + +The individual targets are _owned_ by the contributor and credit is due to the creator of the community board. + +## License + +The community target contributions are licensed under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). + +## Code of Conduct + +This project has adopted the code of conduct defined by the [Contributor Covenant](http://contributor-covenant.org/) +to clarify expected behavior in our community. diff --git a/source/native/nf-interpreter/targets-community/azure-pipelines-templates/clone-nf-interpreter-repo.yml b/source/native/nf-interpreter/targets-community/azure-pipelines-templates/clone-nf-interpreter-repo.yml new file mode 100644 index 00000000..411246ef --- /dev/null +++ b/source/native/nf-interpreter/targets-community/azure-pipelines-templates/clone-nf-interpreter-repo.yml @@ -0,0 +1,20 @@ +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. + +steps: + # clone nf-interpreter repo to launch the build + - task: PowerShell@2 + inputs: + targetType: 'inline' + script: git clone https://github.com/nanoframework/nf-interpreter.git -b develop nf-interpreter --depth 1 -q + errorActionPreference: 'stop' + displayName: Clone nf-interpreter repo + + # Copy target files to nf-interpreter folder + - task: CopyFiles@2 + inputs: + sourceFolder: $(Build.SourcesDirectory)\CMSIS-OS + targetFolder: $(Build.SourcesDirectory)\nf-interpreter\targets-community\CMSIS-OS + cleanTargetFolder: false + overWrite: true + displayName: Copy community target to nf-interpreter diff --git a/source/native/nf-interpreter/targets-community/azure-pipelines-templates/set-build-version.yml b/source/native/nf-interpreter/targets-community/azure-pipelines-templates/set-build-version.yml new file mode 100644 index 00000000..c964eace --- /dev/null +++ b/source/native/nf-interpreter/targets-community/azure-pipelines-templates/set-build-version.yml @@ -0,0 +1,24 @@ +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. + +steps: + # compute build version + - task: PowerShell@2 + inputs: + targetType: 'inline' + script: | + $counter = $env:REVISION + $version = [int]$counter + + $buildSimpleVersion = "1.1." + $version.ToString() + $buildFullVersion = $buildSimpleVersion + ".0" + + Write-Host ">>$buildFullVersion<<" + + # need to hijack NBGV variable that is expected in the build CMake command and others that follow + Write-Host "$("##vso[task.setvariable variable=NBGV_Version]")$buildFullVersion" + Write-Host "$("##vso[task.setvariable variable=NBGV_SimpleVersion]")$buildSimpleVersion" + Write-Host "$("##vso[task.setvariable variable=NBGV_PrereleaseVersion]").0" + + condition: succeeded() + displayName: compute the build version diff --git a/source/native/nf-interpreter/targets-community/azure-pipelines.yml b/source/native/nf-interpreter/targets-community/azure-pipelines.yml new file mode 100644 index 00000000..b9ce8bad --- /dev/null +++ b/source/native/nf-interpreter/targets-community/azure-pipelines.yml @@ -0,0 +1,552 @@ +# Copyright (c) 2018 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. + +trigger: + branches: + include: + - master + paths: + exclude: + - /*.md + - .gitignore + +pr: + branches: + include: + - master + autoCancel: true + +schedules: +- cron: "50 23 * * *" + branches: + include: + - master + always: true + displayName: Daily build at 23:50 + +# add nf-tools repo to resources (for Azure Pipelines templates) +# add nf-interpreter repo to resources (for Azure Pipelines templates) +resources: + repositories: + - repository: templates + type: github + name: nanoframework/nf-tools + endpoint: nanoframework + - repository: templatesBuild + type: github + name: nanoframework/nf-interpreter + ref: refs/heads/develop + endpoint: nanoframework + +variables: + GNU_GCC_TOOLCHAIN_PATH: $(Agent.TempDirectory)\GNU_Tools_ARM_Embedded + +jobs: + +############################## +- job: Check_Build_Options + pool: + vmImage: 'VS2017-Win2016' + + steps: + - checkout: self + fetchDepth: 1 + + - powershell: | + + # get commit date, if this is NOT a PR + if($env:Build_SourceBranch -like "refs/pull*") + { + # this is a PR: always build + echo "##vso[task.setvariable variable=GO;isOutput=true]true" + } + else + { + # clone nf-interpreter + git clone https://github.com/nanoframework/nf-interpreter.git -b develop nf-interpreter --depth 1 -q + cd "nf-interpreter" > $null + + $commitDate = git show -s --format=%cd --date=short + $commitDate = [DateTime]$commitDate + + if($commitDate -eq [System.DateTime]::UtcNow.Date) + { + # last commit from nf-interpreter is from today, build images + echo "##vso[task.setvariable variable=GO;isOutput=true]true" + } + else + { + # last commit from nf-interpreter is older than today, skip build + + "**********************************************************************" | Write-Host + "* Last commit from nf-interpreter is older than today, skiping build *" | Write-Host + "**********************************************************************" | Write-Host + + echo "##vso[task.setvariable variable=GO;isOutput=true]false" + } + } + + name: BuildOptions + displayName: Evaluate build options + +############################## +- job: Get_Commit_Message + condition: eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) + pool: + vmImage: 'VS2017-Win2016' + + dependsOn: + - Check_Build_Options + + steps: + - checkout: self + fetchDepth: 1 + + # get commint message + - powershell: | + + if($env:Build_SourceBranch -like "refs/pull*") + { + # PR build, get PR message + + # need to get PR number from branch as the Azure Pipeline var can't be trusted + if($env:Build_SourceBranch -match '(?<=(pull\/))\w*(?=(\/))') + { + $prNumber = $matches[0] + + $prUrl = "https://api.github.com/repos/$env:Build_Repository_Name/pulls/$prNumber" + + $commit = Invoke-RestMethod -Uri $prUrl -ContentType "application/json" -Method GET + + $commitMessage = $commit.body + } + } + else + { + # not a PR, get subject and commit message for commit + $commitMessage = git log --format='%B' -1 + } + + # need to flatten message by removing new lines + $commitMessage = $commitMessage -replace "`r`n", " " + + # set variable to foward to jobs + echo "##vso[task.setvariable variable=COMMIT_MESSAGE;isOutput=true]$commitMessage" + name: getCommitMessage + displayName: grab commit message + +############################## +- job: Build_GHI_FEZ_CERB40_NF + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***GHI_FEZ_CERB40_NF***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: GHI_FEZ_CERB40_NF + BuildOptions: -DTARGET_SERIES=STM32F4xx -DNF_FEATURE_DEBUGGER=ON -DNF_FEATURE_RTC=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('GHI_FEZ_CERB40_NF_versioncounter', 3)] + GccArm_Version: + NeedsDFU: true + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_I2M_ELECTRON_NF + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***I2M_ELECTRON_NF***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: I2M_ELECTRON_NF + BuildOptions: -DTARGET_SERIES=STM32F4xx -DNF_FEATURE_DEBUGGER=ON -DUSE_RNG=OFF -DNF_FEATURE_RTC=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('I2M_ELECTRON_NF_versioncounter', 3)] + GccArm_Version: + NeedsDFU: true + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_I2M_OXYGEN_NF + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***I2M_OXYGEN_NF***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: I2M_OXYGEN_NF + BuildOptions: -DTARGET_SERIES=STM32F4xx -DNF_FEATURE_DEBUGGER=ON -DUSE_RNG=OFF -DNF_FEATURE_RTC=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('I2M_OXYGEN_NF_versioncounter', 3)] + GccArm_Version: + NeedsDFU: true + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_ST_NUCLEO64_F401RE_NF + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ST_NUCLEO64_F401RE_NF***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: ST_NUCLEO64_F401RE_NF + BuildOptions: -DTARGET_SERIES=STM32F4xx -DNF_FEATURE_DEBUGGER=ON -DUSE_RNG=OFF -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_nanoFramework.Devices.OneWire=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('ST_NUCLEO64_F401RE_NF_versioncounter', 3)] + GccArm_Version: + NeedsDFU: false + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_ST_NUCLEO64_F411RE_NF + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ST_NUCLEO64_F411RE_NF***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: ST_NUCLEO64_F411RE_NF + BuildOptions: -DTARGET_SERIES=STM32F4xx -DNF_FEATURE_DEBUGGER=ON -DUSE_RNG=OFF -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('ST_NUCLEO64_F411RE_NF_versioncounter', 3)] + GccArm_Version: + NeedsDFU: false + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_ST_NUCLEO144_F412ZG_NF + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ST_NUCLEO144_F412ZG_NF***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: ST_NUCLEO144_F412ZG_NF + BuildOptions: -DTARGET_SERIES=STM32F4xx -DNF_FEATURE_DEBUGGER=ON -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=OFF -DAPI_Windows.Devices.Adc=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('ST_NUCLEO144_F412ZG_NF_versioncounter', 3)] + GccArm_Version: + NeedsDFU: false + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_ST_NUCLEO144_F746ZG + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ST_NUCLEO144_F746ZG***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: ST_NUCLEO144_F746ZG + BuildOptions: -DTARGET_SERIES=STM32F7xx -DRTOS=CHIBIOS -DNF_FEATURE_DEBUGGER=ON -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DNF_FEATURE_HAS_CONFIG_BLOCK=ON -DAPI_System.Math=ON -DAPI_Hardware.Stm32=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_System.Net=ON -DNF_SECURITY_MBEDTLS=ON -DAPI_nanoFramework.Devices.OneWire=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('ST_NUCLEO144_F746ZG_versioncounter', 3)] + GccArm_Version: + NeedsDFU: false + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_ST_STM32F4_DISCOVERY + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ST_STM32F4_DISCOVERY***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: ST_STM32F4_DISCOVERY + BuildOptions: -DTARGET_SERIES=STM32F4xx -DRTOS=CHIBIOS -DSUPPORT_ANY_BASE_CONVERSION=ON -DNF_FEATURE_DEBUGGER=ON -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DAPI_System.Math=ON -DAPI_Hardware.Stm32=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_nanoFramework.Devices.OneWire=ON -DAPI_nanoFramework.Devices.Can=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('ST_STM32F4_DISCOVERY_versioncounter', 3)] + GccArm_Version: + NeedsDFU: false + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +############################## +- job: Build_ST_NUCLEO144_F439ZI + condition: and( or( contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ST_NUCLEO144_F439ZI***'), contains(dependencies.Get_Commit_Message.outputs['getCommitMessage.COMMIT_MESSAGE'], '***ALL***'), eq(variables['BUILD_ALL'], 'true') ), eq( dependencies.Check_Build_Options.outputs['BuildOptions.GO'], true ) ) + + dependsOn: + - Get_Commit_Message + - Check_Build_Options + + pool: + vmImage: 'VS2017-Win2016' + + variables: + BoardName: ST_NUCLEO144_F439ZI + BuildOptions: -DTARGET_SERIES=STM32F4xx -DRTOS=CHIBIOS -DNF_FEATURE_DEBUGGER=ON -DSWO_OUTPUT=ON -DNF_FEATURE_RTC=ON -DNF_FEATURE_HAS_CONFIG_BLOCK=ON -DAPI_System.Math=ON -DAPI_Hardware.Stm32=ON -DAPI_Windows.Devices.Gpio=ON -DAPI_Windows.Devices.Spi=ON -DAPI_Windows.Devices.I2c=ON -DAPI_Windows.Devices.Pwm=ON -DAPI_Windows.Devices.SerialCommunication=ON -DAPI_Windows.Devices.Adc=ON -DAPI_System.Net=ON -DNF_SECURITY_MBEDTLS=ON + # creates a counter and assigns it to the revision variable + REVISION: $[counter('ST_NUCLEO144_F439ZI_versioncounter', 3)] + GccArm_Version: + NeedsDFU: false + + steps: + - checkout: self + fetchDepth: 1 + + - template: azure-pipelines-templates/set-build-version.yml + + - template: azure-pipelines-templates/clone-nf-interpreter-repo.yml + + - template: azure-pipelines-templates/download-install-arm-gcc-toolchain.yml@templatesBuild + + - template: azure-pipelines-templates/download-install-ninja.yml@templatesBuild + + - template: azure-pipelines-templates/download-hexdfu.yml@templatesBuild + + - template: azure-pipelines-templates/build-chibios-stm32.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/pack-publish-artifacts.yml@templatesBuild + parameters: + buildDirectory: $(Build.SourcesDirectory)\nf-interpreter\build + + - template: azure-pipelines-templates/publish-bintray.yml@templatesBuild + +################################## +# report build failure to Discord +- job: Report_Build_Failure + dependsOn: + - Build_GHI_FEZ_CERB40_NF + - Build_I2M_ELECTRON_NF + - Build_I2M_OXYGEN_NF + - Build_ST_NUCLEO64_F401RE_NF + - Build_ST_NUCLEO64_F411RE_NF + - Build_ST_NUCLEO144_F412ZG_NF + - Build_ST_NUCLEO144_F746ZG + - Build_ST_STM32F4_DISCOVERY + condition: or( failed('Build_GHI_FEZ_CERB40_NF'), failed('Build_I2M_ELECTRON_NF'), failed('Build_I2M_OXYGEN_NF'), failed('Build_ST_NUCLEO64_F401RE_NF'), failed('Build_ST_NUCLEO64_F411RE_NF'), failed('Build_ST_NUCLEO144_F412ZG_NF'), failed('Build_ST_NUCLEO144_F746ZG'), failed('Build_ST_STM32F4_DISCOVERY')) + + pool: + vmImage: 'VS2017-Win2016' + + steps: + - checkout: self + fetchDepth: 1 + + # step from template @ nf-tools repo + - template: azure-pipelines-templates/discord-webhook.yml@templates + parameters: + status: 'failure' + webhookUrl: '$(DiscordWebhook)' + message: '' + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/CMakeLists.txt new file mode 100644 index 00000000..a362ead4 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/CMakeLists.txt @@ -0,0 +1,493 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +include(STM32_CubePackage) + +######################################################## +# check availability of hex2dfu tool if specified +if(NOT "${TOOL_HEX2DFU_PREFIX}" STREQUAL "") + if(NOT EXISTS ${TOOL_HEX2DFU_PREFIX}/hex2dfu.exe) + message(STATUS "") + message(STATUS "Couldn't find the hex2dfu tool at the specified path: ${TOOL_HEX2DFU_PREFIX}/hex2dfu.exe") + message(STATUS "Make sure that the CMake option TOOL_HEX2DFU_PREFIX has the correct path.") + message(STATUS "If you don't have this tool download it from https://github.com/nanoframework/nf-tools/releases") + message(STATUS "") + message(FATAL_ERROR "hex2dfu tool not found") + else() + set(HEX2DFU_TOOL_AVAILABLE TRUE CACHE INTERNAL "hex2dfu tool available") + endif() +endif() + +# check if CHIBIOS_SOURCE was specified or if it's empty (default is empty) +set(NO_CHIBIOS_SOURCE TRUE) +if(CHIBIOS_SOURCE) + if(NOT "${CHIBIOS_SOURCE}" STREQUAL "") + set(NO_CHIBIOS_SOURCE FALSE) + endif() +endif() + +# check if CHIBIOS-Contrib_SOURCE was specified or if it's empty (default is empty) +set(NO_CHIBIOS_CONTRIB_SOURCE TRUE) +if(CHIBIOS_CONTRIB_SOURCE) + if(NOT "${CHIBIOS_CONTRIB_SOURCE}" STREQUAL "") + set(NO_CHIBIOS_CONTRIB_SOURCE FALSE) + endif() +endif() + +if(NO_CHIBIOS_SOURCE) + # no CHIBIOS source specified, download it from it's repo + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + # ChibiOS version + set(CHIBIOS_GIT_TAG "stable_19.1.x") + message(STATUS "RTOS is: CHIBIOS (latest available code from ${CHIBIOS_GIT_TAG})") + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/ChibiOS.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/ChibiOS_Download/CMakeLists.txt") + + # setup CMake project for ChibiOS download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/ChibiOS_Download") + + # run build on ChibiOS download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/ChibiOS_Download") + + # add ChibiOS as external project + ExternalProject_Add( + ChibiOS + PREFIX ChibiOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/ChibiOS_Source + GIT_REPOSITORY https://github.com/nanoframework/chibios + GIT_TAG ${CHIBIOS_GIT_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for ChibiOS CMake project + ExternalProject_Get_Property(ChibiOS SOURCE_DIR) + +else() + # ChibiOS source was specified + + # sanity check is source path exists + if(EXISTS "${CHIBIOS_SOURCE}/") + message(STATUS "RTOS is: ChibiOS (source from: ${CHIBIOS_SOURCE})") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/ChibiOS_Source") + file(COPY "${CHIBIOS_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/ChibiOS_Source") + else() + message(STATUS "Using local cache of ChibiOS source from ${CHIBIOS_SOURCE}") + endif() + + set(CHIBIOS_INCLUDE_DIR ${CMAKE_BINARY_DIR}/ChibiOS_Source/include) + else() + message(FATAL_ERROR "Couldn't find ChibiOS source at ${CHIBIOS_SOURCE}/") + endif() + + # add ChibiOS as external project + ExternalProject_Add( + ChibiOS + PREFIX ChibiOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/ChibiOS_Source + + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for ChibiOS CMake project + ExternalProject_Get_Property(ChibiOS SOURCE_DIR) + +endif() + +if(CHIBIOS_CONTRIB_REQUIRED) + if(NO_CHIBIOS_CONTRIB_SOURCE) + # no CHIBIOS_CONTRIB source specified, download it from it's repo + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + message(STATUS "ChibiOS-Contrib source from GitHub repo") + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/ChibiOS-Contrib.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Download/CMakeLists.txt") + + # setup CMake project for ChibiOS-Contrib download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Download") + + # run build on ChibiOS-Contrib download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Download") + + # add ChibiOS-Contrib as external project + # need to specify nanoframework as the active branch + ExternalProject_Add( + ChibiOS-Contrib + PREFIX ChibiOS-Contrib + SOURCE_DIR ${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Source + GIT_REPOSITORY https://github.com/nanoframework/ChibiOS-Contrib + GIT_TAG nanoframework # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for ChibiOS-Contrib CMake project + ExternalProject_Get_Property(ChibiOS-Contrib SOURCE_DIR) + + else() + # ChibiOS-Contrib source was specified + + # sanity check is source path exists + if(EXISTS "${CHIBIOS_CONTRIB_SOURCE}/") + message(STATUS "ChibiOS-Contrib source from: ${CHIBIOS_CONTRIB_SOURCE}") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Source") + file(COPY "${CHIBIOS_CONTRIB_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Source") + else() + message(STATUS "Using local cache of ChibiOS-Contrib source from ${CHIBIOS_CONTRIB_SOURCE}") + endif() + + set(CHIBIOS_INCLUDE_DIR ${CMAKE_BINARY_DIR}/ChibiOS_Source/include) + else() + message(FATAL_ERROR "Couldn't find ChibiOS-Contrib source at ${CHIBIOS_CONTRIB_SOURCE}/") + endif() + + # add ChibiOS-Contrib as external project + ExternalProject_Add( + ChibiOS-Contrib + PREFIX ChibiOS-Contrib + SOURCE_DIR ${CMAKE_BINARY_DIR}/ChibiOS-Contrib_Source + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for ChibiOS-Contrib CMake project + ExternalProject_Get_Property(ChibiOS-Contrib SOURCE_DIR) + + endif() +endif() + +# if mbed TLS is enabled add it to the build +if(NF_SECURITY_MBEDTLS) + + # check if MBEDTLS_SOURCE was specified or if it's empty (default is empty) + set(NO_MBEDTLS_SOURCE TRUE) + + if(MBEDTLS_SOURCE) + if(NOT "${MBEDTLS_SOURCE}" STREQUAL "") + set(NO_MBEDTLS_SOURCE FALSE) + endif() + endif() + + # set options for mbed TLS + option(ENABLE_TESTING "no testing when building mbed TLS." OFF) + + if(NO_MBEDTLS_SOURCE) + # no mbed TLS source specified, download it from it's repo + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + # set tag for currently supported version + set(MBEDTLS_GIT_TAG "mbedtls-2.16.3") + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/mbedTLS.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/mbedTLS_Download/CMakeLists.txt") + + # setup CMake project for mbedTLS download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/mbedTLS_Download") + + # run build on mbedTLS download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/mbedTLS_Download") + + # add mbedTLS as external project + ExternalProject_Add( + mbedTLS + PREFIX mbedTLS + SOURCE_DIR ${CMAKE_BINARY_DIR}/mbedTLS_Source + GIT_REPOSITORY https://github.com/nanoframework/mbedtls + GIT_TAG ${MBEDTLS_GIT_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + else() + # mbedTLS source was specified + + # sanity check is source path exists + if(EXISTS "${MBEDTLS_SOURCE}/") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/mbedTLS_Source") + message(STATUS "mbedTLS source from: ${MBEDTLS_SOURCE}") + file(COPY "${MBEDTLS_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/mbedTLS_Source") + else() + message(STATUS "Using local cache of mbedTLS source from ${MBEDTLS_SOURCE}") + endif() + + set(MBEDTLS_INCLUDE_DIR ${CMAKE_BINARY_DIR}/mbedTLS_Source/include) + else() + message(FATAL_ERROR "Couldn't find mbedTLS source at ${MBEDTLS_SOURCE}/") + endif() + + # add mbedTLS as external project + ExternalProject_Add( + mbedTLS + PREFIX mbedTLS + SOURCE_DIR ${CMAKE_BINARY_DIR}/mbedTLS_Source + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + endif() + + set(mbedTLS_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/3rdparty/humblelogging/include") + set(mbedTLS_LIBRARIES "${CMAKE_SHARED_LIBRARY_PREFIX}mbedTLS${CMAKE_SHARED_LIBRARY_SUFFIX}") + include_directories(${mbedTLS_INCLUDE_DIRS}) + +endif() + +# set target base location +# this has to be set before the class library modules are pulled in +if(EXISTS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}) + # set target base location + set(TARGET_BASE_LOCATION "${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}") +else() + # try to find board in the Community targets folder + if(EXISTS ${PROJECT_SOURCE_DIR}/targets-community/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}) + # set target base location + set(TARGET_BASE_LOCATION "${PROJECT_SOURCE_DIR}/targets-community/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}") + else() + # board NOT found in targets folder + # can't continue + message(FATAL_ERROR "\n\nSorry but support for ${CHIBIOS_BOARD} target is not available...\n\nYou can wait for that to be added or you might want to contribute and start working on a PR for that.\n\n") + endif() +endif() + +# set CMSIS RTOS include directory +include_directories( ${CMSIS_RTOS_INCLUDE_DIR}) + +# need to find board definition files (board.c and board.h) + +# assume no community board... until proven otherwise +set(CHIBIOS_COMMUNITY_TARGET FALSE CACHE INTERNAL "Community target flag") + +# start search in nanoFramework ChibiOS 'overlay' folder +if(EXISTS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/boards/${CHIBIOS_BOARD}) + # board found + # if it's on nF overlay board.c and board.h exist there for sure + set(CHIBIOS_BOARD_DEFINITIONS_LOCATION "Board definition files taken from nanoFramework overlay" CACHE INTERNAL "Location of board definition files") +else() + # board NOT found in ChibiOS 'overlay' + + # try to find it in the target boards + if(EXISTS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}) + # board found + # check if the board definition files are available at the target folder + if( EXISTS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}/board.c AND + EXISTS ${PROJECT_SOURCE_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}/board.h) + # definition files found + set(CHIBIOS_BOARD_DEFINITIONS_LOCATION "Board definition files taken from target folder" CACHE INTERNAL "Location of board definition files") + + else() + # board.c and board.h are NOT in the target folder, try to find them in the official distribution + + if(EXISTS ${PROJECT_BINARY_DIR}/ChibiOS_Source/os/hal/boards/${CHIBIOS_BOARD}) + # board found + # if it's on the ChibiOS official distribution board.c and board.h exist here for sure + set(CHIBIOS_BOARD_DEFINITIONS_LOCATION "Board definition files taken from official ChibiOS distribution" CACHE INTERNAL "Location of board definition files") + + else() + # board NOT found in official distribution + # quit now as there is no were else to search for these + message(FATAL_ERROR "\n\nSorry but couldn't find definition files for ${CHIBIOS_BOARD} in the available list of ChibiOS supported boards...\n\n") + + endif() + endif() + + else() + # try to find board in the Community targets folder + if(EXISTS ${PROJECT_SOURCE_DIR}/targets-community/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}) + # set flag for this being a community board + set(CHIBIOS_COMMUNITY_TARGET TRUE CACHE INTERNAL "Community target flag") + else() + # board NOT found in official distribution + # quit now as there is no were else to search for these + message(FATAL_ERROR "\n\nSorry but couldn't find definition files for ${CHIBIOS_BOARD} in the available list of ChibiOS supported boards...\n\n") + endif() + + endif() + +endif() + +# (default is OFF so STM Cube package is NOT included) +option(STM32_CUBE_PACKAGE_REQUIRED "option to include STM Cube pcakge in the build") +if(STM32_CUBE_PACKAGE_REQUIRED) + ProcessSTM32CubePackage() +endif() + +# if support for SPIFFS is enabled add it to the build +if(NF_FEATURE_USE_SPIFFS) + + # check if SPIFFS_SOURCE was specified or if it's empty (default is empty) + set(NO_SPIFFS_SOURCE TRUE) + + if(SPIFFS_SOURCE) + if(NOT "${SPIFFS_SOURCE}" STREQUAL "") + set(NO_SPIFFS_SOURCE FALSE) + endif() + endif() + + if(NO_SPIFFS_SOURCE) + # no SPIFFS source specified, download it from it's repo + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/SPIFFS.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/SPIFFS_Download/CMakeLists.txt") + + # setup CMake project for SPIFFS download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/SPIFFS_Download") + + # run build on SPIFFS download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/SPIFFS_Download") + + # add SPIFFS as external project + ExternalProject_Add( + SPIFFS + PREFIX SPIFFS + SOURCE_DIR ${CMAKE_BINARY_DIR}/SPIFFS_Source + GIT_REPOSITORY https://github.com/nanoframework/spiffs + GIT_TAG "nf-build" # target nanoFramework modified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + else() + # SPIFFS source was specified + + # sanity check is source path exists + if(EXISTS "${SPIFFS_SOURCE}/") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/SPIFFS_Source") + message(STATUS "SPIFFS source from: ${SPIFFS_SOURCE}") + file(COPY "${SPIFFS_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/SPIFFS_Source") + else() + message(STATUS "Using local cache of SPIFFS source from ${SPIFFS_SOURCE}") + endif() + + set(SPIFFS_INCLUDE_DIR ${CMAKE_BINARY_DIR}/SPIFFS_Source/include) + else() + message(FATAL_ERROR "Couldn't find SPIFFS source at ${SPIFFS_SOURCE}/") + endif() + + # add SPIFFS as external project + ExternalProject_Add( + SPIFFS + PREFIX SPIFFS + SOURCE_DIR ${CMAKE_BINARY_DIR}/SPIFFS_Source + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + endif() + + # get source dir for SPIFFS CMake project + ExternalProject_Get_Property(SPIFFS SOURCE_DIR) + + set(SPIFFS_LIBRARIES "${CMAKE_SHARED_LIBRARY_PREFIX}SPIFFS${CMAKE_SHARED_LIBRARY_SUFFIX}") + include_directories(${SPIFFS_INCLUDE_DIRS}) + + add_subdirectory(spiffs) + +endif() + +# add target ChibiOS dirs +add_subdirectory(Include) +add_subdirectory(common) +add_subdirectory(nanoBooter) +add_subdirectory(nanoCLR) + +# board folder will be added in main CMakeList diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CLR_Startup_Thread.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CLR_Startup_Thread.h new file mode 100644 index 00000000..3c394ef4 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CLR_Startup_Thread.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _CLRSTARTUPTHREAD_ +#define _CLRSTARTUPTHREAD_ + +// declaration of RTOS thread +void CLRStartupThread(void const * argument); + +#endif //_CLRSTARTUPTHREAD_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CMakeLists.txt new file mode 100644 index 00000000..011c8fad --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append include directory for target ChibiOS +list(APPEND TARGET_CHIBIOS_COMMON_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") + +# make var global +set(TARGET_CHIBIOS_COMMON_INCLUDE_DIRS ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} CACHE INTERNAL "make global") + +# add header with target platform definitions +if(CHIBIOS_COMMUNITY_TARGET) + configure_file("${CMAKE_SOURCE_DIR}/CMake/ChibiOS_target_os.h.in" + "${CMAKE_BINARY_DIR}/targets-community/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}/target_os.h" @ONLY) +else() + configure_file("${CMAKE_SOURCE_DIR}/CMake/ChibiOS_target_os.h.in" + "${CMAKE_BINARY_DIR}/targets/CMSIS-OS/ChibiOS/${CHIBIOS_BOARD}/target_os.h" @ONLY) +endif() diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/LaunchCLR.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/LaunchCLR.h new file mode 100644 index 00000000..15e319ef --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/LaunchCLR.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _LAUNCHCLR_H_ +#define _LAUNCHCLR_H_ + +void LaunchCLR(uint32_t address); +bool CheckValidCLRImage(uint32_t address); + +#endif //_LAUNCHCLR_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/TargetPAL_BlockStorage.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/TargetPAL_BlockStorage.h new file mode 100644 index 00000000..805c2e32 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/TargetPAL_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_BLOCKSTORAGE_H_ +#define _TARGET_PAL_BLOCKSTORAGE_H_ 1 + +#include + +#endif // _TARGET_PAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_BlockStorage_STM32FlashDriver.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_BlockStorage_STM32FlashDriver.h new file mode 100644 index 00000000..421ebc4d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_BlockStorage_STM32FlashDriver.h @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_STM32FLASH_DRIVER_H_ +#define _TARGET_STM32FLASH_DRIVER_H_ 1 + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool STM32FlashDriver_InitializeDevice(void*); +bool STM32FlashDriver_UninitializeDevice(void*); +DeviceBlockInfo* STM32FlashDriver_GetDeviceInfo(void*); +bool STM32FlashDriver_Read(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer); +bool STM32FlashDriver_Write(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite); +bool STM32FlashDriver_IsBlockErased(void*, ByteAddress blockAddress, unsigned int length); +bool STM32FlashDriver_EraseBlock(void*, ByteAddress address); + +#ifdef __cplusplus +} +#endif + +#endif //_TARGET_STM32FLASH_DRIVER_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_Windows_Storage.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_Windows_Storage.h new file mode 100644 index 00000000..57bd9b3f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/Target_Windows_Storage.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_WINDOWS_STORAGE_H_ +#define _TARGET_WINDOWS_STORAGE_H_ 1 + +#define SDCARD_POLLING_INTERVAL (10) +#define SDCARD_POLLING_DELAY (500) + + +#define USB_MSD_POLLING_INTERVAL (1000) +#define USB_MSD_POLLING_DELAY (1000) + +#ifdef __cplusplus +extern "C" { +#endif + + // declaration of storage working threads + void SdCardWorkingThread(void const * argument); + void UsbMsdWorkingThread(void const * argument); + +#ifdef __cplusplus +} +#endif + +#endif //_TARGET_WINDOWS_STORAGE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/WireProtocol_ReceiverThread.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/WireProtocol_ReceiverThread.h new file mode 100644 index 00000000..c6b75c3e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/WireProtocol_ReceiverThread.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_RECEIVERTHREAD_H_ +#define _WIREPROTOCOL_RECEIVERTHREAD_H_ + +// declaration of RTOS thread +void ReceiverThread(void const * argument); + +#endif //_WIREPROTOCOL_RECEIVERTHREAD_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/platform_target_capabilities.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/platform_target_capabilities.h new file mode 100644 index 00000000..eb7f38d8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/platform_target_capabilities.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _PLATFORM_TARGET_CAPABILITIES_H_ +#define _PLATFORM_TARGET_CAPABILITIES_H_ 1 + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.Stm32.TargetCapabilities (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +// this platform doesn't have any declared capabilities + +// the targets of this platform can declate these capabilities +typedef enum TargetCapabilities +{ + // JTAG update + TargetCapabilities_JtagUpdate = 0x00000000, + + // DFU update + TargetCapabilities_DfuUpdate = 0x00040000, + +}TargetCapabilities; + +#ifdef __cplusplus +} +#endif + +#endif //_PLATFORM_TARGET_CAPABILITIES_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL.h new file mode 100644 index 00000000..fe2ab9b4 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_H_ +#define _TARGET_HAL_H_ + +#include +#include +#include +#include + +#define GLOBAL_LOCK() chSysLock(); +#define GLOBAL_UNLOCK(); chSysUnlock(); +// platform dependent delay +#define PLATFORM_DELAY(milliSecs) osDelay(milliSecs); + +// Definitions for Sockets/Network +#define GLOBAL_LOCK_SOCKETS(x) + +#define PLATFORM_DEPENDENT__SOCKETS_MAX_COUNT 16 + +#define LPCSTR const char* + +// these macros are to be used at entry/exit of native interrupt handlers +#define NATIVE_INTERRUPT_START SystemState_SetNoLock( SYSTEM_STATE_ISR ); \ + SystemState_SetNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); +#define NATIVE_INTERRUPT_END SystemState_ClearNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); \ + SystemState_ClearNoLock( SYSTEM_STATE_ISR ); + +#if !defined(BUILD_RTM) + +#define HARD_BREAKPOINT() HARD_Breakpoint() + +// #if defined(_DEBUG) +// #define DEBUG_HARD_BREAKPOINT() HARD_Breakpoint() +// #else +// #define DEBUG_HARD_BREAKPOINT() +// #endif + +// #else + +// #define HARD_BREAKPOINT() +// #define DEBUG_HARD_BREAKPOINT() + +#endif // !defined(BUILD_RTM) + + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// DEBUGGER HELPER // +// The line below is meant to be used as helper on checking that the execution engine is running. // +// This can be inferred by checking if Events_WaitForEvents loop is running. // +// The implementation should is to be provided by each target at target_common.h.in // +//////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(BUILD_RTM) + #define EVENTS_HEART_BEAT +#else + #ifndef EVENTS_HEART_BEAT + #define EVENTS_HEART_BEAT __NOP() + #endif // EVENTS_HEART_BEAT +#endif + +#define NANOCLR_STOP() CPU_Reset(); + +extern int HeapBegin; +extern int HeapEnd; + +extern uint32_t __nanoImage_start__; +extern uint32_t __nanoImage_end__; +extern uint32_t __nanoConfig_start__; +extern uint32_t __nanoConfig_end__; +extern uint32_t __deployment_start__; +extern uint32_t __deployment_end__; + +#endif //_TARGET_HAL_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Power.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Power.h new file mode 100644 index 00000000..96d00fee --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Power.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_POWER_H_ +#define _TARGET_HAL_POWER_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +#endif //_TARGET_HAL_POWER_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Time.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Time.h new file mode 100644 index 00000000..88083178 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Time.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_TIME_H_ +#define _TARGET_HAL_TIME_H_ 1 + +#include + +#define HAL_Time_CurrentSysTicks osKernelSysTick + +#endif //_TARGET_HAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Watchdog.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Watchdog.h new file mode 100644 index 00000000..c0748717 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetHAL_Watchdog.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#include +#include + +#ifndef _TARGETHAL_WATCHDOG_H_ +#define _TARGETHAL_WATCHDOG_H_ 1 + +#if (HAL_USE_WDG) + #if (STM32_LSI_ENABLED == FALSE) + #error "LSI clock must be enabled for independent watchdog (IWDG) to work" + #endif + + // if the timeout isn't set at target level, set a default value (10 seconds) + #if !defined(IWATCHDOG_TIMEOUT_MILLIS) + #define IWATCHDOG_TIMEOUT_MILLIS 10000 + #endif + +#endif + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL.h new file mode 100644 index 00000000..b8edb901 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL.h @@ -0,0 +1,22 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_H_ +#define _TARGETPAL_H_ + +#include + + +#if defined(STM32L0XX) || defined(STM32F0XX) || defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32H7XX) + +// Contains available GPIO ports for the current board +extern stm32_gpio_t* gpioPort[]; + +//Gets the GPIO according to a pin number +#define GPIO_PORT(pin) (gpioPort[pin/16]) + +#endif + +#endif // _TARGETPAL_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL_Time.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL_Time.h new file mode 100644 index 00000000..3d857fd3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/targetPAL_Time.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_TIME_H_ +#define _TARGET_PAL_TIME_H_ 1 + +#include + + +#endif //_TARGET_PAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/vectors.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/vectors.h new file mode 100644 index 00000000..bdf3a46a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Include/vectors.h @@ -0,0 +1,57 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Interrupt vectors for Cortex-Mx devices. + +#ifndef VECTORS_H +#define VECTORS_H + +#include "cmparams.h" + +#if !defined(_FROM_ASM_) +/** + * @brief Type of an IRQ vector. + */ +typedef void (*irq_vector_t)(void); + +// Type of a structure representing the 16 system vectors of Cortex-M. +// The remaining interrupt vectors are not included. +typedef struct { + uint32_t *init_stack; + irq_vector_t reset_handler; + irq_vector_t nmi_handler; + irq_vector_t hardfault_handler; + irq_vector_t memmanage_handler; + irq_vector_t busfault_handler; + irq_vector_t usagefault_handler; + irq_vector_t vector1c; + irq_vector_t vector20; + irq_vector_t vector24; + irq_vector_t vector28; + irq_vector_t svc_handler; + irq_vector_t debugmonitor_handler; + irq_vector_t vector34; + irq_vector_t pendsv_handler; + irq_vector_t systick_handler; + irq_vector_t vectors[CORTEX_NUM_VECTORS]; +} vectors_t; +#endif /* !defined(_FROM_ASM_) */ + +#if !defined(_FROM_ASM_) +extern vectors_t _vectors; +#endif + +#endif // VECTORS_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.c new file mode 100644 index 00000000..b9c58339 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.c @@ -0,0 +1,477 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + * **** This file incorporates work covered by the following copyright and **** + * **** permission notice: **** + * + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/** + * @file lwipthread.c + * @brief LWIP wrapper thread code. + * @addtogroup LWIP_THREAD + * @{ + */ + +#include "hal.h" +#include "evtimer.h" + +#include "nf_lwipthread.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LWIP_DHCP +#include +#endif + +#if LWIP_AUTOIP +#include +#endif + +#define PERIODIC_TIMER_ID 1 +#define FRAME_RECEIVED_ID 2 + +/* + * Suspension point for initialization procedure. + */ +thread_reference_t lwip_trp = NULL; + +/* + * Stack area for the LWIP-MAC thread. + */ +static THD_WORKING_AREA(wa_lwip_thread, LWIP_THREAD_STACK_SIZE); + +/* + * Initialization. + */ +static void low_level_init(struct netif *netif) { + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* maximum transfer unit */ + netif->mtu = LWIP_NETIF_MTU; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an Ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + /* Do whatever else is needed to initialize interface. */ +} + +/* + * This function does the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +static err_t low_level_output(struct netif *netif, struct pbuf *p) { + struct pbuf *q; + MACTransmitDescriptor td; + + (void)netif; + if (macWaitTransmitDescriptor(ÐD1, &td, TIME_MS2I(LWIP_SEND_TIMEOUT)) != MSG_OK) + return ERR_TIMEOUT; + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* Iterates through the pbuf chain. */ + for(q = p; q != NULL; q = q->next) + macWriteTransmitDescriptor(&td, (uint8_t *)q->payload, (size_t)q->len); + macReleaseTransmitDescriptor(&td); + + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); + if (((u8_t*)p->payload)[0] & 1) { + /* broadcast or multicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + } + else { + /* unicast packet */ + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + } + /* increase ifoutdiscards or ifouterrors on error */ + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +/* + * Receives a frame. + * Allocates a pbuf and transfers the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static bool low_level_input(struct netif *netif, struct pbuf **pbuf) { + MACReceiveDescriptor rd; + struct pbuf *q; + u16_t len; + + (void)netif; + + osalDbgAssert(pbuf != NULL, "invalid null pointer"); + + if (macWaitReceiveDescriptor(ÐD1, &rd, TIME_IMMEDIATE) != MSG_OK) + return false; + + len = (u16_t)rd.size; + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + *pbuf = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (*pbuf != NULL) { +#if ETH_PAD_SIZE + pbuf_header(pbuf, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* Iterates through the pbuf chain. */ + for(q = *pbuf; q != NULL; q = q->next) + macReadReceiveDescriptor(&rd, (uint8_t *)q->payload, (size_t)q->len); + macReleaseReceiveDescriptor(&rd); + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, *pbuf->tot_len); + + if (*(uint8_t *)((*pbuf)->payload) & 1) { + /* broadcast or multicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); + } + else { + /* unicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + } + +#if ETH_PAD_SIZE + pbuf_header(pbuf, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } + else { + macReleaseReceiveDescriptor(&rd); // Drop packet + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifindiscards); + } + + return true; +} + +/* + * Called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netifapi_netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialised + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +static err_t ethernetif_init(struct netif *netif) { + osalDbgAssert((netif != NULL), "netif != NULL"); + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LWIP_LINK_SPEED); + + netif->state = NULL; + netif->name[0] = LWIP_IFNAME0; + netif->name[1] = LWIP_IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +static struct netif thisif = { 0 }; + +struct netif * nf_getNetif() { + return &thisif; +} + +/** + * @brief LWIP handling thread. + * + * @param[in] p pointer to a @p lwipthread_opts structure or @p NULL + * @return The function does not return. + */ +static THD_FUNCTION(lwip_thread, p) { + event_timer_t evt; + event_listener_t el0, el1; + ip_addr_t ip, gateway, netmask; + static const MACConfig mac_config = {thisif.hwaddr}; + net_addr_mode_t addressMode; + err_t result; + + chRegSetThreadName(LWIP_THREAD_NAME); + + /* Initializes the thing.*/ + tcpip_init(NULL, NULL); + + /* TCP/IP parameters, runtime or compile time.*/ + if (p) { + struct lwipthread_opts *opts = p; + unsigned i; + + for (i = 0; i < 6; i++) + { + thisif.hwaddr[i] = opts->macaddress[i]; + } +#if LWIP_IPV6 + // FIXME IPV6 + //ip.u_addr = opts->address; + //gateway.u_addr = opts->gateway; + //netmask.u_addr = opts->netmask; +#else + ip.addr = opts->address; + gateway.addr = opts->gateway; + netmask.addr = opts->netmask; +#endif + addressMode = opts->addrMode; +#if LWIP_NETIF_HOSTNAME + thisif.hostname = opts->ourHostName; +#endif + } + else { + thisif.hwaddr[0] = LWIP_ETHADDR_0; + thisif.hwaddr[1] = LWIP_ETHADDR_1; + thisif.hwaddr[2] = LWIP_ETHADDR_2; + thisif.hwaddr[3] = LWIP_ETHADDR_3; + thisif.hwaddr[4] = LWIP_ETHADDR_4; + thisif.hwaddr[5] = LWIP_ETHADDR_5; +#if LWIP_IPV6 + // FIXME IPV6 + // LWIP_IPADDR(&ip); + // LWIP_GATEWAY(&gateway); + // LWIP_NETMASK(&netmask); +#else + LWIP_IPADDR(&ip); + LWIP_GATEWAY(&gateway); + LWIP_NETMASK(&netmask); +#endif + addressMode = NET_ADDRESS_STATIC; +#if LWIP_NETIF_HOSTNAME + thisif.hostname = NULL; +#endif + } + +#if LWIP_NETIF_HOSTNAME + if (thisif.hostname == NULL) + thisif.hostname = LWIP_NETIF_HOSTNAME_STRING; +#endif + + macStart(ÐD1, &mac_config); + +#if LWIP_NETCONN_SEM_PER_THREAD + sys_arch_netconn_sem_alloc(); +#endif + + /* Add interface. */ + result = netifapi_netif_add(&thisif, &ip, &netmask, &gateway, NULL, ethernetif_init, tcpip_input); + if (result != ERR_OK) + { + chThdSleepMilliseconds(1000); // Give some time to print any other diagnostics. + osalSysHalt("netif_add error"); // Not sure what else we can do if an error occurs here. + }; + + netif_set_default(&thisif); + + switch (addressMode) + { +#if LWIP_AUTOIP + case NET_ADDRESS_AUTO: + autoip_start(&thisif); + break; +#endif + + default: + netif_set_up(&thisif); + break; + } + + /* Setup event sources.*/ + evtObjectInit(&evt, LWIP_LINK_POLL_INTERVAL); + evtStart(&evt); + chEvtRegisterMask(&evt.et_es, &el0, PERIODIC_TIMER_ID); + chEvtRegisterMask(macGetReceiveEventSource(ÐD1), &el1, FRAME_RECEIVED_ID); + chEvtAddEvents(PERIODIC_TIMER_ID | FRAME_RECEIVED_ID); + + /* Resumes the caller and goes to the final priority.*/ + chThdResume(&lwip_trp, MSG_OK); + chThdSetPriority(LWIP_THREAD_PRIORITY); + + // setup SNTP + #if SNTP_SERVER_DNS + sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_setservername(0, SNTP_SERVER_DEFAULT_ADDRESS); + sntp_init(); + #endif + + while (true) { + eventmask_t mask = chEvtWaitAny(ALL_EVENTS); + if (mask & PERIODIC_TIMER_ID) { + bool current_link_status = macPollLinkStatus(ÐD1); + if (current_link_status != netif_is_link_up(&thisif)) { + if (current_link_status) { + tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up, + &thisif, 0); +#if LWIP_DHCP + if (addressMode == NET_ADDRESS_DHCP) + { + dhcp_start(&thisif); + } + + // start SNTP request + #if SNTP_SERVER_DNS + sntp_init(); + #endif +#endif + + } + else { + tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down, + &thisif, 0); +#if LWIP_DHCP + if (addressMode == NET_ADDRESS_DHCP) + dhcp_stop(&thisif); +#endif + // no connection, stop SNTP + #if SNTP_SERVER_DNS + sntp_stop(); + #endif + } + } + } + + if (mask & FRAME_RECEIVED_ID) { + struct pbuf *p; + while (low_level_input(&thisif, &p)) { + if (p != NULL) { + struct eth_hdr *ethhdr = p->payload; + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: + /* full packet send to tcpip_thread to process */ + if (thisif.input(p, &thisif) == ERR_OK) + break; + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + /* Falls through */ + default: + pbuf_free(p); + } + } + } + } + } + +#if LWIP_NETCONN_SEM_PER_THREAD + sys_arch_netconn_sem_free(); +#endif +} + +/** + * @brief Initializes the lwIP subsystem. + * @note The function exits after the initialization is finished. + * + * @param[in] opts pointer to the configuration structure, if @p NULL + * then the static configuration is used. + */ +void lwipInit(const lwipthread_opts_t *opts) { + /* Creating the lwIP thread (it changes priority internally).*/ + chThdCreateStatic(wa_lwip_thread, sizeof (wa_lwip_thread), + chThdGetPriorityX() - 1, lwip_thread, (void *)opts); + + /* Waiting for the lwIP thread complete initialization. Note, + this thread reaches the thread reference object first because + the relative priorities.*/ + chSysLock(); + chThdSuspendS(&lwip_trp); + chSysUnlock(); +} + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.h new file mode 100644 index 00000000..9b6c2cc9 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/nf_lwipthread.h @@ -0,0 +1,247 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file lwipthread.h + * @brief LWIP wrapper thread macros and structures. + * @addtogroup LWIP_THREAD + * @{ + */ + +#ifndef LWIPTHREAD_H +#define LWIPTHREAD_H + +#include + +/** + * @brief lwIP default network interface maximum transmission unit (MTU). + */ +#if !defined(LWIP_NETIF_MTU) || defined(__DOXYGEN__) +#define LWIP_NETIF_MTU 1500 +#endif + +/** + * @brief Default network interface hostname. + */ +#if !defined(LWIP_NETIF_HOSTNAME_STRING) || defined(__DOXYGEN__) +#define LWIP_NETIF_HOSTNAME_STRING "lwip" +#endif + +/** + * @brief Default network interface hostname. + */ +#if !defined(LWIP_THREAD_NAME) || defined(__DOXYGEN__) +#define LWIP_THREAD_NAME "lwipthread" +#endif + +/** + * @brief lwIP thread priority. + */ +#ifndef LWIP_THREAD_PRIORITY +#define LWIP_THREAD_PRIORITY NORMALPRIO +#endif + +/** + * @brief lwIP thread stack size. + */ +#if !defined(LWIP_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define LWIP_THREAD_STACK_SIZE 672 +#endif + +/** + * @brief Link poll interval. + */ +#if !defined(LWIP_LINK_POLL_INTERVAL) || defined(__DOXYGEN__) +#define LWIP_LINK_POLL_INTERVAL TIME_S2I(5) +#endif + +/** + * @brief IP Address. + */ +#if !defined(LWIP_IPADDR) || defined(__DOXYGEN__) +#define LWIP_IPADDR(p) IP4_ADDR(p, 192, 168, 1, 10) +#endif + +/** + * @brief IP Gateway. + */ +#if !defined(LWIP_GATEWAY) || defined(__DOXYGEN__) +#define LWIP_GATEWAY(p) IP4_ADDR(p, 192, 168, 1, 1) +#endif + +/** + * @brief IP netmask. + */ +#if !defined(LWIP_NETMASK) || defined(__DOXYGEN__) +#define LWIP_NETMASK(p) IP4_ADDR(p, 255, 255, 255, 0) +#endif + +/** + * @brief Transmission timeout. + */ +#if !defined(LWIP_SEND_TIMEOUT) || defined(__DOXYGEN__) +#define LWIP_SEND_TIMEOUT 50 +#endif + +/** + * @brief Link speed. + */ +#if !defined(LWIP_LINK_SPEED) || defined(__DOXYGEN__) +#define LWIP_LINK_SPEED 100000000 +#endif + +/** + * @brief MAC Address byte 0. + */ +#if !defined(LWIP_ETHADDR_0) || defined(__DOXYGEN__) +#define LWIP_ETHADDR_0 0xC2 +#endif + +/** + * @brief MAC Address byte 1. + */ +#if !defined(LWIP_ETHADDR_1) || defined(__DOXYGEN__) +#define LWIP_ETHADDR_1 0xAF +#endif + +/** + * @brief MAC Address byte 2. + */ +#if !defined(LWIP_ETHADDR_2) || defined(__DOXYGEN__) +#define LWIP_ETHADDR_2 0x51 +#endif + +/** + * @brief MAC Address byte 3. + */ +#if !defined(LWIP_ETHADDR_3) || defined(__DOXYGEN__) +#define LWIP_ETHADDR_3 0x03 +#endif + +/** + * @brief MAC Address byte 4. + */ +#if !defined(LWIP_ETHADDR_4) || defined(__DOXYGEN__) +#define LWIP_ETHADDR_4 0xCF +#endif + +/** + * @brief MAC Address byte 5. + */ +#if !defined(LWIP_ETHADDR_5) || defined(__DOXYGEN__) +#define LWIP_ETHADDR_5 0x46 +#endif + +/** + * @brief Interface name byte 0. + */ +#if !defined(LWIP_IFNAME0) || defined(__DOXYGEN__) +#define LWIP_IFNAME0 'm' +#endif + +/** + * @brief Interface name byte 1. + */ +#if !defined(LWIP_IFNAME1) || defined(__DOXYGEN__) +#define LWIP_IFNAME1 's' +#endif + +/** + * @brief Utility macro to define an IPv4 address. + * + * @note Within the networking subsystem, IPv4 network addresses are + * stored with LS byte of network address in MS byte of unsigned int. + */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define IP4_ADDR_VALUE(a,b,c,d) \ + (((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff)) +#else +#define IP4_ADDR_VALUE(a,b,c,d) \ + (((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff)) +#endif + +/** + * @brief Startup network assigning modes. + */ +typedef enum { +#if LWIP_DHCP || defined(__DOXYGEN__) + /** + * @brief Assign a DHCP given address. + */ + NET_ADDRESS_DHCP = 1, +#endif + /** + * @brief Assign a statically IPv4 address. + */ + NET_ADDRESS_STATIC = 2, +#if LWIP_AUTOIP || defined(__DOXYGEN__) + /** + * @brief Assign an IPv4 link-Local address. + */ + NET_ADDRESS_AUTO = 3 +#endif +} net_addr_mode_t; + +/** + * @brief Runtime TCP/IP settings. + */ +typedef struct lwipthread_opts { + /** + * @brief Pointer to MAC address as an array of 6 unsigned bytes. + */ + uint8_t *macaddress; + /** + * @brief Network address as 32-bit unsigned integer. + */ + uint32_t address; + /** + * @brief Network subnet mask as 32-bit unsigned integer. + */ + uint32_t netmask; + /** + * @brief Network gateway as 32-bit unsigned integer. + */ + uint32_t gateway; + /** + * @brief Startup network addressing mode - static, DHCP, auto. + */ + net_addr_mode_t addrMode; + /** + * @brief Host name. If NULL, a default string is used. + * @note Not checked for validity. In particular, spaces not allowed. + */ +#if LWIP_NETIF_HOSTNAME || defined(__DOXYGEN__) + const char *ourHostName; +#endif +} lwipthread_opts_t; + +#ifdef __cplusplus +extern "C" { +#endif + void lwipInit(const lwipthread_opts_t *opts); +#ifdef __cplusplus +} +#endif + +#endif /* LWIPTHREAD_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/platform_sys_arch.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/platform_sys_arch.c new file mode 100644 index 00000000..d73760a8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/Lwip/platform_sys_arch.c @@ -0,0 +1,186 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science. All rights reserved. +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// from the original source code file +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGE. +// +// This file is part of the lwIP TCP/IP stack. +// +// Author: Adam Dunkels + +// see http://lwip.wikia.com/wiki/Porting_for_an_OS for instructions + +#include +#include +#include + +#include "lwip/opt.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" + +#include "arch/cc.h" +#include "arch/sys_arch.h" + +// Creates an empty mailbox. +// Developer notes +// Because ChibiOS CMSIS wrapper requires static allocation of message queues we can't use the +// standard CMSIS define like osMessageQDef(QUEUE, size, void *); +// the workaround is to use a ChibiOS mailbox and allocate memory for the mailbox and the buffer +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + *mbox = platform_malloc(sizeof(mailbox_t) + sizeof(msg_t) * size); + if (*mbox == NULL) + { + return ERR_MEM; + } + + // init the mailbox + chMBObjectInit((mailbox_t*)*mbox, (void *)(((uint8_t *)*mbox) + sizeof(mailbox_t)), size); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + if (*mbox == NULL) + { + return ERR_MEM; + } + + return ERR_OK; +} + +// Deallocates a mailbox. +// Because this mailbox was created from heap (see sys_mbox_new above) need to free it here +void sys_mbox_free(sys_mbox_t *mbox) +{ + msg_t msgp; + + // check for messages waiting + // If there are messages still present in the + // mailbox when the mailbox is deallocated, it is an indication of a + // programming error in lwIP and the developer should be notified. + if(chMBFetchI((mailbox_t*)*mbox, &msgp) != MSG_TIMEOUT) + { + #if SYS_STATS + lwip_stats.sys.mbox.err++; + #endif /* SYS_STATS */ + + // breaks execution to ensure developer is aware that this function needs a strong implementation at platform level + __asm volatile("BKPT #0\n"); + } + + // ...free memory from mailbox + platform_free(*mbox); +} + +u32_t sys_now(void) +{ + #if OSAL_ST_FREQUENCY == 1000 + return (u32_t)chVTGetSystemTimeX(); + #elif (OSAL_ST_FREQUENCY / 1000) >= 1 && (OSAL_ST_FREQUENCY % 1000) == 0 + return ((u32_t)chVTGetSystemTimeX() - 1) / (OSAL_ST_FREQUENCY / 1000) + 1; + #elif (1000 / OSAL_ST_FREQUENCY) >= 1 && (1000 % OSAL_ST_FREQUENCY) == 0 + return ((u32_t)chVTGetSystemTimeX() - 1) * (1000 / OSAL_ST_FREQUENCY) + 1; + #else + return (u32_t)(((u64_t)(chVTGetSystemTimeX() - 1) * 1000) / OSAL_ST_FREQUENCY) + 1; + #endif +} + +// need to implement this calling the CMSIS implementation because ChibiOS declares this +// TODO can be removed if we ever stop using ChibiOS lwIP source +void sys_sem_signal_S(sys_sem_t* sem) +{ + sys_sem_signal(sem); +} + +#if LWIP_NETCONN_SEM_PER_THREAD + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// required for LWIP_NETCONN_SEM_PER_THREAD +// need to implement this with ChibiOS API because CMSIS RTOS doesn't have an API to deal with this +// +// For this to work ChibiOS thread struct has to be extended at target level. +// This is accomplished by adding the following line at the target 'chconf.h' file +// void* localStorage; + +sys_sem_t* sys_arch_netconn_sem_get(void) +{ + thread_t* currentThread = chThdGetSelfX(); + LWIP_ASSERT("thread != NULL", currentThread != NULL); +volatile char* tName = (char*)currentThread->name; +(void)tName; + return currentThread->localStorage; +} + +void sys_arch_netconn_sem_alloc(void) +{ + void* storage; + + thread_t* currentThread = chThdGetSelfX(); + LWIP_ASSERT("thread != NULL", currentThread != NULL); + + storage = currentThread->localStorage; + if(storage == NULL) + { + // semaphore doesn't exist + sys_sem_t* semaphore = NULL; + err_t err; + + err = sys_sem_new(semaphore, 0); + LWIP_ASSERT("err == ERR_OK", err == ERR_OK); + LWIP_ASSERT("semaphore invalid", sys_sem_valid(semaphore)); + + // store it in thread struc + currentThread->localStorage = semaphore; + } +} + +void sys_arch_netconn_sem_free(void) +{ + void* storage; + + thread_t* currentThread = chThdGetSelfX(); + LWIP_ASSERT("thread != NULL", currentThread != NULL); + + storage = currentThread->localStorage; + if(storage == NULL) + { + // there is a semaphore + sys_sem_t* semaphore = storage; + + // free memory allocation + sys_sem_free(semaphore); + + // clear pointer in thread struct + currentThread->localStorage = NULL; + } +} + +#endif // LWIP_NETCONN_SEM_PER_THREAD diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/CMakeLists.txt new file mode 100644 index 00000000..8e04d314 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/CMakeLists.txt @@ -0,0 +1,237 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# add dependencies from CHIBIOS_FILESYSTEM_COMPONENTS (this is required to make sure that ChibiOS filesystem components are unzip at the proper locations before the build starts) +# only required if filesystem is ON +if(USE_FILESYSTEM_OPTION) + add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf CHIBIOS_FILESYSTEM_COMPONENTS) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf CHIBIOS_FILESYSTEM_COMPONENTS) +endif() + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/mbn_quail_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/mbn_quail_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/mbn_quail_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/mbn_quail_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +############################################################################ +# CRT heap is assigned to RAM4 region @ CCM SRAM so we are OK to use it all +############################################################################ +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x10000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x10000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) + +# if HEX2DFU tool is available pack the binaries into a DFU package +if(HEX2DFU_TOOL_AVAILABLE) + + #################################################################################################### + ## when changing the linker file make sure to update the new addresses for the image files below ## + ## DO NOT use the leading 0x notation, just the address in plain hexadecimal formating ## + #################################################################################################### + + if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08008000 + ${PROJECT_SOURCE_DIR}/build/nanobooter-nanoclr.dfu + ) + else() + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08004000 + ${PROJECT_SOURCE_DIR}/build/nanobooter-nanoclr.dfu + ) + endif() + + +endif() diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/README.md new file mode 100644 index 00000000..7f328793 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/README.md @@ -0,0 +1,34 @@ +## Configuration of Chibios, HAL and MCU ## + +For a successful build the following changes are required: + +In _halconf.g_ (in both nanoBooter and nanoCLR folders), when compared with a default file: +- HAL_USE_SERIAL to TRUE +- HAL_USE_SERIAL_USB to TRUE +- HAL_USE_USB to TRUE +- SERIAL_DEFAULT_BITRATE to 921600 + +In _mcuconf.h_ (in both nanoBooter and nanoCLR folders), when compared with a default file: +- STM32_SERIAL_USE_USART2 to TRUE +- STM32_USB_USE_OTG1 to TRUE + +In _chconf.h_ (_**only**_ for nanoCLR folder), when compared with a default file: +- set the CORTEX_VTOR_INIT with the appropriate address of the vector table for nanoCLR + + +## Definitions for each image ## + +Any defines specific to an image (nanoBooter or nanoCLR) that are to be made available throughout the code should be added to the _target_board.h.in_. There is one in [nanoBooter](nanoBooter/target_board.h.in) and another in [nanoCLR](nanoCLR/target_board.h.in) directories, allowing different defines for each one. +Defines that are common to a target board should be added to the [_target_common.h.in_](target_common.h.in). +The content of these files is parsed by CMake. It can include CMake variables. Check the documentation of CMake config files [here](https://cmake.org/cmake/help/v3.7/command/configure_file.html?highlight=configure_file). + + + + +**NOTE: this configuration was successfully tested in a ST_STM32F4_DISCOVERY board using the Serial over USB connection on USB port 1 that creates a virtual COM port.** + + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.c new file mode 100644 index 00000000..8b90ece5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +// #if STM32_HAS_GPIOF || defined(__DOXYGEN__) +// gpio_setup_t PFData; +// #endif +// #if STM32_HAS_GPIOG || defined(__DOXYGEN__) +// gpio_setup_t PGData; +// #endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +// #if STM32_HAS_GPIOI || defined(__DOXYGEN__) +// gpio_setup_t PIData; +// #endif +// #if STM32_HAS_GPIOJ || defined(__DOXYGEN__) +// gpio_setup_t PJData; +// #endif +// #if STM32_HAS_GPIOK || defined(__DOXYGEN__) +// gpio_setup_t PKData; +// #endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +// #if STM32_HAS_GPIOF +// {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, +// VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +// #endif +// #if STM32_HAS_GPIOG +// {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, +// VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +// #endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +// #if STM32_HAS_GPIOI +// {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, +// VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +// #endif +// #if STM32_HAS_GPIOJ +// {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, +// VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +// #endif +// #if STM32_HAS_GPIOK +// {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, +// VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +// #endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +// #if STM32_HAS_GPIOF +// gpio_init(GPIOF, &gpio_default_config.PFData); +// #endif +// #if STM32_HAS_GPIOG +// gpio_init(GPIOG, &gpio_default_config.PGData); +// #endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +// #if STM32_HAS_GPIOI +// gpio_init(GPIOI, &gpio_default_config.PIData); +// #endif +// #if STM32_HAS_GPIOJ +// gpio_init(GPIOJ, &gpio_default_config.PJData); +// #endif +// #if STM32_HAS_GPIOK +// gpio_init(GPIOK, &gpio_default_config.PKData); +// #endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + + return !palReadLine(LINE_SD_DETECT); +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.h new file mode 100644 index 00000000..11a4490d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/board.h @@ -0,0 +1,976 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef BOARD_H +#define BOARD_H + +/* + * Board identifier. + */ +#define BOARD_MBN_QUAIL +#define BOARD_NAME "Mikrobus.Net QUAIL" + +#define BOARD_OTG_NOVBUSSENS + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 12000000U +#endif + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F427xx + +/* + * IO pins assignments. + */ +#define GPIOA_PA0 0U +#define GPIOA_INT1 1U +#define GPIOA_RST1 2U +#define GPIOA_CS1 3U +#define GPIOA_AN2 4U +#define GPIOA_AN4 5U +#define GPIOA_AN1 6U +#define GPIOA_AN3 7U +#define GPIOA_FLASH_HOLD 8U +#define GPIOA_TX4 9U +#define GPIOA_RX4 10U +#define GPIOA_OTG_FS_DM 11U +#define GPIOA_OTG_FS_DP 12U +#define GPIOA_FLASH_CS 13U +#define GPIOA_INT4 14U +#define GPIOA_GPIO1 15U + +#define GPIOB_GPIO2 0U +#define GPIOB_PB1 1U +#define GPIOB_BOOT1 2U +#define GPIOB_SPI1_CLK 3U +#define GPIOB_SPI1_MISO 4U +#define GPIOB_SPI1_MOSI 5U +#define GPIOB_I2C1_SCL 6U +#define GPIOB_I2C1_SDA 7U +#define GPIOB_PB8 8U +#define GPIOB_INT2 9U +#define GPIOB_GPIO3 10U +#define GPIOB_GPIO4 11U +#define GPIOB_GPIO5 12U +#define GPIOB_GPIO6 13U +#define GPIOB_OTG_HS_DM 14U +#define GPIOB_OTG_HS_DP 15U + +#define GPIOC_ID0 0U +#define GPIOC_ID1 1U +#define GPIOC_ID2 2U +#define GPIOC_LED3 3U +#define GPIOC_GPIO7 4U +#define GPIOC_GPIO8 5U +#define GPIOC_TX3 6U +#define GPIOC_RX3 7U +#define GPIOC_INT3 8U +#define GPIOC_FLASH_WP 9U +#define GPIOC_SPI3_CLK 10U +#define GPIOC_SPI3_MISO 11U +#define GPIOC_SPI3_MOSI 12U +#define GPIOC_GPIO9 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_RST4 0U +#define GPIOD_CS4 1U +#define GPIOD_GPIO10 2U +#define GPIOD_GPIO11 3U +#define GPIOD_GPIO12 4U +#define GPIOD_TX2 5U +#define GPIOD_RX2 6U +#define GPIOD_GPIO13 7U +#define GPIOD_TX1 8U +#define GPIOD_RX1 9U +#define GPIOD_GPIO14 10U +#define GPIOD_CS3 11U +#define GPIOD_RST3 12U +#define GPIOD_PWM3 13U +#define GPIOD_PWM4 14U +#define GPIOD_PWM2 15U + +#define GPIOE_CS2 0U +#define GPIOE_RST2 1U +#define GPIOE_GPIO15 2U +#define GPIOE_GPIO16 3U +#define GPIOE_GPIO17 4U +#define GPIOE_GPIO18 5U +#define GPIOE_GPIO19 6U +#define GPIOE_GPIO20 7U +#define GPIOE_GPIO21 8U +#define GPIOE_PWM1 9U +#define GPIOE_LED2 10U +#define GPIOE_GPIO22 11U +#define GPIOE_USB_DETECT 12U +#define GPIOE_GPIO23 13U +#define GPIOE_GPIO24 14U +#define GPIOE_LED1 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +/* + * IO lines assignments. + */ + + + // Christophe : what are those "lines" used for ? + +#define LINE_INT1 PAL_LINE(GPIOA, 1U) +#define LINE_RST1 PAL_LINE(GPIOA, 2U) +#define LINE_CS1 PAL_LINE(GPIOA, 3U) +#define LINE_AN2 PAL_LINE(GPIOA, 4U) +#define LINE_AN4 PAL_LINE(GPIOA, 5U) +#define LINE_AN1 PAL_LINE(GPIOA, 6U) +#define LINE_AN3 PAL_LINE(GPIOA, 7U) +#define LINE_FLASH_HOLD PAL_LINE(GPIOA, 8U) +#define LINE_TX4 PAL_LINE(GPIOA, 9U) +#define LINE_RX4 PAL_LINE(GPIOA, 10U) +#define LINE_OTG_FS_DM PAL_LINE(GPIOA, 11U) +#define LINE_OTG_FS_DP PAL_LINE(GPIOA, 12U) +#define LINE_FLASH_CS PAL_LINE(GPIOA, 13U) +#define LINE_INT4 PAL_LINE(GPIOA, 14U) +#define LINE_GPIO1 PAL_LINE(GPIOA, 15U) + +#define LINE_GPIO2 PAL_LINE(GPIOB, 0U) +#define LINE_PB1 PAL_LINE(GPIOB, 1U) +#define LINE_BOOT1 PAL_LINE(GPIOB, 2U) +#define LINE_SPI1_CLK PAL_LINE(GPIOB, 3U) +#define LINE_SPI1_MISO PAL_LINE(GPIOB, 4U) +#define LINE_SPI1_MOSI PAL_LINE(GPIOB, 5U) +#define LINE_I2C1_SCL PAL_LINE(GPIOB, 6U) +#define LINE_I2C1_SDA PAL_LINE(GPIOB, 7U) +#define LINE_PB8 PAL_LINE(GPIOB, 8U) +#define LINE_INT2 PAL_LINE(GPIOB, 9U) +#define LINE_GPIO3 PAL_LINE(GPIOB, 10U) +#define LINE_GPIO4 PAL_LINE(GPIOB, 11U) +#define LINE_GPIO5 PAL_LINE(GPIOB, 12U) +#define LINE_GPIO6 PAL_LINE(GPIOB, 13U) +#define LINE_OTG_HS_DM PAL_LINE(GPIOB, 14U) +#define LINE_OTG_HS_DP PAL_LINE(GPIOB, 15U) + +#define LINE_ID0 PAL_LINE(GPIOC, 0U) +#define LINE_ID1 PAL_LINE(GPIOC, 1U) +#define LINE_ID2 PAL_LINE(GPIOC, 2U) +#define LINE_LED3 PAL_LINE(GPIOC, 3U) +#define LINE_GPIO7 PAL_LINE(GPIOC, 4U) +#define LINE_GPIO8 PAL_LINE(GPIOC, 5U) +#define LINE_TX3 PAL_LINE(GPIOC, 6U) +#define LINE_RX3 PAL_LINE(GPIOC, 7U) +#define LINE_INT3 PAL_LINE(GPIOC, 8U) +#define LINE_FLASH_WP PAL_LINE(GPIOC, 9U) +#define LINE_SPI3_CLK PAL_LINE(GPIOC, 10U) +#define LINE_SPI3_MISO PAL_LINE(GPIOC, 11U) +#define LINE_SPI3_MOSI PAL_LINE(GPIOC, 12U) +#define LINE_GPIO9 PAL_LINE(GPIOC, 13U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) + +#define LINE_RST4 PAL_LINE(GPIOD, 0U) +#define LINE_CS4 PAL_LINE(GPIOD, 1U) +#define LINE_CS5 PAL_LINE(GPIOD, 2U) +#define LINE_GPIO11 PAL_LINE(GPIOD, 3U) +#define LINE_GPIO12 PAL_LINE(GPIOD, 4U) +#define LINE_CS6 PAL_LINE(GPIOD, 5U) +#define LINE_RX2 PAL_LINE(GPIOD, 6U) +#define LINE_CS7 PAL_LINE(GPIOD, 7U) +#define LINE_TX1 PAL_LINE(GPIOD, 8U) +#define LINE_RX1 PAL_LINE(GPIOD, 9U) +#define LINE_GPIO14 PAL_LINE(GPIOD, 10U) +#define LINE_CS3 PAL_LINE(GPIOD, 11U) +#define LINE_RST3 PAL_LINE(GPIOD, 12U) +#define LINE_PWM3 PAL_LINE(GPIOD, 13U) +#define LINE_PWM4 PAL_LINE(GPIOD, 14U) +#define LINE_PWM2 PAL_LINE(GPIOD, 15U) + +#define LINE_CS2 PAL_LINE(GPIOE, 0U) +#define LINE_RST2 PAL_LINE(GPIOE, 1U) +#define LINE_GPIO15 PAL_LINE(GPIOE, 2U) +#define LINE_GPIO16 PAL_LINE(GPIOE, 3U) +#define LINE_GPIO17 PAL_LINE(GPIOE, 4U) +#define LINE_GPIO18 PAL_LINE(GPIOE, 5U) +#define LINE_GPIO19 PAL_LINE(GPIOE, 6U) +#define LINE_GPIO20 PAL_LINE(GPIOE, 7U) +#define LINE_GPIO21 PAL_LINE(GPIOE, 8U) +#define LINE_PWM1 PAL_LINE(GPIOE, 9U) +#define LINE_LED2 PAL_LINE(GPIOE, 10U) +#define LINE_GPIO22 PAL_LINE(GPIOE, 11U) +#define LINE_USB_DETECT PAL_LINE(GPIOE, 12U) +#define LINE_GPIO23 PAL_LINE(GPIOE, 13U) +#define LINE_GPIO24 PAL_LINE(GPIOE, 14U) +#define LINE_LED1 PAL_LINE(GPIOE, 15U) + +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - N/A + * PA1 - INT1 (input floating). + * PA2 - RST1 (input floating). + * PA3 - CS1 (alternate 14). + * PA4 - AN2 (alternate 14). + * PA5 - AN5 (input pullup). + * PA6 - AN1 (alternate 14). + * PA7 - AN3 (input pullup). + * PA8 - FLASH_HOLD (alternate 4). + * PA9 - TX4 (alternate 7). + * PA10 - RX4 (alternate 7). + * PA11 - OTG_FS_DM (alternate 14). + * PA12 - OTG_FS_DP (alternate 14). + * PA13 - FLASH_CS (alternate 0). + * PA14 - INT4 (alternate 0). + * PA15 - GPIO1 (input floating). + */ +#define VAL_GPIOA_MODER (PIN_MODE_ALTERNATE(GPIOA_PA0) | \ + PIN_MODE_INPUT(GPIOA_INT1) | \ + PIN_MODE_INPUT(GPIOA_RST1) | \ + PIN_MODE_OUTPUT(GPIOA_CS1) | \ + PIN_MODE_ANALOG(GPIOA_AN2) | \ + PIN_MODE_ANALOG(GPIOA_AN4) | \ + PIN_MODE_ANALOG(GPIOA_AN1) | \ + PIN_MODE_ANALOG(GPIOA_AN3) | \ + PIN_MODE_OUTPUT(GPIOA_FLASH_HOLD) | \ + PIN_MODE_ALTERNATE(GPIOA_TX4) | \ + PIN_MODE_ALTERNATE(GPIOA_RX4) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DP) | \ + PIN_MODE_OUTPUT(GPIOA_FLASH_CS) | \ + PIN_MODE_INPUT(GPIOA_INT4) | \ + PIN_MODE_INPUT(GPIOA_GPIO1)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PA0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_INT1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_RST1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_CS1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_AN2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_AN4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_AN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_AN3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_FLASH_HOLD) | \ + PIN_OTYPE_PUSHPULL(GPIOA_TX4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_RX4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_FLASH_CS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_INT4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_GPIO1)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_PA0) | \ + PIN_OSPEED_HIGH(GPIOA_INT1) | \ + PIN_OSPEED_HIGH(GPIOA_RST1) | \ + PIN_OSPEED_HIGH(GPIOA_CS1) | \ + PIN_OSPEED_HIGH(GPIOA_AN2) | \ + PIN_OSPEED_HIGH(GPIOA_AN4) | \ + PIN_OSPEED_HIGH(GPIOA_AN1) | \ + PIN_OSPEED_HIGH(GPIOA_AN3) | \ + PIN_OSPEED_HIGH(GPIOA_FLASH_HOLD) | \ + PIN_OSPEED_HIGH(GPIOA_TX4) | \ + PIN_OSPEED_HIGH(GPIOA_RX4) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_OSPEED_HIGH(GPIOA_FLASH_CS) | \ + PIN_OSPEED_HIGH(GPIOA_INT4) | \ + PIN_OSPEED_HIGH(GPIOA_GPIO1)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PA0) | \ + PIN_PUPDR_FLOATING(GPIOA_INT1) | \ + PIN_PUPDR_FLOATING(GPIOA_RST1) | \ + PIN_PUPDR_FLOATING(GPIOA_CS1) | \ + PIN_PUPDR_FLOATING(GPIOA_AN2) | \ + PIN_PUPDR_FLOATING(GPIOA_AN4) | \ + PIN_PUPDR_FLOATING(GPIOA_AN1) | \ + PIN_PUPDR_FLOATING(GPIOA_AN3) | \ + PIN_PUPDR_FLOATING(GPIOA_FLASH_HOLD) | \ + PIN_PUPDR_FLOATING(GPIOA_TX4) | \ + PIN_PUPDR_FLOATING(GPIOA_RX4) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | \ + PIN_PUPDR_FLOATING(GPIOA_FLASH_CS) | \ + PIN_PUPDR_FLOATING(GPIOA_INT4) | \ + PIN_PUPDR_FLOATING(GPIOA_GPIO1)) +#define VAL_GPIOA_ODR (PIN_ODR_LOW(GPIOA_PA0) | \ + PIN_ODR_LOW(GPIOA_INT1) | \ + PIN_ODR_LOW(GPIOA_RST1) | \ + PIN_ODR_LOW(GPIOA_CS1) | \ + PIN_ODR_LOW(GPIOA_AN2) | \ + PIN_ODR_LOW(GPIOA_AN4) | \ + PIN_ODR_LOW(GPIOA_AN1) | \ + PIN_ODR_LOW(GPIOA_AN3) | \ + PIN_ODR_HIGH(GPIOA_FLASH_HOLD) | \ + PIN_ODR_LOW(GPIOA_TX4) | \ + PIN_ODR_LOW(GPIOA_RX4) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_ODR_HIGH(GPIOA_FLASH_CS) | \ + PIN_ODR_LOW(GPIOA_INT4) | \ + PIN_ODR_LOW(GPIOA_GPIO1)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PA0, 0U) | \ + PIN_AFIO_AF(GPIOA_INT1, 0U) | \ + PIN_AFIO_AF(GPIOA_RST1, 0U) | \ + PIN_AFIO_AF(GPIOA_CS1, 0U) | \ + PIN_AFIO_AF(GPIOA_AN2, 0U) | \ + PIN_AFIO_AF(GPIOA_AN4, 0U) | \ + PIN_AFIO_AF(GPIOA_AN1, 0U) | \ + PIN_AFIO_AF(GPIOA_AN3, 0U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_FLASH_HOLD, 0U) | \ + PIN_AFIO_AF(GPIOA_TX4, 7U) | \ + PIN_AFIO_AF(GPIOA_RX4, 7U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_FLASH_CS, 0U) | \ + PIN_AFIO_AF(GPIOA_INT4, 0U) | \ + PIN_AFIO_AF(GPIOA_GPIO1, 0U)) + +/* + * GPIOB setup: + * + * PB0 - GPIO2 (alternate 14). + * PB1 - PB1 (alternate 14). + * PB2 - BOOT1 (input pullup). + * PB3 - SPI1_CLK (alternate 0). + * PB4 - SPI1_MISO (input pullup). + * PB5 - SPI1_MOSI (alternate 12). + * PB6 - I2C1_SCL (alternate 12). + * PB7 - PIN7 (input pullup). + * PB8 - PB8 (alternate 14). + * PB9 - INT2 (alternate 14). + * PB10 - GPIO3 (alternate 14). + * PB11 - GPIO4 (alternate 14). + * PB12 - GPIO5 (alternate 12). + * PB13 - GPIO6 (input pulldown). + * PB14 - OTG_HS_DM (alternate 12). + * PB15 - OTG_HS_DP (alternate 12). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_GPIO2) | \ + PIN_MODE_ALTERNATE(GPIOB_PB1) | \ + PIN_MODE_ALTERNATE(GPIOB_BOOT1) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI1_CLK) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI1_MISO) | \ + PIN_MODE_ALTERNATE(GPIOB_SPI1_MOSI) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_INPUT(GPIOB_PB8) | \ + PIN_MODE_INPUT(GPIOB_INT2) | \ + PIN_MODE_INPUT(GPIOB_GPIO3) | \ + PIN_MODE_INPUT(GPIOB_GPIO4) | \ + PIN_MODE_INPUT(GPIOB_GPIO5) | \ + PIN_MODE_INPUT(GPIOB_GPIO6) | \ + PIN_MODE_ALTERNATE(GPIOB_OTG_HS_DM) | \ + PIN_MODE_ALTERNATE(GPIOB_OTG_HS_DP)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_GPIO2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PB1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_BOOT1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI1_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI1_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI1_MOSI) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PB8) | \ + PIN_OTYPE_PUSHPULL(GPIOB_INT2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_GPIO3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_GPIO4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_GPIO5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_GPIO6) |\ + PIN_OTYPE_PUSHPULL(GPIOB_OTG_HS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOB_OTG_HS_DP)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_GPIO2) | \ + PIN_OSPEED_HIGH(GPIOB_PB1) | \ + PIN_OSPEED_HIGH(GPIOB_BOOT1) | \ + PIN_OSPEED_HIGH(GPIOB_SPI1_CLK) | \ + PIN_OSPEED_HIGH(GPIOB_SPI1_MISO) | \ + PIN_OSPEED_HIGH(GPIOB_SPI1_MOSI) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_PB8) | \ + PIN_OSPEED_HIGH(GPIOB_INT2) | \ + PIN_OSPEED_HIGH(GPIOB_GPIO3) | \ + PIN_OSPEED_HIGH(GPIOB_GPIO4) | \ + PIN_OSPEED_HIGH(GPIOB_GPIO5) | \ + PIN_OSPEED_HIGH(GPIOB_GPIO6) |\ + PIN_OSPEED_HIGH(GPIOB_OTG_HS_DM) | \ + PIN_OSPEED_HIGH(GPIOB_OTG_HS_DP)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_GPIO2) | \ + PIN_PUPDR_FLOATING(GPIOB_PB1) | \ + PIN_PUPDR_FLOATING(GPIOB_BOOT1) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI1_CLK) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI1_MISO) | \ + PIN_PUPDR_FLOATING(GPIOB_SPI1_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_FLOATING(GPIOB_PB8) | \ + PIN_PUPDR_FLOATING(GPIOB_INT2) | \ + PIN_PUPDR_FLOATING(GPIOB_GPIO3) | \ + PIN_PUPDR_FLOATING(GPIOB_GPIO4) | \ + PIN_PUPDR_FLOATING(GPIOB_GPIO5) | \ + PIN_PUPDR_FLOATING(GPIOB_GPIO6) |\ + PIN_PUPDR_FLOATING(GPIOB_OTG_HS_DM) | \ + PIN_PUPDR_FLOATING(GPIOB_OTG_HS_DP)) +#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_GPIO2) | \ + PIN_ODR_LOW(GPIOB_PB1) | \ + PIN_ODR_HIGH(GPIOB_BOOT1) | \ + PIN_ODR_LOW(GPIOB_SPI1_CLK) | \ + PIN_ODR_LOW(GPIOB_SPI1_MISO) | \ + PIN_ODR_LOW(GPIOB_SPI1_MOSI) | \ + PIN_ODR_LOW(GPIOB_I2C1_SCL) | \ + PIN_ODR_LOW(GPIOB_I2C1_SDA) | \ + PIN_ODR_LOW(GPIOB_PB8) | \ + PIN_ODR_LOW(GPIOB_INT2) | \ + PIN_ODR_LOW(GPIOB_GPIO3) | \ + PIN_ODR_LOW(GPIOB_GPIO4) | \ + PIN_ODR_LOW(GPIOB_GPIO5) | \ + PIN_ODR_LOW(GPIOB_GPIO6) | \ + PIN_ODR_LOW(GPIOB_OTG_HS_DM) | \ + PIN_ODR_LOW(GPIOB_OTG_HS_DP)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_GPIO2, 0U) | \ + PIN_AFIO_AF(GPIOB_PB1, 0U) | \ + PIN_AFIO_AF(GPIOB_BOOT1, 0U) | \ + PIN_AFIO_AF(GPIOB_SPI1_CLK, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI1_MISO, 5U) | \ + PIN_AFIO_AF(GPIOB_SPI1_MOSI, 5U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PB8, 0U) | \ + PIN_AFIO_AF(GPIOB_INT2, 0U) | \ + PIN_AFIO_AF(GPIOB_GPIO3, 0U) | \ + PIN_AFIO_AF(GPIOB_GPIO4, 0U) | \ + PIN_AFIO_AF(GPIOB_GPIO5, 0U) | \ + PIN_AFIO_AF(GPIOB_GPIO6, 0U) | \ + PIN_AFIO_AF(GPIOB_OTG_HS_DM, 12U) | \ + PIN_AFIO_AF(GPIOB_OTG_HS_DP, 12U)) + +/* + * GPIOC setup: + * + * PC0 - ID1 (alternate 12). + * PC1 - ID1 (output pushpull maximum). + * PC2 - ID2 (output pushpull maximum). + * PC3 - PIN3 (input pullup). + * PC4 - GPIO7 (output pushpull maximum). + * PC5 - GPIO8 (input floating). + * PC6 - TX3 (alternate 14). + * PC7 - RX3 (alternate 14). + * PC8 - PIN8 (input pullup). + * PC9 - FLASH_WP (alternate 4). + * PC10 - SPI3_CLK (alternate 14). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - PIN13 (input pullup). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ID0) | \ + PIN_MODE_INPUT(GPIOC_ID1) | \ + PIN_MODE_INPUT(GPIOC_ID2) | \ + PIN_MODE_OUTPUT(GPIOC_LED3) | \ + PIN_MODE_INPUT(GPIOC_GPIO7) | \ + PIN_MODE_INPUT(GPIOC_GPIO8) | \ + PIN_MODE_ALTERNATE(GPIOC_TX3) | \ + PIN_MODE_ALTERNATE(GPIOC_RX3) | \ + PIN_MODE_INPUT(GPIOC_INT3) | \ + PIN_MODE_OUTPUT(GPIOC_FLASH_WP) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_CLK) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MISO) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MOSI) | \ + PIN_MODE_INPUT(GPIOC_GPIO9) | \ + PIN_MODE_ALTERNATE(GPIOC_OSC32_IN) | \ + PIN_MODE_ALTERNATE(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ID0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ID1) |\ + PIN_OTYPE_PUSHPULL(GPIOC_ID2) |\ + PIN_OTYPE_PUSHPULL(GPIOC_LED3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_GPIO7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_GPIO8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_TX3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RX3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_INT3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_FLASH_WP) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOC_GPIO9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ID0) | \ + PIN_OSPEED_HIGH(GPIOC_ID1) | \ + PIN_OSPEED_HIGH(GPIOC_ID2) | \ + PIN_OSPEED_HIGH(GPIOC_LED3) | \ + PIN_OSPEED_HIGH(GPIOC_GPIO7) | \ + PIN_OSPEED_HIGH(GPIOC_GPIO8) | \ + PIN_OSPEED_HIGH(GPIOC_TX3) | \ + PIN_OSPEED_HIGH(GPIOC_RX3) | \ + PIN_OSPEED_HIGH(GPIOC_INT3) | \ + PIN_OSPEED_HIGH(GPIOC_FLASH_WP) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_CLK) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MISO) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MOSI) | \ + PIN_OSPEED_HIGH(GPIOC_GPIO9) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_ID0) | \ + PIN_PUPDR_FLOATING(GPIOC_ID1) |\ + PIN_PUPDR_FLOATING(GPIOC_ID2) |\ + PIN_PUPDR_FLOATING(GPIOC_LED3) | \ + PIN_PUPDR_FLOATING(GPIOC_GPIO7) | \ + PIN_PUPDR_FLOATING(GPIOC_GPIO8) | \ + PIN_PUPDR_FLOATING(GPIOC_TX3) | \ + PIN_PUPDR_FLOATING(GPIOC_RX3) | \ + PIN_PUPDR_FLOATING(GPIOC_INT3) | \ + PIN_PUPDR_FLOATING(GPIOC_FLASH_WP) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_CLK) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MISO) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOC_GPIO9) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_LOW(GPIOC_ID0) | \ + PIN_ODR_LOW(GPIOC_ID1) | \ + PIN_ODR_LOW(GPIOC_ID2) | \ + PIN_ODR_LOW(GPIOC_LED3) | \ + PIN_ODR_LOW(GPIOC_GPIO7) | \ + PIN_ODR_LOW(GPIOC_GPIO8) | \ + PIN_ODR_LOW(GPIOC_TX3) | \ + PIN_ODR_LOW(GPIOC_RX3) | \ + PIN_ODR_LOW(GPIOC_INT3) | \ + PIN_ODR_HIGH(GPIOC_FLASH_WP) | \ + PIN_ODR_LOW(GPIOC_SPI3_CLK) | \ + PIN_ODR_LOW(GPIOC_SPI3_MISO) | \ + PIN_ODR_LOW(GPIOC_SPI3_MOSI) | \ + PIN_ODR_LOW(GPIOC_GPIO9) | \ + PIN_ODR_LOW(GPIOC_OSC32_IN) | \ + PIN_ODR_LOW(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ID0, 0U) | \ + PIN_AFIO_AF(GPIOC_ID1, 0U) | \ + PIN_AFIO_AF(GPIOC_ID2, 0U) | \ + PIN_AFIO_AF(GPIOC_LED3, 0U) | \ + PIN_AFIO_AF(GPIOC_GPIO7, 0U) | \ + PIN_AFIO_AF(GPIOC_GPIO8, 0U) | \ + PIN_AFIO_AF(GPIOC_TX3, 8U) | \ + PIN_AFIO_AF(GPIOC_RX3, 8U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_INT3, 0U) | \ + PIN_AFIO_AF(GPIOC_FLASH_WP, 0U) | \ + PIN_AFIO_AF(GPIOC_SPI3_CLK, 6U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MISO, 6U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MOSI, 6U) | \ + PIN_AFIO_AF(GPIOC_GPIO9, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - RST4 (alternate 12). + * PD1 - CS4 (alternate 12). + * PD2 - PIN2 (input pullup). + * PD3 - GPIO11 (alternate 14). + * PD4 - GPIO12 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - RX2 (alternate 14). + * PD7 - PIN7 (input pullup). + * PD8 - TX1 (alternate 12). + * PD9 - RX1 (alternate 12). + * PD10 - GPIO14 (alternate 12). + * PD11 - CS3 (input floating). + * PD12 - RST3 (output pushpull maximum). + * PD13 - PWM3 (output pushpull maximum). + * PD14 - PWM4 (alternate 12). + * PD15 - FMC_D1 (alternate 12). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_RST4) | \ + PIN_MODE_OUTPUT(GPIOD_CS4) | \ + PIN_MODE_INPUT(GPIOD_GPIO10) | \ + PIN_MODE_INPUT(GPIOD_GPIO11) | \ + PIN_MODE_INPUT(GPIOD_GPIO12) | \ + PIN_MODE_ALTERNATE(GPIOD_TX2) | \ + PIN_MODE_ALTERNATE(GPIOD_RX2) | \ + PIN_MODE_INPUT(GPIOD_GPIO13) | \ + PIN_MODE_ALTERNATE(GPIOD_TX1) | \ + PIN_MODE_ALTERNATE(GPIOD_RX1) | \ + PIN_MODE_INPUT(GPIOD_GPIO14) | \ + PIN_MODE_OUTPUT(GPIOD_CS3) | \ + PIN_MODE_INPUT(GPIOD_RST3) | \ + PIN_MODE_ALTERNATE(GPIOD_PWM3) | \ + PIN_MODE_ALTERNATE(GPIOD_PWM4) | \ + PIN_MODE_ALTERNATE(GPIOD_PWM2)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_RST4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_CS4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_GPIO10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_GPIO11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_GPIO12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_TX2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_RX2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_GPIO13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_TX1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_RX1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_GPIO14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_CS3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_RST3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PWM3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PWM4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PWM2)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_RST4) | \ + PIN_OSPEED_HIGH(GPIOD_CS4) | \ + PIN_OSPEED_HIGH(GPIOD_GPIO10) | \ + PIN_OSPEED_HIGH(GPIOD_GPIO11) | \ + PIN_OSPEED_HIGH(GPIOD_GPIO12) | \ + PIN_OSPEED_HIGH(GPIOD_TX2) | \ + PIN_OSPEED_HIGH(GPIOD_RX2) | \ + PIN_OSPEED_HIGH(GPIOD_GPIO13) | \ + PIN_OSPEED_HIGH(GPIOD_TX1) | \ + PIN_OSPEED_HIGH(GPIOD_RX1) | \ + PIN_OSPEED_HIGH(GPIOD_GPIO14) | \ + PIN_OSPEED_HIGH(GPIOD_CS3) | \ + PIN_OSPEED_HIGH(GPIOD_RST3) | \ + PIN_OSPEED_HIGH(GPIOD_PWM3) | \ + PIN_OSPEED_HIGH(GPIOD_PWM4) | \ + PIN_OSPEED_HIGH(GPIOD_PWM2)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_RST4) | \ + PIN_PUPDR_FLOATING(GPIOD_CS4) | \ + PIN_PUPDR_FLOATING(GPIOD_GPIO10) | \ + PIN_PUPDR_FLOATING(GPIOD_GPIO11) | \ + PIN_PUPDR_FLOATING(GPIOD_GPIO12) | \ + PIN_PUPDR_FLOATING(GPIOD_TX2) | \ + PIN_PUPDR_FLOATING(GPIOD_RX2) | \ + PIN_PUPDR_FLOATING(GPIOD_GPIO13) | \ + PIN_PUPDR_FLOATING(GPIOD_TX1) | \ + PIN_PUPDR_FLOATING(GPIOD_RX1) | \ + PIN_PUPDR_FLOATING(GPIOD_GPIO14) | \ + PIN_PUPDR_FLOATING(GPIOD_CS3) | \ + PIN_PUPDR_FLOATING(GPIOD_RST3) | \ + PIN_PUPDR_FLOATING(GPIOD_PWM3) | \ + PIN_PUPDR_FLOATING(GPIOD_PWM4) | \ + PIN_PUPDR_FLOATING(GPIOD_PWM2)) +#define VAL_GPIOD_ODR (PIN_ODR_LOW(GPIOD_RST4) | \ + PIN_ODR_LOW(GPIOD_CS4) | \ + PIN_ODR_LOW(GPIOD_GPIO10) | \ + PIN_ODR_LOW(GPIOD_GPIO11) | \ + PIN_ODR_LOW(GPIOD_GPIO12) | \ + PIN_ODR_LOW(GPIOD_TX2) | \ + PIN_ODR_LOW(GPIOD_RX2) | \ + PIN_ODR_LOW(GPIOD_GPIO13) | \ + PIN_ODR_LOW(GPIOD_TX1) | \ + PIN_ODR_LOW(GPIOD_RX1) | \ + PIN_ODR_LOW(GPIOD_GPIO14) | \ + PIN_ODR_LOW(GPIOD_CS3) | \ + PIN_ODR_LOW(GPIOD_RST3) | \ + PIN_ODR_LOW(GPIOD_PWM3) | \ + PIN_ODR_LOW(GPIOD_PWM4) | \ + PIN_ODR_LOW(GPIOD_PWM2)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_RST4, 0U) | \ + PIN_AFIO_AF(GPIOD_CS4, 0U) | \ + PIN_AFIO_AF(GPIOD_GPIO10, 0U) | \ + PIN_AFIO_AF(GPIOD_GPIO11, 0U) | \ + PIN_AFIO_AF(GPIOD_GPIO12, 0U) | \ + PIN_AFIO_AF(GPIOD_TX2, 7U) | \ + PIN_AFIO_AF(GPIOD_RX2, 7U) | \ + PIN_AFIO_AF(GPIOD_GPIO13, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_TX1, 7U) | \ + PIN_AFIO_AF(GPIOD_RX1, 7U) | \ + PIN_AFIO_AF(GPIOD_GPIO14, 0U) | \ + PIN_AFIO_AF(GPIOD_CS3, 0U) | \ + PIN_AFIO_AF(GPIOD_RST3, 0U) | \ + PIN_AFIO_AF(GPIOD_PWM3, 2U) | \ + PIN_AFIO_AF(GPIOD_PWM4, 2U) | \ + PIN_AFIO_AF(GPIOD_PWM2, 2U)) + +/* + * GPIOE setup: + * + * PE0 - CS2 (alternate 12). + * PE1 - RST2 (alternate 12). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 (input pullup). + * PE4 - SPI1_MISO (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - GPIO20 (alternate 12). + * PE8 - GPIO21 (alternate 12). + * PE9 - PWM1 (alternate 12). + * PE10 - FMC_D7 (alternate 12). + * PE11 - GPIO22 (alternate 12). + * PE12 - USB_DETECT (alternate 12). + * PE13 - GPIO23 (alternate 12). + * PE14 - GPIO24 (alternate 12). + * PE15 - FMC_D12 (alternate 12). + */ +#define VAL_GPIOE_MODER (PIN_MODE_OUTPUT(GPIOE_CS2) | \ + PIN_MODE_INPUT(GPIOE_RST2) | \ + PIN_MODE_INPUT(GPIOE_GPIO15) | \ + PIN_MODE_INPUT(GPIOE_GPIO16) | \ + PIN_MODE_INPUT(GPIOE_GPIO17) | \ + PIN_MODE_INPUT(GPIOE_GPIO18) | \ + PIN_MODE_INPUT(GPIOE_GPIO19) | \ + PIN_MODE_INPUT(GPIOE_GPIO20) | \ + PIN_MODE_INPUT(GPIOE_GPIO21) | \ + PIN_MODE_ALTERNATE(GPIOE_PWM1) | \ + PIN_MODE_OUTPUT(GPIOE_LED2) | \ + PIN_MODE_INPUT(GPIOE_GPIO22) | \ + PIN_MODE_ALTERNATE(GPIOE_USB_DETECT) | \ + PIN_MODE_INPUT(GPIOE_GPIO23) | \ + PIN_MODE_INPUT(GPIOE_GPIO24) | \ + PIN_MODE_OUTPUT(GPIOE_LED1)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_CS2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_RST2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO15) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO16) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO17) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO18) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO19) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO20) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO21) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PWM1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_LED2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO22) | \ + PIN_OTYPE_PUSHPULL(GPIOE_USB_DETECT) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO23) | \ + PIN_OTYPE_PUSHPULL(GPIOE_GPIO24) | \ + PIN_OTYPE_PUSHPULL(GPIOE_LED1)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_CS2) | \ + PIN_OSPEED_HIGH(GPIOE_RST2) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO15) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO16) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO17) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO18) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO19) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO20) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO21) | \ + PIN_OSPEED_HIGH(GPIOE_PWM1) | \ + PIN_OSPEED_HIGH(GPIOE_LED2) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO22) | \ + PIN_OSPEED_HIGH(GPIOE_USB_DETECT) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO23) | \ + PIN_OSPEED_HIGH(GPIOE_GPIO24) | \ + PIN_OSPEED_HIGH(GPIOE_LED1)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_CS2) | \ + PIN_PUPDR_FLOATING(GPIOE_RST2) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO15) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO16) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO17) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO18) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO19) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO20) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO21) | \ + PIN_PUPDR_FLOATING(GPIOE_PWM1) | \ + PIN_PUPDR_FLOATING(GPIOE_LED2) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO22) | \ + PIN_PUPDR_FLOATING(GPIOE_USB_DETECT) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO23) | \ + PIN_PUPDR_FLOATING(GPIOE_GPIO24) | \ + PIN_PUPDR_FLOATING(GPIOE_LED1)) +#define VAL_GPIOE_ODR (PIN_ODR_LOW(GPIOE_CS2) | \ + PIN_ODR_LOW(GPIOE_RST2) | \ + PIN_ODR_LOW(GPIOE_GPIO15) | \ + PIN_ODR_LOW(GPIOE_GPIO16) | \ + PIN_ODR_LOW(GPIOE_GPIO17) | \ + PIN_ODR_LOW(GPIOE_GPIO18) | \ + PIN_ODR_LOW(GPIOE_GPIO19) | \ + PIN_ODR_LOW(GPIOE_GPIO20) | \ + PIN_ODR_LOW(GPIOE_GPIO21) | \ + PIN_ODR_LOW(GPIOE_PWM1) | \ + PIN_ODR_LOW(GPIOE_LED2) | \ + PIN_ODR_LOW(GPIOE_GPIO22) | \ + PIN_ODR_LOW(GPIOE_USB_DETECT) | \ + PIN_ODR_LOW(GPIOE_GPIO23) | \ + PIN_ODR_LOW(GPIOE_GPIO24) | \ + PIN_ODR_LOW(GPIOE_LED1)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_CS2, 0U) | \ + PIN_AFIO_AF(GPIOE_RST2, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO15, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO16, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO17, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO18, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO19, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO20, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_GPIO21, 0U) | \ + PIN_AFIO_AF(GPIOE_PWM1, 1U) | \ + PIN_AFIO_AF(GPIOE_LED2, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO22, 0U) | \ + PIN_AFIO_AF(GPIOE_USB_DETECT, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO23, 0U) | \ + PIN_AFIO_AF(GPIOE_GPIO24, 0U) | \ + PIN_AFIO_AF(GPIOE_LED1, 0U)) + + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - SPI1_MISO (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/CMakeLists.txt new file mode 100644 index 00000000..aa7f1d54 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..a970be77 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 0x08008000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 3 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 4, 6 }, // 0x080A0000 deployment +}; + +//16kB block +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +//64kB block +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +//128kB block +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + (0), // no attributes for this region + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + (0), // no attributes for this region + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + (0), // no attributes for this region + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage.c new file mode 100644 index 00000000..23428263 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/Device_BlockStorage.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 0x08004000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 }, // 0x08040000 deployment +}; + +//16kB block +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +//64kB block +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +//128kB block +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + (0), // no attributes for this region + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + (0), // no attributes for this region + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + (0), // no attributes for this region + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.c new file mode 100644 index 00000000..7545d9e3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.c @@ -0,0 +1,454 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD2. + */ +#define USBD2_DATA_REQUEST_EP 1 +#define USBD2_DATA_AVAILABLE_EP 1 +#define USBD2_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"Mikrobus.Net" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"Quail Virtual COM Port" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(0x0043, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + if (usbp->state == USB_ACTIVE) { + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD2_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD2_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + } + else if (usbp->state == USB_SELECTED) { + usbDisableEndpointsI(usbp); + } + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handling messages not implemented in the default handler nor in the + * SerialUSB handler. + */ +static bool requests_hook(USBDriver *usbp) { + + if (((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE) && + (usbp->setup[1] == USB_REQ_SET_INTERFACE)) { + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + } + return sduRequestsHook(usbp); +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + requests_hook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD2_DATA_REQUEST_EP, + USBD2_DATA_AVAILABLE_EP, + USBD2_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.h new file mode 100644 index 00000000..167e1df8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/common/usbcfg.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/chconf.h new file mode 100644 index 00000000..57d60bed --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf.h new file mode 100644 index 00000000..117bbda7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/main.c new file mode 100644 index 00000000..6465edf2 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/main.c @@ -0,0 +1,69 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // check for valid CLR image at address contiguous to nanoBooter + // this target DOES NOT have configuration block, so we need to use the __nanoImage_end__ address here + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOE, GPIOE_LED1); + osDelay(500); + palClearPad(GPIOE, GPIOE_LED1); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter-DEBUG.ld new file mode 100644 index 00000000..505f0a7a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08007FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter.ld new file mode 100644 index 00000000..31588162 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mbn_quail_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08003FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf.h new file mode 100644 index 00000000..11c84d5f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf.h @@ -0,0 +1,335 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 6 +#define STM32_PLLN_VALUE 168 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 2 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/chconf.h new file mode 100644 index 00000000..15a95e76 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf.h new file mode 100644 index 00000000..a838d4cb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf.h @@ -0,0 +1,525 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI TRUE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..5ac68c7c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/halconf_nf.h @@ -0,0 +1,14 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/main.c new file mode 100644 index 00000000..18e0c329 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/main.c @@ -0,0 +1,102 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// Using Devantech LCD03 display in I2C mode @ address 0xC8 + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 4096, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // find out wakeup reason + if((RTC->ISR & RTC_ISR_ALRAF) == RTC_ISR_ALRAF) + { + // standby, match WakeupReason_FromStandby enum + WakeupReasonStore = 1; + } + else if((PWR->CSR & PWR_CSR_WUF) == PWR_CSR_WUF) + { + // wake from pin, match WakeupReason_FromPin enum + WakeupReasonStore = 2; + } + else + { + // undetermined reason, match WakeupReason_Undetermined enum + WakeupReasonStore = 0; + } + + // first things first: need to clear any possible wakeup flags + // if this is not done here the next standby -> wakeup sequence won't work + CLEAR_BIT(RTC->CR, RTC_CR_ALRAIE); + CLEAR_BIT(RTC->ISR, RTC_ISR_ALRAF); + SET_BIT(PWR->CR, PWR_CR_CWUF); + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + /////////////////////////////////////////////////////////////////////////////////////////////////////// + // for STM32F4 family if watchdog is enabled can't use standby mode because the IWDG can't be stoped // + /////////////////////////////////////////////////////////////////////////////////////////////////////// + Watchdog_Init(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR-DEBUG.ld new file mode 100644 index 00000000..d2ef582b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 2M - 32k - 1408k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x080A0000, len = 1408k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR.ld new file mode 100644 index 00000000..5a59730e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mbn_quail_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 2M - 16k - 1792k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 1792k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf.h new file mode 100644 index 00000000..0570b319 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf.h @@ -0,0 +1,335 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 6 +#define STM32_PLLN_VALUE 168 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 2 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 TRUE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 TRUE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 TRUE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 TRUE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 TRUE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.c new file mode 100644 index 00000000..ccee7c5e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.c @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" +#include + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; + +// this target use DFU for updates +uint32_t GetTargetCapabilities() +{ + return TargetCapabilities_DfuUpdate; +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.h.in new file mode 100644 index 00000000..f1449ae9 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_common.h.in @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x200000C0) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00030000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00200000) + +///////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +////////////////////////////////////////////// + +///////////////////////////////////// +//#define EVENTS_HEART_BEAT palToggleLine(GPIOE_LED1) +///////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..5df22a7d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_nf_devices_onewire_config.h" +#include + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port for TX pin is: GPIOC +// TX pin: is GPIOC_6 +// GPIO alternate pin function is 8 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +UART_CONFIG_PINS(6, GPIOC, 10, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..d0fb1c87 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_nf_devices_onewire_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART6 // +/////////// + +// enable USART6 +#define NF_ONEWIRE_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 32 bytes +#define UART6_TX_SIZE 32 +// rx buffer size: 32 bytes +#define UART6_RX_SIZE 32 \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..97181d6f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_system_devices_dac_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T HAVE SUPPORT FOR DAC PINS // +////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..18b1cd19 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_6 +// SDA pin: is GPIOB_7 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 6, 7, 4) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..d4957c6d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,131 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include + +/////////// +// UART1 // +/////////// + +// pin configuration for UART1 +// port for TX pin is: GPIOA +// port for RX pin is: GPIOA +// TX pin: is GPIOA_9 +// RX pin: is GPIOA_10 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(1, GPIOA, GPIOA, 9, 10, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_TxBuffer[UART1_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_RxBuffer[UART1_RX_SIZE]; + +// initialization for UART1 +UART_INIT(1, UART1_TX_SIZE, UART1_RX_SIZE) + +// un-initialization for UART1 +UART_UNINIT(1) + + +/////////// +// UART2 // +/////////// + +// pin configuration for UART2 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOD +// TX pin: is GPIOD_5 +// RX pin: is GPIOD_6 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(2, GPIOD, GPIOD, 5, 6, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// initialization for UART2 +UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// un-initialization for UART2 +UART_UNINIT(2) + + +/////////// +// UART3 // +/////////// + +// pin configuration for UART3 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOD +// TX pin: is GPIOD_8 +// RX pin: is GPIOD_9 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(3, GPIOD, GPIOD, 8, 9, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_TxBuffer[UART3_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_RxBuffer[UART3_RX_SIZE]; + +// initialization for UART3 +UART_INIT(3, UART3_TX_SIZE, UART3_RX_SIZE) + +// un-initialization for UART3 +UART_UNINIT(3) + + +// /////////// +// // UART6 // +// /////////// + +// // pin configuration for UART6 +// // port for TX pin is: GPIOC +// // port for RX pin is: GPIOC +// // TX pin: is GPIOC_6 +// // RX pin: is GPIOC_7 +// // GPIO alternate pin function is 8 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +// UART_CONFIG_PINS(6, GPIOC, GPIOC, 6, 7, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; + +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; + +// // initialization for UART6 +// UART_INIT(6, UART6_TX_SIZE, UART6_RX_SIZE) + +// // un-initialization for UART6 +// UART_UNINIT(6) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..9f7ead72 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART1 // +/////////// + +// enable USART1 +#define NF_SERIAL_COMM_STM32_UART_USE_USART1 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART1_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART1_RX_SIZE 256 + + +/////////// +// UART2 // +/////////// + +// enable USART2 +#define NF_SERIAL_COMM_STM32_UART_USE_USART2 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART2_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART2_RX_SIZE 256 + + +/////////// +// UART3 // +/////////// + +// enable USART3 +#define NF_SERIAL_COMM_STM32_UART_USE_USART3 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART3_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART3_RX_SIZE 256 + + +// /////////// +// // UART6 // +// /////////// + +// // enable USART6 +// #define NF_SERIAL_COMM_STM32_UART_USE_USART6 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART6_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART6_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/MBN_QUAIL/target_windows_devices_spi_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/CMakeLists.txt new file mode 100644 index 00000000..8fa69c82 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/CMakeLists.txt @@ -0,0 +1,242 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for ChibiOS FatFS + ${CHIBIOS_FATFS_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# add dependencies from CHIBIOS_FILESYSTEM_COMPONENTS (this is required to make sure that ChibiOS filesystem components are unzip at the proper locations before the build starts) +# only required if filesystem is ON +if(USE_FILESYSTEM_OPTION) + add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf CHIBIOS_FILESYSTEM_COMPONENTS) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf CHIBIOS_FILESYSTEM_COMPONENTS) +endif() + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS FatFS + ${CHIBIOS_FATFS_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/netduino3wifi_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/netduino3wifi_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/netduino3wifi_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/netduino3wifi_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +############################################################################ +# CRT heap is assigned to RAM4 region @ CCM SRAM so we are OK to use it all +############################################################################ +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x10000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x10000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) + +# if HEX2DFU tool is available pack the binaries into a DFU package +if(HEX2DFU_TOOL_AVAILABLE) + + #################################################################################################### + ## when changing the linker file make sure to update the new addresses for the image files below ## + ## DO NOT use the leading 0x notation, just the address in plain hexadecimal formating ## + #################################################################################################### + + if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08008000 + ${PROJECT_SOURCE_DIR}/build/nanobooter-nanoclr.dfu + ) + else() + NF_GENERATE_DFU_PACKAGE( + ${PROJECT_SOURCE_DIR}/build/${NANOBOOTER_PROJECT_NAME}.bin 08000000 + ${PROJECT_SOURCE_DIR}/build/${NANOCLR_PROJECT_NAME}.bin 08004000 + ${PROJECT_SOURCE_DIR}/build/nanobooter-nanoclr.dfu + ) + endif() + +endif() diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/README.md new file mode 100644 index 00000000..f42f6d25 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/README.md @@ -0,0 +1,28 @@ +## Configuration of Chibios, HAL and MCU ## + +In this folder you'll find a 'port' of the nanoframework to work on a WildernessLabs Netduino 3 Wifi board. You can find [here] some more information on the board specifics, used MCU, RAM and FLASH memory available. + + + +**NOTE: the configuration was successfully tested on a WildernessLabs NETDUINO3_WIFI board using the Serial over USB connection on USB port 1 that creates a virtual COM port.** + +## ADC configurations + +The following ADC channels (and respective GPIO pins) are available to the managed API, in the respective index: +- PC0, ADC1 IN10 +- PC1 ADC1 IN11 +- PC2 ADC2 IN14 +- PC3 ADC2 IN15 +- PC4 ADC3 IN12 +- PC5 ADC3 IN13 +- Temp Sensor ADC1 +- VrefInt ADC1 +- Vbatt ADC1 + +These first 6 channels are exposed in the board J4 connector as A0 to A5. + + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.c new file mode 100644 index 00000000..5d508db9 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +// #if STM32_HAS_GPIOF || defined(__DOXYGEN__) +// gpio_setup_t PFData; +// #endif +// #if STM32_HAS_GPIOG || defined(__DOXYGEN__) +// gpio_setup_t PGData; +// #endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +// #if STM32_HAS_GPIOI || defined(__DOXYGEN__) +// gpio_setup_t PIData; +// #endif +// #if STM32_HAS_GPIOJ || defined(__DOXYGEN__) +// gpio_setup_t PJData; +// #endif +// #if STM32_HAS_GPIOK || defined(__DOXYGEN__) +// gpio_setup_t PKData; +// #endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +// #if STM32_HAS_GPIOF +// {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, +// VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +// #endif +// #if STM32_HAS_GPIOG +// {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, +// VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +// #endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +// #if STM32_HAS_GPIOI +// {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, +// VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +// #endif +// #if STM32_HAS_GPIOJ +// {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, +// VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +// #endif +// #if STM32_HAS_GPIOK +// {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, +// VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +// #endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +// #if STM32_HAS_GPIOF +// gpio_init(GPIOF, &gpio_default_config.PFData); +// #endif +// #if STM32_HAS_GPIOG +// gpio_init(GPIOG, &gpio_default_config.PGData); +// #endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +// #if STM32_HAS_GPIOI +// gpio_init(GPIOI, &gpio_default_config.PIData); +// #endif +// #if STM32_HAS_GPIOJ +// gpio_init(GPIOJ, &gpio_default_config.PJData); +// #endif +// #if STM32_HAS_GPIOK +// gpio_init(GPIOK, &gpio_default_config.PKData); +// #endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + + return !palReadLine(LINE_SD_DETECT); +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.h new file mode 100644 index 00000000..b72dcb4e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/board.h @@ -0,0 +1,893 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef BOARD_H +#define BOARD_H + +/* + * Board identifier. + */ +#define BOARD_NETDUINO3WIFI +#define BOARD_NAME "Netduino 3 Wifi" + +#define BOARD_OTG_NOVBUSSENS + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 25000000U +#endif + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F427xx + +/* + * IO pins assignments. + */ +#define GPIOA_D8 0U +#define GPIOA_D7 1U +#define GPIOA_D3 2U +#define GPIOA_D2 3U +#define GPIOA_CC_IRQ 4U +#define GPIOA_CC_SCK 5U +#define GPIOA_CC_MISO 6U +#define GPIOA_CC_MOSI 7U +#define GPIOA_STATE_LED 8U +#define GPIOA_VBUS 9U +#define GPIOA_USR_LED 10U +#define GPIOA_OTG_FS_DM 11U +#define GPIOA_OTG_FS_DP 12U +#define GPIOA_JTMS 13U +#define GPIOA_JTCK 14U +#define GPIOA_JTDI 15U + +#define GPIOB_MICROSD_CS 0U +#define GPIOB_MICROSD_CTRL 1U +#define GPIOB_BOOT1 2U +#define GPIOB_JTDO 3U +#define GPIOB_PB4 4U +#define GPIOB_SWITCH1 5U +#define GPIOB_I2C1_SCL 6U +#define GPIOB_I2C1_SDA 7U +#define GPIOB_D5 8U +#define GPIOB_D6 9U +#define GPIOB_D10 10U +#define GPIOB_MICROSD_INS 11U +#define GPIOB_D4 12U +#define GPIOB_D13 13U +#define GPIOB_D12 14U +#define GPIOB_D11 15U + +#define GPIOC_A0 0U +#define GPIOC_A1 1U +#define GPIOC_A2 2U +#define GPIOC_A3 3U +#define GPIOC_A4 4U +#define GPIOC_A5 5U +#define GPIOC_D1 6U +#define GPIOC_D0 7U +#define GPIOC_CC_CS 8U +#define GPIOC_LINK_LED 9U +#define GPIOC_SPI3_CLK 10U +#define GPIOC_SPI3_MISO 11U +#define GPIOC_SPI3_MOSI 12U +#define GPIOC_POWER_LED 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_SPI_CS_GOPORT1 0U +#define GPIOD_SPI_CS_GOPORT2 1U +#define GPIOD_SPI_CS_GOPORT3 2U +#define GPIOD_CC_RTS 3U +#define GPIOD_CC_CTS 4U +#define GPIOD_CC_RX 5U +#define GPIOD_CC_TX 6U +#define GPIOD_PWR_ON_GOPORT1 7U +#define GPIOD_USART3_TX_GOPORT1 8U +#define GPIOD_USART3_RX_GOPORT1 9U +#define GPIOD_PWR_ON_GOPORT2 10U +#define GPIOD_SWITCH1 11U +#define GPIOD_PWR_ON_GOPORT3 12U +#define GPIOD_INT_GOPORT1 13U +#define GPIOD_INT_GOPORT2 14U +#define GPIOD_INT_GOPORT3 15U + +#define GPIOE_USART8_RX_GOPORT3 0U +#define GPIOE_USART8_TX_GOPORT3 1U +#define GPIOE_SPI4_SCK 2U +#define GPIOE_EN_UART_TX_PU_GOPORT1 3U +#define GPIOE_CC_HIB 4U +#define GPIOE_D9 5U +#define GPIOE_SPI4_MOSI 6U +#define GPIOE_USART7_RX_GOPORT2 7U +#define GPIOE_USART7_TX_GOPORT2 8U +#define GPIOE_LED_GOPORT1 9U +#define GPIOE_EN_UART_TX_PU_GOPORT2 10U +#define GPIOE_LED_GOPORT2 11U +#define GPIOE_EN_UART_TX_PU_GOPORT3 12U +#define GPIOE_SPI4_MISO 13U +#define GPIOE_LED_GOPORT3 14U +#define GPIOE_CC_TCXO_EN_SOP2 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_LED1 PAL_LINE(GPIOA, 10U) +#define LINE_SD_DETECT PAL_LINE(GPIOB, 11U) + +#define LINE_LED_GOPORT1 PAL_LINE(GPIOE, 9U) + +#define LINE_LED_GOPORT2 PAL_LINE(GPIOE, 11U) + +#define LINE_LED_GOPORT3 PAL_LINE(GPIOE, 14U) + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - D8 + * PA1 - D7 + * PA2 - D3 + * PA3 - D2 + * PA4 - CC_IRQ + * PA5 - CC_SCK + * PA6 - CC_MISO + * PA7 - CC_MOSI + * PA8 - STATE_LED + * PA9 - VBUS + * PA10 - USR_LED + * PA11 - OTG_FS_DM + * PA12 - OTG_FS_DP + * PA13 - JTMS + * PA14 - JTCK + * PA15 - JTDI + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_D8) | \ + PIN_MODE_INPUT(GPIOA_D7) | \ + PIN_MODE_INPUT(GPIOA_D3) | \ + PIN_MODE_INPUT(GPIOA_D2) | \ + PIN_MODE_INPUT(GPIOA_CC_IRQ) | \ + PIN_MODE_ALTERNATE(GPIOA_CC_SCK) | \ + PIN_MODE_ALTERNATE(GPIOA_CC_MISO) | \ + PIN_MODE_ALTERNATE(GPIOA_CC_MOSI) | \ + PIN_MODE_OUTPUT(GPIOA_STATE_LED) | \ + PIN_MODE_INPUT(GPIOA_VBUS) | \ + PIN_MODE_OUTPUT(GPIOA_USR_LED) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_OTG_FS_DP) | \ + PIN_MODE_INPUT(GPIOA_JTMS) | \ + PIN_MODE_INPUT(GPIOA_JTCK) | \ + PIN_MODE_INPUT(GPIOA_JTDI)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_CC_IRQ) | \ + PIN_OTYPE_PUSHPULL(GPIOA_CC_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_CC_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_CC_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOA_STATE_LED) | \ + PIN_OTYPE_PUSHPULL(GPIOA_VBUS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USR_LED) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_OTG_FS_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_JTMS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_JTCK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_JTDI)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_D8) | \ + PIN_OSPEED_HIGH(GPIOA_D7) | \ + PIN_OSPEED_HIGH(GPIOA_D3) | \ + PIN_OSPEED_HIGH(GPIOA_D2) | \ + PIN_OSPEED_HIGH(GPIOA_CC_IRQ) | \ + PIN_OSPEED_HIGH(GPIOA_CC_SCK) | \ + PIN_OSPEED_HIGH(GPIOA_CC_MISO) | \ + PIN_OSPEED_HIGH(GPIOA_CC_MOSI) | \ + PIN_OSPEED_HIGH(GPIOA_STATE_LED) | \ + PIN_OSPEED_HIGH(GPIOA_VBUS) | \ + PIN_OSPEED_HIGH(GPIOA_USR_LED) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_OSPEED_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_OSPEED_HIGH(GPIOA_JTMS) | \ + PIN_OSPEED_HIGH(GPIOA_JTCK) | \ + PIN_OSPEED_HIGH(GPIOA_JTDI)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_D8) | \ + PIN_PUPDR_FLOATING(GPIOA_D7) | \ + PIN_PUPDR_FLOATING(GPIOA_D3) | \ + PIN_PUPDR_FLOATING(GPIOA_D2) | \ + PIN_PUPDR_FLOATING(GPIOA_CC_IRQ) | \ + PIN_PUPDR_FLOATING(GPIOA_CC_SCK) | \ + PIN_PUPDR_FLOATING(GPIOA_CC_MISO) | \ + PIN_PUPDR_FLOATING(GPIOA_CC_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOA_STATE_LED) | \ + PIN_PUPDR_FLOATING(GPIOA_VBUS) | \ + PIN_PUPDR_FLOATING(GPIOA_USR_LED) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | \ + PIN_PUPDR_FLOATING(GPIOA_JTMS) | \ + PIN_PUPDR_FLOATING(GPIOA_JTCK) | \ + PIN_PUPDR_FLOATING(GPIOA_JTDI)) +#define VAL_GPIOA_ODR (PIN_ODR_LOW(GPIOA_D8) | \ + PIN_ODR_LOW(GPIOA_D7) | \ + PIN_ODR_LOW(GPIOA_D3) | \ + PIN_ODR_LOW(GPIOA_D2) | \ + PIN_ODR_LOW(GPIOA_CC_IRQ) | \ + PIN_ODR_LOW(GPIOA_CC_SCK) | \ + PIN_ODR_LOW(GPIOA_CC_MISO) | \ + PIN_ODR_LOW(GPIOA_CC_MOSI) | \ + PIN_ODR_LOW(GPIOA_STATE_LED) | \ + PIN_ODR_LOW(GPIOA_VBUS) | \ + PIN_ODR_LOW(GPIOA_USR_LED) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DM) | \ + PIN_ODR_HIGH(GPIOA_OTG_FS_DP) | \ + PIN_ODR_LOW(GPIOA_JTMS) | \ + PIN_ODR_LOW(GPIOA_JTCK) | \ + PIN_ODR_LOW(GPIOA_JTDI)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_D8, 0U) | \ + PIN_AFIO_AF(GPIOA_D7, 0U) | \ + PIN_AFIO_AF(GPIOA_D3, 0U) | \ + PIN_AFIO_AF(GPIOA_D2, 0U) | \ + PIN_AFIO_AF(GPIOA_CC_IRQ, 0U) | \ + PIN_AFIO_AF(GPIOA_CC_SCK, 5U) | \ + PIN_AFIO_AF(GPIOA_CC_MISO, 5U) | \ + PIN_AFIO_AF(GPIOA_CC_MOSI, 5U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_STATE_LED, 0U) | \ + PIN_AFIO_AF(GPIOA_VBUS, 0U) | \ + PIN_AFIO_AF(GPIOA_USR_LED, 0U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_JTMS, 0U) | \ + PIN_AFIO_AF(GPIOA_JTCK, 0U) | \ + PIN_AFIO_AF(GPIOA_JTDI, 0U)) + +/* + * GPIOB setup: + * + * PB0 - MICROSD_CS + * PB1 - MICROSD_CTRL + * PB2 - BOOT1 + * PB3 - JTDO + * PB4 - PB4 + * PB5 - SWITCH1 + * PB6 - I2C1_SCL + * PB7 - I2C1_SDA + * PB8 - D5 + * PB9 - D6 + * PB10 - D10 (=SPI2_SS) + * PB11 - MICROSD_INS + * PB12 - D4 + * PB13 - D13 (=SPI2_SCK) + * PB14 - D12 (=SPI2_MISO) + * PB15 - D11 (=SPI2_MOSI) + */ +#define VAL_GPIOB_MODER (PIN_MODE_OUTPUT(GPIOB_MICROSD_CS) | \ + PIN_MODE_OUTPUT(GPIOB_MICROSD_CTRL) | \ + PIN_MODE_OUTPUT(GPIOB_BOOT1) | \ + PIN_MODE_OUTPUT(GPIOB_JTDO) | \ + PIN_MODE_INPUT(GPIOB_PB4) | \ + PIN_MODE_INPUT(GPIOB_SWITCH1) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_INPUT(GPIOB_D5) | \ + PIN_MODE_INPUT(GPIOB_D6) | \ + PIN_MODE_OUTPUT(GPIOB_D10) | \ + PIN_MODE_INPUT(GPIOB_MICROSD_INS) | \ + PIN_MODE_INPUT(GPIOB_D4) | \ + PIN_MODE_ALTERNATE(GPIOB_D13) | \ + PIN_MODE_ALTERNATE(GPIOB_D12) | \ + PIN_MODE_ALTERNATE(GPIOB_D11)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_MICROSD_CS) | \ + PIN_OTYPE_PUSHPULL(GPIOB_MICROSD_CTRL) | \ + PIN_OTYPE_PUSHPULL(GPIOB_BOOT1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_JTDO) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PB4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SWITCH1) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_MICROSD_INS) | \ + PIN_OTYPE_PUSHPULL(GPIOB_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_D13) |\ + PIN_OTYPE_PUSHPULL(GPIOB_D12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_D11)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_MICROSD_CS) | \ + PIN_OSPEED_HIGH(GPIOB_MICROSD_CTRL) | \ + PIN_OSPEED_HIGH(GPIOB_BOOT1) | \ + PIN_OSPEED_HIGH(GPIOB_JTDO) | \ + PIN_OSPEED_HIGH(GPIOB_PB4) | \ + PIN_OSPEED_HIGH(GPIOB_SWITCH1) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_D5) | \ + PIN_OSPEED_HIGH(GPIOB_D6) | \ + PIN_OSPEED_HIGH(GPIOB_D10) | \ + PIN_OSPEED_HIGH(GPIOB_MICROSD_INS) | \ + PIN_OSPEED_HIGH(GPIOB_D4) | \ + PIN_OSPEED_HIGH(GPIOB_D13) |\ + PIN_OSPEED_HIGH(GPIOB_D12) | \ + PIN_OSPEED_HIGH(GPIOB_D11)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_MICROSD_CS) | \ + PIN_PUPDR_FLOATING(GPIOB_MICROSD_CTRL) | \ + PIN_PUPDR_FLOATING(GPIOB_BOOT1) | \ + PIN_PUPDR_FLOATING(GPIOB_JTDO) | \ + PIN_PUPDR_FLOATING(GPIOB_PB4) | \ + PIN_PUPDR_FLOATING(GPIOB_SWITCH1) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_FLOATING(GPIOB_D5) | \ + PIN_PUPDR_FLOATING(GPIOB_D6) | \ + PIN_PUPDR_FLOATING(GPIOB_D10) | \ + PIN_PUPDR_FLOATING(GPIOB_MICROSD_INS) | \ + PIN_PUPDR_FLOATING(GPIOB_D4) | \ + PIN_PUPDR_FLOATING(GPIOB_D13) |\ + PIN_PUPDR_FLOATING(GPIOB_D12) | \ + PIN_PUPDR_FLOATING(GPIOB_D11)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_MICROSD_CS) | \ + PIN_ODR_HIGH(GPIOB_MICROSD_CTRL) | \ + PIN_ODR_HIGH(GPIOB_BOOT1) | \ + PIN_ODR_LOW(GPIOB_JTDO) | \ + PIN_ODR_LOW(GPIOB_PB4) | \ + PIN_ODR_LOW(GPIOB_SWITCH1) | \ + PIN_ODR_LOW(GPIOB_I2C1_SCL) | \ + PIN_ODR_LOW(GPIOB_I2C1_SDA) | \ + PIN_ODR_LOW(GPIOB_D5) | \ + PIN_ODR_LOW(GPIOB_D6) | \ + PIN_ODR_LOW(GPIOB_D10) | \ + PIN_ODR_HIGH(GPIOB_MICROSD_INS) | \ + PIN_ODR_LOW(GPIOB_D4) | \ + PIN_ODR_LOW(GPIOB_D13) | \ + PIN_ODR_LOW(GPIOB_D12) | \ + PIN_ODR_LOW(GPIOB_D11)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_MICROSD_CS, 0U) | \ + PIN_AFIO_AF(GPIOB_MICROSD_CTRL, 0U) | \ + PIN_AFIO_AF(GPIOB_BOOT1, 0U) | \ + PIN_AFIO_AF(GPIOB_JTDO, 0U) | \ + PIN_AFIO_AF(GPIOB_PB4, 0U) | \ + PIN_AFIO_AF(GPIOB_SWITCH1, 0U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_D5, 0U) | \ + PIN_AFIO_AF(GPIOB_D6, 0U) | \ + PIN_AFIO_AF(GPIOB_D10, 0U) | \ + PIN_AFIO_AF(GPIOB_MICROSD_INS, 0U) | \ + PIN_AFIO_AF(GPIOB_D4, 0U) | \ + PIN_AFIO_AF(GPIOB_D13, 5U) | \ + PIN_AFIO_AF(GPIOB_D12, 5U) | \ + PIN_AFIO_AF(GPIOB_D11, 5U)) + +/* + * GPIOC setup: + * + * PC0 - A0 + * PC1 - A1 + * PC2 - A2 + * PC3 - A3 + * PC4 - A4 + * PC5 - A5 + * PC6 - USART6_TX_D1 + * PC7 - USART6_RX_D0 + * PC8 - CC_CS + * PC9 - LINK_LED + * PC10 - SPI3_CLK + * PC11 - SPI3_MISO + * PC12 - SPI3_MOSI + * PC13 - POWER_LED + * PC14 - OSC32_IN + * PC15 - OSC32_OUT + */ +#define VAL_GPIOC_MODER (PIN_MODE_ANALOG(GPIOC_A0) | \ + PIN_MODE_ANALOG(GPIOC_A1) | \ + PIN_MODE_ANALOG(GPIOC_A2) | \ + PIN_MODE_ANALOG(GPIOC_A3) | \ + PIN_MODE_ANALOG(GPIOC_A4) | \ + PIN_MODE_ANALOG(GPIOC_A5) | \ + PIN_MODE_ALTERNATE(GPIOC_D1) | \ + PIN_MODE_ALTERNATE(GPIOC_D0) | \ + PIN_MODE_OUTPUT(GPIOC_CC_CS) | \ + PIN_MODE_OUTPUT(GPIOC_LINK_LED) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_CLK) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MISO) | \ + PIN_MODE_ALTERNATE(GPIOC_SPI3_MOSI) | \ + PIN_MODE_OUTPUT(GPIOC_POWER_LED) | \ + PIN_MODE_ALTERNATE(GPIOC_OSC32_IN) | \ + PIN_MODE_ALTERNATE(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_A1) |\ + PIN_OTYPE_PUSHPULL(GPIOC_A2) |\ + PIN_OTYPE_PUSHPULL(GPIOC_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_CC_CS) | \ + PIN_OTYPE_PUSHPULL(GPIOC_LINK_LED) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOC_SPI3_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOC_POWER_LED) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_A0) | \ + PIN_OSPEED_HIGH(GPIOC_A1) | \ + PIN_OSPEED_HIGH(GPIOC_A2) | \ + PIN_OSPEED_HIGH(GPIOC_A3) | \ + PIN_OSPEED_HIGH(GPIOC_A4) | \ + PIN_OSPEED_HIGH(GPIOC_A5) | \ + PIN_OSPEED_HIGH(GPIOC_D1) | \ + PIN_OSPEED_HIGH(GPIOC_D0) | \ + PIN_OSPEED_HIGH(GPIOC_CC_CS) | \ + PIN_OSPEED_HIGH(GPIOC_LINK_LED) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_CLK) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MISO) | \ + PIN_OSPEED_HIGH(GPIOC_SPI3_MOSI) | \ + PIN_OSPEED_HIGH(GPIOC_POWER_LED) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \ + PIN_OSPEED_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_A0) | \ + PIN_PUPDR_FLOATING(GPIOC_A1) |\ + PIN_PUPDR_FLOATING(GPIOC_A2) |\ + PIN_PUPDR_FLOATING(GPIOC_A3) | \ + PIN_PUPDR_FLOATING(GPIOC_A4) | \ + PIN_PUPDR_FLOATING(GPIOC_A5) | \ + PIN_PUPDR_FLOATING(GPIOC_D1) | \ + PIN_PUPDR_FLOATING(GPIOC_D0) | \ + PIN_PUPDR_FLOATING(GPIOC_CC_CS) | \ + PIN_PUPDR_FLOATING(GPIOC_LINK_LED) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_CLK) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MISO) | \ + PIN_PUPDR_FLOATING(GPIOC_SPI3_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOC_POWER_LED) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_LOW(GPIOC_A0) | \ + PIN_ODR_LOW(GPIOC_A1) | \ + PIN_ODR_LOW(GPIOC_A2) | \ + PIN_ODR_LOW(GPIOC_A3) | \ + PIN_ODR_LOW(GPIOC_A4) | \ + PIN_ODR_LOW(GPIOC_A5) | \ + PIN_ODR_LOW(GPIOC_D1) | \ + PIN_ODR_LOW(GPIOC_D0) | \ + PIN_ODR_LOW(GPIOC_CC_CS) | \ + PIN_ODR_LOW(GPIOC_LINK_LED) | \ + PIN_ODR_LOW(GPIOC_SPI3_CLK) | \ + PIN_ODR_LOW(GPIOC_SPI3_MISO) | \ + PIN_ODR_LOW(GPIOC_SPI3_MOSI) | \ + PIN_ODR_LOW(GPIOC_POWER_LED) | \ + PIN_ODR_LOW(GPIOC_OSC32_IN) | \ + PIN_ODR_LOW(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_A0, 0U) | \ + PIN_AFIO_AF(GPIOC_A1, 0U) | \ + PIN_AFIO_AF(GPIOC_A2, 0U) | \ + PIN_AFIO_AF(GPIOC_A3, 0U) | \ + PIN_AFIO_AF(GPIOC_A4, 0U) | \ + PIN_AFIO_AF(GPIOC_A5, 0U) | \ + PIN_AFIO_AF(GPIOC_D1, 8U) | \ + PIN_AFIO_AF(GPIOC_D0, 8U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_CC_CS, 0U) | \ + PIN_AFIO_AF(GPIOC_LINK_LED, 0U) | \ + PIN_AFIO_AF(GPIOC_SPI3_CLK, 6U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MISO, 6U) | \ + PIN_AFIO_AF(GPIOC_SPI3_MOSI, 6U) | \ + PIN_AFIO_AF(GPIOC_POWER_LED, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - SPI_CS_GOPORT1 + * PD1 - SPI_CS_GOPORT2 + * PD2 - SPI_CS_GOPORT3 + * PD3 - CC_RTS + * PD4 - CC_CTS + * PD5 - CC_RX + * PD6 - CC_TX + * PD7 - PWR_ON_GOPORT1 + * PD8 - USART3_TX_GOPORT1 + * PD9 - USART3_RX_GOPORT1 + * PD10 - PWR_ON_GOPORT2 + * PD11 - SWITCH1 + * PD12 - PWR_ON_GOPORT3 + * PD13 - INT_GOPORT1 + * PD14 - INT_GOPORT2 + * PD15 - INT_GOPORT3 + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_SPI_CS_GOPORT1) | \ + PIN_MODE_INPUT(GPIOD_SPI_CS_GOPORT2) | \ + PIN_MODE_INPUT(GPIOD_SPI_CS_GOPORT3) | \ + PIN_MODE_ALTERNATE(GPIOD_CC_RTS) | \ + PIN_MODE_ALTERNATE(GPIOD_CC_CTS) | \ + PIN_MODE_ALTERNATE(GPIOD_CC_RX) | \ + PIN_MODE_ALTERNATE(GPIOD_CC_TX) | \ + PIN_MODE_OUTPUT(GPIOD_PWR_ON_GOPORT1) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_TX_GOPORT1) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_RX_GOPORT1) | \ + PIN_MODE_OUTPUT(GPIOD_PWR_ON_GOPORT2) | \ + PIN_MODE_INPUT(GPIOD_SWITCH1) | \ + PIN_MODE_OUTPUT(GPIOD_PWR_ON_GOPORT3) | \ + PIN_MODE_OUTPUT(GPIOD_INT_GOPORT1) | \ + PIN_MODE_OUTPUT(GPIOD_INT_GOPORT2) | \ + PIN_MODE_OUTPUT(GPIOD_INT_GOPORT3)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_SPI_CS_GOPORT1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_SPI_CS_GOPORT2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_SPI_CS_GOPORT3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_CC_RTS) | \ + PIN_OTYPE_PUSHPULL(GPIOD_CC_CTS) | \ + PIN_OTYPE_PUSHPULL(GPIOD_CC_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_CC_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PWR_ON_GOPORT1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_TX_GOPORT1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_RX_GOPORT1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PWR_ON_GOPORT2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_SWITCH1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PWR_ON_GOPORT3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_INT_GOPORT1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_INT_GOPORT2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_INT_GOPORT3)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_SPI_CS_GOPORT1) | \ + PIN_OSPEED_HIGH(GPIOD_SPI_CS_GOPORT2) | \ + PIN_OSPEED_HIGH(GPIOD_SPI_CS_GOPORT3) | \ + PIN_OSPEED_HIGH(GPIOD_CC_RTS) | \ + PIN_OSPEED_HIGH(GPIOD_CC_CTS) | \ + PIN_OSPEED_HIGH(GPIOD_CC_RX) | \ + PIN_OSPEED_HIGH(GPIOD_CC_TX) | \ + PIN_OSPEED_HIGH(GPIOD_PWR_ON_GOPORT1) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_TX_GOPORT1) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_RX_GOPORT1) | \ + PIN_OSPEED_HIGH(GPIOD_PWR_ON_GOPORT2) | \ + PIN_OSPEED_HIGH(GPIOD_SWITCH1) | \ + PIN_OSPEED_HIGH(GPIOD_PWR_ON_GOPORT3) | \ + PIN_OSPEED_HIGH(GPIOD_INT_GOPORT1) | \ + PIN_OSPEED_HIGH(GPIOD_INT_GOPORT2) | \ + PIN_OSPEED_HIGH(GPIOD_INT_GOPORT3)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_SPI_CS_GOPORT1) | \ + PIN_PUPDR_FLOATING(GPIOD_SPI_CS_GOPORT2) | \ + PIN_PUPDR_FLOATING(GPIOD_SPI_CS_GOPORT3) | \ + PIN_PUPDR_FLOATING(GPIOD_CC_RTS) | \ + PIN_PUPDR_FLOATING(GPIOD_CC_CTS) | \ + PIN_PUPDR_FLOATING(GPIOD_CC_RX) | \ + PIN_PUPDR_FLOATING(GPIOD_CC_TX) | \ + PIN_PUPDR_FLOATING(GPIOD_PWR_ON_GOPORT1) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_TX_GOPORT1) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_RX_GOPORT1) | \ + PIN_PUPDR_FLOATING(GPIOD_PWR_ON_GOPORT2) | \ + PIN_PUPDR_PULLDOWN(GPIOD_SWITCH1) | \ + PIN_PUPDR_FLOATING(GPIOD_PWR_ON_GOPORT3) | \ + PIN_PUPDR_FLOATING(GPIOD_INT_GOPORT1) | \ + PIN_PUPDR_FLOATING(GPIOD_INT_GOPORT2) | \ + PIN_PUPDR_FLOATING(GPIOD_INT_GOPORT3)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_SPI_CS_GOPORT1) | \ + PIN_ODR_HIGH(GPIOD_SPI_CS_GOPORT2) | \ + PIN_ODR_HIGH(GPIOD_SPI_CS_GOPORT3) | \ + PIN_ODR_LOW(GPIOD_CC_RTS) | \ + PIN_ODR_LOW(GPIOD_CC_CTS) | \ + PIN_ODR_LOW(GPIOD_CC_RX) | \ + PIN_ODR_LOW(GPIOD_CC_TX) | \ + PIN_ODR_LOW(GPIOD_PWR_ON_GOPORT1) | \ + PIN_ODR_LOW(GPIOD_USART3_TX_GOPORT1) | \ + PIN_ODR_LOW(GPIOD_USART3_RX_GOPORT1) | \ + PIN_ODR_LOW(GPIOD_PWR_ON_GOPORT2) | \ + PIN_ODR_LOW(GPIOD_SWITCH1) | \ + PIN_ODR_LOW(GPIOD_PWR_ON_GOPORT3) | \ + PIN_ODR_HIGH(GPIOD_INT_GOPORT1) | \ + PIN_ODR_HIGH(GPIOD_INT_GOPORT2) | \ + PIN_ODR_HIGH(GPIOD_INT_GOPORT3)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_SPI_CS_GOPORT1, 0U) | \ + PIN_AFIO_AF(GPIOD_SPI_CS_GOPORT2, 0U) | \ + PIN_AFIO_AF(GPIOD_SPI_CS_GOPORT3, 0U) | \ + PIN_AFIO_AF(GPIOD_CC_RTS, 7U) | \ + PIN_AFIO_AF(GPIOD_CC_CTS, 7U) | \ + PIN_AFIO_AF(GPIOD_CC_RX, 7U) | \ + PIN_AFIO_AF(GPIOD_CC_TX, 7U) | \ + PIN_AFIO_AF(GPIOD_PWR_ON_GOPORT1, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_USART3_TX_GOPORT1, 7U) | \ + PIN_AFIO_AF(GPIOD_USART3_RX_GOPORT1, 7U) | \ + PIN_AFIO_AF(GPIOD_PWR_ON_GOPORT2, 0U) | \ + PIN_AFIO_AF(GPIOD_SWITCH1, 0U) | \ + PIN_AFIO_AF(GPIOD_PWR_ON_GOPORT3, 0U) | \ + PIN_AFIO_AF(GPIOD_INT_GOPORT1, 0U) | \ + PIN_AFIO_AF(GPIOD_INT_GOPORT2, 0U) | \ + PIN_AFIO_AF(GPIOD_INT_GOPORT3, 0U)) + +/* + * GPIOE setup: + * + * PE0 - USART8_RX_GOPORT3 + * PE1 - USART8_TX_GOPORT3 + * PE2 - SPI4_SCK + * PE3 - EN_UART_TX_PU_GOPORT1 + * PE4 - CC_HIB + * PE5 - D9 + * PE6 - SPI4_MOSI + * PE7 - USART7_RX_GOPORT2 + * PE8 - USART7_TX_GOPORT2 + * PE9 - LED_GOPORT1 + * PE10 - EN_UART_TX_PU_GOPORT2 + * PE11 - LED_GOPORT2 + * PE12 - EN_UART_TX_PU_GOPORT3 + * PE13 - SPI4_MISO + * PE14 - LED_GOPORT3 + * PE15 - CC_TCXO_EN_SOP2 + */ +#define VAL_GPIOE_MODER (PIN_MODE_ALTERNATE(GPIOE_USART8_RX_GOPORT3) | \ + PIN_MODE_ALTERNATE(GPIOE_USART8_TX_GOPORT3) | \ + PIN_MODE_ALTERNATE(GPIOE_SPI4_SCK) | \ + PIN_MODE_ALTERNATE(GPIOE_EN_UART_TX_PU_GOPORT1) | \ + PIN_MODE_OUTPUT(GPIOE_CC_HIB) | \ + PIN_MODE_INPUT(GPIOE_D9) | \ + PIN_MODE_ALTERNATE(GPIOE_SPI4_MOSI) | \ + PIN_MODE_ALTERNATE(GPIOE_USART7_RX_GOPORT2) | \ + PIN_MODE_ALTERNATE(GPIOE_USART7_TX_GOPORT2) | \ + PIN_MODE_OUTPUT(GPIOE_LED_GOPORT1) | \ + PIN_MODE_OUTPUT(GPIOE_EN_UART_TX_PU_GOPORT2) | \ + PIN_MODE_OUTPUT(GPIOE_LED_GOPORT2) | \ + PIN_MODE_OUTPUT(GPIOE_EN_UART_TX_PU_GOPORT3) | \ + PIN_MODE_ALTERNATE(GPIOE_SPI4_MISO) | \ + PIN_MODE_OUTPUT(GPIOE_LED_GOPORT3) | \ + PIN_MODE_INPUT(GPIOE_CC_TCXO_EN_SOP2)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_USART8_RX_GOPORT3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_USART8_TX_GOPORT3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_SPI4_SCK) | \ + PIN_OTYPE_PUSHPULL(GPIOE_EN_UART_TX_PU_GOPORT1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_CC_HIB) | \ + PIN_OTYPE_PUSHPULL(GPIOE_D9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_SPI4_MOSI) | \ + PIN_OTYPE_PUSHPULL(GPIOE_USART7_RX_GOPORT2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_USART7_TX_GOPORT2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_LED_GOPORT1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_EN_UART_TX_PU_GOPORT2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_LED_GOPORT2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_EN_UART_TX_PU_GOPORT3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_SPI4_MISO) | \ + PIN_OTYPE_PUSHPULL(GPIOE_LED_GOPORT3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_CC_TCXO_EN_SOP2)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_USART8_RX_GOPORT3) | \ + PIN_OSPEED_HIGH(GPIOE_USART8_TX_GOPORT3) | \ + PIN_OSPEED_HIGH(GPIOE_SPI4_SCK) | \ + PIN_OSPEED_HIGH(GPIOE_EN_UART_TX_PU_GOPORT1) | \ + PIN_OSPEED_HIGH(GPIOE_CC_HIB) | \ + PIN_OSPEED_HIGH(GPIOE_D9) | \ + PIN_OSPEED_HIGH(GPIOE_SPI4_MOSI) | \ + PIN_OSPEED_HIGH(GPIOE_USART7_RX_GOPORT2) | \ + PIN_OSPEED_HIGH(GPIOE_USART7_TX_GOPORT2) | \ + PIN_OSPEED_HIGH(GPIOE_LED_GOPORT1) | \ + PIN_OSPEED_HIGH(GPIOE_EN_UART_TX_PU_GOPORT2) | \ + PIN_OSPEED_HIGH(GPIOE_LED_GOPORT2) | \ + PIN_OSPEED_HIGH(GPIOE_EN_UART_TX_PU_GOPORT3) | \ + PIN_OSPEED_HIGH(GPIOE_SPI4_MISO) | \ + PIN_OSPEED_HIGH(GPIOE_LED_GOPORT3) | \ + PIN_OSPEED_HIGH(GPIOE_CC_TCXO_EN_SOP2)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_USART8_RX_GOPORT3) | \ + PIN_PUPDR_FLOATING(GPIOE_USART8_TX_GOPORT3) | \ + PIN_PUPDR_FLOATING(GPIOE_SPI4_SCK) | \ + PIN_PUPDR_PULLDOWN(GPIOE_EN_UART_TX_PU_GOPORT1) | \ + PIN_PUPDR_PULLDOWN(GPIOE_CC_HIB) | \ + PIN_PUPDR_FLOATING(GPIOE_D9) | \ + PIN_PUPDR_FLOATING(GPIOE_SPI4_MOSI) | \ + PIN_PUPDR_FLOATING(GPIOE_USART7_RX_GOPORT2) | \ + PIN_PUPDR_FLOATING(GPIOE_USART7_TX_GOPORT2) | \ + PIN_PUPDR_FLOATING(GPIOE_LED_GOPORT1) | \ + PIN_PUPDR_PULLDOWN(GPIOE_EN_UART_TX_PU_GOPORT2) | \ + PIN_PUPDR_FLOATING(GPIOE_LED_GOPORT2) | \ + PIN_PUPDR_PULLDOWN(GPIOE_EN_UART_TX_PU_GOPORT3) | \ + PIN_PUPDR_FLOATING(GPIOE_SPI4_MISO) | \ + PIN_PUPDR_FLOATING(GPIOE_LED_GOPORT3) | \ + PIN_PUPDR_FLOATING(GPIOE_CC_TCXO_EN_SOP2)) +#define VAL_GPIOE_ODR (PIN_ODR_LOW(GPIOE_USART8_RX_GOPORT3) | \ + PIN_ODR_LOW(GPIOE_USART8_TX_GOPORT3) | \ + PIN_ODR_LOW(GPIOE_SPI4_SCK) | \ + PIN_ODR_LOW(GPIOE_EN_UART_TX_PU_GOPORT1) | \ + PIN_ODR_LOW(GPIOE_CC_HIB) | \ + PIN_ODR_LOW(GPIOE_D9) | \ + PIN_ODR_LOW(GPIOE_SPI4_MOSI) | \ + PIN_ODR_LOW(GPIOE_USART7_RX_GOPORT2) | \ + PIN_ODR_LOW(GPIOE_USART7_TX_GOPORT2) | \ + PIN_ODR_LOW(GPIOE_LED_GOPORT1) | \ + PIN_ODR_LOW(GPIOE_EN_UART_TX_PU_GOPORT2) | \ + PIN_ODR_LOW(GPIOE_LED_GOPORT2) | \ + PIN_ODR_LOW(GPIOE_EN_UART_TX_PU_GOPORT3) | \ + PIN_ODR_LOW(GPIOE_SPI4_MISO) | \ + PIN_ODR_LOW(GPIOE_LED_GOPORT3) | \ + PIN_ODR_LOW(GPIOE_CC_TCXO_EN_SOP2)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_USART8_RX_GOPORT3, 8U) | \ + PIN_AFIO_AF(GPIOE_USART8_TX_GOPORT3, 8U) | \ + PIN_AFIO_AF(GPIOE_SPI4_SCK, 5U) | \ + PIN_AFIO_AF(GPIOE_EN_UART_TX_PU_GOPORT1, 0U) | \ + PIN_AFIO_AF(GPIOE_CC_HIB, 0U) | \ + PIN_AFIO_AF(GPIOE_D9, 0U) | \ + PIN_AFIO_AF(GPIOE_SPI4_MOSI, 5U) | \ + PIN_AFIO_AF(GPIOE_USART7_RX_GOPORT2, 8U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_USART7_TX_GOPORT2, 8U) | \ + PIN_AFIO_AF(GPIOE_LED_GOPORT1, 0U) | \ + PIN_AFIO_AF(GPIOE_EN_UART_TX_PU_GOPORT2, 0U) | \ + PIN_AFIO_AF(GPIOE_LED_GOPORT2, 0U) | \ + PIN_AFIO_AF(GPIOE_EN_UART_TX_PU_GOPORT3, 0U) | \ + PIN_AFIO_AF(GPIOE_SPI4_MISO, 0U) | \ + PIN_AFIO_AF(GPIOE_LED_GOPORT3, 0U) | \ + PIN_AFIO_AF(GPIOE_CC_TCXO_EN_SOP2, 0U)) + + +/* + * GPIOH setup: + * + * PH0 - OSC_IN + * PH1 - OSC_OUT + * PH2 - PIN2 + * PH3 - PIN3 + * PH4 - PIN4 + * PH5 - PIN5 + * PH6 - PIN6 + * PH7 - PIN7 + * PH8 - PIN8 + * PH9 - PIN9 + * PH10 - PIN10 + * PH11 - PIN11 + * PH12 - PIN12 + * PH13 - PIN13 + * PH14 - PIN14 + * PH15 - PIN15 + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/CMakeLists.txt new file mode 100644 index 00000000..aa7f1d54 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..a970be77 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 0x08008000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 3 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 4, 6 }, // 0x080A0000 deployment +}; + +//16kB block +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +//64kB block +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +//128kB block +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + (0), // no attributes for this region + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + (0), // no attributes for this region + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + (0), // no attributes for this region + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage.c new file mode 100644 index 00000000..23428263 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/Device_BlockStorage.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//16kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 0x08004000 nanoCLR +}; + +//64kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 }, // 0x08040000 deployment +}; + +//16kB block +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +//64kB block +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +//128kB block +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + (0), // no attributes for this region + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + (0), // no attributes for this region + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + (0), // no attributes for this region + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.c new file mode 100644 index 00000000..9fd0a5ad --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.c @@ -0,0 +1,454 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD2. + */ +#define USBD2_DATA_REQUEST_EP 1 +#define USBD2_DATA_AVAILABLE_EP 1 +#define USBD2_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"WildernessLabs" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"Netduino3_Wifi" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(0x0043, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + if (usbp->state == USB_ACTIVE) { + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD2_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD2_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + } + else if (usbp->state == USB_SELECTED) { + usbDisableEndpointsI(usbp); + } + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handling messages not implemented in the default handler nor in the + * SerialUSB handler. + */ +static bool requests_hook(USBDriver *usbp) { + + if (((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE) && + (usbp->setup[1] == USB_REQ_SET_INTERFACE)) { + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + } + return sduRequestsHook(usbp); +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + requests_hook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD2_DATA_REQUEST_EP, + USBD2_DATA_AVAILABLE_EP, + USBD2_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.h new file mode 100644 index 00000000..167e1df8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/common/usbcfg.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/ffconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/ffconf.h new file mode 100644 index 00000000..85b623af --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/ffconf.h @@ -0,0 +1,272 @@ +/* CHIBIOS FIX */ +#include "ch.h" + +/*---------------------------------------------------------------------------/ +/ FatFs - Configuration file +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 87030 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: All basic functions are enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_STRFUNC 1 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 1 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 0 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 1 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 850 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 3 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added +/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255. +/ It should be set 255 to support full featured LFN operations. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree(), must be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16, +/ when LFN is enabled. Also behavior of string I/O functions will be affected by +/ this option. When LFN is not enabled, this option has no effect. +*/ + + +#define FF_STRF_ENCODE 3 +/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(), +/ f_putc(), f_puts and f_printf() convert the character encoding in it. +/ This option selects assumption of character encoding ON THE FILE to be +/ read/written via those functions. +/ +/ 0: ANSI/OEM +/ 1: UTF-16LE +/ 2: UTF-16BE +/ 3: UTF-8 +*/ + + +#define FF_FS_RPATH 2 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 3 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 1 +#define FF_VOLUME_STRS "D","E","F" +/* FF_STR_VOLUME_ID switches string support for volume ID. +/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each +/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for +/ the drive ID strings are: A-Z and 0-9. */ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 0 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ When enable exFAT, also LFN needs to be enabled. +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 1 +#define FF_NORTC_MON 8 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2018 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 1 +#define FF_FS_TIMEOUT TIME_MS2I(1000) +#define FF_SYNC_t semaphore_t* +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +/* #include // O/S definitions */ + + + +/*--- End of configuration options ---*/ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/NETDUINO3_WIFI.Adc.cs b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/NETDUINO3_WIFI.Adc.cs new file mode 100644 index 00000000..825543d5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/NETDUINO3_WIFI.Adc.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.NETDUINO3_WIFI +{ + /// + /// Enumeration of ADC channels available in NETDUINO3_WIFI + /// + public static class AdcChannels + { + /// + /// Channel 0, connected to PC0 (ADC1 - IN10) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, connected to PC1 (ADC1 - IN11) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, connected to PC2 (ADC2 - IN14) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, connected to PC3 (ADC2 - IN15) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, connected to PC4 (ADC3 - IN12) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, connected to PC5 (ADC3 - IN13) + /// + public const int Channel_5 = 5; + + /// + /// Channel 6, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 6; + + /// + /// Channel 7, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 7; + + /// + /// Channel 8, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 8; + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/README.md new file mode 100644 index 00000000..d3c16dd1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](NETDUINO3_WIFI.Adc.cs) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/package.nuspec b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/package.nuspec new file mode 100644 index 00000000..4a89a9c1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/managed_helpers/package.nuspec @@ -0,0 +1,28 @@ + + + + nanoFramework.Targets.NETDUINO3_WIFI + nanoFramework.Targets.NETDUINO3_WIFI + 1.0.0 + nanoFramework project contributors + nanoFramework project contributors + false + + Helper classes to use NETDUINO3_WIFI target in C# applications. + + + + + This is an extension for .NET nanoFramework enhacing support for Windows.Devices.Gpio.GpioController when using STM32 MCUs. + + https://github.com/nanoframework + https://secure.gravatar.com/avatar/97d0e092247f0716db6d4b47b7d1d1ad + https://github.com/nanoframework/nf-interpreter/blob/develop/LICENSE.md + Copyright (c) 2019 The nanoFramework project contributors + + nanoFramework, nano Framework, NETNF, NETMF, Micro Framework, STM32, .net, NETDUINO3_WIFI + + + + + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/chconf.h new file mode 100644 index 00000000..13cec578 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf.h new file mode 100644 index 00000000..b970c22f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/main.c new file mode 100644 index 00000000..f10973a0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/main.c @@ -0,0 +1,77 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // check for valid CLR image at address contiguous to nanoBooter + // this target DOES NOT have configuration block, so we need to use the __nanoImage_end__ address here + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palClearPad(GPIOE, GPIOE_LED_GOPORT3); + palSetPad(GPIOA, GPIOA_USR_LED); + osDelay(250); + palClearPad(GPIOA, GPIOA_USR_LED); + palSetPad(GPIOE, GPIOE_LED_GOPORT1); + osDelay(250); + palClearPad(GPIOE, GPIOE_LED_GOPORT1); + palSetPad(GPIOE, GPIOE_LED_GOPORT2); + osDelay(250); + palClearPad(GPIOE, GPIOE_LED_GOPORT2); + palSetPad(GPIOE, GPIOE_LED_GOPORT3); + osDelay(250); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf.h new file mode 100644 index 00000000..0ac31e2c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf.h @@ -0,0 +1,335 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 25 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter-DEBUG.ld new file mode 100644 index 00000000..505f0a7a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08007FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter.ld new file mode 100644 index 00000000..31588162 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/netduino3wifi_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08003FFF)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/chconf.h new file mode 100644 index 00000000..390ce3a6 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf.h new file mode 100644 index 00000000..264cfad6 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf.h @@ -0,0 +1,525 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC TRUE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM TRUE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI TRUE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..af4677fe --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +// enables STM32 Can driver +#if !defined(HAL_USE_STM32_CAN) +#define HAL_USE_STM32_CAN TRUE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/main.c new file mode 100644 index 00000000..1902b00c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/main.c @@ -0,0 +1,104 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // find out wakeup reason + if((RTC->ISR & RTC_ISR_ALRAF) == RTC_ISR_ALRAF) + { + // standby, match WakeupReason_FromStandby enum + WakeupReasonStore = 1; + } + else if((PWR->CSR & PWR_CSR_WUF) == PWR_CSR_WUF) + { + // wake from pin, match WakeupReason_FromPin enum + WakeupReasonStore = 2; + } + else + { + // undetermined reason, match WakeupReason_Undetermined enum + WakeupReasonStore = 0; + } + + // first things first: need to clear any possible wakeup flags + // if this is not done here the next standby -> wakeup sequence won't work + CLEAR_BIT(RTC->CR, RTC_CR_ALRAIE); + CLEAR_BIT(RTC->ISR, RTC_ISR_ALRAF); + SET_BIT(PWR->CR, PWR_CR_CWUF); + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + /////////////////////////////////////////////////////////////////////////////////////////////////////// + // for STM32F4 family if watchdog is enabled can't use standby mode because the IWDG can't be stoped // + /////////////////////////////////////////////////////////////////////////////////////////////////////// + Watchdog_Init(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf.h new file mode 100644 index 00000000..01dd9af2 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf.h @@ -0,0 +1,357 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 25 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_HSEDIV +#define STM32_RTCPRE_VALUE 25 +#define STM32_RTC_PRESA_VALUE 125 +#define STM32_RTC_PRESS_VALUE 8000 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PLLI2SQ_VALUE 2 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 TRUE +#define STM32_ADC_USE_ADC3 TRUE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 TRUE +#define STM32_CAN_USE_CAN2 TRUE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE TRUE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 TRUE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 TRUE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 TRUE +#define STM32_SPI_USE_SPI4 TRUE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 TRUE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USE_UART7 FALSE +#define STM32_UART_USE_UART8 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(0, 0) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(0, 0) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_UART7_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART7_TX_DMA_STREAM STM32_DMA_STREAM_ID(0, 0) +#define STM32_UART_UART8_RX_DMA_STREAM STM32_DMA_STREAM_ID(0, 0) +#define STM32_UART_UART8_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_UART7_IRQ_PRIORITY 12 +#define STM32_UART_UART8_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_UART7_DMA_PRIORITY 0 +#define STM32_UART_UART8_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR-DEBUG.ld new file mode 100644 index 00000000..d2ef582b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 2M - 32k - 1408k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x080A0000, len = 1408k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR.ld new file mode 100644 index 00000000..5a59730e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/netduino3wifi_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F427Vx memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 2M - 16k - 1792k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 1792k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.c new file mode 100644 index 00000000..ccee7c5e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.c @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" +#include + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; + +// this target use DFU for updates +uint32_t GetTargetCapabilities() +{ + return TargetCapabilities_DfuUpdate; +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.h.in new file mode 100644 index 00000000..563fe883 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_common.h.in @@ -0,0 +1,38 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x200000C0) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00030000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00200000) + +///////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +////////////////////////////////////////////// + + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.cpp new file mode 100644 index 00000000..7dbe7ff1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_nf_devices_can_config.h" +#include + +/////////// +// CAN1 // +/////////// + +// pin configuration for CAN1 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_09 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_08 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(1, GPIOB, GPIOB, 9, 8, 9) + +// buffer +CANRxFrame Can1_MsgBuffer[CAN1_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(1, CAN1_RX_BUFFER_SIZE) + +/////////// +// CAN2 // +/////////// + +// pin configuration for CAN2 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_06 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_05 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(2, GPIOB, GPIOB, 6, 5, 9) + +// buffer +CANRxFrame Can2_MsgBuffer[CAN2_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(2, CAN2_RX_BUFFER_SIZE) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.h new file mode 100644 index 00000000..adc8ace3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_can_config.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +////////// +// CAN1 // +////////// + +// enable CAN1 +#define NF_CAN_STM32_CAN_USE_CAN1 TRUE + +// buffers size +#define CAN1_RX_BUFFER_SIZE 16 + +////////// +// CAN2 // +////////// + +// enable CAN2 +#define NF_CAN_STM32_CAN_USE_CAN2 TRUE + +// buffers size +#define CAN2_RX_BUFFER_SIZE 16 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..89ad1d83 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_nf_devices_onewire_config.h" +#include + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port for TX pin is: GPIOC +// TX pin: is GPIOC_6 +// GPIO alternate pin function is 8 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +UART_CONFIG_PINS(6, GPIOC, 6, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..d0fb1c87 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_nf_devices_onewire_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART6 // +/////////// + +// enable USART6 +#define NF_ONEWIRE_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 32 bytes +#define UART6_TX_SIZE 32 +// rx buffer size: 32 bytes +#define UART6_RX_SIZE 32 \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..97181d6f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_system_devices_dac_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T HAVE SUPPORT FOR DAC PINS // +////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..362011df --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_adc_config.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOC, 0, ADC_CHANNEL_IN10}, + {1, GPIOC, 1, ADC_CHANNEL_IN11}, + + // ADC2 + {2, GPIOC, 2, ADC_CHANNEL_IN14}, + {2, GPIOC, 3, ADC_CHANNEL_IN15}, + + // ADC3 + {3, GPIOC, 4, ADC_CHANNEL_IN12}, + {3, GPIOC, 5, ADC_CHANNEL_IN13}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..18b1cd19 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_6 +// SDA pin: is GPIOB_7 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 6, 7, 4) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..6f13e26c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include + +/////////// +// UART3 // +/////////// + +// pin configuration for UART3 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOD +// TX pin: is GPIOD_8 +// RX pin: is GPIOD_9 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(3, GPIOD, GPIOD, 8, 9, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_TxBuffer[UART3_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_RxBuffer[UART3_RX_SIZE]; + +// initialization for UART3 +UART_INIT(3, UART3_TX_SIZE, UART3_RX_SIZE) + +// un-initialization for UART3 +UART_UNINIT(3) + +// /////////// +// // UART6 // +// /////////// + +// // pin configuration for UART6 +// // port for TX pin is: GPIOC +// // port for RX pin is: GPIOC +// // TX pin: is GPIOC_6 +// // RX pin: is GPIOC_7 +// // GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +// UART_CONFIG_PINS(6, GPIOC, GPIOC, 6, 7, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; + +// // initialization for UART6 +// UART_INIT(6, UART6_TX_SIZE, UART6_RX_SIZE) + +// // un-initialization for UART6 +// UART_UNINIT(6) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..07dc7c6f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART3 // +/////////// + +// enable USART3 +#define NF_SERIAL_COMM_STM32_UART_USE_USART3 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART3_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART3_RX_SIZE 256 + + +// /////////// +// // UART6 // +// /////////// + +// // enable USART6 +// #define NF_SERIAL_COMM_STM32_UART_USE_USART6 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART6_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART6_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_devices_spi_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_storage_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_storage_config.h new file mode 100644 index 00000000..8601cffd --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/NETDUINO3_WIFI/target_windows_storage_config.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// maps the SD Card driver +#define SD_CARD_DRIVER SDCD1 + +// maps the SD Card detect GPIO definition (in Target_Windows_Storage.c) to board GPIO line (in board.h) +#define SDCARD_LINE_DETECT LINE_SD_DETECT + +// includes SPIFFS in storage +#define USE_SPIFFS_FOR_STORAGE FALSE diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/CMakeLists.txt new file mode 100644 index 00000000..d3e4d14f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/CMakeLists.txt @@ -0,0 +1,209 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for ChibiOS FatFS + ${CHIBIOS_FATFS_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS FatFS + ${CHIBIOS_FATFS_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf -DRUNTIME_MEMORY_PROFILE__extrasmall=1) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F091xC_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F091xC_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F091xC_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F091xC_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x1000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x2800") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/README.md new file mode 100644 index 00000000..6e63d062 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/README.md @@ -0,0 +1,42 @@ +## Configuration of Chibios, HAL and MCU ## + +For a successful build the following changes are required: + +In _halconf.g_ (in both nanoBooter and nanoCLR folders), when compared with a default file: +- HAL_USE_SERIAL to TRUE +- SERIAL_DEFAULT_BITRATE to 921600 +- SERIAL_BUFFERS_SIZE has to be at least 64 (2x the Wire Protocol packet size) otherwise the transmission will be garbled as the packets overrun each other + +In _mcuconf.h_ (in both nanoBooter and nanoCLR folders), when compared with a default file: +- STM32_SERIAL_USE_USART2 to TRUE + + +## Definitions for each image ## + +Any defines specific to an image (nanoBooter or nanoCLR) that are to be made available throughout the code should be added to the _target_board.h.in_. There is one in [nanoBooter](nanoBooter/target_board.h.in) and another in [nanoCLR](nanoCLR/target_board.h.in) directories, allowing different defines for each one. +Defines that are common to a target board should be added to the [_target_common.h.in_](target_common.h.in). +The content of these files is parsed by CMake. It can include CMake variables. Check the documentation of CMake config files [here](https://cmake.org/cmake/help/v3.7/command/configure_file.html?highlight=configure_file). + + +## nanoCLR image start address ## + +The start address of nanoCLR (it's vector table) is defined in the linker file (STM32F091xC.ld)[nanoCLR/STM32F091xC.ld] by setting the initial address of the _flash_ region. The total size has to be the flash region size less the space reserved for nanoBooter. + + +## Vector table copy to RAM ## + +Because the STM32F0 series don't have the SCB->VTOR register that allows offsetting the vector table another approach as to be taken: copy the vector table to a RAM location and remap the memory mode using SYSCFG->CFGR1. This is accomplished by reserving in RAM0 region the required space (in the linker file) and by performing the copy of the vector table right after the nanoCLR starts. This code block is located in main() right after the call to halInit(). + +If porting this reference board to another SMT32F0 (or L0) series make sure this piece of code is kept there. + + + + +**NOTE: this configuration was successfully tested in a NUCLEO_F091RC board using the virtual COM port through the ST Link USB connection.** + + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. +There is no FPU available, so floating point is provided through software implementation. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/CMakeLists.txt new file mode 100644 index 00000000..777d4ec3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append source files required for ChibiOS interface +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..eb549300 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//2kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0 , 5 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 6 , 101 }, // 0x08003000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 102, 127 } // 0x08033000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 128, // total number of blocks in this region + 0x800, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00040000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +__attribute__((__used__)) BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage.c new file mode 100644 index 00000000..ecd9b529 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/Device_BlockStorage.c @@ -0,0 +1,66 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//2kB block +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 4 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 5, 83 }, // 0x08002800 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 84, 127 } // 0x0802A000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 128, // total number of blocks in this region + 0x800, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00040000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +__attribute__((__used__)) BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/serialcfg.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/serialcfg.h new file mode 100644 index 00000000..a9e1b9b5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/common/serialcfg.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef SERIALCFG_H +#define SERIALCFG_H + +// define which serial driver the Wire Protocol will be using +#define SERIAL_DRIVER SD2 + +#endif /* SERIALCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter-DEBUG.ld new file mode 100644 index 00000000..d7a37aba --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + + +/* + * STM32F091xC memory setup. + */ +MEMORY +{ + flash : org = 0x08000000, len = 12k /* space reserved for nanoBooter */ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 32k + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter.ld new file mode 100644 index 00000000..94753e9d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/STM32F091xC_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + + +/* + * STM32F091xC memory setup. + */ +MEMORY +{ + flash : org = 0x08000000, len = 10k /* space reserved for nanoBooter */ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 32k + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/chconf.h new file mode 100644 index 00000000..e6e3fc71 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/chconf.h @@ -0,0 +1,704 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM FALSE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES FALSE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS FALSE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES FALSE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP TRUE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS TRUE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS TRUE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf.h new file mode 100644 index 00000000..f0824d67 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf.h @@ -0,0 +1,513 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/main.c new file mode 100644 index 00000000..b8de9ab5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/main.c @@ -0,0 +1,80 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 512, "ReceiverThread"); + +// configuration for debugger serial port +// dev notes: +// conservative baud rate value as 921600 has a high error percentage on baud rate clocking +// OVER8 bit on CR1 to further decrease baud rate clocking error +static const SerialConfig uartConfig = +{ + 460800, + USART_CR1_OVER8, + USART_CR2_STOP1_BITS, + 0 +}; + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + if (palReadPad(GPIOC, GPIOC_BUTTON)) + { + // check for valid CLR image at address contiguous to nanoBooter + // this target DOES NOT have configuration block, so we need to use the __nanoImage_end__ address here + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, &uartConfig); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palClearPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + palSetPad(GPIOA, GPIOA_LED_GREEN); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf.h new file mode 100644 index 00000000..08bc4e02 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf.h @@ -0,0 +1,246 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F0xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 3...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F0xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_HSI14_ENABLED TRUE +#define STM32_HSI48_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PREDIV_VALUE 2 +#define STM32_PLLMUL_VALUE 12 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE STM32_PPRE_DIV1 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#define STM32_PLLNODIV STM32_PLLNODIV_DIV2 +#define STM32_CECSW STM32_CECSW_HSI +#define STM32_I2C1SW STM32_I2C1SW_HSI +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_1_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI2_3_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI4_15_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI16_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI17_20_IRQ_PRIORITY 3 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 3 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 2 +#define STM32_GPT_TIM2_IRQ_PRIORITY 2 +#define STM32_GPT_TIM3_IRQ_PRIORITY 2 +#define STM32_GPT_TIM6_IRQ_PRIORITY 2 +#define STM32_GPT_TIM7_IRQ_PRIORITY 2 +#define STM32_GPT_TIM14_IRQ_PRIORITY 2 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 3 +#define STM32_I2C_I2C2_IRQ_PRIORITY 3 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI1 FALSE +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#define STM32_I2S_SPI1_IRQ_PRIORITY 2 +#define STM32_I2S_SPI2_IRQ_PRIORITY 2 +#define STM32_I2S_SPI1_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2S_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 3 +#define STM32_ICU_TIM2_IRQ_PRIORITY 3 +#define STM32_ICU_TIM3_IRQ_PRIORITY 3 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 3 +#define STM32_PWM_TIM2_IRQ_PRIORITY 3 +#define STM32_PWM_TIM3_IRQ_PRIORITY 3 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 3 +#define STM32_SERIAL_USART2_PRIORITY 3 +#define STM32_SERIAL_USART3_8_PRIORITY 3 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 2 +#define STM32_SPI_SPI2_IRQ_PRIORITY 2 +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 2 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USE_UART7 FALSE +#define STM32_UART_USE_UART8 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 3 +#define STM32_UART_USART2_IRQ_PRIORITY 3 +#define STM32_UART_USART3_8_IRQ_PRIORITY 3 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_UART7_DMA_PRIORITY 0 +#define STM32_UART_UART8_DMA_PRIORITY 0 +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART7_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART7_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART8_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_UART8_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR-DEBUG.ld new file mode 100644 index 00000000..6f8e270f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR-DEBUG.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + + +/* + * STM32F091xC memory setup. + */ +MEMORY +{ + flash : org = 0x08003000, len = 256k - 12k - 50k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08033000, len = 50k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0xC0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x200000C0, len = 32k - 0xC0 /* remaining RAM is free for use */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR.ld new file mode 100644 index 00000000..d622e155 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/STM32F091xC_CLR.ld @@ -0,0 +1,76 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + + +/* + * STM32F091xC memory setup. + */ +MEMORY +{ + flash : org = 0x08002800, len = 256k - 10k - 88k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x0802A000, len = 88k /* space reserved for application deployment */ + ramvt : org = 0x20000000, len = 0xC0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x200000C0, len = 32k - 0xC0 /* remaining RAM is free for use */ + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ram0); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/chconf.h new file mode 100644 index 00000000..83434f36 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/chconf.h @@ -0,0 +1,704 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM FALSE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES TRUE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS TRUE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES TRUE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP TRUE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS TRUE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS TRUE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf.h new file mode 100644 index 00000000..a99b33ac --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf.h @@ -0,0 +1,524 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC FALSE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM FALSE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..e35b7bec --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/halconf_nf.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +#define HAL_USE_STM32_RNG FALSE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/main.c new file mode 100644 index 00000000..1e7ec5b3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/main.c @@ -0,0 +1,98 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////////// +// RAM vector table declaration (valid for GCC only) +__IO uint32_t vectorTable[48] __attribute__((section(".RAMVectorTable"))); + +#define SYSCFG_MemoryRemap_SRAM ((uint8_t)0x03) + +/////////////////////////////////////////////////////////////////////////////////////////// + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 512, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// configuration for debugger serial port +// dev notes: +// conservative baud rate value as 921600 has a high error percentage on baud rate clocking +// OVER8 bit on CR1 to further decrease baud rate clocking error +static const SerialConfig uartConfig = +{ + 460800, + USART_CR1_OVER8, + USART_CR2_STOP1_BITS, + 0 +}; + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // relocate the vector table to RAM + // Copy the vector table from the Flash (mapped at the base of the application + // load address) to the base address of the SRAM at 0x20000000. + for(int i = 0; i < 48; i++) + { + vectorTable[i] = *(__IO uint32_t*)((uint32_t)&__nanoImage_start__ + (i<<2)); + } + + // set CFGR1 register MEM_MODE bits value as "memory remap to SRAM" + SYSCFG->CFGR1 |= SYSCFG_MemoryRemap_SRAM; + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, &uartConfig); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf.h new file mode 100644 index 00000000..d023f997 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf.h @@ -0,0 +1,253 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F0xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 3...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F0xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_HSI14_ENABLED TRUE +#define STM32_HSI48_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PREDIV_VALUE 2 +#define STM32_PLLMUL_VALUE 12 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE STM32_PPRE_DIV1 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#define STM32_PLLNODIV STM32_PLLNODIV_DIV2 +#define STM32_CECSW STM32_CECSW_HSI +#define STM32_I2C1SW STM32_I2C1SW_HSI +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_1_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI2_3_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI4_15_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI16_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI17_20_IRQ_PRIORITY 3 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 3 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 2 +#define STM32_GPT_TIM2_IRQ_PRIORITY 2 +#define STM32_GPT_TIM3_IRQ_PRIORITY 2 +#define STM32_GPT_TIM6_IRQ_PRIORITY 2 +#define STM32_GPT_TIM7_IRQ_PRIORITY 2 +#define STM32_GPT_TIM14_IRQ_PRIORITY 2 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 3 +#define STM32_I2C_I2C2_IRQ_PRIORITY 3 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI1 TRUE +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \ + STM32_I2S_MODE_RX) +#define STM32_I2S_SPI1_IRQ_PRIORITY 2 +#define STM32_I2S_SPI2_IRQ_PRIORITY 2 +#define STM32_I2S_SPI1_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2S_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 3 +#define STM32_ICU_TIM2_IRQ_PRIORITY 3 +#define STM32_ICU_TIM3_IRQ_PRIORITY 3 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 3 +#define STM32_PWM_TIM2_IRQ_PRIORITY 3 +#define STM32_PWM_TIM3_IRQ_PRIORITY 3 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 3 +#define STM32_SERIAL_USART2_PRIORITY 3 +#define STM32_SERIAL_USART3_8_PRIORITY 3 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 2 +#define STM32_SPI_SPI2_IRQ_PRIORITY 2 +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 2 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USE_UART7 FALSE +#define STM32_UART_USE_UART8 TRUE +#define STM32_UART_USART1_IRQ_PRIORITY 3 +#define STM32_UART_USART2_IRQ_PRIORITY 3 +#define STM32_UART_USART3_8_IRQ_PRIORITY 3 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_UART7_DMA_PRIORITY 0 +#define STM32_UART_UART8_DMA_PRIORITY 0 +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART7_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART7_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART8_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_UART8_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 FALSE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_LP_IRQ_PRIORITY 3 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..574b9636 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/mcuconf_nf.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.h.in new file mode 100644 index 00000000..e629d90b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_common.h.in @@ -0,0 +1,48 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00008000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00040000) + +///////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////// +// set Wire Protocol packet size +// valid sizes are 1024, 512, 256, 128 +// check Monitor_Ping_Source_Flags enum +#define WP_PACKET_SIZE 256U +////////////////////////////////////////////// + +////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F0" +////////////////////////////////////////////// + +///////////////////////////////////// +//#define EVENTS_HEART_BEAT palToggleLine(GPIOA_LED_GREEN) +///////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..049422f7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_system_devices_dac_config.cpp @@ -0,0 +1,14 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2618ec3e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..673d3b7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include + +//////////// +// USART8 // +//////////// + +// pin configuration for USART8 +// port for TX pin is: GPIOC +// port for RX pin is: GPIOC +// TX pin: is GPIOC_2 +// RX pin: is GPIOC_3 +// GPIO alternate pin function is 1 (see "Table 16. Alternate functions selected through GPIOC_AFR registers for port C" in STM32F091RC datasheet) +UART_CONFIG_PINS(8, GPIOC, GPIOC, 2, 3, 2) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart8_TxBuffer[UART8_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart8_RxBuffer[UART8_RX_SIZE]; + +// initialization for UART8 +UART_INIT(8, UART8_TX_SIZE, UART8_RX_SIZE) + +// un-initialization for UART8 +UART_UNINIT(8) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..6def329e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +//////////// +// USART8 // +//////////// + +// enable USART8 +#define NF_SERIAL_COMM_STM32_UART_USE_UART8 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART8_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART8_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_NUCLEO64_F091RC/target_windows_devices_spi_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt new file mode 100644 index 00000000..77249ac0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/CMakeLists.txt @@ -0,0 +1,213 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + # the next one is required is the target implements and it's using external memory + "${CMAKE_CURRENT_SOURCE_DIR}/target_external_memory.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for ChibiOS FatFS + ${CHIBIOS_FATFS_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS FatFS + ${CHIBIOS_FATFS_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F429xI_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F429xI_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F429xI_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F429xI_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +############################################################################ +# CRT heap is assigned to RAM4 region @ CCM SRAM so we are OK to use it all +############################################################################ +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x10000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x10000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/README.md new file mode 100644 index 00000000..4ddda46f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/README.md @@ -0,0 +1,34 @@ +## Configuration of Chibios, HAL and MCU ## + +For a successful build the following changes are required: + +In _halconf.g_ (in both nanoBooter and nanoCLR folders), when compared with a default file: +- HAL_USE_SERIAL to TRUE +- HAL_USE_SERIAL_USB to TRUE +- HAL_USE_USB to TRUE +- SERIAL_DEFAULT_BITRATE to 921600 + +In _mcuconf.h_ (in both nanoBooter and nanoCLR folders), when compared with a default file: +- STM32_SERIAL_USE_USART2 to TRUE +- STM32_USB_USE_OTG1 to TRUE + +In _chconf.h_ (_**only**_ for nanoCLR folder), when compared with a default file: +- set the CORTEX_VTOR_INIT with the appropriate address of the vector table for nanoCLR + + +## Definitions for each image ## + +Any defines specific to an image (nanoBooter or nanoCLR) that are to be made available throughout the code should be added to the _target_board.h.in_. There is one in [nanoBooter](nanoBooter/target_board.h.in) and another in [nanoCLR](nanoCLR/target_board.h.in) directories, allowing different defines for each one. +Defines that are common to a target board should be added to the [_target_common.h.in_](target_common.h.in). +The content of these files is parsed by CMake. It can include CMake variables. Check the documentation of CMake config files [here](https://cmake.org/cmake/help/v3.7/command/configure_file.html?highlight=configure_file). + + + + +**NOTE: this configuration was successfully tested in a ST_STM32F429I_DISCOVERY board using the Serial over USB connection on USB port 1 that creates a virtual COM port.** + + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/CMakeLists.txt new file mode 100644 index 00000000..aa7f1d54 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..66a8d940 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 16kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 1 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 0x08008000 nanoCLR +}; + +// 64kB blocks +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +// 128kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 3 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 4, 6 }, // 0x080A0000 deployment +}; + +// 16kB blocks +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +// 64kB blocks +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +// 128kB blocks +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + (0), // no attributes for this region + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + (0), // no attributes for this region + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + (0), // no attributes for this region + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage.c new file mode 100644 index 00000000..7e34313e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/Device_BlockStorage.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 16kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 0x08004000 nanoCLR +}; + +// 64kB blocks +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08010000 nanoCLR +}; + +// 128kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 0x08020000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 }, // 0x08040000 deployment +}; + +// 16kB blocks +const BlockRange BlockRange4[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 3 } // 0x08100000 deployment +}; + +// 64kB blocks +const BlockRange BlockRange5[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 } // 0x08110000 deployment +}; + +// 128kB blocks +const BlockRange BlockRange6[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 6 } // 0x08120000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08010000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + + { + (0), // no attributes for this region + 0x08100000, // start address for block region + 4, // total number of blocks in this region + 0x4000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange4), + BlockRange4, + }, + + { + (0), // no attributes for this region + 0x08110000, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange5), + BlockRange5, + }, + + { + (0), // no attributes for this region + 0x08120000, // start address for block region + 7, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange6), + BlockRange6, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.c new file mode 100644 index 00000000..217a411e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.c @@ -0,0 +1,454 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD2. + */ +#define USBD2_DATA_REQUEST_EP 1 +#define USBD2_DATA_AVAILABLE_EP 1 +#define USBD2_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"STMicroelectronics" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"nanoFramework Virtual COM Port" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[18] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[67] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(67, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + if (usbp->state == USB_ACTIVE) { + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD2_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD2_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + } + else if (usbp->state == USB_SELECTED) { + usbDisableEndpointsI(usbp); + } + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handling messages not implemented in the default handler nor in the + * SerialUSB handler. + */ +static bool requests_hook(USBDriver *usbp) { + + if (((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE) && + (usbp->setup[1] == USB_REQ_SET_INTERFACE)) { + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + } + return sduRequestsHook(usbp); +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + requests_hook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD2, + USBD2_DATA_REQUEST_EP, + USBD2_DATA_AVAILABLE_EP, + USBD2_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.h new file mode 100644 index 00000000..167e1df8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/common/usbcfg.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/ffconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/ffconf.h new file mode 100644 index 00000000..7ffb3957 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/ffconf.h @@ -0,0 +1,272 @@ +/* CHIBIOS FIX */ +#include "ch.h" + +/*---------------------------------------------------------------------------/ +/ FatFs - Configuration file +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 87030 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: All basic functions are enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_STRFUNC 0 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 0 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 850 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 3 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added +/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255. +/ It should be set 255 to support full featured LFN operations. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree(), must be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16, +/ when LFN is enabled. Also behavior of string I/O functions will be affected by +/ this option. When LFN is not enabled, this option has no effect. +*/ + + +#define FF_STRF_ENCODE 3 +/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(), +/ f_putc(), f_puts and f_printf() convert the character encoding in it. +/ This option selects assumption of character encoding ON THE FILE to be +/ read/written via those functions. +/ +/ 0: ANSI/OEM +/ 1: UTF-16LE +/ 2: UTF-16BE +/ 3: UTF-8 +*/ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 1 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches string support for volume ID. +/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each +/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for +/ the drive ID strings are: A-Z and 0-9. */ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 0 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ When enable exFAT, also LFN needs to be enabled. +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 1 +#define FF_NORTC_MON 8 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2018 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT TIME_MS2I(1000) +#define FF_SYNC_t semaphore_t* +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +/* #include // O/S definitions */ + + + +/*--- End of configuration options ---*/ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/README.md new file mode 100644 index 00000000..87944cda --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](STM32F429I_DISCOVERY.Adc.cs) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/STM32F429I_DISCOVERY.Adc.cs b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/STM32F429I_DISCOVERY.Adc.cs new file mode 100644 index 00000000..78d7cb98 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/STM32F429I_DISCOVERY.Adc.cs @@ -0,0 +1,43 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.STM32F429I_DISCOVERY +{ + /// + /// Enumeration of ADC channels available in STM32F429I_DISCOVERY + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed on PA5, connected to PA5 (ADC1 - IN5) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed on PC3, connected to PC3 (ADC2 - IN13) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed on PF6, connected to PF6 (ADC3 - IN4) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 3; + + /// + /// Channel 4, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 4; + + /// + /// Channel 5, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 5; + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/package.nuspec b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/package.nuspec new file mode 100644 index 00000000..2bec8324 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/managed_helpers/package.nuspec @@ -0,0 +1,28 @@ + + + + nanoFramework.Targets.ST_STM32F429I_DISCOVERY + nanoFramework.Targets.ST_STM32F429I_DISCOVERY + 1.0.0 + nanoFramework project contributors + nanoFramework project contributors + false + + Helper classes to use ST_STM32F429I_DISCOVERY target in C# applications. + + + + + This is an extension for .NET nanoFramework enhacing support for Windows.Devices.Gpio.GpioController when using STM32 MCUs. + + https://github.com/nanoframework + https://secure.gravatar.com/avatar/97d0e092247f0716db6d4b47b7d1d1ad + https://github.com/nanoframework/nf-interpreter/blob/develop/LICENSE.md + Copyright (c) 2019 The nanoFramework project contributors + + nanoFramework, nano Framework, NETNF, NETMF, Micro Framework, STM32, .net, STM32F429I + + + + + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..291f47e1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter-DEBUG.ld new file mode 100644 index 00000000..c0e72445 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter-DEBUG.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F429xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st two sectors 0x08000000 to 0x08008000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter.ld new file mode 100644 index 00000000..306edee7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/STM32F429xI_booter.ld @@ -0,0 +1,80 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F429xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08000000, len = 16k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08004000)*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* Stacks rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/chconf.h new file mode 100644 index 00000000..ef98a914 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf.h new file mode 100644 index 00000000..13104b34 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf.h @@ -0,0 +1,519 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/main.c new file mode 100644 index 00000000..d5540458 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/main.c @@ -0,0 +1,84 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + osDelay(20); // Let init stabilize + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + // the user button in this board has a pull-up resistor so the check has to be inverted + if (!palReadPad(GPIOA, GPIOA_BUTTON)) + { + // check for valid CLR image + // this target DOES NOT have configuration block, so we need to use the __nanoImage_end__ address here + if(CheckValidCLRImage((uint32_t)&__nanoImage_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoImage_end__); + } + } + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // Normal main() thread + while (true) { + palSetPad(GPIOG, GPIOG_LED3_GREEN); + osDelay(250); + palClearPad(GPIOG, GPIOG_LED3_GREEN); + osDelay(250); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf.h new file mode 100644 index 00000000..10f82577 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf.h @@ -0,0 +1,354 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * EXT driver system settings. + */ +#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI17_IRQ_PRIORITY 15 +#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI20_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI21_IRQ_PRIORITY 15 +#define STM32_EXT_EXTI22_IRQ_PRIORITY 15 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_USE_SPI5 FALSE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 TRUE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR-DEBUG.ld new file mode 100644 index 00000000..bd27c829 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR-DEBUG.ld @@ -0,0 +1,77 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F429xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08008000, len = 2M - 32k - 1408k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x080A0000, len = 1408k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 + ext_ram : org = 0xD0000000, len = 8M /* external SDRAM */ +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ext_ram); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld new file mode 100644 index 00000000..1c731acf --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/STM32F429xI_CLR.ld @@ -0,0 +1,77 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * ST32F429xI memory setup. + * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0. + */ +MEMORY +{ + flash : org = 0x08004000, len = 2M - 16k - 1664k /* flash size less the space reserved for nanoBooter and application deployment*/ + config : org = 0x00000000, len = 0 /* space reserved for configuration block */ + deployment : org = 0x08040000, len = 1664k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */ + ram1 : org = 0x20000000, len = 112k /* SRAM1 */ + ram2 : org = 0x2001C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20020000, len = 64k /* SRAM3 */ + ram4 : org = 0x10000000, len = 64k /* CCM SRAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 + ext_ram : org = 0xD0000000, len = 8M /* external SDRAM */ +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram4); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ext_ram); + +INCLUDE rules.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/chconf.h new file mode 100644 index 00000000..ef39575e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/chconf.h @@ -0,0 +1,616 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 1000 // this is 1 millisecond + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf.h new file mode 100644 index 00000000..554a9b96 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf.h @@ -0,0 +1,541 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC FALSE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM FALSE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC FALSE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ + +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..07183116 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/halconf_nf.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +// Enables the FSMC subsystem. +#if !defined(HAL_USE_FSMC) +#define HAL_USE_FSMC TRUE +#endif + +// enables STM32 Can driver +#if !defined(HAL_USE_STM32_CAN) +#define HAL_USE_STM32_CAN TRUE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c new file mode 100644 index 00000000..2cb1bf2b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/main.c @@ -0,0 +1,104 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +// Application entry point. +int main(void) { + + // find out wakeup reason + if((RTC->ISR & RTC_ISR_ALRAF) == RTC_ISR_ALRAF) + { + // standby, match WakeupReason_FromStandby enum + WakeupReasonStore = 1; + } + else if((PWR->CSR & PWR_CSR_WUF) == PWR_CSR_WUF) + { + // wake from pin, match WakeupReason_FromPin enum + WakeupReasonStore = 2; + } + else + { + // undetermined reason, match WakeupReason_Undetermined enum + WakeupReasonStore = 0; + } + + // first things first: need to clear any possible wakeup flags + // if this is not done here the next standby -> wakeup sequence won't work + CLEAR_BIT(RTC->CR, RTC_CR_ALRAIE); + CLEAR_BIT(RTC->ISR, RTC_ISR_ALRAF); + SET_BIT(PWR->CR, PWR_CR_CWUF); + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP +#if (SWO_OUTPUT == TRUE) + SwoInit(); +#endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + /////////////////////////////////////////////////////////////////////////////////////////////////////// + // for STM32F4 family if watchdog is enabled can't use standby mode because the IWDG can't be stoped // + /////////////////////////////////////////////////////////////////////////////////////////////////////// + Watchdog_Init(); + + // config and init external memory + // this has to be called after osKernelInitialize, otherwise an hard fault will occur + Target_ExternalMemoryInit(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable after a reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf.h new file mode 100644 index 00000000..e5a11f75 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf.h @@ -0,0 +1,355 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F429_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV8 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 TRUE +#define STM32_ADC_USE_ADC3 TRUE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 TRUE +#define STM32_CAN_USE_CAN2 TRUE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 TRUE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 TRUE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_USE_SPI5 TRUE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 TRUE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 TRUE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..b34976b4 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/mcuconf_nf.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + + +/* + * FSMC driver system settings. + */ +#define STM32_FSMC_USE_FSMC1 TRUE +#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10 +#define STM32_FSMC_DMA_CHN 0x03010201 + +/* + * FSMC SDRAM driver system settings. + */ +#define STM32_USE_FSMC_SDRAM TRUE +#define STM32_SDRAM_USE_FSMC_SDRAM1 FALSE +#define STM32_SDRAM_USE_FSMC_SDRAM2 TRUE + +#endif // _MCUCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.c new file mode 100644 index 00000000..c633da5b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in new file mode 100644 index 00000000..8ca77162 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_common.h.in @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0xD0000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00800000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00200000) + +///////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +////////////////////////////////////////////// + +///////////////////////////////////// +//#define EVENTS_HEART_BEAT palToggleLine(GPIOG_LED3_GREEN) +///////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_external_memory.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_external_memory.c new file mode 100644 index 00000000..61e2bfae --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_external_memory.c @@ -0,0 +1,106 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "hal.h" +#include "fsmc_sdram_lld.h" + + +// SDRAM Mode definition register defines +#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_BURST_LENGTH_2 ((uint16_t)0x0001) +#define FMC_SDCMR_MRD_BURST_LENGTH_4 ((uint16_t)0x0002) +#define FMC_SDCMR_MRD_BURST_LENGTH_8 ((uint16_t)0x0004) +#define FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) +#define FMC_SDCMR_MRD_CAS_LATENCY_2 ((uint16_t)0x0020) +#define FMC_SDCMR_MRD_CAS_LATENCY_3 ((uint16_t)0x0030) +#define FMC_SDCMR_MRD_OPERATING_MODE_STANDARD ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +// FMC_ReadPipe_Delay +#define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000) +#define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000) +#define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000) +#define FMC_ReadPipe_Delay_Mask ((uint32_t)0x00006000) + +// FMC_Read_Burst +#define FMC_Read_Burst_Disable ((uint32_t)0x00000000) +#define FMC_Read_Burst_Enable ((uint32_t)0x00001000) +#define FMC_Read_Burst_Mask ((uint32_t)0x00001000) + +// FMC_SDClock_Period +#define FMC_SDClock_Disable ((uint32_t)0x00000000) +#define FMC_SDClock_Period_2 ((uint32_t)0x00000800) +#define FMC_SDClock_Period_3 ((uint32_t)0x00000C00) +#define FMC_SDClock_Period_Mask ((uint32_t)0x00000C00) + +// FMC_ColumnBits_Number +#define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000) +#define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001) +#define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002) +#define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003) + +// FMC_RowBits_Number +#define FMC_RowBits_Number_11b ((uint32_t)0x00000000) +#define FMC_RowBits_Number_12b ((uint32_t)0x00000004) +#define FMC_RowBits_Number_13b ((uint32_t)0x00000008) + +// FMC_SDMemory_Data_Width +#define FMC_SDMemory_Width_8b ((uint32_t)0x00000000) +#define FMC_SDMemory_Width_16b ((uint32_t)0x00000010) +#define FMC_SDMemory_Width_32b ((uint32_t)0x00000020) + +// FMC_InternalBank_Number +#define FMC_InternalBank_Number_2 ((uint32_t)0x00000000) +#define FMC_InternalBank_Number_4 ((uint32_t)0x00000040) + +// FMC_CAS_Latency +#define FMC_CAS_Latency_1 ((uint32_t)0x00000080) +#define FMC_CAS_Latency_2 ((uint32_t)0x00000100) +#define FMC_CAS_Latency_3 ((uint32_t)0x00000180) + +// FMC_Write_Protection +#define FMC_Write_Protection_Disable ((uint32_t)0x00000000) +#define FMC_Write_Protection_Enable ((uint32_t)0x00000200) + +#define SDRAM_SIZE (8 * 1024 * 1024) +#define SDRAM_START ((void *)FSMC_Bank6_MAP_BASE) + + +// SDRAM driver configuration structure. +static const SDRAMConfig sdram_cfg = { + .sdcr = (uint32_t) FMC_ColumnBits_Number_8b | + FMC_RowBits_Number_12b | + FMC_SDMemory_Width_16b | + FMC_InternalBank_Number_4 | + FMC_CAS_Latency_3 | + FMC_Write_Protection_Disable | + FMC_SDClock_Period_2 | + FMC_Read_Burst_Enable | + FMC_ReadPipe_Delay_1, + .sdtr = (uint32_t) (2 - 1) | // FMC_LoadToActiveDelay = 2 (TMRD: 2 Clock cycles) + (7 << 4) | // FMC_ExitSelfRefreshDelay = 7 (TXSR: min=70ns (7x11.11ns)) + (4 << 8) | // FMC_SelfRefreshTime = 4 (TRAS: min=42ns (4x11.11ns) max=120k (ns)) + (7 << 12) | // FMC_RowCycleDelay = 7 (TRC: min=70 (7x11.11ns)) + (3 << 16) | // FMC_WriteRecoveryTime = 2 (TWR: min=1+ 7ns (1+1x11.11ns)) + (2 << 20) | // FMC_RPDelay = 2 (TRP: 20ns => 2x11.11ns) + (2 << 24), // FMC_RCDDelay = 2 (TRCD: 20ns => 2x11.11ns) + // NRFS = 4-1 + .sdcmr = (3 << 5) | (FMC_SDCMR_MRD_BURST_LENGTH_2 | + FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL | + FMC_SDCMR_MRD_CAS_LATENCY_3 | + FMC_SDCMR_MRD_OPERATING_MODE_STANDARD | + FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE) << 9, + + .sdrtr = (uint32_t)(683 << 1), +}; + +void Target_ExternalMemoryInit() +{ + fsmcSdramInit(); + fsmcSdramStart(&SDRAMD, &sdram_cfg); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.cpp new file mode 100644 index 00000000..7dbe7ff1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_nf_devices_can_config.h" +#include + +/////////// +// CAN1 // +/////////// + +// pin configuration for CAN1 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_09 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_08 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(1, GPIOB, GPIOB, 9, 8, 9) + +// buffer +CANRxFrame Can1_MsgBuffer[CAN1_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(1, CAN1_RX_BUFFER_SIZE) + +/////////// +// CAN2 // +/////////// + +// pin configuration for CAN2 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_06 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_05 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(2, GPIOB, GPIOB, 6, 5, 9) + +// buffer +CANRxFrame Can2_MsgBuffer[CAN2_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(2, CAN2_RX_BUFFER_SIZE) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.h new file mode 100644 index 00000000..adc8ace3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_can_config.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +////////// +// CAN1 // +////////// + +// enable CAN1 +#define NF_CAN_STM32_CAN_USE_CAN1 TRUE + +// buffers size +#define CAN1_RX_BUFFER_SIZE 16 + +////////// +// CAN2 // +////////// + +// enable CAN2 +#define NF_CAN_STM32_CAN_USE_CAN2 TRUE + +// buffers size +#define CAN2_RX_BUFFER_SIZE 16 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..22cb4e03 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_nf_devices_onewire_config.h" +#include + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port for TX pin is: GPIOC +// TX pin: is GPIOC_6 +// GPIO alternate pin function is 8 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(6, GPIOC, 6, 8) + + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..56079a65 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_nf_devices_onewire_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART6 // +/////////// + +// enable USART4 +#define NF_ONEWIRE_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 32 bytes +#define UART6_TX_SIZE 32 +// rx buffer size: 32 bytes +#define UART6_RX_SIZE 32 \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..e3a0eee9 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_system_devices_dac_config.cpp @@ -0,0 +1,17 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + + // DAC1, channel 2, GPIO port A, pin 5 + {1, 2, GPIOA, 5}, +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..88d00fa8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_adc_config.cpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 5, ADC_CHANNEL_IN5}, + + // ADC2 + {2, GPIOC, 3, ADC_CHANNEL_IN13}, + + // ADC3 + {3, GPIOF, 6, ADC_CHANNEL_IN4}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2563aa28 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +////////// +// I2C3 // +////////// + +// pin configuration for I2C3 +// port for SCL pin is: GPIOA +// port for SDA pin is: GPIOC +// SCL pin: is GPIOA_8 +// SDA pin: is GPIOC_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(3, GPIOA, GPIOC, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..6a9ad77f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include + +/////////// +// UART1 // +/////////// + +// pin configuration for UART1 +// port for TX pin is: GPIOA +// port for RX pin is: GPIOA +// TX pin: is GPIOA_9 +// RX pin: is GPIOA_10 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(1, GPIOA, GPIOA, 9, 10, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_TxBuffer[UART1_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_RxBuffer[UART1_RX_SIZE]; + +// initialization for UART1 +UART_INIT(1, UART1_TX_SIZE, UART1_RX_SIZE) + +// un-initialization for UART1 +UART_UNINIT(1) + + +/////////// +// UART3 // +/////////// + +// pin configuration for UART3 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOD +// TX pin: is GPIOD_8 +// RX pin: is GPIOD_9 +// GPIO alternate pin function is 7 (see "Table 12. STM32F427xx and STM32F429xx alternate function mapping" in STM32F427xx and STM32F429xx datasheet) +UART_CONFIG_PINS(3, GPIOD, GPIOD, 8, 9, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_TxBuffer[UART3_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart3_RxBuffer[UART3_RX_SIZE]; + +// initialization for UART3 +UART_INIT(3, UART3_TX_SIZE, UART3_RX_SIZE) + +// un-initialization for UART3 +UART_UNINIT(3) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..66229d12 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART1 // +/////////// + +// enable USART1 +#define NF_SERIAL_COMM_STM32_UART_USE_USART1 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART1_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART1_RX_SIZE 256 + + +/////////// +// UART3 // +/////////// + +// enable USART3 +#define NF_SERIAL_COMM_STM32_UART_USE_USART3 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART3_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART3_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F429I_DISCOVERY/target_windows_devices_spi_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/CMakeLists.txt new file mode 100644 index 00000000..f733d882 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/CMakeLists.txt @@ -0,0 +1,268 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) + find_package(NF_NETWORKING REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +# security provider is mbedTLS +if(USE_SECURITY_MBEDTLS_OPTION) + find_package(mbedTLS REQUIRED) +endif() + +# SPIFFS +if(NF_FEATURE_USE_SPIFFS) + find_package(STM32F7_CubePackage REQUIRED) + find_package(SPIFFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + # the next one is required is the target implements and it's using external memory + "${CMAKE_CURRENT_SOURCE_DIR}/target_external_memory.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + ${STM32F7_CubePackage_SOURCES} + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for ChibiOS FatFS + ${CHIBIOS_FATFS_SOURCES} + + # sources for nanoFramework Network LWIP, Sockets and TLS + ${CHIBIOS_LWIP_SOURCES} + ${NF_Networking_SOURCES} + ${mbedTLS_SOURCES} + + # sources for SPIFFS + ${SPIFFS_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# add dependencies from CHIBIOS_NETWORK_COMPONENTS (this is required to make sure that ChibiOS network components are unzip at the proper locations before the build starts) +# only required if networking is ON +if(USE_NETWORKING_OPTION) + add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf CHIBIOS_NETWORK_COMPONENTS) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf CHIBIOS_NETWORK_COMPONENTS) + + # add dependency for security provider mbedTLS + if(USE_SECURITY_MBEDTLS_OPTION) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf mbedTLS) + endif() +endif() + +# add dependencies from CHIBIOS_FILESYSTEM_COMPONENTS (this is required to make sure that ChibiOS filesystem components are unzip at the proper locations before the build starts) +# only required if filesystem is ON +if(USE_FILESYSTEM_OPTION) + add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf CHIBIOS_FILESYSTEM_COMPONENTS) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf CHIBIOS_FILESYSTEM_COMPONENTS) +endif() + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + ${STM32F7_CubePackage_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoBooter + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS FatFS + ${CHIBIOS_FATFS_INCLUDE_DIRS} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} + + # incudes for Networking and TLS + ${NF_Networking_INCLUDE_DIRS} + ${mbedTLS_INCLUDE_DIRS} + + # includes for SPIFFS + ${SPIFFS_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# mbed TLS requires a config file +if(USE_SECURITY_MBEDTLS_OPTION) + # this seems to be only option to properly set a compiler define through the command line that needs to be a string literal + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h>\"") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h>\"") +endif() + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F76xx_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F76xx_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F76xx_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F76xx_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x2000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x3B000") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/README.md new file mode 100644 index 00000000..f39844f1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/README.md @@ -0,0 +1,32 @@ +## Configuration of ChibiOS, HAL and MCU + +For a successful build the following changes are required: + +For memory maps, uuid etc. the reference document used was: http://www.st.com/content/ccc/resource/technical/document/reference_manual/group0/96/8b/0d/ec/16/22/43/71/DM00224583/files/DM00224583.pdf/jcr:content/translations/en.DM00224583.pdf + +In _halconf.g_ (in both nanoBooter and nanoCLR folders), when compared with a default file available from (https://github.com/ChibiOS/ChibiOS/tree/master/demos/STM32/RT-STM32F769I-DISCOVERY): +- HAL_USE_SERIAL to TRUE +- SERIAL_DEFAULT_BITRATE to 921600 + +In _mcuconf.h_ (in both nanoBooter and nanoCLR folders), when compared with a default file available from (https://github.com/ChibiOS/ChibiOS/tree/master/demos/STM32/RT-STM32F769I-DISCOVERY): +- STM32_SERIAL_USE_USART1 to TRUE + +NOTE: this configuration was successfully tested in an ST_STM32F769I_DISCOVERY board using the Serial port through the onboard 7ST Link USB connection. + +## ADC configurations + +The following ADC channels (and respective GPIO pins) are available to the managed API, in the respective index: +- PA6, ADC1 IN6 +- PA4 ADC1 IN4 +- PC2 ADC1 IN12 +- PF10 ADC1 IN8 +- PF8 ADC3 IN6 +- PB8 ADC3 IN7 +- Temp Sensor ADC1 +- VrefInt ADC1 +- Vbatt ADC1 + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.c new file mode 100644 index 00000000..d08d4203 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + + return !palReadLine(LINE_SD_DETECT); +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.h new file mode 100644 index 00000000..7da9cd17 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/board.h @@ -0,0 +1,1768 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#ifndef BOARD_H +#define BOARD_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* + * Setup for STMicroelectronics STM32F769I-Discovery board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_STM32F769I_DISCOVERY +#define BOARD_NAME "STMicroelectronics STM32F769I-Discovery" + +/* + * Ethernet PHY type. + */ +#define BOARD_PHY_ID MII_LAN8742A_ID +#define BOARD_PHY_RMII + +/* + * The board has an ULPI USB PHY. + */ +#define BOARD_OTG2_USES_ULPI + +/* + * Board oscillators-related settings. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 25000000U +#endif + +#define STM32_HSE_BYPASS + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F769xx + +/* + * IO pins assignments. + */ +#define GPIOA_BUTTON_USER 0U +#define GPIOA_RMII_REF_CLK 1U +#define GPIOA_RMII_MDIO 2U +#define GPIOA_ULPI_D0 3U +#define GPIOA_ARD_A1 4U +#define GPIOA_ULPI_CK 5U +#define GPIOA_ARD_A0 6U +#define GPIOA_RMII_CRS_DV 7U +#define GPIOA_CEC_CLK 8U +#define GPIOA_VCP_TX 9U +#define GPIOA_VCP_RX 10U +#define GPIOA_ARD_D10 11U +#define GPIOA_ARD_D13 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_CEC 15U + +#define GPIOB_ULPI_D1 0U +#define GPIOB_ULPI_D2 1U +#define GPIOB_QSPI_CLK 2U +#define GPIOB_SD_D2 3U +#define GPIOB_SD_D3 4U +#define GPIOB_ULPI_D7 5U +#define GPIOB_QUADSPI_BK1_NCS 6U +#define GPIOB_AUDIO_SDA 7U +#define GPIOB_LCD_SDA 7U +#define GPIOB_ARD_D15 8U +#define GPIOB_ARD_D14 9U +#define GPIOB_ULPI_D3 10U +#define GPIOB_ULPI_D4 11U +#define GPIOB_ULPI_D5 12U +#define GPIOB_ULPI_D6 13U +#define GPIOB_ARD_D12 14U +#define GPIOB_ARD_D11 15U + +#define GPIOC_ULPI_STP 0U +#define GPIOC_RMII_MDC 1U +#define GPIOC_ARD_A2 2U +#define GPIOC_DFSDM_DATIN1 3U +#define GPIOC_RMII_RXD0 4U +#define GPIOC_RMII_RXD1 5U +#define GPIOC_ARD_D1 6U +#define GPIOC_ARD_D0 7U +#define GPIOC_ARD_D5 8U +#define GPIOB_I2C1_SCL 8U +#define GPIOC_QSPI_D0 9U +#define GPIOB_I2C1_SDA 9U +#define GPIOC_QSPI_D1 10U +#define GPIOC_DFSDM_DATIN5 11U +#define GPIOC_WIFI_RX 12U +#define GPIOC_PIN13 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_FMC_D2 0U +#define GPIOD_FMC_D3 1U +#define GPIOD_WIFI_TX 2U +#define GPIOD_DFSDM_CKOUT 3U +#define GPIOD_OTG_HS_OVER_CURRENT 4U +#define GPIOD_RMII_RXER 5U +#define GPIOD_SD_CLK 6U +#define GPIOD_SD_CMD 7U +#define GPIOD_FMC_D13 8U +#define GPIOD_FMC_D14 9U +#define GPIOD_FMC_D15 10U +#define GPIOD_SPDIF_I2S 11U +#define GPIOD_AUDIO_SCL 12U +#define GPIOD_LCD_SCL 12U +#define GPIOD_QSPI_D3 13U +#define GPIOD_FMC_D0 14U +#define GPIOD_FMC_D1 15U + +#define GPIOE_FMC_NBL0 0U +#define GPIOE_FMC_NBL1 1U +#define GPIOE_QSPI_D2 2U +#define GPIOE_SAI1_SDB 3U +#define GPIOE_SAI1_FSA 4U +#define GPIOE_SAI1_SCKA 5U +#define GPIOE_SAI1_SDA 6U +#define GPIOE_FMC_D4 7U +#define GPIOE_FMC_D5 8U +#define GPIOE_FMC_D6 9U +#define GPIOE_FMC_D7 10U +#define GPIOE_FMC_D8 11U +#define GPIOE_FMC_D9 12U +#define GPIOE_FMC_D10 13U +#define GPIOE_FMC_11 14U +#define GPIOE_FMC_D12 15U + +#define GPIOF_FMC_A0 0U +#define GPIOF_FMC_A1 1U +#define GPIOF_FMC_A2 2U +#define GPIOF_FMC_A3 3U +#define GPIOF_FMC_A4 4U +#define GPIOF_FMC_A5 5U +#define GPIOF_ARD_D3 6U +#define GPIOF_ARD_D6 7U +#define GPIOF_ARD_A4 8U +#define GPIOF_ARD_A5 9U +#define GPIOF_ARD_A3 10U +#define GPIOF_FMC_SDNRAS 11U +#define GPIOF_FMC_A6 12U +#define GPIOF_FMC_A7 13U +#define GPIOF_FMC_A8 14U +#define GPIOF_FMC_A9 15U + +#define GPIOG_FMC_A10 0U +#define GPIOG_FMC_A11 1U +#define GPIOG_FMC_A12 2U +#define GPIOG_EXT_SCL 3U +#define GPIOG_FMC_BA0 4U +#define GPIOG_FMC_BA1 5U +#define GPIOG_EXT_SDA 6U +#define GPIOG_SAI1_MCLKA 7U +#define GPIOG_FMC_SDCLK 8U +#define GPIOG_SD_D0 9U +#define GPIOG_SD_D1 10U +#define GPIOG_RMII_TX_EN 11U +#define GPIOG_SPDIF_RX 12U +#define GPIOG_RMII_TXD0 13U +#define GPIOG_RMII_TXD1 14U +#define GPIOG_FMC_SDNCAS 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_FMC_SDCKE0 2U +#define GPIOH_FMC_SDNE0 3U +#define GPIOH_ULPI_NXT 4U +#define GPIOH_FMC_SDNWE 5U +#define GPIOH_ARD_D9 6U +#define GPIOH_EXT_RST 7U +#define GPIOH_FMC_D16 8U +#define GPIOH_FMC_D17 9U +#define GPIOH_FMC_D18 10U +#define GPIOH_FMC_D19 11U +#define GPIOH_FMC_D20 12U +#define GPIOH_FMC_D21 13U +#define GPIOH_FMC_D22 14U +#define GPIOH_FMC_D23 15U + +#define GPIOI_FMC_D24 0U +#define GPIOI_FMC_D25 1U +#define GPIOI_FMC_D26 2U +#define GPIOI_FMC_D27 3U +#define GPIOI_FMC_NBL2 4U +#define GPIOI_FMC_NBL3 5U +#define GPIOI_FMC_D28 6U +#define GPIOI_FMC_D29 7U +#define GPIOI_PIN8 8U +#define GPIOI_FMC_D30 9U +#define GPIOI_FMC_D31 10U +#define GPIOI_ULPI_DIR 11U +#define GPIOI_PIN12 12U +#define GPIOI_LCD_INT 13U +#define GPIOI_LCD_BL_CTRL 14U +#define GPIOI_SD_DETECT 15U + +#define GPIOJ_ARD_D4 0U +#define GPIOJ_ARD_D2 1U +#define GPIOJ_DSI_TE 2U +#define GPIOJ_ARD_D7 3U +#define GPIOJ_ARD_D8 4U +#define GPIOJ_LED2_GREEN 5U +#define GPIOJ_PIN6 6U +#define GPIOJ_PIN7 7U +#define GPIOJ_PIN8 8U +#define GPIOJ_PIN9 9U +#define GPIOJ_PIN10 10U +#define GPIOJ_PIN11 11U +#define GPIOJ_AUDIO_INT 12U +#define GPIOJ_LED1_RED 13U +#define GPIOJ_WIFI_RST 14U +#define GPIOJ_DSI_RESET 15U + +#define GPIOK_PIN0 0U +#define GPIOK_PIN1 1U +#define GPIOK_PIN2 2U +#define GPIOK_PIN3 3U +#define GPIOK_PIN4 4U +#define GPIOK_PIN5 5U +#define GPIOK_PIN6 6U +#define GPIOK_PIN7 7U +#define GPIOK_PIN8 8U +#define GPIOK_PIN9 9U +#define GPIOK_PIN10 10U +#define GPIOK_PIN11 11U +#define GPIOK_PIN12 12U +#define GPIOK_PIN13 13U +#define GPIOK_PIN14 14U +#define GPIOK_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_BUTTON_USER PAL_LINE(GPIOA, 0U) +#define LINE_RMII_REF_CLK PAL_LINE(GPIOA, 1U) +#define LINE_RMII_MDIO PAL_LINE(GPIOA, 2U) +#define LINE_ULPI_D0 PAL_LINE(GPIOA, 3U) +#define LINE_ARD_A1 PAL_LINE(GPIOA, 4U) +#define LINE_ULPI_CK PAL_LINE(GPIOA, 5U) +#define LINE_ARD_A0 PAL_LINE(GPIOA, 6U) +#define LINE_RMII_CRS_DV PAL_LINE(GPIOA, 7U) +#define LINE_CEC_CLK PAL_LINE(GPIOA, 8U) +#define LINE_VCP_TX PAL_LINE(GPIOA, 9U) +#define LINE_VCP_RX PAL_LINE(GPIOA, 10U) +#define LINE_ARD_D10 PAL_LINE(GPIOA, 11U) +#define LINE_ARD_D13 PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) +#define LINE_CEC PAL_LINE(GPIOA, 15U) +#define LINE_ULPI_D1 PAL_LINE(GPIOB, 0U) +#define LINE_ULPI_D2 PAL_LINE(GPIOB, 1U) +#define LINE_QSPI_CLK PAL_LINE(GPIOB, 2U) +#define LINE_SD_D2 PAL_LINE(GPIOB, 3U) +#define LINE_SD_D3 PAL_LINE(GPIOB, 4U) +#define LINE_ULPI_D7 PAL_LINE(GPIOB, 5U) +#define LINE_QUADSPI_BK1_NCS PAL_LINE(GPIOB, 6U) +#define LINE_AUDIO_SDA PAL_LINE(GPIOB, 7U) +#define LINE_LCD_SDA PAL_LINE(GPIOB, 7U) +#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U) +#define LINE_I2C1_SCL PAL_LINE(GPIOB, 8U) +#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U) +#define LINE_I2C1_SDA PAL_LINE(GPIOB, 9U) +#define LINE_ULPI_D3 PAL_LINE(GPIOB, 10U) +#define LINE_ULPI_D4 PAL_LINE(GPIOB, 11U) +#define LINE_ULPI_D5 PAL_LINE(GPIOB, 12U) +#define LINE_ULPI_D6 PAL_LINE(GPIOB, 13U) +#define LINE_ARD_D12 PAL_LINE(GPIOB, 14U) +#define LINE_ARD_D11 PAL_LINE(GPIOB, 15U) +#define LINE_ULPI_STP PAL_LINE(GPIOC, 0U) +#define LINE_RMII_MDC PAL_LINE(GPIOC, 1U) +#define LINE_ARD_A2 PAL_LINE(GPIOC, 2U) +#define LINE_DFSDM_DATIN1 PAL_LINE(GPIOC, 3U) +#define LINE_RMII_RXD0 PAL_LINE(GPIOC, 4U) +#define LINE_RMII_RXD1 PAL_LINE(GPIOC, 5U) +#define LINE_ARD_D1 PAL_LINE(GPIOC, 6U) +#define LINE_ARD_D0 PAL_LINE(GPIOC, 7U) +#define LINE_ARD_D5 PAL_LINE(GPIOC, 8U) +#define LINE_QSPI_D0 PAL_LINE(GPIOC, 9U) +#define LINE_QSPI_D1 PAL_LINE(GPIOC, 10U) +#define LINE_DFSDM_DATIN5 PAL_LINE(GPIOC, 11U) +#define LINE_WIFI_RX PAL_LINE(GPIOC, 12U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) +#define LINE_FMC_D2 PAL_LINE(GPIOD, 0U) +#define LINE_FMC_D3 PAL_LINE(GPIOD, 1U) +#define LINE_WIFI_TX PAL_LINE(GPIOD, 2U) +#define LINE_DFSDM_CKOUT PAL_LINE(GPIOD, 3U) +#define LINE_OTG_HS_OVER_CURRENT PAL_LINE(GPIOD, 4U) +#define LINE_RMII_RXER PAL_LINE(GPIOD, 5U) +#define LINE_SD_CLK PAL_LINE(GPIOD, 6U) +#define LINE_SD_CMD PAL_LINE(GPIOD, 7U) +#define LINE_FMC_D13 PAL_LINE(GPIOD, 8U) +#define LINE_FMC_D14 PAL_LINE(GPIOD, 9U) +#define LINE_FMC_D15 PAL_LINE(GPIOD, 10U) +#define LINE_SPDIF_I2S PAL_LINE(GPIOD, 11U) +#define LINE_AUDIO_SCL PAL_LINE(GPIOD, 12U) +#define LINE_LCD_SCL PAL_LINE(GPIOD, 12U) +#define LINE_QSPI_D3 PAL_LINE(GPIOD, 13U) +#define LINE_FMC_D0 PAL_LINE(GPIOD, 14U) +#define LINE_FMC_D1 PAL_LINE(GPIOD, 15U) +#define LINE_FMC_NBL0 PAL_LINE(GPIOE, 0U) +#define LINE_FMC_NBL1 PAL_LINE(GPIOE, 1U) +#define LINE_QSPI_D2 PAL_LINE(GPIOE, 2U) +#define LINE_SAI1_SDB PAL_LINE(GPIOE, 3U) +#define LINE_SAI1_FSA PAL_LINE(GPIOE, 4U) +#define LINE_SAI1_SCKA PAL_LINE(GPIOE, 5U) +#define LINE_SAI1_SDA PAL_LINE(GPIOE, 6U) +#define LINE_FMC_D4 PAL_LINE(GPIOE, 7U) +#define LINE_FMC_D5 PAL_LINE(GPIOE, 8U) +#define LINE_FMC_D6 PAL_LINE(GPIOE, 9U) +#define LINE_FMC_D7 PAL_LINE(GPIOE, 10U) +#define LINE_FMC_D8 PAL_LINE(GPIOE, 11U) +#define LINE_FMC_D9 PAL_LINE(GPIOE, 12U) +#define LINE_FMC_D10 PAL_LINE(GPIOE, 13U) +#define LINE_FMC_11 PAL_LINE(GPIOE, 14U) +#define LINE_FMC_D12 PAL_LINE(GPIOE, 15U) +#define LINE_FMC_A0 PAL_LINE(GPIOF, 0U) +#define LINE_FMC_A1 PAL_LINE(GPIOF, 1U) +#define LINE_FMC_A2 PAL_LINE(GPIOF, 2U) +#define LINE_FMC_A3 PAL_LINE(GPIOF, 3U) +#define LINE_FMC_A4 PAL_LINE(GPIOF, 4U) +#define LINE_FMC_A5 PAL_LINE(GPIOF, 5U) +#define LINE_ARD_D3 PAL_LINE(GPIOF, 6U) +#define LINE_ARD_D6 PAL_LINE(GPIOF, 7U) +#define LINE_ARD_A4 PAL_LINE(GPIOF, 8U) +#define LINE_ARD_A5 PAL_LINE(GPIOF, 9U) +#define LINE_ARD_A3 PAL_LINE(GPIOF, 10U) +#define LINE_FMC_SDNRAS PAL_LINE(GPIOF, 11U) +#define LINE_FMC_A6 PAL_LINE(GPIOF, 12U) +#define LINE_FMC_A7 PAL_LINE(GPIOF, 13U) +#define LINE_FMC_A8 PAL_LINE(GPIOF, 14U) +#define LINE_FMC_A9 PAL_LINE(GPIOF, 15U) +#define LINE_FMC_A10 PAL_LINE(GPIOG, 0U) +#define LINE_FMC_A11 PAL_LINE(GPIOG, 1U) +#define LINE_FMC_A12 PAL_LINE(GPIOG, 2U) +#define LINE_EXT_SCL PAL_LINE(GPIOG, 3U) +#define LINE_FMC_BA0 PAL_LINE(GPIOG, 4U) +#define LINE_FMC_BA1 PAL_LINE(GPIOG, 5U) +#define LINE_EXT_SDA PAL_LINE(GPIOG, 6U) +#define LINE_SAI1_MCLKA PAL_LINE(GPIOG, 7U) +#define LINE_FMC_SDCLK PAL_LINE(GPIOG, 8U) +#define LINE_SD_D0 PAL_LINE(GPIOG, 9U) +#define LINE_SD_D1 PAL_LINE(GPIOG, 10U) +#define LINE_RMII_TX_EN PAL_LINE(GPIOG, 11U) +#define LINE_SPDIF_RX PAL_LINE(GPIOG, 12U) +#define LINE_RMII_TXD0 PAL_LINE(GPIOG, 13U) +#define LINE_RMII_TXD1 PAL_LINE(GPIOG, 14U) +#define LINE_FMC_SDNCAS PAL_LINE(GPIOG, 15U) +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) +#define LINE_FMC_SDCKE0 PAL_LINE(GPIOH, 2U) +#define LINE_FMC_SDNE0 PAL_LINE(GPIOH, 3U) +#define LINE_ULPI_NXT PAL_LINE(GPIOH, 4U) +#define LINE_FMC_SDNWE PAL_LINE(GPIOH, 5U) +#define LINE_ARD_D9 PAL_LINE(GPIOH, 6U) +#define LINE_EXT_RST PAL_LINE(GPIOH, 7U) +#define LINE_FMC_D16 PAL_LINE(GPIOH, 8U) +#define LINE_FMC_D17 PAL_LINE(GPIOH, 9U) +#define LINE_FMC_D18 PAL_LINE(GPIOH, 10U) +#define LINE_FMC_D19 PAL_LINE(GPIOH, 11U) +#define LINE_FMC_D20 PAL_LINE(GPIOH, 12U) +#define LINE_FMC_D21 PAL_LINE(GPIOH, 13U) +#define LINE_FMC_D22 PAL_LINE(GPIOH, 14U) +#define LINE_FMC_D23 PAL_LINE(GPIOH, 15U) +#define LINE_FMC_D24 PAL_LINE(GPIOI, 0U) +#define LINE_FMC_D25 PAL_LINE(GPIOI, 1U) +#define LINE_FMC_D26 PAL_LINE(GPIOI, 2U) +#define LINE_FMC_D27 PAL_LINE(GPIOI, 3U) +#define LINE_FMC_NBL2 PAL_LINE(GPIOI, 4U) +#define LINE_FMC_NBL3 PAL_LINE(GPIOI, 5U) +#define LINE_FMC_D28 PAL_LINE(GPIOI, 6U) +#define LINE_FMC_D29 PAL_LINE(GPIOI, 7U) +#define LINE_FMC_D30 PAL_LINE(GPIOI, 9U) +#define LINE_FMC_D31 PAL_LINE(GPIOI, 10U) +#define LINE_ULPI_DIR PAL_LINE(GPIOI, 11U) +#define LINE_LCD_INT PAL_LINE(GPIOI, 13U) +#define LINE_LCD_BL_CTRL PAL_LINE(GPIOI, 14U) +#define LINE_SD_DETECT PAL_LINE(GPIOI, 15U) +#define LINE_ARD_D4 PAL_LINE(GPIOJ, 0U) +#define LINE_ARD_D2 PAL_LINE(GPIOJ, 1U) +#define LINE_DSI_TE PAL_LINE(GPIOJ, 2U) +#define LINE_ARD_D7 PAL_LINE(GPIOJ, 3U) +#define LINE_ARD_D8 PAL_LINE(GPIOJ, 4U) +#define LINE_LED2_GREEN PAL_LINE(GPIOJ, 5U) +#define LINE_AUDIO_INT PAL_LINE(GPIOJ, 12U) +#define LINE_LED1_RED PAL_LINE(GPIOJ, 13U) +#define LINE_WIFI_RST PAL_LINE(GPIOJ, 14U) +#define LINE_DSI_RESET PAL_LINE(GPIOJ, 15U) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - BUTTON_USER (input floating). + * PA1 - RMII_REF_CLK (alternate 11). + * PA2 - RMII_MDIO (alternate 11). + * PA3 - ULPI_D0 (alternate 10). + * PA4 - ARD_A1 (input pullup). + * PA5 - ULPI_CK (alternate 10). + * PA6 - ARD_A0 (input pullup). + * PA7 - RMII_CRS_DV (alternate 11). + * PA8 - CEC_CLK (alternate 0). + * PA9 - VCP_TX (alternate 7). + * PA10 - VCP_RX (alternate 7). + * PA11 - ARD_D10 (input pullup). + * PA12 - ARD_D13 (input pullup). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - CEC (alternate 3). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_BUTTON_USER) | \ + PIN_MODE_ALTERNATE(GPIOA_RMII_REF_CLK) |\ + PIN_MODE_ALTERNATE(GPIOA_RMII_MDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_ULPI_D0) | \ + PIN_MODE_INPUT(GPIOA_ARD_A1) | \ + PIN_MODE_ALTERNATE(GPIOA_ULPI_CK) | \ + PIN_MODE_INPUT(GPIOA_ARD_A0) | \ + PIN_MODE_ALTERNATE(GPIOA_RMII_CRS_DV) |\ + PIN_MODE_ALTERNATE(GPIOA_CEC_CLK) | \ + PIN_MODE_ALTERNATE(GPIOA_VCP_TX) | \ + PIN_MODE_ALTERNATE(GPIOA_VCP_RX) | \ + PIN_MODE_INPUT(GPIOA_ARD_D10) | \ + PIN_MODE_INPUT(GPIOA_ARD_D13) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_ALTERNATE(GPIOA_CEC)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_BUTTON_USER) |\ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_REF_CLK) |\ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_MDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ULPI_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ULPI_CK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_RMII_CRS_DV) |\ + PIN_OTYPE_PUSHPULL(GPIOA_CEC_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_VCP_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_VCP_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D13) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_CEC)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_BUTTON_USER) | \ + PIN_OSPEED_HIGH(GPIOA_RMII_REF_CLK) | \ + PIN_OSPEED_HIGH(GPIOA_RMII_MDIO) | \ + PIN_OSPEED_HIGH(GPIOA_ULPI_D0) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \ + PIN_OSPEED_HIGH(GPIOA_ULPI_CK) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \ + PIN_OSPEED_VERYLOW(GPIOA_RMII_CRS_DV) |\ + PIN_OSPEED_HIGH(GPIOA_CEC_CLK) | \ + PIN_OSPEED_HIGH(GPIOA_VCP_TX) | \ + PIN_OSPEED_HIGH(GPIOA_VCP_RX) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D10) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D13) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_HIGH(GPIOA_CEC)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_BUTTON_USER) |\ + PIN_PUPDR_FLOATING(GPIOA_RMII_REF_CLK) |\ + PIN_PUPDR_PULLUP(GPIOA_RMII_MDIO) | \ + PIN_PUPDR_FLOATING(GPIOA_ULPI_D0) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A1) | \ + PIN_PUPDR_FLOATING(GPIOA_ULPI_CK) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \ + PIN_PUPDR_FLOATING(GPIOA_RMII_CRS_DV) |\ + PIN_PUPDR_FLOATING(GPIOA_CEC_CLK) | \ + PIN_PUPDR_FLOATING(GPIOA_VCP_TX) | \ + PIN_PUPDR_FLOATING(GPIOA_VCP_RX) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D10) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D13) | \ + PIN_PUPDR_FLOATING(GPIOA_SWDIO) | \ + PIN_PUPDR_FLOATING(GPIOA_SWCLK) | \ + PIN_PUPDR_FLOATING(GPIOA_CEC)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_BUTTON_USER) | \ + PIN_ODR_HIGH(GPIOA_RMII_REF_CLK) | \ + PIN_ODR_HIGH(GPIOA_RMII_MDIO) | \ + PIN_ODR_HIGH(GPIOA_ULPI_D0) | \ + PIN_ODR_HIGH(GPIOA_ARD_A1) | \ + PIN_ODR_HIGH(GPIOA_ULPI_CK) | \ + PIN_ODR_HIGH(GPIOA_ARD_A0) | \ + PIN_ODR_HIGH(GPIOA_RMII_CRS_DV) | \ + PIN_ODR_HIGH(GPIOA_CEC_CLK) | \ + PIN_ODR_HIGH(GPIOA_VCP_TX) | \ + PIN_ODR_HIGH(GPIOA_VCP_RX) | \ + PIN_ODR_HIGH(GPIOA_ARD_D10) | \ + PIN_ODR_HIGH(GPIOA_ARD_D13) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_CEC)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_BUTTON_USER, 0U) | \ + PIN_AFIO_AF(GPIOA_RMII_REF_CLK, 11U) | \ + PIN_AFIO_AF(GPIOA_RMII_MDIO, 11U) | \ + PIN_AFIO_AF(GPIOA_ULPI_D0, 10U) | \ + PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \ + PIN_AFIO_AF(GPIOA_ULPI_CK, 10U) | \ + PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \ + PIN_AFIO_AF(GPIOA_RMII_CRS_DV, 11U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_CEC_CLK, 0U) | \ + PIN_AFIO_AF(GPIOA_VCP_TX, 7U) | \ + PIN_AFIO_AF(GPIOA_VCP_RX, 7U) | \ + PIN_AFIO_AF(GPIOA_ARD_D10, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D13, 0U) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \ + PIN_AFIO_AF(GPIOA_CEC, 3U)) + +/* + * GPIOB setup: + * + * PB0 - ULPI_D1 (alternate 10). + * PB1 - ULPI_D2 (alternate 10). + * PB2 - QSPI_CLK (alternate 9). + * PB3 - SD_D2 (alternate 10). + * PB4 - SD_D3 (alternate 10). + * PB5 - ULPI_D7 (alternate 10). + * PB6 - QUADSPI_BK1_NCS (alternate 10). + * PB7 - AUDIO_SDA LCD_SDA (alternate 11). + * PB8 - ARD_D15 (input pullup). + * PB9 - ARD_D14 (input pullup). + * PB10 - ULPI_D3 (alternate 10). + * PB11 - ULPI_D4 (alternate 10). + * PB12 - ULPI_D5 (alternate 10). + * PB13 - ULPI_D6 (alternate 10). + * PB14 - ARD_D12 (input pullup). + * PB15 - ARD_D11 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_ALTERNATE(GPIOB_ULPI_D1) | \ + PIN_MODE_ALTERNATE(GPIOB_ULPI_D2) | \ + PIN_MODE_ALTERNATE(GPIOB_QSPI_CLK) | \ + PIN_MODE_ALTERNATE(GPIOB_SD_D2) | \ + PIN_MODE_ALTERNATE(GPIOB_SD_D3) | \ + PIN_MODE_ALTERNATE(GPIOB_ULPI_D7) | \ + PIN_MODE_ALTERNATE(GPIOB_QUADSPI_BK1_NCS) | \ + PIN_MODE_ALTERNATE(GPIOB_AUDIO_SDA) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \ + PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ + PIN_MODE_ALTERNATE(GPIOB_ULPI_D3) | \ + PIN_MODE_ALTERNATE(GPIOB_ULPI_D4) | \ + PIN_MODE_ALTERNATE(GPIOB_ULPI_D5) | \ + PIN_MODE_ALTERNATE(GPIOB_ULPI_D6) | \ + PIN_MODE_INPUT(GPIOB_ARD_D12) | \ + PIN_MODE_INPUT(GPIOB_ARD_D11)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ULPI_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ULPI_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_QSPI_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SD_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SD_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ULPI_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOB_QUADSPI_BK1_NCS) | \ + PIN_OTYPE_PUSHPULL(GPIOB_AUDIO_SDA) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SCL) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_I2C1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ULPI_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ULPI_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ULPI_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ULPI_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ARD_D11)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ULPI_D1) | \ + PIN_OSPEED_HIGH(GPIOB_ULPI_D2) | \ + PIN_OSPEED_HIGH(GPIOB_QSPI_CLK) | \ + PIN_OSPEED_HIGH(GPIOB_SD_D2) | \ + PIN_OSPEED_HIGH(GPIOB_SD_D3) | \ + PIN_OSPEED_HIGH(GPIOB_ULPI_D7) | \ + PIN_OSPEED_HIGH(GPIOB_QUADSPI_BK1_NCS) | \ + PIN_OSPEED_HIGH(GPIOB_AUDIO_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SCL) | \ + PIN_OSPEED_HIGH(GPIOB_I2C1_SDA) | \ + PIN_OSPEED_HIGH(GPIOB_ULPI_D3) | \ + PIN_OSPEED_HIGH(GPIOB_ULPI_D4) | \ + PIN_OSPEED_HIGH(GPIOB_ULPI_D5) | \ + PIN_OSPEED_HIGH(GPIOB_ULPI_D6) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D12) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D11)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_ULPI_D1) | \ + PIN_PUPDR_FLOATING(GPIOB_ULPI_D2) | \ + PIN_PUPDR_FLOATING(GPIOB_QSPI_CLK) | \ + PIN_PUPDR_FLOATING(GPIOB_SD_D2) | \ + PIN_PUPDR_FLOATING(GPIOB_SD_D3) | \ + PIN_PUPDR_PULLUP(GPIOB_ULPI_D7) | \ + PIN_PUPDR_FLOATING(GPIOB_QUADSPI_BK1_NCS) | \ + PIN_PUPDR_FLOATING(GPIOB_AUDIO_SDA) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SCL) | \ + PIN_PUPDR_FLOATING(GPIOB_I2C1_SDA) | \ + PIN_PUPDR_FLOATING(GPIOB_ULPI_D3) | \ + PIN_PUPDR_FLOATING(GPIOB_ULPI_D4) | \ + PIN_PUPDR_FLOATING(GPIOB_ULPI_D5) | \ + PIN_PUPDR_FLOATING(GPIOB_ULPI_D6) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D12) | \ + PIN_PUPDR_PULLUP(GPIOB_ARD_D11)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_ULPI_D1) | \ + PIN_ODR_HIGH(GPIOB_ULPI_D2) | \ + PIN_ODR_HIGH(GPIOB_QSPI_CLK) | \ + PIN_ODR_HIGH(GPIOB_SD_D2) | \ + PIN_ODR_HIGH(GPIOB_SD_D3) | \ + PIN_ODR_HIGH(GPIOB_ULPI_D7) | \ + PIN_ODR_HIGH(GPIOB_QUADSPI_BK1_NCS) | \ + PIN_ODR_HIGH(GPIOB_AUDIO_SDA) | \ + PIN_ODR_LOW(GPIOB_I2C1_SCL) | \ + PIN_ODR_LOW(GPIOB_I2C1_SDA) | \ + PIN_ODR_HIGH(GPIOB_ULPI_D3) | \ + PIN_ODR_HIGH(GPIOB_ULPI_D4) | \ + PIN_ODR_HIGH(GPIOB_ULPI_D5) | \ + PIN_ODR_HIGH(GPIOB_ULPI_D6) | \ + PIN_ODR_HIGH(GPIOB_ARD_D12) | \ + PIN_ODR_HIGH(GPIOB_ARD_D11)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ULPI_D1, 10U) | \ + PIN_AFIO_AF(GPIOB_ULPI_D2, 10U) | \ + PIN_AFIO_AF(GPIOB_QSPI_CLK, 9U) | \ + PIN_AFIO_AF(GPIOB_SD_D2, 10U) | \ + PIN_AFIO_AF(GPIOB_SD_D3, 10U) | \ + PIN_AFIO_AF(GPIOB_ULPI_D7, 10U) | \ + PIN_AFIO_AF(GPIOB_QUADSPI_BK1_NCS, 10U) | \ + PIN_AFIO_AF(GPIOB_AUDIO_SDA, 11U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_I2C1_SCL, 4U) | \ + PIN_AFIO_AF(GPIOB_I2C1_SDA, 4U) | \ + PIN_AFIO_AF(GPIOB_ULPI_D3, 10U) | \ + PIN_AFIO_AF(GPIOB_ULPI_D4, 10U) | \ + PIN_AFIO_AF(GPIOB_ULPI_D5, 10U) | \ + PIN_AFIO_AF(GPIOB_ULPI_D6, 10U) | \ + PIN_AFIO_AF(GPIOB_ARD_D12, 0U) | \ + PIN_AFIO_AF(GPIOB_ARD_D11, 0U)) + +/* + * GPIOC setup: + * + * PC0 - ULPI_STP (alternate 10). + * PC1 - RMII_MDC (alternate 11). + * PC2 - ARD_A2 (input pullup). + * PC3 - DFSDM_DATIN1 (alternate 3). + * PC4 - RMII_RXD0 (alternate 11). + * PC5 - RMII_RXD1 (alternate 11). + * PC6 - ARD_D1 (input pullup). + * PC7 - ARD_D0 (input floating). + * PC8 - ARD_D5 (input floating). + * PC9 - QSPI_D0 (alternate 9). + * PC10 - QSPI_D1 (alternate 9). + * PC11 - DFSDM_DATIN5 (alternate 3). + * PC12 - WIFI_RX (alternate 8). + * PC13 - PIN13 (input pullup). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_ALTERNATE(GPIOC_ULPI_STP) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_MDC) | \ + PIN_MODE_INPUT(GPIOC_ARD_A2) | \ + PIN_MODE_ALTERNATE(GPIOC_DFSDM_DATIN1) |\ + PIN_MODE_ALTERNATE(GPIOC_RMII_RXD0) | \ + PIN_MODE_ALTERNATE(GPIOC_RMII_RXD1) | \ + PIN_MODE_INPUT(GPIOC_ARD_D1) | \ + PIN_MODE_INPUT(GPIOC_ARD_D0) | \ + PIN_MODE_INPUT(GPIOC_ARD_D5) | \ + PIN_MODE_ALTERNATE(GPIOC_QSPI_D0) | \ + PIN_MODE_ALTERNATE(GPIOC_QSPI_D1) | \ + PIN_MODE_ALTERNATE(GPIOC_DFSDM_DATIN5) |\ + PIN_MODE_ALTERNATE(GPIOC_WIFI_RX) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_OSC32_IN) | \ + PIN_MODE_INPUT(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ULPI_STP) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_MDC) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_DFSDM_DATIN1) |\ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_QSPI_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_QSPI_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_DFSDM_DATIN5) |\ + PIN_OTYPE_PUSHPULL(GPIOC_WIFI_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ULPI_STP) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_MDC) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_A2) | \ + PIN_OSPEED_HIGH(GPIOC_DFSDM_DATIN1) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_RXD0) | \ + PIN_OSPEED_HIGH(GPIOC_RMII_RXD1) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_D1) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_D0) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_D5) | \ + PIN_OSPEED_HIGH(GPIOC_QSPI_D0) | \ + PIN_OSPEED_HIGH(GPIOC_QSPI_D1) | \ + PIN_OSPEED_HIGH(GPIOC_DFSDM_DATIN5) | \ + PIN_OSPEED_HIGH(GPIOC_WIFI_RX) | \ + PIN_OSPEED_HIGH(GPIOC_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_ULPI_STP) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_MDC) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A2) | \ + PIN_PUPDR_FLOATING(GPIOC_DFSDM_DATIN1) |\ + PIN_PUPDR_FLOATING(GPIOC_RMII_RXD0) | \ + PIN_PUPDR_FLOATING(GPIOC_RMII_RXD1) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_D1) | \ + PIN_PUPDR_FLOATING(GPIOC_ARD_D0) | \ + PIN_PUPDR_FLOATING(GPIOC_ARD_D5) | \ + PIN_PUPDR_FLOATING(GPIOC_QSPI_D0) | \ + PIN_PUPDR_FLOATING(GPIOC_QSPI_D1) | \ + PIN_PUPDR_FLOATING(GPIOC_DFSDM_DATIN5) |\ + PIN_PUPDR_FLOATING(GPIOC_WIFI_RX) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ULPI_STP) | \ + PIN_ODR_HIGH(GPIOC_RMII_MDC) | \ + PIN_ODR_HIGH(GPIOC_ARD_A2) | \ + PIN_ODR_HIGH(GPIOC_DFSDM_DATIN1) | \ + PIN_ODR_HIGH(GPIOC_RMII_RXD0) | \ + PIN_ODR_HIGH(GPIOC_RMII_RXD1) | \ + PIN_ODR_HIGH(GPIOC_ARD_D1) | \ + PIN_ODR_HIGH(GPIOC_ARD_D0) | \ + PIN_ODR_HIGH(GPIOC_ARD_D5) | \ + PIN_ODR_HIGH(GPIOC_QSPI_D0) | \ + PIN_ODR_HIGH(GPIOC_QSPI_D1) | \ + PIN_ODR_HIGH(GPIOC_DFSDM_DATIN5) | \ + PIN_ODR_HIGH(GPIOC_WIFI_RX) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_OSC32_IN) | \ + PIN_ODR_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ULPI_STP, 10U) | \ + PIN_AFIO_AF(GPIOC_RMII_MDC, 11U) | \ + PIN_AFIO_AF(GPIOC_ARD_A2, 0U) | \ + PIN_AFIO_AF(GPIOC_DFSDM_DATIN1, 3U) | \ + PIN_AFIO_AF(GPIOC_RMII_RXD0, 11U) | \ + PIN_AFIO_AF(GPIOC_RMII_RXD1, 11U) | \ + PIN_AFIO_AF(GPIOC_ARD_D1, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_D0, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_ARD_D5, 0U) | \ + PIN_AFIO_AF(GPIOC_QSPI_D0, 9U) | \ + PIN_AFIO_AF(GPIOC_QSPI_D1, 9U) | \ + PIN_AFIO_AF(GPIOC_DFSDM_DATIN5, 3U) | \ + PIN_AFIO_AF(GPIOC_WIFI_RX, 8U) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - FMC_D2 (alternate 12). + * PD1 - FMC_D3 (alternate 12). + * PD2 - WIFI_TX (alternate 8). + * PD3 - DFSDM_CKOUT (alternate 3). + * PD4 - OTG_HS_OVER_CURRENT (input floating). + * PD5 - RMII_RXER (alternate 11). + * PD6 - SD_CLK (alternate 11). + * PD7 - SD_CMD (alternate 11). + * PD8 - FMC_D13 (alternate 12). + * PD9 - FMC_D14 (alternate 12). + * PD10 - FMC_D15 (alternate 12). + * PD11 - SPDIF_I2S (alternate 10). + * PD12 - AUDIO_SCL LCD_SCL (alternate 4). + * PD13 - QSPI_D3 (alternate 9). + * PD14 - FMC_D0 (alternate 12). + * PD15 - FMC_D1 (alternate 12). + */ +#define VAL_GPIOD_MODER (PIN_MODE_ALTERNATE(GPIOD_FMC_D2) | \ + PIN_MODE_ALTERNATE(GPIOD_FMC_D3) | \ + PIN_MODE_ALTERNATE(GPIOD_WIFI_TX) | \ + PIN_MODE_ALTERNATE(GPIOD_DFSDM_CKOUT) |\ + PIN_MODE_INPUT(GPIOD_OTG_HS_OVER_CURRENT) |\ + PIN_MODE_ALTERNATE(GPIOD_RMII_RXER) | \ + PIN_MODE_ALTERNATE(GPIOD_SD_CLK) | \ + PIN_MODE_ALTERNATE(GPIOD_SD_CMD) | \ + PIN_MODE_ALTERNATE(GPIOD_FMC_D13) | \ + PIN_MODE_ALTERNATE(GPIOD_FMC_D14) | \ + PIN_MODE_ALTERNATE(GPIOD_FMC_D15) | \ + PIN_MODE_ALTERNATE(GPIOD_SPDIF_I2S) | \ + PIN_MODE_ALTERNATE(GPIOD_AUDIO_SCL) | \ + PIN_MODE_ALTERNATE(GPIOD_QSPI_D3) | \ + PIN_MODE_ALTERNATE(GPIOD_FMC_D0) | \ + PIN_MODE_ALTERNATE(GPIOD_FMC_D1)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_FMC_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_FMC_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_WIFI_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_DFSDM_CKOUT) |\ + PIN_OTYPE_PUSHPULL(GPIOD_OTG_HS_OVER_CURRENT) |\ + PIN_OTYPE_PUSHPULL(GPIOD_RMII_RXER) | \ + PIN_OTYPE_PUSHPULL(GPIOD_SD_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOD_SD_CMD) | \ + PIN_OTYPE_PUSHPULL(GPIOD_FMC_D13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_FMC_D14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_FMC_D15) | \ + PIN_OTYPE_PUSHPULL(GPIOD_SPDIF_I2S) | \ + PIN_OTYPE_PUSHPULL(GPIOD_AUDIO_SCL) | \ + PIN_OTYPE_PUSHPULL(GPIOD_QSPI_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_FMC_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_FMC_D1)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_FMC_D2) | \ + PIN_OSPEED_HIGH(GPIOD_FMC_D3) | \ + PIN_OSPEED_HIGH(GPIOD_WIFI_TX) | \ + PIN_OSPEED_HIGH(GPIOD_DFSDM_CKOUT) | \ + PIN_OSPEED_HIGH(GPIOD_OTG_HS_OVER_CURRENT) |\ + PIN_OSPEED_HIGH(GPIOD_RMII_RXER) | \ + PIN_OSPEED_HIGH(GPIOD_SD_CLK) | \ + PIN_OSPEED_HIGH(GPIOD_SD_CMD) | \ + PIN_OSPEED_HIGH(GPIOD_FMC_D13) | \ + PIN_OSPEED_HIGH(GPIOD_FMC_D14) | \ + PIN_OSPEED_HIGH(GPIOD_FMC_D15) | \ + PIN_OSPEED_HIGH(GPIOD_SPDIF_I2S) | \ + PIN_OSPEED_HIGH(GPIOD_AUDIO_SCL) | \ + PIN_OSPEED_HIGH(GPIOD_QSPI_D3) | \ + PIN_OSPEED_HIGH(GPIOD_FMC_D0) | \ + PIN_OSPEED_HIGH(GPIOD_FMC_D1)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_FMC_D2) | \ + PIN_PUPDR_FLOATING(GPIOD_FMC_D3) | \ + PIN_PUPDR_FLOATING(GPIOD_WIFI_TX) | \ + PIN_PUPDR_FLOATING(GPIOD_DFSDM_CKOUT) |\ + PIN_PUPDR_FLOATING(GPIOD_OTG_HS_OVER_CURRENT) |\ + PIN_PUPDR_FLOATING(GPIOD_RMII_RXER) | \ + PIN_PUPDR_FLOATING(GPIOD_SD_CLK) | \ + PIN_PUPDR_FLOATING(GPIOD_SD_CMD) | \ + PIN_PUPDR_FLOATING(GPIOD_FMC_D13) | \ + PIN_PUPDR_FLOATING(GPIOD_FMC_D14) | \ + PIN_PUPDR_FLOATING(GPIOD_FMC_D15) | \ + PIN_PUPDR_FLOATING(GPIOD_SPDIF_I2S) | \ + PIN_PUPDR_FLOATING(GPIOD_AUDIO_SCL) | \ + PIN_PUPDR_FLOATING(GPIOD_QSPI_D3) | \ + PIN_PUPDR_FLOATING(GPIOD_FMC_D0) | \ + PIN_PUPDR_FLOATING(GPIOD_FMC_D1)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_FMC_D2) | \ + PIN_ODR_HIGH(GPIOD_FMC_D3) | \ + PIN_ODR_HIGH(GPIOD_WIFI_TX) | \ + PIN_ODR_HIGH(GPIOD_DFSDM_CKOUT) | \ + PIN_ODR_HIGH(GPIOD_OTG_HS_OVER_CURRENT) |\ + PIN_ODR_HIGH(GPIOD_RMII_RXER) | \ + PIN_ODR_HIGH(GPIOD_SD_CLK) | \ + PIN_ODR_HIGH(GPIOD_SD_CMD) | \ + PIN_ODR_HIGH(GPIOD_FMC_D13) | \ + PIN_ODR_HIGH(GPIOD_FMC_D14) | \ + PIN_ODR_HIGH(GPIOD_FMC_D15) | \ + PIN_ODR_HIGH(GPIOD_SPDIF_I2S) | \ + PIN_ODR_HIGH(GPIOD_AUDIO_SCL) | \ + PIN_ODR_HIGH(GPIOD_QSPI_D3) | \ + PIN_ODR_LOW(GPIOD_FMC_D0) | \ + PIN_ODR_LOW(GPIOD_FMC_D1)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_FMC_D2, 12U) | \ + PIN_AFIO_AF(GPIOD_FMC_D3, 12U) | \ + PIN_AFIO_AF(GPIOD_WIFI_TX, 8U) | \ + PIN_AFIO_AF(GPIOD_DFSDM_CKOUT, 3U) | \ + PIN_AFIO_AF(GPIOD_OTG_HS_OVER_CURRENT, 0U) |\ + PIN_AFIO_AF(GPIOD_RMII_RXER, 11U) | \ + PIN_AFIO_AF(GPIOD_SD_CLK, 11U) | \ + PIN_AFIO_AF(GPIOD_SD_CMD, 11U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_FMC_D13, 12U) | \ + PIN_AFIO_AF(GPIOD_FMC_D14, 12U) | \ + PIN_AFIO_AF(GPIOD_FMC_D15, 12U) | \ + PIN_AFIO_AF(GPIOD_SPDIF_I2S, 10U) | \ + PIN_AFIO_AF(GPIOD_AUDIO_SCL, 4U) | \ + PIN_AFIO_AF(GPIOD_QSPI_D3, 9U) | \ + PIN_AFIO_AF(GPIOD_FMC_D0, 12U) | \ + PIN_AFIO_AF(GPIOD_FMC_D1, 12U)) + +/* + * GPIOE setup: + * + * PE0 - FMC_NBL0 (alternate 12). + * PE1 - FMC_NBL1 (alternate 12). + * PE2 - QSPI_D2 (alternate 9). + * PE3 - SAI1_SDB (alternate 6). + * PE4 - SAI1_FSA (alternate 6). + * PE5 - SAI1_SCKA (alternate 6). + * PE6 - SAI1_SDA (alternate 6). + * PE7 - FMC_D4 (alternate 12). + * PE8 - FMC_D5 (alternate 12). + * PE9 - FMC_D6 (alternate 12). + * PE10 - FMC_D7 (alternate 12). + * PE11 - FMC_D8 (alternate 12). + * PE12 - FMC_D9 (alternate 12). + * PE13 - FMC_D10 (alternate 12). + * PE14 - FMC_11 (alternate 12). + * PE15 - FMC_D12 (alternate 12). + */ +#define VAL_GPIOE_MODER (PIN_MODE_ALTERNATE(GPIOE_FMC_NBL0) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_NBL1) | \ + PIN_MODE_ALTERNATE(GPIOE_QSPI_D2) | \ + PIN_MODE_ALTERNATE(GPIOE_SAI1_SDB) | \ + PIN_MODE_ALTERNATE(GPIOE_SAI1_FSA) | \ + PIN_MODE_ALTERNATE(GPIOE_SAI1_SCKA) | \ + PIN_MODE_ALTERNATE(GPIOE_SAI1_SDA) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D4) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D5) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D6) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D7) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D8) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D9) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D10) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_11) | \ + PIN_MODE_ALTERNATE(GPIOE_FMC_D12)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_FMC_NBL0) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_NBL1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_QSPI_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_SAI1_SDB) | \ + PIN_OTYPE_PUSHPULL(GPIOE_SAI1_FSA) | \ + PIN_OTYPE_PUSHPULL(GPIOE_SAI1_SCKA) | \ + PIN_OTYPE_PUSHPULL(GPIOE_SAI1_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_FMC_D12)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_FMC_NBL0) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_NBL1) | \ + PIN_OSPEED_HIGH(GPIOE_QSPI_D2) | \ + PIN_OSPEED_HIGH(GPIOE_SAI1_SDB) | \ + PIN_OSPEED_HIGH(GPIOE_SAI1_FSA) | \ + PIN_OSPEED_HIGH(GPIOE_SAI1_SCKA) | \ + PIN_OSPEED_HIGH(GPIOE_SAI1_SDA) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D4) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D5) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D6) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D7) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D8) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D9) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D10) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_11) | \ + PIN_OSPEED_HIGH(GPIOE_FMC_D12)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_FMC_NBL0) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_NBL1) | \ + PIN_PUPDR_FLOATING(GPIOE_QSPI_D2) | \ + PIN_PUPDR_FLOATING(GPIOE_SAI1_SDB) | \ + PIN_PUPDR_FLOATING(GPIOE_SAI1_FSA) | \ + PIN_PUPDR_FLOATING(GPIOE_SAI1_SCKA) | \ + PIN_PUPDR_FLOATING(GPIOE_SAI1_SDA) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D4) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D5) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D6) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D7) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D8) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D9) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D10) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_11) | \ + PIN_PUPDR_FLOATING(GPIOE_FMC_D12)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_FMC_NBL0) | \ + PIN_ODR_HIGH(GPIOE_FMC_NBL1) | \ + PIN_ODR_HIGH(GPIOE_QSPI_D2) | \ + PIN_ODR_HIGH(GPIOE_SAI1_SDB) | \ + PIN_ODR_HIGH(GPIOE_SAI1_FSA) | \ + PIN_ODR_HIGH(GPIOE_SAI1_SCKA) | \ + PIN_ODR_HIGH(GPIOE_SAI1_SDA) | \ + PIN_ODR_HIGH(GPIOE_FMC_D4) | \ + PIN_ODR_HIGH(GPIOE_FMC_D5) | \ + PIN_ODR_HIGH(GPIOE_FMC_D6) | \ + PIN_ODR_HIGH(GPIOE_FMC_D7) | \ + PIN_ODR_HIGH(GPIOE_FMC_D8) | \ + PIN_ODR_HIGH(GPIOE_FMC_D9) | \ + PIN_ODR_HIGH(GPIOE_FMC_D10) | \ + PIN_ODR_HIGH(GPIOE_FMC_11) | \ + PIN_ODR_HIGH(GPIOE_FMC_D12)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_FMC_NBL0, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_NBL1, 12U) | \ + PIN_AFIO_AF(GPIOE_QSPI_D2, 9U) | \ + PIN_AFIO_AF(GPIOE_SAI1_SDB, 6U) | \ + PIN_AFIO_AF(GPIOE_SAI1_FSA, 6U) | \ + PIN_AFIO_AF(GPIOE_SAI1_SCKA, 6U) | \ + PIN_AFIO_AF(GPIOE_SAI1_SDA, 6U) | \ + PIN_AFIO_AF(GPIOE_FMC_D4, 12U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_FMC_D5, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_D6, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_D7, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_D8, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_D9, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_D10, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_11, 12U) | \ + PIN_AFIO_AF(GPIOE_FMC_D12, 12U)) + +/* + * GPIOF setup: + * + * PF0 - FMC_A0 (alternate 12). + * PF1 - FMC_A1 (alternate 12). + * PF2 - FMC_A2 (alternate 12). + * PF3 - FMC_A3 (alternate 12). + * PF4 - FMC_A4 (alternate 12). + * PF5 - FMC_A5 (alternate 12). + * PF6 - ARD_D3 (input pullup). + * PF7 - ARD_D6 (input pullup). + * PF8 - ARD_A4 (input pullup). + * PF9 - ARD_A5 (input pullup). + * PF10 - ARD_A3 (input pullup). + * PF11 - FMC_SDNRAS (alternate 12). + * PF12 - FMC_A6 (alternate 12). + * PF13 - FMC_A7 (alternate 12). + * PF14 - FMC_A8 (alternate 12). + * PF15 - FMC_A9 (alternate 12). + */ +#define VAL_GPIOF_MODER (PIN_MODE_ALTERNATE(GPIOF_FMC_A0) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A1) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A2) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A3) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A4) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A5) | \ + PIN_MODE_INPUT(GPIOF_ARD_D3) | \ + PIN_MODE_INPUT(GPIOF_ARD_D6) | \ + PIN_MODE_INPUT(GPIOF_ARD_A4) | \ + PIN_MODE_INPUT(GPIOF_ARD_A5) | \ + PIN_MODE_INPUT(GPIOF_ARD_A3) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_SDNRAS) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A6) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A7) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A8) | \ + PIN_MODE_ALTERNATE(GPIOF_FMC_A9)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_FMC_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A1) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_SDNRAS) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_FMC_A9)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_FMC_A0) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A1) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A2) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A3) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A4) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A5) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_D3) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_D6) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A4) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A5) | \ + PIN_OSPEED_HIGH(GPIOF_ARD_A3) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_SDNRAS) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A6) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A7) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A8) | \ + PIN_OSPEED_HIGH(GPIOF_FMC_A9)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_FMC_A0) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A1) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A2) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A3) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A4) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A5) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D3) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D6) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A4) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A5) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_A3) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_SDNRAS) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A6) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A7) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A8) | \ + PIN_PUPDR_FLOATING(GPIOF_FMC_A9)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_FMC_A0) | \ + PIN_ODR_HIGH(GPIOF_FMC_A1) | \ + PIN_ODR_HIGH(GPIOF_FMC_A2) | \ + PIN_ODR_HIGH(GPIOF_FMC_A3) | \ + PIN_ODR_HIGH(GPIOF_FMC_A4) | \ + PIN_ODR_HIGH(GPIOF_FMC_A5) | \ + PIN_ODR_HIGH(GPIOF_ARD_D3) | \ + PIN_ODR_HIGH(GPIOF_ARD_D6) | \ + PIN_ODR_HIGH(GPIOF_ARD_A4) | \ + PIN_ODR_HIGH(GPIOF_ARD_A5) | \ + PIN_ODR_HIGH(GPIOF_ARD_A3) | \ + PIN_ODR_HIGH(GPIOF_FMC_SDNRAS) | \ + PIN_ODR_HIGH(GPIOF_FMC_A6) | \ + PIN_ODR_HIGH(GPIOF_FMC_A7) | \ + PIN_ODR_HIGH(GPIOF_FMC_A8) | \ + PIN_ODR_HIGH(GPIOF_FMC_A9)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_FMC_A0, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A1, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A2, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A3, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A4, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A5, 12U) | \ + PIN_AFIO_AF(GPIOF_ARD_D3, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D6, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_ARD_A4, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_A5, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_A3, 0U) | \ + PIN_AFIO_AF(GPIOF_FMC_SDNRAS, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A6, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A7, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A8, 12U) | \ + PIN_AFIO_AF(GPIOF_FMC_A9, 12U)) + +/* + * GPIOG setup: + * + * PG0 - FMC_A10 (alternate 12). + * PG1 - FMC_A11 (alternate 12). + * PG2 - FMC_A12 (alternate 12). + * PG3 - EXT_SCL (input pullup). + * PG4 - FMC_BA0 (alternate 12). + * PG5 - FMC_BA1 (alternate 12). + * PG6 - EXT_SDA (input pullup). + * PG7 - SAI1_MCLKA (alternate 6). + * PG8 - FMC_SDCLK (alternate 12). + * PG9 - SD_D0 (alternate 11). + * PG10 - SD_D1 (alternate 11). + * PG11 - RMII_TX_EN (alternate 11). + * PG12 - SPDIF_RX (alternate 7). + * PG13 - RMII_TXD0 (alternate 11). + * PG14 - RMII_TXD1 (alternate 11). + * PG15 - FMC_SDNCAS (alternate 12). + */ +#define VAL_GPIOG_MODER (PIN_MODE_ALTERNATE(GPIOG_FMC_A10) | \ + PIN_MODE_ALTERNATE(GPIOG_FMC_A11) | \ + PIN_MODE_ALTERNATE(GPIOG_FMC_A12) | \ + PIN_MODE_INPUT(GPIOG_EXT_SCL) | \ + PIN_MODE_ALTERNATE(GPIOG_FMC_BA0) | \ + PIN_MODE_ALTERNATE(GPIOG_FMC_BA1) | \ + PIN_MODE_INPUT(GPIOG_EXT_SDA) | \ + PIN_MODE_ALTERNATE(GPIOG_SAI1_MCLKA) | \ + PIN_MODE_ALTERNATE(GPIOG_FMC_SDCLK) | \ + PIN_MODE_ALTERNATE(GPIOG_SD_D0) | \ + PIN_MODE_ALTERNATE(GPIOG_SD_D1) | \ + PIN_MODE_ALTERNATE(GPIOG_RMII_TX_EN) | \ + PIN_MODE_ALTERNATE(GPIOG_SPDIF_RX) | \ + PIN_MODE_ALTERNATE(GPIOG_RMII_TXD0) | \ + PIN_MODE_ALTERNATE(GPIOG_RMII_TXD1) | \ + PIN_MODE_ALTERNATE(GPIOG_FMC_SDNCAS)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_FMC_A10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_FMC_A11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_FMC_A12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_EXT_SCL) | \ + PIN_OTYPE_PUSHPULL(GPIOG_FMC_BA0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_FMC_BA1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_EXT_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOG_SAI1_MCLKA) | \ + PIN_OTYPE_PUSHPULL(GPIOG_FMC_SDCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOG_SD_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_SD_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_RMII_TX_EN) | \ + PIN_OTYPE_PUSHPULL(GPIOG_SPDIF_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOG_RMII_TXD0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_RMII_TXD1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_FMC_SDNCAS)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_HIGH(GPIOG_FMC_A10) | \ + PIN_OSPEED_HIGH(GPIOG_FMC_A11) | \ + PIN_OSPEED_HIGH(GPIOG_FMC_A12) | \ + PIN_OSPEED_HIGH(GPIOG_EXT_SCL) | \ + PIN_OSPEED_HIGH(GPIOG_FMC_BA0) | \ + PIN_OSPEED_HIGH(GPIOG_FMC_BA1) | \ + PIN_OSPEED_HIGH(GPIOG_EXT_SDA) | \ + PIN_OSPEED_HIGH(GPIOG_SAI1_MCLKA) | \ + PIN_OSPEED_HIGH(GPIOG_FMC_SDCLK) | \ + PIN_OSPEED_HIGH(GPIOG_SD_D0) | \ + PIN_OSPEED_HIGH(GPIOG_SD_D1) | \ + PIN_OSPEED_HIGH(GPIOG_RMII_TX_EN) | \ + PIN_OSPEED_HIGH(GPIOG_SPDIF_RX) | \ + PIN_OSPEED_HIGH(GPIOG_RMII_TXD0) | \ + PIN_OSPEED_HIGH(GPIOG_RMII_TXD1) | \ + PIN_OSPEED_HIGH(GPIOG_FMC_SDNCAS)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_FLOATING(GPIOG_FMC_A10) | \ + PIN_PUPDR_FLOATING(GPIOG_FMC_A11) | \ + PIN_PUPDR_FLOATING(GPIOG_FMC_A12) | \ + PIN_PUPDR_PULLUP(GPIOG_EXT_SCL) | \ + PIN_PUPDR_FLOATING(GPIOG_FMC_BA0) | \ + PIN_PUPDR_FLOATING(GPIOG_FMC_BA1) | \ + PIN_PUPDR_PULLUP(GPIOG_EXT_SDA) | \ + PIN_PUPDR_PULLUP(GPIOG_SAI1_MCLKA) | \ + PIN_PUPDR_FLOATING(GPIOG_FMC_SDCLK) | \ + PIN_PUPDR_FLOATING(GPIOG_SD_D0) | \ + PIN_PUPDR_FLOATING(GPIOG_SD_D1) | \ + PIN_PUPDR_FLOATING(GPIOG_RMII_TX_EN) | \ + PIN_PUPDR_FLOATING(GPIOG_SPDIF_RX) | \ + PIN_PUPDR_FLOATING(GPIOG_RMII_TXD0) | \ + PIN_PUPDR_FLOATING(GPIOG_RMII_TXD1) | \ + PIN_PUPDR_FLOATING(GPIOG_FMC_SDNCAS)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_FMC_A10) | \ + PIN_ODR_HIGH(GPIOG_FMC_A11) | \ + PIN_ODR_HIGH(GPIOG_FMC_A12) | \ + PIN_ODR_HIGH(GPIOG_EXT_SCL) | \ + PIN_ODR_HIGH(GPIOG_FMC_BA0) | \ + PIN_ODR_HIGH(GPIOG_FMC_BA1) | \ + PIN_ODR_HIGH(GPIOG_EXT_SDA) | \ + PIN_ODR_HIGH(GPIOG_SAI1_MCLKA) | \ + PIN_ODR_HIGH(GPIOG_FMC_SDCLK) | \ + PIN_ODR_HIGH(GPIOG_SD_D0) | \ + PIN_ODR_HIGH(GPIOG_SD_D1) | \ + PIN_ODR_HIGH(GPIOG_RMII_TX_EN) | \ + PIN_ODR_HIGH(GPIOG_SPDIF_RX) | \ + PIN_ODR_HIGH(GPIOG_RMII_TXD0) | \ + PIN_ODR_HIGH(GPIOG_RMII_TXD1) | \ + PIN_ODR_HIGH(GPIOG_FMC_SDNCAS)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_FMC_A10, 12U) | \ + PIN_AFIO_AF(GPIOG_FMC_A11, 12U) | \ + PIN_AFIO_AF(GPIOG_FMC_A12, 12U) | \ + PIN_AFIO_AF(GPIOG_EXT_SCL, 0U) | \ + PIN_AFIO_AF(GPIOG_FMC_BA0, 12U) | \ + PIN_AFIO_AF(GPIOG_FMC_BA1, 12U) | \ + PIN_AFIO_AF(GPIOG_EXT_SDA, 0U) | \ + PIN_AFIO_AF(GPIOG_SAI1_MCLKA, 6U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_FMC_SDCLK, 12U) | \ + PIN_AFIO_AF(GPIOG_SD_D0, 11U) | \ + PIN_AFIO_AF(GPIOG_SD_D1, 11U) | \ + PIN_AFIO_AF(GPIOG_RMII_TX_EN, 11U) | \ + PIN_AFIO_AF(GPIOG_SPDIF_RX, 7U) | \ + PIN_AFIO_AF(GPIOG_RMII_TXD0, 11U) | \ + PIN_AFIO_AF(GPIOG_RMII_TXD1, 11U) | \ + PIN_AFIO_AF(GPIOG_FMC_SDNCAS, 12U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - FMC_SDCKE0 (alternate 12). + * PH3 - FMC_SDNE0 (alternate 12). + * PH4 - ULPI_NXT (alternate 10). + * PH5 - FMC_SDNWE (alternate 12). + * PH6 - ARD_D9 (input pullup). + * PH7 - EXT_RST (input floating). + * PH8 - FMC_D16 (alternate 12). + * PH9 - FMC_D17 (alternate 12). + * PH10 - FMC_D18 (alternate 12). + * PH11 - FMC_D19 (alternate 12). + * PH12 - FMC_D20 (alternate 12). + * PH13 - FMC_D21 (alternate 12). + * PH14 - FMC_D22 (alternate 12). + * PH15 - FMC_D23 (alternate 12). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_SDCKE0) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_SDNE0) | \ + PIN_MODE_ALTERNATE(GPIOH_ULPI_NXT) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_SDNWE) | \ + PIN_MODE_INPUT(GPIOH_ARD_D9) | \ + PIN_MODE_INPUT(GPIOH_EXT_RST) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D16) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D17) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D18) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D19) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D20) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D21) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D22) | \ + PIN_MODE_ALTERNATE(GPIOH_FMC_D23)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_SDCKE0) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_SDNE0) | \ + PIN_OTYPE_PUSHPULL(GPIOH_ULPI_NXT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_SDNWE) | \ + PIN_OTYPE_PUSHPULL(GPIOH_ARD_D9) | \ + PIN_OTYPE_OPENDRAIN(GPIOH_EXT_RST) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D16) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D17) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D18) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D19) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D20) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D21) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D22) | \ + PIN_OTYPE_PUSHPULL(GPIOH_FMC_D23)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_SDCKE0) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_SDNE0) | \ + PIN_OSPEED_HIGH(GPIOH_ULPI_NXT) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_SDNWE) | \ + PIN_OSPEED_HIGH(GPIOH_ARD_D9) | \ + PIN_OSPEED_HIGH(GPIOH_EXT_RST) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D16) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D17) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D18) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D19) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D20) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D21) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D22) | \ + PIN_OSPEED_HIGH(GPIOH_FMC_D23)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_SDCKE0) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_SDNE0) | \ + PIN_PUPDR_FLOATING(GPIOH_ULPI_NXT) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_SDNWE) | \ + PIN_PUPDR_PULLUP(GPIOH_ARD_D9) | \ + PIN_PUPDR_FLOATING(GPIOH_EXT_RST) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D16) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D17) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D18) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D19) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D20) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D21) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D22) | \ + PIN_PUPDR_FLOATING(GPIOH_FMC_D23)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_FMC_SDCKE0) | \ + PIN_ODR_HIGH(GPIOH_FMC_SDNE0) | \ + PIN_ODR_HIGH(GPIOH_ULPI_NXT) | \ + PIN_ODR_HIGH(GPIOH_FMC_SDNWE) | \ + PIN_ODR_HIGH(GPIOH_ARD_D9) | \ + PIN_ODR_HIGH(GPIOH_EXT_RST) | \ + PIN_ODR_HIGH(GPIOH_FMC_D16) | \ + PIN_ODR_HIGH(GPIOH_FMC_D17) | \ + PIN_ODR_HIGH(GPIOH_FMC_D18) | \ + PIN_ODR_HIGH(GPIOH_FMC_D19) | \ + PIN_ODR_HIGH(GPIOH_FMC_D20) | \ + PIN_ODR_HIGH(GPIOH_FMC_D21) | \ + PIN_ODR_HIGH(GPIOH_FMC_D22) | \ + PIN_ODR_HIGH(GPIOH_FMC_D23)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_FMC_SDCKE0, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_SDNE0, 12U) | \ + PIN_AFIO_AF(GPIOH_ULPI_NXT, 10U) | \ + PIN_AFIO_AF(GPIOH_FMC_SDNWE, 12U) | \ + PIN_AFIO_AF(GPIOH_ARD_D9, 0U) | \ + PIN_AFIO_AF(GPIOH_EXT_RST, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_FMC_D16, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_D17, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_D18, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_D19, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_D20, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_D21, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_D22, 12U) | \ + PIN_AFIO_AF(GPIOH_FMC_D23, 12U)) + +/* + * GPIOI setup: + * + * PI0 - FMC_D24 (alternate 12). + * PI1 - FMC_D25 (alternate 12). + * PI2 - FMC_D26 (alternate 12). + * PI3 - FMC_D27 (alternate 12). + * PI4 - FMC_NBL2 (alternate 12). + * PI5 - FMC_NBL3 (alternate 12). + * PI6 - FMC_D28 (alternate 12). + * PI7 - FMC_D29 (alternate 12). + * PI8 - PIN8 (input pullup). + * PI9 - FMC_D30 (alternate 12). + * PI10 - FMC_D31 (alternate 12). + * PI11 - ULPI_DIR (alternate 10). + * PI12 - PIN12 (input pullup). + * PI13 - LCD_INT (alternate 14). + * PI14 - LCD_BL_CTRL (alternate 14). + * PI15 - SD_DETECT (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_ALTERNATE(GPIOI_FMC_D24) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_D25) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_D26) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_D27) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_NBL2) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_NBL3) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_D28) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_D29) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_D30) | \ + PIN_MODE_ALTERNATE(GPIOI_FMC_D31) | \ + PIN_MODE_ALTERNATE(GPIOI_ULPI_DIR) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_ALTERNATE(GPIOI_LCD_INT) | \ + PIN_MODE_ALTERNATE(GPIOI_LCD_BL_CTRL) |\ + PIN_MODE_INPUT(GPIOI_SD_DETECT)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_FMC_D24) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_D25) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_D26) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_D27) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_NBL2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_NBL3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_D28) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_D29) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_D30) | \ + PIN_OTYPE_PUSHPULL(GPIOI_FMC_D31) | \ + PIN_OTYPE_PUSHPULL(GPIOI_ULPI_DIR) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_LCD_INT) | \ + PIN_OTYPE_PUSHPULL(GPIOI_LCD_BL_CTRL) |\ + PIN_OTYPE_PUSHPULL(GPIOI_SD_DETECT)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_HIGH(GPIOI_FMC_D24) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_D25) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_D26) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_D27) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_NBL2) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_NBL3) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_D28) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_D29) | \ + PIN_OSPEED_HIGH(GPIOI_PIN8) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_D30) | \ + PIN_OSPEED_HIGH(GPIOI_FMC_D31) | \ + PIN_OSPEED_HIGH(GPIOI_ULPI_DIR) | \ + PIN_OSPEED_HIGH(GPIOI_PIN12) | \ + PIN_OSPEED_HIGH(GPIOI_LCD_INT) | \ + PIN_OSPEED_HIGH(GPIOI_LCD_BL_CTRL) | \ + PIN_OSPEED_HIGH(GPIOI_SD_DETECT)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_FLOATING(GPIOI_FMC_D24) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_D25) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_D26) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_D27) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_NBL2) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_NBL3) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_D28) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_D29) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_D30) | \ + PIN_PUPDR_FLOATING(GPIOI_FMC_D31) | \ + PIN_PUPDR_FLOATING(GPIOI_ULPI_DIR) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOI_LCD_INT) | \ + PIN_PUPDR_FLOATING(GPIOI_LCD_BL_CTRL) |\ + PIN_PUPDR_PULLUP(GPIOI_SD_DETECT)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_FMC_D24) | \ + PIN_ODR_HIGH(GPIOI_FMC_D25) | \ + PIN_ODR_HIGH(GPIOI_FMC_D26) | \ + PIN_ODR_HIGH(GPIOI_FMC_D27) | \ + PIN_ODR_HIGH(GPIOI_FMC_NBL2) | \ + PIN_ODR_HIGH(GPIOI_FMC_NBL3) | \ + PIN_ODR_HIGH(GPIOI_FMC_D28) | \ + PIN_ODR_HIGH(GPIOI_FMC_D29) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_FMC_D30) | \ + PIN_ODR_HIGH(GPIOI_FMC_D31) | \ + PIN_ODR_HIGH(GPIOI_ULPI_DIR) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_LCD_INT) | \ + PIN_ODR_HIGH(GPIOI_LCD_BL_CTRL) | \ + PIN_ODR_HIGH(GPIOI_SD_DETECT)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_FMC_D24, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_D25, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_D26, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_D27, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_NBL2, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_NBL3, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_D28, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_D29, 12U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_FMC_D30, 12U) | \ + PIN_AFIO_AF(GPIOI_FMC_D31, 12U) | \ + PIN_AFIO_AF(GPIOI_ULPI_DIR, 10U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_LCD_INT, 14U) | \ + PIN_AFIO_AF(GPIOI_LCD_BL_CTRL, 14U) | \ + PIN_AFIO_AF(GPIOI_SD_DETECT, 0U)) + +/* + * GPIOJ setup: + * + * PJ0 - ARD_D4 (input floating). + * PJ1 - ARD_D2 (input floating). + * PJ2 - DSI_TE (alternate 13). + * PJ3 - ARD_D7 (input floating). + * PJ4 - ARD_D8 (input floating). + * PJ5 - LED2_GREEN (output pushpull maximum). + * PJ6 - PIN6 (input floating). + * PJ7 - PIN7 (input floating). + * PJ8 - PIN8 (input floating). + * PJ9 - PIN9 (input floating). + * PJ10 - PIN10 (input floating). + * PJ11 - PIN11 (input floating). + * PJ12 - AUDIO_INT (input floating). + * PJ13 - LED1_RED (output pushpull maximum). + * PJ14 - WIFI_RST (input floating). + * PJ15 - DSI_RESET (input floating). + */ +#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_ARD_D4) | \ + PIN_MODE_INPUT(GPIOJ_ARD_D2) | \ + PIN_MODE_ALTERNATE(GPIOJ_DSI_TE) | \ + PIN_MODE_INPUT(GPIOJ_ARD_D7) | \ + PIN_MODE_INPUT(GPIOJ_ARD_D8) | \ + PIN_MODE_OUTPUT(GPIOJ_LED2_GREEN) | \ + PIN_MODE_INPUT(GPIOJ_PIN6) | \ + PIN_MODE_INPUT(GPIOJ_PIN7) | \ + PIN_MODE_INPUT(GPIOJ_PIN8) | \ + PIN_MODE_INPUT(GPIOJ_PIN9) | \ + PIN_MODE_INPUT(GPIOJ_PIN10) | \ + PIN_MODE_INPUT(GPIOJ_PIN11) | \ + PIN_MODE_INPUT(GPIOJ_AUDIO_INT) | \ + PIN_MODE_OUTPUT(GPIOJ_LED1_RED) | \ + PIN_MODE_INPUT(GPIOJ_WIFI_RST) | \ + PIN_MODE_INPUT(GPIOJ_DSI_RESET)) +#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_ARD_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_ARD_D2) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_DSI_TE) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_ARD_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_ARD_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_LED2_GREEN) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_AUDIO_INT) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_LED1_RED) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_WIFI_RST) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_DSI_RESET)) +#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOJ_ARD_D4) | \ + PIN_OSPEED_VERYLOW(GPIOJ_ARD_D2) | \ + PIN_OSPEED_VERYLOW(GPIOJ_DSI_TE) | \ + PIN_OSPEED_VERYLOW(GPIOJ_ARD_D7) | \ + PIN_OSPEED_VERYLOW(GPIOJ_ARD_D8) | \ + PIN_OSPEED_HIGH(GPIOJ_LED2_GREEN) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOJ_AUDIO_INT) | \ + PIN_OSPEED_HIGH(GPIOJ_LED1_RED) | \ + PIN_OSPEED_VERYLOW(GPIOJ_WIFI_RST) | \ + PIN_OSPEED_VERYLOW(GPIOJ_DSI_RESET)) +#define VAL_GPIOJ_PUPDR (PIN_PUPDR_FLOATING(GPIOJ_ARD_D4) | \ + PIN_PUPDR_FLOATING(GPIOJ_ARD_D2) | \ + PIN_PUPDR_FLOATING(GPIOJ_DSI_TE) | \ + PIN_PUPDR_FLOATING(GPIOJ_ARD_D7) | \ + PIN_PUPDR_FLOATING(GPIOJ_ARD_D8) | \ + PIN_PUPDR_FLOATING(GPIOJ_LED2_GREEN) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOJ_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOJ_AUDIO_INT) | \ + PIN_PUPDR_FLOATING(GPIOJ_LED1_RED) | \ + PIN_PUPDR_FLOATING(GPIOJ_WIFI_RST) | \ + PIN_PUPDR_FLOATING(GPIOJ_DSI_RESET)) +#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_ARD_D4) | \ + PIN_ODR_HIGH(GPIOJ_ARD_D2) | \ + PIN_ODR_HIGH(GPIOJ_DSI_TE) | \ + PIN_ODR_HIGH(GPIOJ_ARD_D7) | \ + PIN_ODR_HIGH(GPIOJ_ARD_D8) | \ + PIN_ODR_LOW(GPIOJ_LED2_GREEN) | \ + PIN_ODR_HIGH(GPIOJ_PIN6) | \ + PIN_ODR_HIGH(GPIOJ_PIN7) | \ + PIN_ODR_HIGH(GPIOJ_PIN8) | \ + PIN_ODR_HIGH(GPIOJ_PIN9) | \ + PIN_ODR_HIGH(GPIOJ_PIN10) | \ + PIN_ODR_HIGH(GPIOJ_PIN11) | \ + PIN_ODR_HIGH(GPIOJ_AUDIO_INT) | \ + PIN_ODR_LOW(GPIOJ_LED1_RED) | \ + PIN_ODR_HIGH(GPIOJ_WIFI_RST) | \ + PIN_ODR_HIGH(GPIOJ_DSI_RESET)) +#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_ARD_D4, 0U) | \ + PIN_AFIO_AF(GPIOJ_ARD_D2, 0U) | \ + PIN_AFIO_AF(GPIOJ_DSI_TE, 13U) | \ + PIN_AFIO_AF(GPIOJ_ARD_D7, 0U) | \ + PIN_AFIO_AF(GPIOJ_ARD_D8, 0U) | \ + PIN_AFIO_AF(GPIOJ_LED2_GREEN, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN7, 0U)) +#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOJ_AUDIO_INT, 0U) | \ + PIN_AFIO_AF(GPIOJ_LED1_RED, 0U) | \ + PIN_AFIO_AF(GPIOJ_WIFI_RST, 0U) | \ + PIN_AFIO_AF(GPIOJ_DSI_RESET, 0U)) + +/* + * GPIOK setup: + * + * PK0 - PIN0 (input floating). + * PK1 - PIN1 (input floating). + * PK2 - PIN2 (input floating). + * PK3 - PIN3 (input floating). + * PK4 - PIN4 (input floating). + * PK5 - PIN5 (input floating). + * PK6 - PIN6 (input floating). + * PK7 - PIN7 (input floating). + * PK8 - PIN8 (input floating). + * PK9 - PIN9 (input floating). + * PK10 - PIN10 (input floating). + * PK11 - PIN11 (input floating). + * PK12 - PIN12 (input floating). + * PK13 - PIN13 (input floating). + * PK14 - PIN14 (input floating). + * PK15 - PIN15 (input floating). + */ +#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \ + PIN_MODE_INPUT(GPIOK_PIN1) | \ + PIN_MODE_INPUT(GPIOK_PIN2) | \ + PIN_MODE_INPUT(GPIOK_PIN3) | \ + PIN_MODE_INPUT(GPIOK_PIN4) | \ + PIN_MODE_INPUT(GPIOK_PIN5) | \ + PIN_MODE_INPUT(GPIOK_PIN6) | \ + PIN_MODE_INPUT(GPIOK_PIN7) | \ + PIN_MODE_INPUT(GPIOK_PIN8) | \ + PIN_MODE_INPUT(GPIOK_PIN9) | \ + PIN_MODE_INPUT(GPIOK_PIN10) | \ + PIN_MODE_INPUT(GPIOK_PIN11) | \ + PIN_MODE_INPUT(GPIOK_PIN12) | \ + PIN_MODE_INPUT(GPIOK_PIN13) | \ + PIN_MODE_INPUT(GPIOK_PIN14) | \ + PIN_MODE_INPUT(GPIOK_PIN15)) +#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN15)) +#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOK_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN15)) +#define VAL_GPIOK_PUPDR (PIN_PUPDR_FLOATING(GPIOK_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN3) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN7) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN8) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN9) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOK_PIN15)) +#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \ + PIN_ODR_HIGH(GPIOK_PIN1) | \ + PIN_ODR_HIGH(GPIOK_PIN2) | \ + PIN_ODR_HIGH(GPIOK_PIN3) | \ + PIN_ODR_HIGH(GPIOK_PIN4) | \ + PIN_ODR_HIGH(GPIOK_PIN5) | \ + PIN_ODR_HIGH(GPIOK_PIN6) | \ + PIN_ODR_HIGH(GPIOK_PIN7) | \ + PIN_ODR_HIGH(GPIOK_PIN8) | \ + PIN_ODR_HIGH(GPIOK_PIN9) | \ + PIN_ODR_HIGH(GPIOK_PIN10) | \ + PIN_ODR_HIGH(GPIOK_PIN11) | \ + PIN_ODR_HIGH(GPIOK_PIN12) | \ + PIN_ODR_HIGH(GPIOK_PIN13) | \ + PIN_ODR_HIGH(GPIOK_PIN14) | \ + PIN_ODR_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN7, 0U)) +#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN15, 0U)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/CMakeLists.txt new file mode 100644 index 00000000..7c21ff9b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigurationManager.cpp") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") + +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..3695ffd0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 32kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 08000000 nanoBooter + + /////////////////////////////////////////////////////////////////////////////////////// + // because this target is using a configuration block need to add the + // configuration manager files to the CMake and call ConfigurationManager_Initialize() + // in nanoBooter so the configuration can be managed when in booter mode + /////////////////////////////////////////////////////////////////////////////////////// + { BlockRange_BLOCKTYPE_CONFIG , 1, 1 }, // 08008000 configuration block + /////////////////////////////////////////////////////////////////////////////////////// + + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 08020000 nanoCLR +}; + +// 256kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 1 }, // 08040000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 2, 6 } // 080C0000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x8000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 1, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08040000, // start address for block region + 7, // total number of blocks in this region + 0x40000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage.c new file mode 100644 index 00000000..d5aa4657 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/Device_BlockStorage.c @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 32kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + + /////////////////////////////////////////////////////////////////////////////////////// + // because this target is using a configuration block need to add the + // configuration manager files to the CMake and call ConfigurationManager_Initialize() + // in nanoBooter so the configuration can be managed when in booter mode + /////////////////////////////////////////////////////////////////////////////////////// + { BlockRange_BLOCKTYPE_CONFIG , 1, 1 }, // 0x08008000 configuration block + /////////////////////////////////////////////////////////////////////////////////////// + + { BlockRange_BLOCKTYPE_CODE , 2, 3 } // 0x08010000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08020000 nanoCLR +}; + +// 256kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 08040000 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT, 1, 6 } // 08080000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x8000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 1, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08040000, // start address for block region + 7, // total number of blocks in this region + 0x40000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), // STM32 flash memory is XIP + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/serialcfg.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/serialcfg.h new file mode 100644 index 00000000..cbe6b254 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/serialcfg.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef SERIALCFG_H +#define SERIALCFG_H + +// define which serial driver the Wire Protocol will be using +#define SERIAL_DRIVER SD1 + +#endif /* SERIALCFG_H */ + +/** @} */ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/targetHAL_ConfigurationManager.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/targetHAL_ConfigurationManager.cpp new file mode 100644 index 00000000..178f6aa7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/common/targetHAL_ConfigurationManager.cpp @@ -0,0 +1,35 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +// Default initialisation for Network interface config blocks +// strong implementation replacing ChibiOS 'weak' one +bool InitialiseNetworkDefaultConfig(HAL_Configuration_NetworkInterface * pconfig, uint32_t configurationIndex) +{ + (void)configurationIndex; + + // make sure the config block marker is set + memcpy(pconfig->Marker, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + pconfig->InterfaceType = NetworkInterfaceType_Ethernet; + pconfig->StartupAddressMode = AddressMode_DHCP; + pconfig->AutomaticDNS = 1; + pconfig->SpecificConfigId = 0; + + // set MAC address with ST provided MAC for development boards + // 00:80:E1:01:35:D1 + pconfig->MacAddress[0] = 0x00; + pconfig->MacAddress[1] = 0x80; + pconfig->MacAddress[2] = 0xE1; + pconfig->MacAddress[3] = 0x01; + pconfig->MacAddress[4] = 0x35; + pconfig->MacAddress[5] = 0xD1; + + return true; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/ffconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/ffconf.h new file mode 100644 index 00000000..85b623af --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/ffconf.h @@ -0,0 +1,272 @@ +/* CHIBIOS FIX */ +#include "ch.h" + +/*---------------------------------------------------------------------------/ +/ FatFs - Configuration file +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 87030 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: All basic functions are enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_STRFUNC 1 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 1 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 0 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 1 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 850 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 3 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added +/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255. +/ It should be set 255 to support full featured LFN operations. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree(), must be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16, +/ when LFN is enabled. Also behavior of string I/O functions will be affected by +/ this option. When LFN is not enabled, this option has no effect. +*/ + + +#define FF_STRF_ENCODE 3 +/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(), +/ f_putc(), f_puts and f_printf() convert the character encoding in it. +/ This option selects assumption of character encoding ON THE FILE to be +/ read/written via those functions. +/ +/ 0: ANSI/OEM +/ 1: UTF-16LE +/ 2: UTF-16BE +/ 3: UTF-8 +*/ + + +#define FF_FS_RPATH 2 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 3 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 1 +#define FF_VOLUME_STRS "D","E","F" +/* FF_STR_VOLUME_ID switches string support for volume ID. +/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each +/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for +/ the drive ID strings are: A-Z and 0-9. */ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 0 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ When enable exFAT, also LFN needs to be enabled. +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 1 +#define FF_NORTC_MON 8 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2018 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 1 +#define FF_FS_TIMEOUT TIME_MS2I(1000) +#define FF_SYNC_t semaphore_t* +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +/* #include // O/S definitions */ + + + +/*--- End of configuration options ---*/ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/lwipopts.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/lwipopts.h new file mode 100644 index 00000000..e3e393c3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/lwipopts.h @@ -0,0 +1,2167 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science, All Rights Reserved +// See LICENSE file in the project root for full license information. +// +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIPOPT_H__ +#define __LWIPOPT_H__ + + +#define _REENT_ONLY +#define set_errno(err) +#include +#include +#include + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 1 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +// empty on purpose +#define LWIP_TCPIP_THREAD_ALIVE() + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 1 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 1 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 4 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE (16 * 1024) +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#define LWIP_IPV6 0 + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 +#endif + +#define LWIP_RAND rand + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 1 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +#define LWIP_DHCP_CHECK_LINK_UP 1 + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 1 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 1480 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 1 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 1 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 1 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 1 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 1024 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE MEMP_NUM_PBUF +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 1024 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 1024 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 1024 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO (NORMALPRIO) +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 4 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 4 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 40 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 4 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 1 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 +#endif + +/** + * LWIP_SO_LINGER==1: Enable linger option for sockets/netconns + */ +#define LWIP_SO_LINGER 1 + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 1 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 1 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 1 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 0 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +// in order to enable the lwIP debug output the below has to be uncomment and +// the options above changed to LWIP_DBG_ON for the features that are to output debug information +//#define LWIP_DEBUG 1 + +// enable full duplex comms on multiple threads +// this requires adding an extra field in ChibiOS thread_t (see comment on platform_sys_arch.c) +//#define LWIP_NETCONN_FULLDUPLEX 1 + +#endif /* __LWIPOPT_H__ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/README.md new file mode 100644 index 00000000..ac46ddc7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](STM32F769I_DISCOVERY.Adc.cs) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/STM32F769I_DISCOVERY.Adc.cs b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/STM32F769I_DISCOVERY.Adc.cs new file mode 100644 index 00000000..b78ba6eb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/STM32F769I_DISCOVERY.Adc.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.STM32F769I_DISCOVERY +{ + /// + /// Enumeration of ADC channels available in STM32F769I_DISCOVERY + /// + public static class AdcChannels + { + /// + /// Channel 0, exposed on A0, connected to PA6 (ADC1 - IN6) + /// + public const int Channel_0 = 0; + + /// + /// Channel 1, exposed on A1, connected to PA4 (ADC1 - IN4) + /// + public const int Channel_1 = 1; + + /// + /// Channel 2, exposed on A2, connected to PC2 (ADC1 - IN12) + /// + public const int Channel_2 = 2; + + /// + /// Channel 3, exposed on A3, connected to PF10 (ADC1 - IN8) + /// + public const int Channel_3 = 3; + + /// + /// Channel 4, exposed on A4, connected to PF8 (ADC3 - IN6) + /// + public const int Channel_4 = 4; + + /// + /// Channel 5, internal temperature sensor, connected to ADC1 + /// + public const int Channel_TemperatureSensor = 5; + + /// + /// Channel 6, internal voltage reference, connected to ADC1 + /// + public const int Channel_VrefIn = 6; + + /// + /// Channel 7, connected to VBatt pin, ADC1 + /// + public const int Channel_Vbatt = 7; + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/package.nuspec b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/package.nuspec new file mode 100644 index 00000000..58e7f992 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/managed_helpers/package.nuspec @@ -0,0 +1,28 @@ + + + + nanoFramework.Targets.ST_STM32F769I_DISCOVERY + nanoFramework.Targets.ST_STM32F769I_DISCOVERY + 1.0.0 + nanoFramework project contributors + nanoFramework project contributors + false + + Helper classes to use ST_STM32F769I_DISCOVERY target in C# applications. + + + + + This is an extension for .NET nanoFramework enhacing support for Windows.Devices.Gpio.GpioController when using STM32 MCUs. + + https://github.com/nanoframework + https://secure.gravatar.com/avatar/97d0e092247f0716db6d4b47b7d1d1ad + https://github.com/nanoframework/nf-interpreter/blob/develop/LICENSE.md + Copyright (c) 2019 The nanoFramework project contributors + + nanoFramework, nano Framework, NETNF, NETMF, Micro Framework, STM32, .net, STM32F769I + + + + + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/mbedtls_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/mbedtls_config.h new file mode 100644 index 00000000..344adf5b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/mbedtls_config.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// See LICENSE file in the project root for full license information. +// + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* For test certificates */ +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_PEM_PARSE_C + +// #define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +// #define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +// #define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +// #define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +// #define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +// #define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET + +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +// #define MBEDTLS_VERSION_FEATURES +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_ERROR_C +// #define MBEDTLS_VERSION_C + +// uncomment the defines below to enable static memory allocation feature +#if 0 +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_MEMORY +#endif + +#ifdef USE_LCD +#include "lcd_log.h" +#define MBEDTLS_PLATFORM_PRINTF_MACRO LCD_UsrLog +#endif + +// uncomment the defines bellow to generate debug output +// set below the threshold level for debug messages +// check mbed TLS mbedtls/debug.h header for details. +// Debug levels: +// 0 No debug +// 1 Error +// 2 State change +// 3 Informational +// 4 Verbose + +// #define MBEDTLS_DEBUG_C +// #define MBEDTLS_SSL_DEBUG_ALL +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +// #define MBEDTLS_DEBUG_THRESHOLD 2 + +#endif // MBEDTLS_CONFIG_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..f0e921f7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# # append nanoBooter source files +list(APPEND NANOBOOTER_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") + +# make var global +set(NANOBOOTER_PROJECT_SOURCES ${NANOBOOTER_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter-DEBUG.ld new file mode 100644 index 00000000..0637fbd7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter-DEBUG.ld @@ -0,0 +1,122 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F76xx generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08008000)*/ + flash_itcm : org = 0x00200000, len = 32k + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20020000, len = 384k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20020000, len = 368k /* SRAM1 */ + ram2 : org = 0x2007C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 128k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter.ld new file mode 100644 index 00000000..0637fbd7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/STM32F76xx_booter.ld @@ -0,0 +1,122 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F76xx generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08000000, len = 32k /* space reserved for nanoBooter (1st sector 0x08000000 to 0x08008000)*/ + flash_itcm : org = 0x00200000, len = 32k + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x00000000, len = 0 /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20020000, len = 384k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20020000, len = 368k /* SRAM1 */ + ram2 : org = 0x2007C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 128k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/chconf.h new file mode 100644 index 00000000..0bd93fbe --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/chconf.h @@ -0,0 +1,606 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#define CH_CFG_INTERVALS_SIZE 32 + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_TIME_TYPES_SIZE 32 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM FALSE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS FALSE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES FALSE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_OBJ_FIFOS TRUE + +#define CH_CFG_USE_PIPES TRUE + + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_FACTORY FALSE + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 + +/** + * @brief Enables the registry of generic objects. + */ +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE + +/** + * @brief Enables factory for generic buffers. + */ +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE + +/** + * @brief Enables factory for semaphores. + */ +#define CH_CFG_FACTORY_SEMAPHORES TRUE + +/** + * @brief Enables factory for mailboxes. + */ +#define CH_CFG_FACTORY_MAILBOXES TRUE + +/** + * @brief Enables factory for objects FIFOs. + */ +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE + +/** + * @brief Enables factory for Pipes. + */ +#define CH_CFG_FACTORY_PIPES TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf.h new file mode 100644 index 00000000..fb74d8ed --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf.h @@ -0,0 +1,518 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + + +// header for nanoFramework overlay +#include "halconf_nf.h" +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf_nf.h new file mode 100644 index 00000000..809a6cfa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/halconf_nf.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +#endif // _HALCONF_NF_H_ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/main.c new file mode 100644 index 00000000..6c7fd212 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/main.c @@ -0,0 +1,86 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + osDelay(20); // Let init stabilize + + // the following IF is not mandatory, it's just providing a way for a user to 'force' + // the board to remain in nanoBooter and not launching nanoCLR + + // if the USER button (blue one) is pressed, skip the check for a valid CLR image and remain in booter + // the user button in this board has a pull-up resistor so the check has to be inverted + if (!palReadLine(LINE_BUTTON_USER)) + { + // check for valid CLR image + // we are checking for a valid image right after the configuration block + if(CheckValidCLRImage((uint32_t)&__nanoConfig_end__)) + { + // there seems to be a valid CLR image + // launch nanoCLR + LaunchCLR((uint32_t)&__nanoConfig_end__); + } + } + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + // initialize block storage list and devices + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it in order to provide the flash map for Monitor_FlashSectorMap command + BlockStorageList_Initialize(); + BlockStorage_AddDevices(); + + // initialize configuration manager + // in CLR this is called in nanoHAL_Initialize() + // for nanoBooter we have to init it here to have access to network configuration blocks + ConfigurationManager_Initialize(); + + // Normal main() thread + while (true) { + palSetLine(LINE_LED2_GREEN); + osDelay(500); + palClearLine(LINE_LED2_GREEN); + osDelay(500); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf.h new file mode 100644 index 00000000..be56ce44 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf.h @@ -0,0 +1,395 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F7xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F7xx_MCUCONF +//#define STM32F765_MCUCONF +//#define STM32F767_MCUCONF +//#define STM32F777_MCUCONF +#define STM32F769_MCUCONF +//#define STM32F779_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED FALSE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 25 +#define STM32_PLLN_VALUE 432 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 9 +#define STM32_PLLR_VALUE 4 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 25 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV4 +#define STM32_I2SSRC STM32_I2SSRC_OFF +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SP_VALUE 4 +#define STM32_PLLI2SQ_VALUE 4 +#define STM32_PLLI2SR_VALUE 4 +#define STM32_PLLI2SDIVQ_VALUE 2 +#define STM32_PLLSAIN_VALUE 192 +#define STM32_PLLSAIP_VALUE 4 +#define STM32_PLLSAIQ_VALUE 4 +#define STM32_PLLSAIR_VALUE 4 +#define STM32_PLLSAIDIVQ_VALUE 2 +#define STM32_PLLSAIDIVR_VALUE 2 +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#define STM32_LCDTFT_REQUIRED FALSE +#define STM32_USART1SEL STM32_USART1SEL_PCLK2 +#define STM32_USART2SEL STM32_USART2SEL_PCLK1 +#define STM32_USART3SEL STM32_USART3SEL_PCLK1 +#define STM32_UART4SEL STM32_UART4SEL_PCLK1 +#define STM32_UART5SEL STM32_UART5SEL_PCLK1 +#define STM32_USART6SEL STM32_USART6SEL_PCLK2 +#define STM32_UART7SEL STM32_UART7SEL_PCLK1 +#define STM32_UART8SEL STM32_UART8SEL_PCLK1 +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_CECSEL STM32_CECSEL_LSE +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#define STM32_SDMMCSEL STM32_SDMMCSEL_PLL48CLK +#define STM32_SRAM2_NOCACHE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_USE_CAN3 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 +#define STM32_CAN_CAN3_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_USE_I2C4 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C4_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_I2C4_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_USE_SDMMC1 FALSE +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#define STM32_SDC_SDMMC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 +#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 TRUE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_USE_SPI5 FALSE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USE_UART7 FALSE +#define STM32_UART_USE_UART8 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_UART7_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART7_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_UART8_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_UART8_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_UART7_IRQ_PRIORITY 12 +#define STM32_UART_UART8_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_UART7_DMA_PRIORITY 0 +#define STM32_UART_UART8_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +/* + * WSPI driver system settings. + */ +#define STM32_WSPI_USE_QUADSPI1 FALSE +#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) + +#endif /* MCUCONF_H */ \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf_nf.h new file mode 100644 index 00000000..5ff03534 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/mcuconf_nf.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/target_board.h.in new file mode 100644 index 00000000..19531d9c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoBooter/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOBOOTER_H_ +#define _TARGET_BOARD_NANOBOOTER_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoBooter running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOBOOTER_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..e5496b7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR-DEBUG.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR-DEBUG.ld new file mode 100644 index 00000000..63725eeb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR-DEBUG.ld @@ -0,0 +1,128 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F76xxI generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08010000, len = 2M - 32k - 32k - 1280k /* flash size less the space reserved for nanoBooter, configuration block and application deployment*/ + flash_itcm : org = 0x00210000, len = 2M - 32k - 32k - 1280k + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x080C0000, len = 1280k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20020000, len = 384k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20020000, len = 368k /* SRAM1 */ + ram2 : org = 0x2007C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 128k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 + ext_ram : org = 0xC0000000, len = 16M /* external SDRAM */ +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ext_ram); + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld new file mode 100644 index 00000000..3bc7ae37 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/STM32F76xx_CLR.ld @@ -0,0 +1,128 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* + * STM32F76xxI generic setup. + * + * RAM0 - Data, Heap. + * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH. + * + * Notes: + * BSS is placed in DTCM RAM in order to simplify DMA buffers management. + */ +MEMORY +{ + flash : org = 0x08010000, len = 2M - 32k - 32k - 1536k /* flash size less the space reserved for nanoBooter, configuration block and application deployment*/ + flash_itcm : org = 0x00210000, len = 2M - 32k - 32k - 1536k + config : org = 0x08008000, len = 32k /* space reserved for configuration block */ + deployment : org = 0x08080000, len = 1536k /* space reserved for application deployment */ + ramvt : org = 0x00000000, len = 0 /* initial RAM address is reserved for a copy of the vector table */ + ram0 : org = 0x20020000, len = 384k /* SRAM1 + SRAM2 */ + ram1 : org = 0x20020000, len = 368k /* SRAM1 */ + ram2 : org = 0x2007C000, len = 16k /* SRAM2 */ + ram3 : org = 0x20000000, len = 128k /* DTCM-RAM */ + ram4 : org = 0x00000000, len = 16k /* ITCM-RAM */ + ram5 : org = 0x40024000, len = 4k /* BCKP SRAM */ + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 + ext_ram : org = 0xC0000000, len = 16M /* external SDRAM */ +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash_itcm); +REGION_ALIAS("VECTORS_FLASH_LMA", flash); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash_itcm); +REGION_ALIAS("XTORS_FLASH_LMA", flash); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash_itcm); +REGION_ALIAS("TEXT_FLASH_LMA", flash); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash); +REGION_ALIAS("RODATA_FLASH_LMA", flash); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash_itcm); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram3); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram3); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram3); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", ext_ram); + +/* rules inclusion.*/ +INCLUDE rules_stacks.ld + +/*===========================================================================*/ +/* Custom sections for STM32F7xx. */ +/*===========================================================================*/ + +/* RAM region to be used for nocache segment.*/ +REGION_ALIAS("NOCACHE_RAM", ram3); + +/* RAM region to be used for eth segment.*/ +REGION_ALIAS("ETH_RAM", ram3); + +SECTIONS +{ + /* Special section for non cache-able areas.*/ + .nocache (NOLOAD) : ALIGN(4) + { + __nocache_base__ = .; + *(.nocache) + *(.nocache.*) + *(.bss.__nocache_*) + . = ALIGN(4); + __nocache_end__ = .; + } > NOCACHE_RAM + + /* Special section for Ethernet DMA non cache-able areas.*/ + .eth (NOLOAD) : ALIGN(4) + { + __eth_base__ = .; + *(.eth) + *(.eth.*) + *(.bss.__eth_*) + . = ALIGN(4); + __eth_end__ = .; + } > ETH_RAM +} + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/chconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/chconf.h new file mode 100644 index 00000000..214cbcd6 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/chconf.h @@ -0,0 +1,705 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_0_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 10000 +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM FALSE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES TRUE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS TRUE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES TRUE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP TRUE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS TRUE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS TRUE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + // this field is required in case lwIP options has LWIP_NETCONN_SEM_PER_THREAD + // void* localStorage; + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf.h new file mode 100644 index 00000000..32abfdc5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf.h @@ -0,0 +1,535 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_0_ + +#include +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +#if !defined(FATFS_HAL_DEVICE) || defined(__DOXYGEN__) +//this board requires SDCD2 not SDCD1 +#define FATFS_HAL_DEVICE SDCD2 +#endif + +//#define STM32_SDC_SDMMC_50MHZ TRUE + +/** + * @brief Enables the ADC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +// #define HAL_USE_ADC FALSE +// #endif + +/** + * @brief Enables the CAN subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +// #define HAL_USE_CAN FALSE +// #endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +// /** +// * @brief Enables the DAC subsystem. +// */ +// #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +// #define HAL_USE_DAC FALSE +// #endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +// this option is set at target_platform.h (from config file) +//#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +//#define HAL_USE_I2C TRUE +//#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +// #define HAL_USE_MAC TRUE +// #endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +// #define HAL_USE_PWM FALSE +// #endif + +/** + * @brief Enables the RTC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +// #define HAL_USE_RTC TRUE +// #endif + +/** + * @brief Enables the SDC subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +// #define HAL_USE_SDC TRUE +// #endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +// #define HAL_USE_SPI FALSE +// #endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +// #define HAL_USE_UART FALSE +// #endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +// this option is set at target_platform.h (from config file) +// #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +// #define HAL_USE_WDG FALSE +// #endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS TRUE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 921600 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 64 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 64 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 1 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +// header for nanoFramework overlay +#include "halconf_nf.h" +#endif /* HALCONF_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf_nf.h new file mode 100644 index 00000000..c2edaf78 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/halconf_nf.h @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _HALCONF_NF_H_ +#define _HALCONF_NF_H_ 1 + +// enables STM32 Flash driver +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH TRUE +#endif + +// Enables the FSMC subsystem. +#if !defined(HAL_USE_FSMC) +#define HAL_USE_FSMC TRUE +#endif + +// enables STM32 Can driver +#if !defined(HAL_USE_STM32_CAN) +#define HAL_USE_STM32_CAN TRUE +#endif + +// enables STM32 QSPI driver +#if !defined(HAL_USE_STM32_QSPI) +#define HAL_USE_STM32_QSPI FALSE +#endif + +#endif // _HALCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/main.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/main.c new file mode 100644 index 00000000..b7bd381f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/main.c @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern uint8_t hal_spiffs_config(); + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); +// declare CLRStartup thread here +osThreadDef(CLRStartupThread, osPriorityNormal, 4096, "CLRStartupThread"); + +#if HAL_USE_SDC +// declare SD Card working thread here +osThreadDef(SdCardWorkingThread, osPriorityNormal, 1024, "SDCWT"); +#endif +#if HAL_USBH_USE_MSD +// declare USB MSD thread here +osThreadDef(UsbMsdWorkingThread, osPriorityNormal, 1024, "USBMSDWT"); +#endif + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // init SWO as soon as possible to make it available to output ASAP + #if (SWO_OUTPUT == TRUE) + SwoInit(); + #endif + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are already enabled. + osKernelInitialize(); + + // start watchdog + Watchdog_Init(); + + // config and init external memory + // this has to be called after osKernelInitialize, otherwise an hard fault will occur + Target_ExternalMemoryInit(); + + #if NF_FEATURE_USE_SPIFFS + // config and init SPIFFS + hal_spiffs_config(); + #endif + + // starts the serial driver + sdStart(&SERIAL_DRIVER, NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // create the CLR Startup thread + osThreadCreate(osThread(CLRStartupThread), &clrSettings); + + #if HAL_USE_SDC + // creates the SD card working thread + osThreadCreate(osThread(SdCardWorkingThread), NULL); + #endif + + #if HAL_USBH_USE_MSD + // create the USB MSD working thread + osThreadCreate(osThread(UsbMsdWorkingThread), &MSBLKD[0]); + #endif + + // start kernel, after this main() will behave like a thread with priority osPriorityNormal + osKernelStart(); + + while (true) { + osDelay(100); + } +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf.h new file mode 100644 index 00000000..2853d5c5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf.h @@ -0,0 +1,404 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F7xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F7xx_MCUCONF +//#define STM32F765_MCUCONF +//#define STM32F767_MCUCONF +//#define STM32F777_MCUCONF +#define STM32F769_MCUCONF +//#define STM32F779_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED TRUE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 25 +#define STM32_PLLN_VALUE 384 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 8 +#define STM32_PLLR_VALUE 2 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTCPRE_VALUE 25 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_OFF +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SP_VALUE 2 +#define STM32_PLLI2SQ_VALUE 2 +#define STM32_PLLI2SR_VALUE 2 +#define STM32_PLLI2SDIVQ_VALUE 1 +#define STM32_PLLSAIN_VALUE 192 +#define STM32_PLLSAIP_VALUE 4 +#define STM32_PLLSAIQ_VALUE 3 +#define STM32_PLLSAIR_VALUE 2 +#define STM32_PLLSAIDIVQ_VALUE 1 +#define STM32_PLLSAIDIVR_VALUE 2 +#define STM32_SAI1SEL STM32_SAI1SEL_SAIPLL +#define STM32_SAI2SEL STM32_SAI2SEL_SAIPLL +#define STM32_LCDTFT_REQUIRED FALSE +#define STM32_USART1SEL STM32_USART1SEL_PCLK2 +#define STM32_USART2SEL STM32_USART2SEL_PCLK1 +#define STM32_USART3SEL STM32_USART3SEL_PCLK1 +#define STM32_UART4SEL STM32_UART4SEL_PCLK1 +#define STM32_UART5SEL STM32_UART5SEL_PCLK1 +#define STM32_USART6SEL STM32_USART6SEL_PCLK2 +#define STM32_UART7SEL STM32_UART7SEL_PCLK1 +#define STM32_UART8SEL STM32_UART8SEL_PCLK1 +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_CECSEL STM32_CECSEL_LSE +#define STM32_CK48MSEL STM32_CK48MSEL_PLL +#define STM32_SDMMC1SEL STM32_SDMMC1SEL_PLL48CLK +#define STM32_SDMMC2SEL STM32_SDMMC2SEL_PLL48CLK +#define STM32_SRAM2_NOCACHE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 TRUE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 TRUE +#define STM32_CAN_USE_CAN2 TRUE +#define STM32_CAN_USE_CAN3 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 +#define STM32_CAN_CAN3_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_USE_I2C4 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C4_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_I2C4_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED TRUE +#define STM32_PWM_USE_TIM1 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 TRUE +#define STM32_PWM_USE_TIM8 TRUE +#define STM32_PWM_USE_TIM9 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_USE_SDMMC1 FALSE +#define STM32_SDC_USE_SDMMC2 TRUE +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#define STM32_SDC_SDMMC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SDC_SDMMC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 +#define STM32_SDC_SDMMC2_DMA_PRIORITY 3 +#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 +#define STM32_SDC_SDMMC2_IRQ_PRIORITY 9 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 TRUE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_USE_SPI5 FALSE +#define STM32_SPI_USE_SPI6 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 TRUE +#define STM32_UART_USE_USART3 TRUE +#define STM32_UART_USE_UART4 TRUE +#define STM32_UART_USE_UART5 TRUE +#define STM32_UART_USE_USART6 TRUE +#define STM32_UART_USE_UART7 TRUE +#define STM32_UART_USE_UART8 TRUE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_UART7_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART7_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_UART8_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_UART8_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_UART7_IRQ_PRIORITY 12 +#define STM32_UART_UART8_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_UART7_DMA_PRIORITY 0 +#define STM32_UART_UART8_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG TRUE + +/* + * WSPI driver system settings. + */ +#define STM32_WSPI_USE_QUADSPI1 FALSE +#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 2 + +// header for nanoFramework overlay drivers +#include "mcuconf_nf.h" + +#endif /* MCUCONF_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf_nf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf_nf.h new file mode 100644 index 00000000..bf6b31e3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/mcuconf_nf.h @@ -0,0 +1,22 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _MCUCONF_NF_H_ +#define _MCUCONF_NF_H_ +/* + * FSMC driver system settings. + */ +#define STM32_FSMC_USE_FSMC1 TRUE +#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10 +#define STM32_FSMC_DMA_CHN 0x03010201 + +/* + * FSMC SDRAM driver system settings. + */ +#define STM32_USE_FSMC_SDRAM TRUE +#define STM32_SDRAM_USE_FSMC_SDRAM1 TRUE +#define STM32_SDRAM_USE_FSMC_SDRAM2 FALSE + +#endif // _MCUCONF_NF_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/target_board.h.in new file mode 100644 index 00000000..b980bc05 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/nanoCLR/target_board.h.in @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include +#include + +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @CHIBIOS_BOARD@ built with ChibiOS v" CH_VERSION "." STR(CH_VERSION_MONTH) + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/spiffs_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/spiffs_config.h new file mode 100644 index 00000000..f0fba80b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/spiffs_config.h @@ -0,0 +1,378 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2013, petera, All Rights Reserved +// See LICENSE file in the project root for full license information. +// + + +///////////////////////////////////////////////////////////////////////////// +// the configurations below are tunned for the MX25L51245G (from MACRONIX) +// that's fitted in the STM32F769I-DISCO board +///////////////////////////////////////////////////////////////////////////// + +#ifndef SPIFFS_CONFIG_H_ +#define SPIFFS_CONFIG_H_ + +#include +#include +#include +#include +#include + +///////////////////////////////////// +// need to map these types +typedef int32_t s32_t; +typedef uint32_t u32_t; +typedef int16_t s16_t; +typedef uint16_t u16_t; +typedef int8_t s8_t; +typedef uint8_t u8_t; + +// compile time switches + +// Set generic spiffs debug output call. +#ifndef SPIFFS_DBG +#define SPIFFS_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for garbage collecting. +#ifndef SPIFFS_GC_DBG +#define SPIFFS_GC_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for caching. +#ifndef SPIFFS_CACHE_DBG +#define SPIFFS_CACHE_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for system consistency checks. +#ifndef SPIFFS_CHECK_DBG +#define SPIFFS_CHECK_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for all api invocations. +#ifndef SPIFFS_API_DBG +#define SPIFFS_API_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) +#endif + + + +// Defines spiffs debug print formatters +// some general signed number +#ifndef _SPIPRIi +#define _SPIPRIi "%d" +#endif +// address +#ifndef _SPIPRIad +#define _SPIPRIad "%08x" +#endif +// block +#ifndef _SPIPRIbl +#define _SPIPRIbl "%04x" +#endif +// page +#ifndef _SPIPRIpg +#define _SPIPRIpg "%04x" +#endif +// span index +#ifndef _SPIPRIsp +#define _SPIPRIsp "%04x" +#endif +// file descriptor +#ifndef _SPIPRIfd +#define _SPIPRIfd "%d" +#endif +// file object id +#ifndef _SPIPRIid +#define _SPIPRIid "%04x" +#endif +// file flags +#ifndef _SPIPRIfl +#define _SPIPRIfl "%02x" +#endif + + +// Enable/disable API functions to determine exact number of bytes +// for filedescriptor and cache buffers. Once decided for a configuration, +// this can be disabled to reduce flash. +#ifndef SPIFFS_BUFFER_HELP +#define SPIFFS_BUFFER_HELP 0 +#endif + +// Enables/disable memory read caching of nucleus file system operations. +// If enabled, memory area must be provided for cache in SPIFFS_mount. +#ifndef SPIFFS_CACHE +#define SPIFFS_CACHE 1 +#endif +#if SPIFFS_CACHE +// Enables memory write caching for file descriptors in hydrogen +#ifndef SPIFFS_CACHE_WR +#define SPIFFS_CACHE_WR 1 +#endif + +// Enable/disable statistics on caching. Debug/test purpose only. +#ifndef SPIFFS_CACHE_STATS +#define SPIFFS_CACHE_STATS 1 +#endif +#endif + +// Always check header of each accessed page to ensure consistent state. +// If enabled it will increase number of reads, will increase flash. +#ifndef SPIFFS_PAGE_CHECK +#define SPIFFS_PAGE_CHECK 1 +#endif + +// Define maximum number of gc runs to perform to reach desired free pages. +#ifndef SPIFFS_GC_MAX_RUNS +#define SPIFFS_GC_MAX_RUNS 5 +#endif + +// Enable/disable statistics on gc. Debug/test purpose only. +#ifndef SPIFFS_GC_STATS +#define SPIFFS_GC_STATS 1 +#endif + +// Garbage collecting examines all pages in a block which and sums up +// to a block score. Deleted pages normally gives positive score and +// used pages normally gives a negative score (as these must be moved). +// To have a fair wear-leveling, the erase age is also included in score, +// whose factor normally is the most positive. +// The larger the score, the more likely it is that the block will +// picked for garbage collection. + +// Garbage collecting heuristics - weight used for deleted pages. +#ifndef SPIFFS_GC_HEUR_W_DELET +#define SPIFFS_GC_HEUR_W_DELET (5) +#endif +// Garbage collecting heuristics - weight used for used pages. +#ifndef SPIFFS_GC_HEUR_W_USED +#define SPIFFS_GC_HEUR_W_USED (-1) +#endif +// Garbage collecting heuristics - weight used for time between +// last erased and erase of this block. +#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE +#define SPIFFS_GC_HEUR_W_ERASE_AGE (50) +#endif + +// Object name maximum length. Note that this length include the +// zero-termination character, meaning maximum string of characters +// can at most be SPIFFS_OBJ_NAME_LEN - 1. +#ifndef SPIFFS_OBJ_NAME_LEN +#define SPIFFS_OBJ_NAME_LEN (256) +#endif + +// Maximum length of the metadata associated with an object. +// Setting to non-zero value enables metadata-related API but also +// changes the on-disk format, so the change is not backward-compatible. +// +// Do note: the meta length must never exceed +// logical_page_size - (SPIFFS_OBJ_NAME_LEN + 64) +// +// This is derived from following: +// logical_page_size - (SPIFFS_OBJ_NAME_LEN + sizeof(spiffs_page_header) + +// spiffs_object_ix_header fields + at least some LUT entries) +#ifndef SPIFFS_OBJ_META_LEN +#define SPIFFS_OBJ_META_LEN (0) +#endif + +// Size of buffer allocated on stack used when copying data. +// Lower value generates more read/writes. No meaning having it bigger +// than logical page size. +#ifndef SPIFFS_COPY_BUFFER_STACK +#define SPIFFS_COPY_BUFFER_STACK (64) +#endif + +// Enable this to have an identifiable spiffs filesystem. This will look for +// a magic in all sectors to determine if this is a valid spiffs system or +// not on mount point. If not, SPIFFS_format must be called prior to mounting +// again. +#ifndef SPIFFS_USE_MAGIC +#define SPIFFS_USE_MAGIC (0) +#endif + +#if SPIFFS_USE_MAGIC +// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is +// enabled, the magic will also be dependent on the length of the filesystem. +// For example, a filesystem configured and formatted for 4 megabytes will not +// be accepted for mounting with a configuration defining the filesystem as 2 +// megabytes. +#ifndef SPIFFS_USE_MAGIC_LENGTH +#define SPIFFS_USE_MAGIC_LENGTH (0) +#endif +#endif + +// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level +// These should be defined on a multithreaded system + +// define this to enter a mutex if you're running on a multithreaded system +#ifndef SPIFFS_LOCK +extern void hal_spiffs_lock(); +#define SPIFFS_LOCK(fs) hal_spiffs_lock(); +#endif +// define this to exit a mutex if you're running on a multithreaded system +#ifndef SPIFFS_UNLOCK +extern void hal_spiffs_unlock(); +#define SPIFFS_UNLOCK(fs) hal_spiffs_unlock(); +#endif + +// Enable if only one spiffs instance with constant configuration will exist +// on the target. This will reduce calculations, flash and memory accesses. +// Parts of configuration must be defined below instead of at time of mount. +#ifndef SPIFFS_SINGLETON +#define SPIFFS_SINGLETON 0 +#endif + +#if SPIFFS_SINGLETON +// Instead of giving parameters in config struct, singleton build must +// give parameters in defines below. +#ifndef SPIFFS_CFG_PHYS_SZ +#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2) +#endif +#ifndef SPIFFS_CFG_PHYS_ERASE_SZ +#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536) +#endif +#ifndef SPIFFS_CFG_PHYS_ADDR +#define SPIFFS_CFG_PHYS_ADDR(ignore) (0) +#endif +#ifndef SPIFFS_CFG_LOG_PAGE_SZ +#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256) +#endif +#ifndef SPIFFS_CFG_LOG_BLOCK_SZ +#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536) +#endif +#endif + +// Enable this if your target needs aligned data for index tables +#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES +#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 0 +#endif + +// Enable this if you want the HAL callbacks to be called with the spiffs struct +#ifndef SPIFFS_HAL_CALLBACK_EXTRA +#define SPIFFS_HAL_CALLBACK_EXTRA 0 +#endif + +// Enable this if you want to add an integer offset to all file handles +// (spiffs_file). This is useful if running multiple instances of spiffs on +// same target, in order to recognise to what spiffs instance a file handle +// belongs. +// NB: This adds config field fh_ix_offset in the configuration struct when +// mounting, which must be defined. +#ifndef SPIFFS_FILEHDL_OFFSET +#define SPIFFS_FILEHDL_OFFSET 0 +#endif + +// Enable this to compile a read only version of spiffs. +// This will reduce binary size of spiffs. All code comprising modification +// of the file system will not be compiled. Some config will be ignored. +// HAL functions for erasing and writing to spi-flash may be null. Cache +// can be disabled for even further binary size reduction (and ram savings). +// Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL. +// If the file system cannot be mounted due to aborted erase operation and +// SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be +// returned. +// Might be useful for e.g. bootloaders and such. +#ifndef SPIFFS_READ_ONLY +#define SPIFFS_READ_ONLY 0 +#endif + +// Enable this to add a temporal file cache using the fd buffer. +// The effects of the cache is that SPIFFS_open will find the file faster in +// certain cases. It will make it a lot easier for spiffs to find files +// opened frequently, reducing number of readings from the spi flash for +// finding those files. +// This will grow each fd by 6 bytes. If your files are opened in patterns +// with a degree of temporal locality, the system is optimized. +// Examples can be letting spiffs serve web content, where one file is the css. +// The css is accessed for each html file that is opened, meaning it is +// accessed almost every second time a file is opened. Another example could be +// a log file that is often opened, written, and closed. +// The size of the cache is number of given file descriptors, as it piggybacks +// on the fd update mechanism. The cache lives in the closed file descriptors. +// When closed, the fd know the whereabouts of the file. Instead of forgetting +// this, the temporal cache will keep handling updates to that file even if the +// fd is closed. If the file is opened again, the location of the file is found +// directly. If all available descriptors become opened, all cache memory is +// lost. +#ifndef SPIFFS_TEMPORAL_FD_CACHE +#define SPIFFS_TEMPORAL_FD_CACHE 1 +#endif + +// Temporal file cache hit score. Each time a file is opened, all cached files +// will lose one point. If the opened file is found in cache, that entry will +// gain SPIFFS_TEMPORAL_CACHE_HIT_SCORE points. One can experiment with this +// value for the specific access patterns of the application. However, it must +// be between 1 (no gain for hitting a cached entry often) and 255. +#ifndef SPIFFS_TEMPORAL_CACHE_HIT_SCORE +#define SPIFFS_TEMPORAL_CACHE_HIT_SCORE 4 +#endif + +// Enable to be able to map object indices to memory. +// This allows for faster and more deterministic reading if cases of reading +// large files and when changing file offset by seeking around a lot. +// When mapping a file's index, the file system will be scanned for index pages +// and the info will be put in memory provided by user. When reading, the +// memory map can be looked up instead of searching for index pages on the +// medium. This way, user can trade memory against performance. +// Whole, parts of, or future parts not being written yet can be mapped. The +// memory array will be owned by spiffs and updated accordingly during garbage +// collecting or when modifying the indices. The latter is invoked by when the +// file is modified in some way. The index buffer is tied to the file +// descriptor. +#ifndef SPIFFS_IX_MAP +#define SPIFFS_IX_MAP 1 +#endif + +// By default SPIFFS in some cases relies on the property of NOR flash that bits +// cannot be set from 0 to 1 by writing and that controllers will ignore such +// bit changes. This results in fewer reads as SPIFFS can in some cases perform +// blind writes, with all bits set to 1 and only those it needs reset set to 0. +// Most of the chips and controllers allow this behavior, so the default is to +// use this technique. If your controller is one of the rare ones that don't, +// turn this option on and SPIFFS will perform a read-modify-write instead. +#ifndef SPIFFS_NO_BLIND_WRITES +#define SPIFFS_NO_BLIND_WRITES 0 +#endif + +// SPIFFS_vis disabled +#define SPIFFS_TEST_VISUALISATION 0 + +#if SPIFFS_TEST_VISUALISATION +#ifndef spiffs_printf +#define spiffs_printf(...) printf(__VA_ARGS__) +#endif +// spiffs_printf argument for a free page +#ifndef SPIFFS_TEST_VIS_FREE_STR +#define SPIFFS_TEST_VIS_FREE_STR "_" +#endif +// spiffs_printf argument for a deleted page +#ifndef SPIFFS_TEST_VIS_DELE_STR +#define SPIFFS_TEST_VIS_DELE_STR "/" +#endif +// spiffs_printf argument for an index page for given object id +#ifndef SPIFFS_TEST_VIS_INDX_STR +#define SPIFFS_TEST_VIS_INDX_STR(id) "i" +#endif +// spiffs_printf argument for a data page for given object id +#ifndef SPIFFS_TEST_VIS_DATA_STR +#define SPIFFS_TEST_VIS_DATA_STR(id) "d" +#endif +#endif + +// Types depending on configuration such as the amount of flash bytes +// given to spiffs file system in total (spiffs_file_system_size), +// the logical block size (log_block_size), and the logical page size +// (log_page_size) + +// Block index type. Make sure the size of this type can hold +// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size +typedef u16_t spiffs_block_ix; +// Page index type. Make sure the size of this type can hold +// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size +typedef u16_t spiffs_page_ix; +// Object id type - most significant bit is reserved for index flag. Make sure the +// size of this type can hold the highest object id on a full system, +// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2 +typedef u16_t spiffs_obj_id; +// Object span index type. Make sure the size of this type can +// hold the largest possible span index on the system - +// i.e. (spiffs_file_system_size / log_page_size) - 1 +typedef u16_t spiffs_span_ix; + +#endif /* SPIFFS_CONFIG_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/stm32f7xx_hal_conf.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/stm32f7xx_hal_conf.h new file mode 100644 index 00000000..a6c88c05 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/stm32f7xx_hal_conf.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef __STM32F7xx_HAL_CONF_H +#define __STM32F7xx_HAL_CONF_H + +#define STM32F769xx + +#ifdef __cplusplus + extern "C" { +#endif + +#define HAL_DMA_MODULE_ENABLED +#define HAL_QSPI_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED + +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f7xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f7xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f7xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + + +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + + +#ifdef __cplusplus +} +#endif + +#endif // __STM32F7xx_HAL_CONF_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.c new file mode 100644 index 00000000..9e7c7f55 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.c new file mode 100644 index 00000000..ee602ba0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.c @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0,//ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.h.in new file mode 100644 index 00000000..ec25526b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_common.h.in @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0xC0000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x01000000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00200000) + +///////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F7" +////////////////////////////////////////////// + +///////////////////////////////////// +#define PLATFORM_HAS_RNG TRUE +///////////////////////////////////// + +///////////////////////////////////// +//#define EVENTS_HEART_BEAT palToggleLine(LINE_LED2_GREEN) +///////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c new file mode 100644 index 00000000..299fe1ef --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c @@ -0,0 +1,111 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "hal.h" +#include "fsmc_sdram_lld.h" + + +// SDRAM Mode definition register defines +#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_BURST_LENGTH_2 ((uint16_t)0x0001) +#define FMC_SDCMR_MRD_BURST_LENGTH_4 ((uint16_t)0x0002) +#define FMC_SDCMR_MRD_BURST_LENGTH_8 ((uint16_t)0x0004) +#define FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) +#define FMC_SDCMR_MRD_CAS_LATENCY_2 ((uint16_t)0x0020) +#define FMC_SDCMR_MRD_CAS_LATENCY_3 ((uint16_t)0x0030) +#define FMC_SDCMR_MRD_OPERATING_MODE_STANDARD ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +// FMC_ReadPipe_Delay +#define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000) +#define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000) +#define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000) +#define FMC_ReadPipe_Delay_Mask ((uint32_t)0x00006000) + +// FMC_Read_Burst +#define FMC_Read_Burst_Disable ((uint32_t)0x00000000) +#define FMC_Read_Burst_Enable ((uint32_t)0x00001000) +#define FMC_Read_Burst_Mask ((uint32_t)0x00001000) + +// FMC_SDClock_Period +#define FMC_SDClock_Disable ((uint32_t)0x00000000) +#define FMC_SDClock_Period_2 ((uint32_t)0x00000800) +#define FMC_SDClock_Period_3 ((uint32_t)0x00000C00) +#define FMC_SDClock_Period_Mask ((uint32_t)0x00000C00) + +// FMC_ColumnBits_Number +#define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000) +#define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001) +#define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002) +#define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003) + +// FMC_RowBits_Number +#define FMC_RowBits_Number_11b ((uint32_t)0x00000000) +#define FMC_RowBits_Number_12b ((uint32_t)0x00000004) +#define FMC_RowBits_Number_13b ((uint32_t)0x00000008) + +// FMC_SDMemory_Data_Width +#define FMC_SDMemory_Width_8b ((uint32_t)0x00000000) +#define FMC_SDMemory_Width_16b ((uint32_t)0x00000010) +#define FMC_SDMemory_Width_32b ((uint32_t)0x00000020) + +// FMC_InternalBank_Number +#define FMC_InternalBank_Number_2 ((uint32_t)0x00000000) +#define FMC_InternalBank_Number_4 ((uint32_t)0x00000040) + +// FMC_CAS_Latency +#define FMC_CAS_Latency_1 ((uint32_t)0x00000080) +#define FMC_CAS_Latency_2 ((uint32_t)0x00000100) +#define FMC_CAS_Latency_3 ((uint32_t)0x00000180) + +// FMC_Write_Protection +#define FMC_Write_Protection_Disable ((uint32_t)0x00000000) +#define FMC_Write_Protection_Enable ((uint32_t)0x00000200) + +#define SDRAM_SIZE (16 * 1024 * 1024) +#define SDRAM_START ((void *)FSMC_Bank5_MAP_BASE) + + +// SDRAM driver configuration structure. +static const SDRAMConfig sdram_cfg = { + .sdcr = (uint32_t) FMC_ColumnBits_Number_8b | + FMC_RowBits_Number_12b | + FMC_SDMemory_Width_32b | + FMC_InternalBank_Number_4 | + FMC_CAS_Latency_3 | + FMC_Write_Protection_Disable | + FMC_SDClock_Period_2 | + FMC_Read_Burst_Enable | + FMC_ReadPipe_Delay_0, + .sdtr = (uint32_t) (2 - 1) | // FMC_LoadToActiveDelay = 2 (TMRD: 2 Clock cycles) + (7 << 4) | // FMC_ExitSelfRefreshDelay = 7 (TXSR: min=70ns (7x11.11ns)) + (4 << 8) | // FMC_SelfRefreshTime = 4 (TRAS: min=42ns (4x11.11ns) max=120k (ns)) + (7 << 12) | // FMC_RowCycleDelay = 7 (TRC: min=70 (7x11.11ns)) + (3 << 16) | // FMC_WriteRecoveryTime = 2 (TWR: min=1+ 7ns (1+1x11.11ns)) + (2 << 20) | // FMC_RPDelay = 2 (TRP: 20ns => 2x11.11ns) + (2 << 24), // FMC_RCDDelay = 2 (TRCD: 20ns => 2x11.11ns) + // NRFS = 4-1 + .sdcmr = (3 << 5) | (FMC_SDCMR_MRD_BURST_LENGTH_2 | + FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL | + FMC_SDCMR_MRD_CAS_LATENCY_3 | + FMC_SDCMR_MRD_OPERATING_MODE_STANDARD | + FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE) << 9, + + .sdrtr = (uint32_t)(683 << 1), +}; + +void Target_ExternalMemoryInit() +{ + fsmcSdramInit(); + + // FIXME + // this swaps SDRAM address to 0x60000000 and makes it L1 cacheable + //SYSCFG->MEMRMP |= SYSCFG_MEMRMP_SWP_FMC_0; + + fsmcSdramStart(&SDRAMD, &sdram_cfg); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_lwip_sntp_opts.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_lwip_sntp_opts.h new file mode 100644 index 00000000..c115cd67 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_lwip_sntp_opts.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#define SNTP_SERVER_DEFAULT_ADDRESS "0.pool.ntp.org" + +// update delay (default 1 hour) +// (value in milliseconds) +#define SNTP_UPDATE_DELAY 3600000 + +// better have a startup delay because we can have DHCP enabled (default 30 seconds) +// value in milliseconds +#define SNTP_STARTUP_DELAY 30000 + +// retry timeout (15 minutes) +// value in milliseconds +#define SNTP_RETRY_TIMEOUT 900000 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.cpp new file mode 100644 index 00000000..7dbe7ff1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_nf_devices_can_config.h" +#include + +/////////// +// CAN1 // +/////////// + +// pin configuration for CAN1 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_09 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_08 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(1, GPIOB, GPIOB, 9, 8, 9) + +// buffer +CANRxFrame Can1_MsgBuffer[CAN1_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(1, CAN1_RX_BUFFER_SIZE) + +/////////// +// CAN2 // +/////////// + +// pin configuration for CAN2 +// port for TX pin is: GPIOB +// TX pin: is GPIOB_06 +// port for RX pin is: GPIOB +// RX pin: is GPIOB_05 +// GPIO alternate pin function is 9 (see "Table 9. STM32F405xx and STM32F407xx alternate function mapping" in STM32F405xx/STM32F407xx datasheet) +CAN_CONFIG_PINS(2, GPIOB, GPIOB, 6, 5, 9) + +// buffer +CANRxFrame Can2_MsgBuffer[CAN2_RX_BUFFER_SIZE]; + +// initialization for CAN1 +CAN_INIT(2, CAN2_RX_BUFFER_SIZE) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.h new file mode 100644 index 00000000..adc8ace3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_can_config.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +////////// +// CAN1 // +////////// + +// enable CAN1 +#define NF_CAN_STM32_CAN_USE_CAN1 TRUE + +// buffers size +#define CAN1_RX_BUFFER_SIZE 16 + +////////// +// CAN2 // +////////// + +// enable CAN2 +#define NF_CAN_STM32_CAN_USE_CAN2 TRUE + +// buffers size +#define CAN2_RX_BUFFER_SIZE 16 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..09f1420e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_nf_devices_onewire_config.h" +#include + +/////////// +// UART4 // +/////////// + +// pin configuration for UART4 +// port for TX pin is: GPIOC +// TX pin: is GPIOC_10 +// GPIO alternate pin function is 8 +UART_CONFIG_PINS(4, GPIOC, 10, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart4_TxBuffer[UART4_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart4_RxBuffer[UART4_RX_SIZE]; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..76f90a10 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_nf_devices_onewire_config.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////// +// UART4 // +/////////// + +// enable USART4 +#define NF_ONEWIRE_STM32_UART_USE_USART4 TRUE + +// buffers size +// tx buffer size: 32 bytes +#define UART4_TX_SIZE 32 +// rx buffer size: 32 bytes +#define UART4_RX_SIZE 32 \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.c new file mode 100644 index 00000000..103930bb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.c @@ -0,0 +1,853 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include "target_spiffs.h" +#include + +static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi); +static uint8_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi); +static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi); +static uint8_t QSPI_EnterMemory_QPI(QSPI_HandleTypeDef *hqspi); +// static uint8_t QSPI_ExitMemory_QPI(QSPI_HandleTypeDef *hqspi); +static uint8_t QSPI_OutDrvStrengthCfg(QSPI_HandleTypeDef *hqspi); +static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi); +static uint8_t QSPI_AutoPollingMemReady (QSPI_HandleTypeDef *hqspi, uint32_t Timeout); +static uint8_t QSPI_ReadChipID(QSPI_HandleTypeDef *hqspi, uint8_t* buffer); + +uint8_t QSPI_Read(uint8_t* pData, uint32_t readAddr, uint32_t size); +uint8_t QSPI_Write(uint8_t* pData, uint32_t writeAddr, uint32_t size); +uint8_t QSPI_Erase_Block(uint32_t blockAddress); + +// initialization of everything required for SPIFFS +// for this target is the QSPI driver +uint8_t target_spiffs_init() +{ + uint8_t device_id[3] = { 0, 0, 0 }; + + /* QSPI initialization */ + /* QSPI freq = SYSCLK /(1 + ClockPrescaler) = 216 MHz/(1+1) = 108 Mhz */ + QSPID1.Init.ClockPrescaler = 1; /* QSPI freq = 216 MHz/(1+1) = 108 Mhz */ + QSPID1.Init.FifoThreshold = 16; + QSPID1.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; + QSPID1.Init.FlashSize = POSITION_VAL(MX25L512_FLASH_SIZE) - 1; + QSPID1.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE; /* Min 30ns for nonRead */ + QSPID1.Init.ClockMode = QSPI_CLOCK_MODE_0; + QSPID1.Init.FlashID = QSPI_FLASH_ID_1; + QSPID1.Init.DualFlash = QSPI_DUALFLASH_DISABLE; + + // init driver + qspiStart(&QSPID1); + + if (HAL_QSPI_Init(&QSPID1) != HAL_OK) + { + return QSPI_ERROR; + } + + /* QSPI memory reset */ + if(QSPI_ResetMemory( &QSPID1 ) != QSPI_OK) + { + return QSPI_NOT_SUPPORTED; + } + + /* Put QSPI memory in QPI mode */ + if(QSPI_EnterMemory_QPI( &QSPID1 )!=QSPI_OK ) + { + return QSPI_NOT_SUPPORTED; + } + + /* Set the QSPI memory in 4-bytes address mode */ + if(QSPI_EnterFourBytesAddress(&QSPID1) != QSPI_OK) + { + return QSPI_NOT_SUPPORTED; + } + + /* Configuration of the dummy cycles on QSPI memory side */ + if (QSPI_DummyCyclesCfg(&QSPID1) != QSPI_OK) + { + return QSPI_NOT_SUPPORTED; + } + + /* Configuration of the Output driver strength on memory side */ + if( QSPI_OutDrvStrengthCfg( &QSPID1 ) != QSPI_OK ) + { + return QSPI_NOT_SUPPORTED; + } + + HAL_Delay(10); + + // sanity check: read device ID and unique ID + if( QSPI_ReadChipID( &QSPID1, device_id ) != QSPI_OK ) + { + return QSPI_ERROR; + } + + // // invalidate cache over read buffer to ensure that content from DMA is read + // // (only required for Cortex-M7) + // cacheBufferInvalidate(device_id, 3); + + // constants from ID Definitions table in MX25L51245G datasheet + ASSERT(device_id[0] == MX25L512_MANUFACTURER_ID); + ASSERT(device_id[1] == MX25L512_DEVICE_ID_MEM_TYPE); + ASSERT(device_id[2] == MX25L512_DEVICE_ID_MEM_CAPACITY); + + return QSPI_OK; +} + +// target specific implementation of hal_spiffs_erase +s32_t hal_spiffs_erase(u32_t addr, u32_t size) +{ + uint32_t i = 0; + + // how many sectors need to be erased? + uint32_t erase_count = (size + SPIFFS_ERASE_BLOCK_SIZE - 1) / SPIFFS_ERASE_BLOCK_SIZE; + + for (i = 0; i < erase_count; i++) + { + if( QSPI_Erase_Block(addr) != QSPI_OK) + { + return SPIFFS_ERROR; + } + + // adjust sector address + addr += i * SPIFFS_ERASE_BLOCK_SIZE; + } + + return SPIFFS_SUCCESS; +} + +// target specific implementation of hal_spiffs_read +s32_t hal_spiffs_read(u32_t addr, u32_t size, u8_t *dst) +{ + if(QSPI_Read(dst, addr, size) != QSPI_OK) + { + return SPIFFS_ERROR; + } + + return SPIFFS_SUCCESS; +} + +// target specific implementation of hal_spiffs_write +s32_t hal_spiffs_write(u32_t addr, u32_t size, u8_t *src) +{ + if( QSPI_Write(src, addr, size) != QSPI_OK) + { + return SPIFFS_ERROR; + } + + return SPIFFS_SUCCESS; +} + +static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) +{ + QSPI_CommandTypeDef s_command; + QSPI_AutoPollingTypeDef s_config; + uint8_t reg; + + /* Send command RESET command in QPI mode (QUAD I/Os) */ + /* Initialize the reset enable command */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = RESET_ENABLE_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_NONE; + s_command.DummyCycles = 0; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + /* Send the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Send the reset memory command */ + s_command.Instruction = RESET_MEMORY_CMD; + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Send command RESET command in SPI mode */ + /* Initialize the reset enable command */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; + s_command.Instruction = RESET_ENABLE_CMD; + /* Send the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + /* Send the reset memory command */ + s_command.Instruction = RESET_MEMORY_CMD; + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* After reset CMD, 1000ms requested if QSPI memory SWReset occured during full chip erase operation */ + HAL_Delay( 1000 ); + + /* Configure automatic polling mode to wait the WIP bit=0 */ + s_config.Match = 0; + s_config.Mask = MX25L512_SR_WIP; + s_config.MatchMode = QSPI_MATCH_MODE_AND; + s_config.StatusBytesSize = 1; + s_config.Interval = 0x10; + s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.DataMode = QSPI_DATA_1_LINE; + + if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Initialize the reading of status register */ + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.NbData = 1; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Enable write operations, command in 1 bit */ + /* Enable write operations */ + s_command.Instruction = WRITE_ENABLE_CMD; + s_command.DataMode = QSPI_DATA_NONE; + s_command.DummyCycles = 0; + s_command.NbData = 0; + + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for write enabling */ + s_config.Match = MX25L512_SR_WREN; + s_config.Mask = MX25L512_SR_WREN; + s_config.MatchMode = QSPI_MATCH_MODE_AND; + s_config.StatusBytesSize = 1; + s_config.Interval = 0x10; + s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.DataMode = QSPI_DATA_1_LINE; + s_command.NbData = 0; + + if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Update the configuration register with new dummy cycles */ + s_command.Instruction = WRITE_STATUS_CFG_REG_CMD; + s_command.DataMode = QSPI_DATA_1_LINE; + s_command.NbData = 1; + + /* Enable the Quad IO on the QSPI memory (Non-volatile bit) */ + reg |= MX25L512_SR_QUADEN; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Transmission of the data */ + if (HAL_QSPI_Transmit(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* 40ms Write Status/Configuration Register Cycle Time */ + HAL_Delay( 40 ); + + // read back register to check MX25L512_SR_QUADEN + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.DataMode = QSPI_DATA_1_LINE; + s_command.DummyCycles = 0; + s_command.NbData = 1; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + if(reg & MX25L512_SR_QUADEN) + { + return QSPI_OK; + } + else + { + return QSPI_ERROR; + } +} + +static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi) +{ + QSPI_CommandTypeDef s_command; + uint8_t reg[2]; + + /* Initialize the reading of status register */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 1; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Initialize the reading of configuration register */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = READ_CFG_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 1; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(hqspi, &(reg[1]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Enable write operations */ + if (QSPI_WriteEnable(hqspi) != QSPI_OK) + { + return QSPI_ERROR; + } + + /* Update the configuration register with new dummy cycles */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = WRITE_STATUS_CFG_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 2; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* MX25L512_DUMMY_CYCLES_READ_QUAD = 3 for 10 cycles in QPI mode */ + MODIFY_REG( reg[1], MX25L512_CR_NB_DUMMY, (MX25L512_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(MX25L512_CR_NB_DUMMY))); + + /* Configure the write volatile configuration register command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Transmission of the data */ + if (HAL_QSPI_Transmit(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* 40ms Write Status/Configuration Register Cycle Time */ + HAL_Delay( 40 ); + + return QSPI_OK; +} + +static uint8_t QSPI_EnterMemory_QPI( QSPI_HandleTypeDef *hqspi ) +{ + QSPI_CommandTypeDef s_command; + QSPI_AutoPollingTypeDef s_config; + + /* Initialize the QPI enable command */ + /* QSPI memory is supported to be in SPI mode, so CMD on 1 LINE */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; + s_command.Instruction = ENTER_QUAD_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_NONE; + s_command.DummyCycles = 0; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Send the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait the QUADEN bit=1 and WIP bit=0 */ + s_config.Match = MX25L512_SR_QUADEN; + s_config.Mask = MX25L512_SR_QUADEN|MX25L512_SR_WIP; + s_config.MatchMode = QSPI_MATCH_MODE_AND; + s_config.StatusBytesSize = 1; + s_config.Interval = 0x10; + s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.DataMode = QSPI_DATA_4_LINES; + + if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +// static uint8_t QSPI_ExitMemory_QPI( QSPI_HandleTypeDef *hqspi) +// { +// QSPI_CommandTypeDef s_command; + +// /* Initialize the QPI enable command */ +// /* QSPI memory is supported to be in QPI mode, so CMD on 4 LINES */ +// s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; +// s_command.Instruction = EXIT_QUAD_CMD; +// s_command.AddressMode = QSPI_ADDRESS_NONE; +// s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; +// s_command.DataMode = QSPI_DATA_NONE; +// s_command.DummyCycles = 0; +// s_command.DdrMode = QSPI_DDR_MODE_DISABLE; +// s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; +// s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + +// /* Send the command */ +// if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) +// { +// return QSPI_ERROR; +// } + +// return QSPI_OK; +// } + +static uint8_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi) +{ + QSPI_CommandTypeDef s_command; + + /* Initialize the command */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = ENTER_4_BYTE_ADDR_MODE_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_NONE; + s_command.DummyCycles = 0; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Enable write operations */ + if (QSPI_WriteEnable(hqspi) != QSPI_OK) + { + return QSPI_ERROR; + } + + /* Send the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait the memory is ready */ + if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) + { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) +{ + + //HAL_QSPI_Abort(&QSPID1); + + QSPI_CommandTypeDef s_command; + QSPI_AutoPollingTypeDef s_config; + + /* Enable write operations */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = WRITE_ENABLE_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_NONE; + s_command.DummyCycles = 0; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for write enabling */ + s_config.Match = MX25L512_SR_WREN; + s_config.Mask = MX25L512_SR_WREN; + s_config.MatchMode = QSPI_MATCH_MODE_AND; + s_config.StatusBytesSize = 1; + s_config.Interval = 0x10; + s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.DataMode = QSPI_DATA_4_LINES; + + if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) +{ + QSPI_CommandTypeDef s_command; + QSPI_AutoPollingTypeDef s_config; + + /* Configure automatic polling mode to wait for memory ready */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + s_config.Match = 0; + s_config.Mask = MX25L512_SR_WIP; + s_config.MatchMode = QSPI_MATCH_MODE_AND; + s_config.StatusBytesSize = 1; + s_config.Interval = 0x10; + s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, Timeout) != HAL_OK) + { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +static uint8_t QSPI_OutDrvStrengthCfg( QSPI_HandleTypeDef *hqspi ) +{ + QSPI_CommandTypeDef s_command; + uint8_t reg[2]; + + /* Initialize the reading of status register */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = READ_STATUS_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 1; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Initialize the reading of configuration register */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = READ_CFG_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 1; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(hqspi, &(reg[1]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Enable write operations */ + if (QSPI_WriteEnable(&QSPID1) != QSPI_OK) + { + return QSPI_ERROR; + } + + /* Update the configuration register with new output driver strength */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = WRITE_STATUS_CFG_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 2; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Set Output Strength of the QSPI memory 15 ohms */ + MODIFY_REG( reg[1], MX25L512_CR_ODS, (MX25L512_CR_ODS_15 << POSITION_VAL(MX25L512_CR_ODS))); + + /* Configure the write volatile configuration register command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Transmission of the data */ + if (HAL_QSPI_Transmit(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +static uint8_t QSPI_ReadChipID(QSPI_HandleTypeDef *hqspi, uint8_t* buffer) +{ + QSPI_CommandTypeDef s_command; + + /* Initialize the reading of status register */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = MULTIPLE_IO_READ_ID_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 3; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(hqspi, buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +uint8_t QSPI_Read(uint8_t* pData, uint32_t readAddr, uint32_t size) +{ + QSPI_CommandTypeDef s_command; + + /* Initialize the read command */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = QSPI_READ_4_BYTE_ADDR_CMD; + s_command.AddressMode = QSPI_ADDRESS_4_LINES; + s_command.AddressSize = QSPI_ADDRESS_32_BITS; + s_command.Address = readAddr; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = MX25L512_DUMMY_CYCLES_READ_QUAD_IO; + s_command.NbData = size; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_QSPI_Command(&QSPID1, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Set S# timing for Read command */ + MODIFY_REG(QSPID1.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_1_CYCLE); + + /* Reception of the data */ + if (HAL_QSPI_Receive(&QSPID1, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + // // invalidate cache over read buffer to ensure that content from DMA is read + // // (only required for Cortex-M7) + // cacheBufferInvalidate(pData, size); + + /* Restore S# timing for nonRead commands */ + MODIFY_REG(QSPID1.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_4_CYCLE); + +SET_BIT(QSPID1.Instance->CR, QUADSPI_CR_ABORT); + + return QSPI_OK; +} + +uint8_t QSPI_Write(uint8_t* pData, uint32_t writeAddr, uint32_t size) +{ + QSPI_CommandTypeDef s_command; + uint32_t end_addr, current_size, current_addr; + + /* Calculation of the size between the write address and the end of the page */ + current_size = MX25L512_PAGE_SIZE - (writeAddr % MX25L512_PAGE_SIZE); + + /* Check if the size of the data is less than the remaining place in the page */ + if (current_size > size) + { + current_size = size; + } + + /* Initialize the address variables */ + current_addr = writeAddr; + end_addr = writeAddr + size; + + /* Initialize the program command */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = PAGE_PROG_CMD; + s_command.AddressMode = QSPI_ADDRESS_4_LINES; + s_command.AddressSize = QSPI_ADDRESS_32_BITS; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Perform the write page by page */ + do + { + s_command.Address = current_addr; + s_command.NbData = current_size; + + /* Enable write operations */ + if (QSPI_WriteEnable(&QSPID1) != QSPI_OK) + { + return QSPI_ERROR; + } + + /* Configure the command */ + if (HAL_QSPI_Command(&QSPID1, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + // // flush DMA buffer to ensure cache coherency + // // (only required for Cortex-M7) + // cacheBufferFlush(pData, current_size); + + /* Transmission of the data */ + if (HAL_QSPI_Transmit(&QSPID1, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for end of program */ + if (QSPI_AutoPollingMemReady(&QSPID1, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) + { + return QSPI_ERROR; + } + + /* Update the address and size variables for next page programming */ + current_addr += current_size; + pData += current_size; + current_size = ((current_addr + MX25L512_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MX25L512_PAGE_SIZE; + + } + while (current_addr < end_addr); + + return QSPI_OK; +} + +uint8_t QSPI_Erase_Block(uint32_t blockAddress) +{ + QSPI_CommandTypeDef s_command; + + /* Initialize the erase command */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = SECTOR_ERASE_4_BYTE_ADDR_CMD; + s_command.AddressMode = QSPI_ADDRESS_4_LINES; + s_command.AddressSize = QSPI_ADDRESS_32_BITS; + s_command.Address = blockAddress; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_NONE; + s_command.DummyCycles = 0; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Enable write operations */ + if (QSPI_WriteEnable(&QSPID1) != QSPI_OK) + { + return QSPI_ERROR; + } + + /* Send the command */ + if (HAL_QSPI_Command(&QSPID1, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for end of erase */ + if (QSPI_AutoPollingMemReady(&QSPID1, MX25L512_SECTOR_ERASE_MAX_TIME) != QSPI_OK) + { + return QSPI_ERROR; + } + + return QSPI_OK; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.h new file mode 100644 index 00000000..c6d1b86a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_spiffs.h @@ -0,0 +1,148 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +//////////////////////////////////// +// buffers configuration +#define SPIFFS_LOGICAL_PAGE_SIZE (256) + +#define SPIFFS_WORK_BUFFER_SIZE (SPIFFS_LOGICAL_PAGE_SIZE * 2) +#define SPIFFS_FILE_DESCRIPTORS_SPACE (32 * 2) +#define SPIFFS_CACHE_SIZE ((SPIFFS_LOGICAL_PAGE_SIZE + 32) * 4) + +#define SPIFFS_DRIVER_QSPI (1) + +// MX25L512 Configuration +#define MX25L512_FLASH_SIZE 0x4000000 /* 512 MBits => 64MBytes */ +#define MX25L512_SECTOR_SIZE 0x10000 /* 1024 sectors of 64KBytes */ +#define MX25L512_SUBSECTOR_SIZE 0x1000 /* 16384 subsectors of 4kBytes */ +#define MX25L512_PAGE_SIZE 0x100 /* 262144 pages of 256 bytes */ + +#define MX25L512_DUMMY_CYCLES_READ_QUAD 3 +#define MX25L512_DUMMY_CYCLES_READ 8 +#define MX25L512_DUMMY_CYCLES_READ_QUAD_IO 10 +#define MX25L512_DUMMY_CYCLES_READ_DTR 6 +#define MX25L512_DUMMY_CYCLES_READ_QUAD_DTR 8 + +#define MX25L512_BULK_ERASE_MAX_TIME 600000 +#define MX25L512_SECTOR_ERASE_MAX_TIME 2000 +#define MX25L512_SUBSECTOR_ERASE_MAX_TIME 800 + +// MX25L512 Commands +/* Reset Operations */ +#define RESET_ENABLE_CMD 0x66 +#define RESET_MEMORY_CMD 0x99 + +/* Identification Operations */ +#define READ_ID_CMD 0x9F +#define MULTIPLE_IO_READ_ID_CMD 0xAF +#define READ_SERIAL_FLASH_DISCO_PARAM_CMD 0x5A + +/* Read Operations */ +#define READ_CMD 0x03 +#define READ_4_BYTE_ADDR_CMD 0x13 + +#define FAST_READ_CMD 0x0B +#define FAST_READ_DTR_CMD 0x0D +#define FAST_READ_4_BYTE_ADDR_CMD 0x0C + +#define DUAL_OUT_FAST_READ_CMD 0x3B +#define DUAL_OUT_FAST_READ_4_BYTE_ADDR_CMD 0x3C + +#define DUAL_INOUT_FAST_READ_CMD 0xBB +#define DUAL_INOUT_FAST_READ_DTR_CMD 0xBD +#define DUAL_INOUT_FAST_READ_4_BYTE_ADDR_CMD 0xBC + +#define QUAD_OUT_FAST_READ_CMD 0x6B +#define QUAD_OUT_FAST_READ_4_BYTE_ADDR_CMD 0x6C + +#define QUAD_INOUT_FAST_READ_CMD 0xEB +#define QUAD_INOUT_FAST_READ_DTR_CMD 0xED +#define QSPI_READ_4_BYTE_ADDR_CMD 0xEC + +/* Write Operations */ +#define WRITE_ENABLE_CMD 0x06 +#define WRITE_DISABLE_CMD 0x04 + +/* Register Operations */ +#define READ_STATUS_REG_CMD 0x05 +#define READ_CFG_REG_CMD 0x15 +#define WRITE_STATUS_CFG_REG_CMD 0x01 + +#define READ_LOCK_REG_CMD 0x2D +#define WRITE_LOCK_REG_CMD 0x2C + +#define READ_EXT_ADDR_REG_CMD 0xC8 +#define WRITE_EXT_ADDR_REG_CMD 0xC5 + +/* Program Operations */ +#define PAGE_PROG_CMD 0x02 +#define QSPI_PAGE_PROG_4_BYTE_ADDR_CMD 0x12 + +#define QUAD_IN_FAST_PROG_CMD 0x38 +#define EXT_QUAD_IN_FAST_PROG_CMD 0x38 +#define QUAD_IN_FAST_PROG_4_BYTE_ADDR_CMD 0x3E + +/* Erase Operations */ +#define SUBSECTOR_ERASE_CMD 0x20 +#define SUBSECTOR_ERASE_4_BYTE_ADDR_CMD 0x21 + +#define SECTOR_ERASE_CMD 0xD8 +#define SECTOR_ERASE_4_BYTE_ADDR_CMD 0xDC + +#define BULK_ERASE_CMD 0xC7 + +#define PROG_ERASE_RESUME_CMD 0x30 +#define PROG_ERASE_SUSPEND_CMD 0xB0 + +/* 4-byte Address Mode Operations */ +#define ENTER_4_BYTE_ADDR_MODE_CMD 0xB7 +#define EXIT_4_BYTE_ADDR_MODE_CMD 0xE9 + +/* Quad Operations */ +#define ENTER_QUAD_CMD 0x35 +#define EXIT_QUAD_CMD 0xF5 + +/* Added for compatibility */ +#define QPI_READ_4_BYTE_ADDR_CMD QSPI_READ_4_BYTE_ADDR_CMD +#define QPI_PAGE_PROG_4_BYTE_ADDR_CMD QSPI_PAGE_PROG_4_BYTE_ADDR_CMD + + +// MX25L512 Registers +/* Status Register */ +#define MX25L512_SR_WIP ((uint8_t)0x01) /*!< Write in progress */ +#define MX25L512_SR_WREN ((uint8_t)0x02) /*!< Write enable latch */ +#define MX25L512_SR_BLOCKPR ((uint8_t)0x5C) /*!< Block protected against program and erase operations */ +#define MX25L512_SR_PRBOTTOM ((uint8_t)0x20) /*!< Protected memory area defined by BLOCKPR starts from top or bottom */ +#define MX25L512_SR_QUADEN ((uint8_t)0x40) /*!< Quad IO mode enabled if =1 */ +#define MX25L512_SR_SRWREN ((uint8_t)0x80) /*!< Status register write enable/disable */ + +/* Configuration Register */ +#define MX25L512_CR_ODS ((uint8_t)0x07) /*!< Output driver strength */ +#define MX25L512_CR_ODS_30 ((uint8_t)0x07) /*!< Output driver strength 30 ohms (default)*/ +#define MX25L512_CR_ODS_15 ((uint8_t)0x06) /*!< Output driver strength 15 ohms */ +#define MX25L512_CR_ODS_20 ((uint8_t)0x05) /*!< Output driver strength 20 ohms */ +#define MX25L512_CR_ODS_45 ((uint8_t)0x03) /*!< Output driver strength 45 ohms */ +#define MX25L512_CR_ODS_60 ((uint8_t)0x02) /*!< Output driver strength 60 ohms */ +#define MX25L512_CR_ODS_90 ((uint8_t)0x01) /*!< Output driver strength 90 ohms */ +#define MX25L512_CR_TB ((uint8_t)0x08) /*!< Top/Bottom bit used to configure the block protect area */ +#define MX25L512_CR_PBE ((uint8_t)0x10) /*!< Preamble Bit Enable */ +#define MX25L512_CR_4BYTE ((uint8_t)0x20) /*!< 3-bytes or 4-bytes addressing */ +#define MX25L512_CR_NB_DUMMY ((uint8_t)0xC0) /*!< Number of dummy clock cycles */ + +#define MX25L512_FLASH_SIZE 0x4000000 // 512MBits => 64MBytes +#define MX25L512_SECTOR_SIZE 0x10000 // 1024 sectors of 64KBytes +#define MX25L512_SUBSECTOR_SIZE 0x1000 // 16384 subsectors of 4kBytes +#define MX25L512_PAGE_SIZE 0x100 // 262144 pages of 256 bytes + +#define MX25L512_SUBSECTOR_ERASE_MAX_TIME 800 +#define MX25L512_MANUFACTURER_ID ((uint8_t)0xC2) +#define MX25L512_DEVICE_ID_MEM_TYPE ((uint8_t)0x20) +#define MX25L512_DEVICE_ID_MEM_CAPACITY ((uint8_t)0x1A) + +//////////////////////////////// + +#define SPIFFS_TOTAL_SIZE MX25L512_FLASH_SIZE +#define SPIFFS_ERASE_BLOCK_SIZE MX25L512_SECTOR_SIZE +#define SPIFFS_LOGICAL_BLOCK_SIZE (64*1024) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..049422f7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_system_devices_dac_config.cpp @@ -0,0 +1,14 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..3a886009 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_adc_config.cpp @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 6, ADC_CHANNEL_IN6}, + {1, GPIOA, 4, ADC_CHANNEL_IN4}, + {1, GPIOC, 2, ADC_CHANNEL_IN12}, + {1, GPIOF, 10, ADC_CHANNEL_IN8}, + + // ADC3 + {3, GPIOF, 8, ADC_CHANNEL_IN6}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2a60a22f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..2f2f4148 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,255 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include + +// /////////// +// // UART1 // +// /////////// + +// // pin configuration for UART1 +// // port for TX pin is: GPIOD +// // port for RX pin is: GPIOC +// // TX pin: is GPIOD_2 +// // RX pin: is GPIOC_12 +// // GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +// UART_CONFIG_PINS(1, GPIOD, GPIOC, 2, 12, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart1_TxBuffer[UART1_TX_SIZE]; + +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart1_RxBuffer[UART1_RX_SIZE]; + +// // initialization for UART1 +// UART_INIT(1, UART1_TX_SIZE, UART1_RX_SIZE) + +// // un-initialization for UART1 +// UART_UNINIT(1) + +// /////////// +// // UART2 // +// /////////// + +// // pin configuration for UART2 +// // port for TX pin is: GPIOD +// // port for RX pin is: GPIOC +// // TX pin: is GPIOD_2 +// // RX pin: is GPIOC_12 +// // GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +// UART_CONFIG_PINS(2, GPIOD, GPIOC, 2, 12, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; + +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// // initialization for UART2 +// UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// // un-initialization for UART2 +// UART_UNINIT(2) + +// /////////// +// // UART3 // +// /////////// + +// // pin configuration for UART3 +// // port for TX pin is: GPIOD +// // port for RX pin is: GPIOC +// // TX pin: is GPIOD_2 +// // RX pin: is GPIOC_12 +// // GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +// UART_CONFIG_PINS(3, GPIOD, GPIOC, 2, 12, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart3_TxBuffer[UART3_TX_SIZE]; + +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart3_RxBuffer[UART3_RX_SIZE]; + +// // initialization for UART3 +// UART_INIT(3, UART3_TX_SIZE, UART3_RX_SIZE) + +// // un-initialization for UART3 +// UART_UNINIT(3) + +// /////////// +// // UART4 // +// /////////// + +// // pin configuration for UART4 +// // port for TX pin is: GPIOD +// // port for RX pin is: GPIOC +// // TX pin: is GPIOD_2 +// // RX pin: is GPIOC_12 +// // GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +// UART_CONFIG_PINS(4, GPIOD, GPIOC, 2, 12, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart4_TxBuffer[UART4_TX_SIZE]; + +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart4_RxBuffer[UART4_RX_SIZE]; + +// // initialization for UART4 +// UART_INIT(4, UART4_TX_SIZE, UART4_RX_SIZE) + +// // un-initialization for UART4 +// UART_UNINIT(4) + +/////////// +// UART5 // +/////////// + +// pin configuration for UART5 +// port for TX pin is: GPIOD +// port for RX pin is: GPIOC +// TX pin: is GPIOD_2 +// RX pin: is GPIOC_12 +// GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +UART_CONFIG_PINS(5, GPIOD, GPIOC, 2, 12, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart5_TxBuffer[UART5_TX_SIZE]; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart5_RxBuffer[UART5_RX_SIZE]; + +// initialization for UART5 +UART_INIT(5, UART5_TX_SIZE, UART5_RX_SIZE) + +// un-initialization for UART5 +UART_UNINIT(5) + +/////////// +// UART6 // +/////////// + +// pin configuration for UART6 +// port for TX pin is: GPIOC +// port for RX pin is: GPIOC +// TX pin: is GPIOC_6 +// RX pin: is GPIOC_7 +// GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +UART_CONFIG_PINS(6, GPIOC, GPIOC, 6, 7, 8) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_TxBuffer[UART6_TX_SIZE]; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart6_RxBuffer[UART6_RX_SIZE]; + +// initialization for UART6 +UART_INIT(6, UART6_TX_SIZE, UART6_RX_SIZE) + +// un-initialization for UART6 +UART_UNINIT(6) + +// /////////// +// // UART7 // +// /////////// + +// // pin configuration for UART7 +// // port for TX pin is: GPIOF +// // port for RX pin is: GPIOF +// // TX pin: is GPIOF_7 +// // RX pin: is GPIOF_6 +// // GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +// UART_CONFIG_PINS(7, GPIOF, GPIOF, 7, 6, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart6_TxBuffer[UART7_TX_SIZE]; + +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart6_RxBuffer[UART7_RX_SIZE]; + +// // initialization for UART6 +// UART_INIT(7, UART7_TX_SIZE, UART7_RX_SIZE) + +// // un-initialization for UART6 +// UART_UNINIT(7) + +// /////////// +// // UART8 // +// /////////// + +// // pin configuration for UART8 +// // port for TX pin is: GPIOC +// // port for RX pin is: GPIOC +// // TX pin: is GPIOC_6 +// // RX pin: is GPIOC_7 +// // GPIO alternate pin function is 8 (see "Table 13. STM32F765xx, STM32F767xx, STM32F768Ax and STM32F769xx alternate function mapping" in STM32F769I datasheet) +// UART_CONFIG_PINS(8, GPIOC, GPIOC, 6, 7, 8) + +// // buffers +// // buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// // because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart8_TxBuffer[UART8_TX_SIZE]; + +// #if defined(__GNUC__) +// __attribute__((aligned (32))) +// #endif +// uint8_t Uart8_RxBuffer[UART8_RX_SIZE]; + +// // initialization for UART6 +// UART_INIT(8, UART8_TX_SIZE, UART8_RX_SIZE) + +// // un-initialization for UART6 +// UART_UNINIT(8) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..346f5674 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,108 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// /////////// +// // UART1 // +// /////////// + +// // enable UART1 +// #define NF_SERIAL_COMM_STM32_UART_USE_UART1 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART1_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART1_RX_SIZE 256 + +// /////////// +// // UART2 // +// /////////// + +// // enable UART2 +// #define NF_SERIAL_COMM_STM32_UART_USE_UART2 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART2_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART2_RX_SIZE 256 + +// /////////// +// // UART3 // +// /////////// + +// // enable UART5 +// #define NF_SERIAL_COMM_STM32_UART_USE_UART3 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART3_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART3_RX_SIZE 256 + +// /////////// +// // UART4 // +// /////////// + +// // enable UART4 +// #define NF_SERIAL_COMM_STM32_UART_USE_UART4 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART4_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART4_RX_SIZE 256 + +/////////// +// UART5 // +/////////// + +// enable UART5 +#define NF_SERIAL_COMM_STM32_UART_USE_UART5 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART5_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART5_RX_SIZE 256 + +/////////// +// UART6 // +/////////// + +// enable USART6 +#define NF_SERIAL_COMM_STM32_UART_USE_USART6 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART6_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART6_RX_SIZE 256 + +// /////////// +// // UART7 // +// /////////// + +// // enable UART7 +// #define NF_SERIAL_COMM_STM32_UART_USE_UART7 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART7_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART7_RX_SIZE 256 + +// /////////// +// // UART8 // +// /////////// + +// // enable UART8 +// #define NF_SERIAL_COMM_STM32_UART_USE_UART8 TRUE + +// // buffers size +// // tx buffer size: 256 bytes +// #define UART8_TX_SIZE 256 +// // rx buffer size: 256 bytes +// #define UART8_RX_SIZE 256 diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_devices_spi_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_storage_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_storage_config.h new file mode 100644 index 00000000..5dc140d8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/ST_STM32F769I_DISCOVERY/target_windows_storage_config.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// maps the SD Card driver +#define SD_CARD_DRIVER SDCD2 + +// maps the SD Card detect GPIO definition (in Target_Windows_Storage.c) to board GPIO line (in board.h) +#define SDCARD_LINE_DETECT LINE_SD_DETECT + +// includes SPIFFS in storage +#define USE_SPIFFS_FOR_STORAGE FALSE diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/CMakeLists.txt new file mode 100644 index 00000000..ba2bf0f7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/CMakeLists.txt @@ -0,0 +1,38 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append target ChibiOS source files +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/LaunchCLR.c") +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoSupport_CRC32.c") +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_ReceiverThread.c") +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_HAL_Interface.c") +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platform_heap.c") +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Target_BlockStorage_STM32FlashDriver.c") + +# append Target files +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platform_BlockStorage.c") + +# include configuration manager file, if feature is enabled +if(NF_FEATURE_HAS_CONFIG_BLOCK) + list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigurationManager.cpp") +endif() + +# append nanoHAL +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL.c") +list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Time.cpp") + +# append hard fault handler if the build type is to include debug info +if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/hard_fault_handler.c") +endif() + +# append networking files, if enabled +if(USE_NETWORKING_OPTION) + list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Network.cpp") + list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/target_Network.cpp") +endif() + +# make var global +set(TARGET_CHIBIOS_COMMON_SOURCES ${TARGET_CHIBIOS_COMMON_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/LaunchCLR.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/LaunchCLR.c new file mode 100644 index 00000000..19f441a3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/LaunchCLR.c @@ -0,0 +1,99 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +void LaunchCLR(uint32_t address) +{ + // function pointer to load nanoCLR ResetHandler address + irq_vector_t JumpToNanoCLR; + + // load nanoCLR vector table + const vectors_t* nanoCLRVectorTable = (vectors_t*) address; + + // load the jump address with the nanoCLR ResetHandler address + JumpToNanoCLR = nanoCLRVectorTable->reset_handler; + + // disable all interrupts in ChibiOS + chSysDisable(); + + // clear any pending interrupts to make sure we are jumping straight to nanoCLR ResetHandler + SCB->ICSR &= SCB_ICSR_PENDSVCLR_Msk; + + // need to set stack pointer from CLR vector table + __set_MSP((uint32_t)nanoCLRVectorTable->init_stack); + + // make the jump to nanoCLR, at last + JumpToNanoCLR(); +} + +bool CheckValidCLRImage(uint32_t address) +{ + uint32_t resetVectorAddress; + + // load nanoCLR vector table + const vectors_t* nanoCLRVectorTable = (vectors_t*) address; + + // 1st check: the flash content pointed by the address can't be all 0's neither all F's + // meaning that the Flash is neither 'all burnt' or erased + if( (uint32_t)(*(uint32_t**)((uint32_t*)address)) == 0xFFFFFFFF || + (uint32_t)(*(uint32_t**)((uint32_t*)address)) == 0x00000000 ) + { + // check failed, there is no valid CLR image + return false; + } + + // 2nd check: the content pointed by the reset vector has to be 0xE002 + // that's an assembly "b.n" (branch instruction) the very first one in the Reset_Handler function + // see os\common\startup\ARMCMx\compilers\GCC\vectors.S + + + // for series that have ART Accelerator the handlers addresses stored in the vector table are for ITCM access + // need to parsed them to reach the equivalent address in AXI access + #ifdef FLASHITCM_BASE + + // read address (ITCM) + resetVectorAddress = (uint32_t)((uint32_t*)nanoCLRVectorTable->reset_handler); + // parse it to get the address in the AXI range + resetVectorAddress -= FLASHITCM_BASE; + resetVectorAddress += FLASHAXI_BASE; + + #else + + // "regular" address mapping + resetVectorAddress = (uint32_t)((uint32_t*)nanoCLRVectorTable->reset_handler); + + #endif + + // sanity check for invalid address (out of flash range which causes a hard fault) + if( resetVectorAddress <= FLASH1_MEMORY_StartAddress || + resetVectorAddress >= (FLASH1_MEMORY_StartAddress + FLASH1_MEMORY_Size) ) + { + // check failed, doesn't seem to be a valid CLR image + return false; + } + + // the linker can place this anywhere on the address space because of optimizations so we better check where the reset pointer points to + uint32_t opCodeAddress = (uint32_t)((uint32_t**)nanoCLRVectorTable->reset_handler); + + // real address is -1 + opCodeAddress -= 1; + + uint32_t opCode = *((uint32_t*)opCodeAddress); + if((uint16_t)opCode == 0xE002) + { + // check, there seems to be a valid CLR image + return true; + } + else + { + // got here so there isn't a valid CLR imaged flashed + return false; + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_BlockStorage_STM32FlashDriver.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_BlockStorage_STM32FlashDriver.c new file mode 100644 index 00000000..deb991a4 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_BlockStorage_STM32FlashDriver.c @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + + +bool STM32FlashDriver_InitializeDevice(void* context) +{ + (void)context; + + // ChibiOS driver takes care of this, so always true + return true; +} + +bool STM32FlashDriver_UninitializeDevice(void* context) +{ + (void)context; + + // ChibiOS driver takes care of this, so always true + return true; +} + +DeviceBlockInfo* STM32FlashDriver_GetDeviceInfo(void* context) +{ + + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = context; + + return config->BlockConfig.BlockDeviceInformation; +} + +bool STM32FlashDriver_Read(void* context, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer) +{ + (void)context; + + // driver doesn't return anything so: we have to perform the operation here... + stm32FlashReadBytes(startAddress, numBytes, buffer); + + // ... and always return true + return true; +} + +bool STM32FlashDriver_Write(void* context, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite) +{ + (void)context; + (void)readModifyWrite; + + return stm32FlashWrite(startAddress, numBytes, buffer); +} + +bool STM32FlashDriver_IsBlockErased(void* context, ByteAddress blockAddress, unsigned int length) +{ + (void)context; + + return stm32FlashIsErased(blockAddress, length); +} + +bool STM32FlashDriver_EraseBlock(void* context, ByteAddress address) +{ + (void)context; + + return stm32FlashErase(address); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Network.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Network.cpp new file mode 100644 index 00000000..e69baef2 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Network.cpp @@ -0,0 +1,62 @@ + +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +extern "C" struct netif * nf_getNetif(); +// +// Works with the Target_NetworkConfig to map the Network_Interface_XXXXX calls to the correct driver + + +bool Network_Interface_Bind(int index) +{ + (void)index; + + return true; +} + +int Network_Interface_Open(int index) +{ + HAL_Configuration_NetworkInterface networkConfiguration; + + // load network interface configuration from storage + if(!ConfigurationManager_GetConfigurationBlock((void*)&networkConfiguration, DeviceConfigurationOption_Network, index)) + { + // failed to load configuration + // FIXME output error? + return SOCK_SOCKET_ERROR; + } + _ASSERTE(networkConfiguration.StartupAddressMode > 0); + + switch(index) + { + case 0: + { + // Open the network interface and set its config + // TODO / FIXME + + // Return index to NetIF in its linked list, return 0 (probably right if only interface) + // This used by Network stack to hook in to status/address changes for events to users + + // For now get the Netif number form original Chibios binding code + struct netif * nptr = nf_getNetif(); + return nptr->num; + } + break; + } + return SOCK_SOCKET_ERROR; +} + +bool Network_Interface_Close(int index) +{ + switch(index) + { + case 0: + return true; + } + return false; +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Windows_Storage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Windows_Storage.c new file mode 100644 index 00000000..84e61617 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/Target_Windows_Storage.c @@ -0,0 +1,266 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include + +#if HAL_USBH_USE_MSD +#include "usbh/dev/msd.h" +#endif + +// need to declare this here as extern +extern void PostManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2); + +// the drive indexes have to be used instead of fixed drive letters because a target can have one or more +// and those have to follow the sequence that is used in ChibiOS FatFS wrappers +// SD Card (or SPI) is 1st and USB MAS is 2nd (if SD Card is enabled) +// this is also mapped in the FatFS configuration +#if defined(HAL_USE_SDC) + +#define SD_CARD_DRIVE_INDEX "0:" +#define SD_CARD_DRIVE_INDEX_NUMERIC (0) + +#endif + +#if defined(HAL_USE_SDC) + +#define USB_MSD_DRIVE_INDEX "1:" +#define USB_MSD_DRIVE_INDEX_NUMERIC (1) + +#endif + +/////////////////////////////////////////// +// code specific to SD Card + +#if HAL_USE_SDC + +// FS for SD Card mounted and ready +bool sdCardFileSystemReady; + +static FATFS sdCard_FS; +static SDCConfig SDC_CFG; + +// SD Card event sources +static event_source_t sdInsertedEvent, sdRemovedEvent; + +// this timer is used to handle the debounce of SD card detect line +static virtual_timer_t sdCardDebounceTimer; +static bool sdCardPresent; + +// Insertion monitor timer callback function. +static void SdCardInsertionMonitorCallback(void *p) +{ + BaseBlockDevice *bbdp = p; + bool currentStatus; + + chSysLockFromISR(); + + // get current status + currentStatus = blkIsInserted(bbdp); + + if(sdCardPresent == currentStatus) + { + // value hasn't change for debounce interval so this is a valid change + if(currentStatus) + { + chEvtBroadcastI(&sdInsertedEvent); + } + else + { + chEvtBroadcastI(&sdRemovedEvent); + } + } + + chSysUnlockFromISR(); +} + +static void SdCardDetectCallback(void *arg) +{ + BaseBlockDevice* bbdp = (BaseBlockDevice*)arg; + + if(chVTIsArmed(&sdCardDebounceTimer)) + { + // there is a debounce timer already running so this change in pin value should be discarded + return; + } + + // save current status + sdCardPresent = blkIsInserted(bbdp); + + // setup timer + chVTSetI(&sdCardDebounceTimer, TIME_MS2I(SDCARD_POLLING_DELAY), SdCardInsertionMonitorCallback, arg); +} + +// Card insertion event handler +void SdcardInsertHandler(eventid_t id) +{ + FRESULT err; + + (void)id; + + // On insertion SDC initialization and FS mount + if (sdcConnect(&SD_CARD_DRIVER)) + { + return; + } + + err = f_mount(&sdCard_FS, SD_CARD_DRIVE_INDEX, 1); + + if (err != FR_OK) + { + osDelay(1000); + + sdcDisconnect(&SD_CARD_DRIVER); + return; + } + else + { + sdCardFileSystemReady = true; + + // post event to managed app + PostManagedEvent( EVENT_STORAGE, 0, StorageEventType_RemovableDeviceInsertion, SD_CARD_DRIVE_INDEX_NUMERIC ); + } +} + +// Card removal event handler +void SdCardRemoveHandler(eventid_t id) +{ + (void)id; + + sdcDisconnect(&SD_CARD_DRIVER); + + sdCardFileSystemReady = false; + + // post event to managed app + PostManagedEvent( EVENT_STORAGE, 0, StorageEventType_RemovableDeviceRemoval, SD_CARD_DRIVE_INDEX_NUMERIC ); +} + +__attribute__((noreturn)) +void SdCardWorkingThread(void const * argument) +{ + (void)argument; + + event_listener_t sdEventListener0, sdEventListener1; + + const evhandler_t sdcardEventHandler[] = + { + SdcardInsertHandler, + SdCardRemoveHandler + }; + + sdCardFileSystemReady = false; + + // activates the SDC driver using default configuration + sdcStart(&SD_CARD_DRIVER, &SDC_CFG); + + // setup line event in SD Card detect GPIO + palEnableLineEvent(SDCARD_LINE_DETECT, PAL_EVENT_MODE_BOTH_EDGES); + palSetLineCallback(SDCARD_LINE_DETECT, SdCardDetectCallback, &SD_CARD_DRIVER); + + // init timer + chVTObjectInit(&sdCardDebounceTimer); + + // init events + chEvtObjectInit(&sdInsertedEvent); + chEvtObjectInit(&sdRemovedEvent); + + // register events + chEvtRegister(&sdInsertedEvent, &sdEventListener0, 0); + chEvtRegister(&sdRemovedEvent, &sdEventListener1, 1); + + // force initial check + SdCardDetectCallback(&SD_CARD_DRIVER); + + for(;;) + { + chEvtDispatch(sdcardEventHandler, chEvtWaitOneTimeout(ALL_EVENTS, TIME_MS2I(SDCARD_POLLING_DELAY))); + } +} + +#endif + +/////////////////////////////////////////// + +/////////////////////////////////////////// +// code specific to USB MSD +#if HAL_USBH_USE_MSD + +// FS for USB MSD mounted and ready +bool usbMsdFileSystemReady; + +static FATFS usbMsd_FS; + +__attribute__((noreturn)) +void UsbMsdWorkingThread(void const * argument) +{ + (void)argument; + + FRESULT err; + + usbMsdFileSystemReady = false; + + // start USB host + usbhStart(&USB_MSD_DRIVER); + + USBHMassStorageLUNDriver* msBlk = (USBHMassStorageLUNDriver*)&MSBLKD[0]; + + for(;;) + { + osDelay(USB_MSD_POLLING_INTERVAL); + + if (blkGetDriverState(msBlk) == BLK_ACTIVE) + { + // file system can't be ready + usbMsdFileSystemReady = false; + + // BLK: Active, connect + usbhmsdLUNConnect(msBlk); + } + + if (blkGetDriverState(msBlk) == BLK_READY) + { + // BLK: Ready + if(!usbMsdFileSystemReady) + { + // USB MSD file system not ready + // mount drive + err = f_mount(&usbMsd_FS, USB_MSD_DRIVE_INDEX, 1); + + if (err != FR_OK) + { + // mount operation failed, disconnect + usbhmsdLUNDisconnect(msBlk); + } + else + { + usbMsdFileSystemReady = true; + + // post event to managed app + PostManagedEvent( EVENT_STORAGE, 0, StorageEventType_RemovableDeviceInsertion, USB_MSD_DRIVE_INDEX_NUMERIC ); + } + } + } + + if (blkGetDriverState(msBlk) == BLK_STOP) + { + if(usbMsdFileSystemReady) + { + usbMsdFileSystemReady = false; + + // post event to managed app + PostManagedEvent( EVENT_STORAGE, 0, StorageEventType_RemovableDeviceRemoval, USB_MSD_DRIVE_INDEX_NUMERIC ); + } + } + + usbhMainLoop(&USB_MSD_DRIVER); + } +} + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_HAL_Interface.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_HAL_Interface.c new file mode 100644 index 00000000..bcfbbbc0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_HAL_Interface.c @@ -0,0 +1,201 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +#include +#include + +#if (HAL_USE_SERIAL_USB == TRUE) +#include "usbcfg.h" +#elif (HAL_USE_SERIAL == TRUE) +#include +#endif + +WP_Message inboundMessage; + +//////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////// +// The functions below are the ones that need to be ported to new channels/HALs when required +// These are to be considered as a reference implementations when working on new ports +// +// This reference implementation provides communication through: +// - serial port (UART/USART) +// - serial over USB (USB CDC class device) +// +//////////////////////////////////////////////////////////////////////////////////////////////// + +#if (HAL_USE_SERIAL_USB == TRUE) + +int WP_ReceiveBytes(uint8_t* ptr, uint16_t* size) +{ + // save for latter comparison + uint16_t requestedSize = *size; + + // sanity check for request of 0 size + if(*size) + { + ////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + ////////////////////////////////////////////////////////// + // change here to read (size) bytes from the input stream + // preferably with read timeout and being able to check + // if the requested number of bytes was actually read + ////////////////////////////////////////////////////////// + + // read from serial stream + size_t read = streamRead(&SDU1, ptr, *size); + + ptr += read; + *size -= read; + + TRACE( TRACE_STATE, "RXMSG: Expecting %d bytes, received %d.\n",requestedSize, read); + + // check if the requested read matches the actual read count + return (requestedSize == read); + } + + return true; +} +#elif (HAL_USE_SERIAL == TRUE) + +int WP_ReceiveBytes(uint8_t* ptr, uint16_t* size) +{ + // save for latter comparison + uint16_t requestedSize = *size; + + // sanity check for request of 0 size + if(*size) + { + ////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + ////////////////////////////////////////////////////////// + // change here to read (size) bytes from the input stream + // preferably with read timeout and being able to check + // if the requested number of bytes was actually read + ////////////////////////////////////////////////////////// + + // non blocking read from serial port with 100ms timeout + volatile size_t read = sdReadTimeout(&SERIAL_DRIVER, ptr, *size, TIME_MS2I(250)); + + ptr += read; + *size -= read; + + TRACE( TRACE_STATE, "RXMSG: Expecting %d bytes, received %d.\n",requestedSize, read); + + // check if the requested read matches the actual read count + return (requestedSize == read); + } + + return true; +} + +#else +#error "Wire Protocol needs a transport. Please make sure that HAL_USE_SERIAL and/or HAL_USE_SERIAL_USB are set to TRUE in 'halconf.h'" +#endif + +#if (HAL_USE_SERIAL_USB == TRUE) + +int WP_TransmitMessage(WP_Message* message) +{ + uint32_t writeResult; + bool operationResult = false; + + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // change here to write (size) bytes to the output stream + // preferably with timeout and being able to check + // if the write was sucessfull or at least buffered + ////////////////////////////////////////////////////////// + + TRACE( TRACE_HEADERS, "TXMSG: 0x%08X, 0x%08X, 0x%08X\n", message->m_header.m_cmd, message->m_header.m_flags, message->m_header.m_size ); + + // write header to output stream + writeResult = streamWrite(&SDU1, (const uint8_t *)&message->m_header, sizeof(message->m_header)); + + if(writeResult == sizeof(message->m_header)) + { + operationResult = true; + + // if there is anything on the payload send it to the output stream + if(message->m_header.m_size && message->m_payload) + { + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // see description above + ////////////////////////////////////////////////////////// + + // reset flag + operationResult = false; + + writeResult = streamWrite(&SDU1, message->m_payload, message->m_header.m_size); + + if(writeResult == message->m_header.m_size) + { + operationResult = true; + + TRACE0( TRACE_ERRORS, "TXMSG: OK\n"); + } + } + } + + return operationResult; +} +#elif (HAL_USE_SERIAL == TRUE) + +int WP_TransmitMessage(WP_Message* message) +{ + uint32_t writeResult; + bool operationResult = false; + + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // change here to write (size) bytes to the output stream + // preferably with timeout and being able to check + // if the write was sucessfull or at least buffered + ////////////////////////////////////////////////////////// + + TRACE( TRACE_HEADERS, "TXMSG: 0x%08X, 0x%08X, 0x%08X\n", message->m_header.m_cmd, message->m_header.m_flags, message->m_header.m_size ); + + // write header to output stream + writeResult = chnWriteTimeout(&SERIAL_DRIVER, (const uint8_t *)&message->m_header, sizeof(message->m_header), TIME_MS2I(250)); + + if(writeResult == sizeof(message->m_header)) + { + operationResult = true; + + // if there is anything on the payload send it to the output stream + if(message->m_header.m_size && message->m_payload) + { + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // see description above + ////////////////////////////////////////////////////////// + + // reset flag + operationResult = false; + + writeResult = chnWriteTimeout(&SERIAL_DRIVER, message->m_payload, message->m_header.m_size, TIME_MS2I(250)); + + if(writeResult == message->m_header.m_size) + { + operationResult = true; + + TRACE0( TRACE_ERRORS, "TXMSG: OK\n"); + } + } + } + + return operationResult; +} + +#else +#error "Wire Protocol needs a transport. Please make sure that HAL_USE_SERIAL and/or HAL_USE_SERIAL_USB are set to TRUE in 'halconf.h'" +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_ReceiverThread.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_ReceiverThread.c new file mode 100644 index 00000000..e2a4aa9f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/WireProtocol_ReceiverThread.c @@ -0,0 +1,63 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +extern WP_Message inboundMessage; + +#if (HAL_USE_SERIAL_USB == TRUE) +extern SerialUSBDriver SDU1; +#endif + +// This thread needs to be implemented at ChibiOS level because it has to include a call to chThdShouldTerminateX() +// in case the thread is requested to terminate by the CMSIS call osThreadTerminate() + +__attribute__((noreturn)) +void ReceiverThread(void const * argument) +{ + (void)argument; + + osDelay(500); + + #if (HAL_USE_STM32_CRC == TRUE) + // startup crc + crcStart(NULL); + #endif + + // loop until thread receives a request to terminate + while (1) { + + #if (HAL_USE_SERIAL_USB == TRUE) + // only bother to wait for WP message is USB is connected + if (SDU1.config->usbp->state == USB_ACTIVE) + { + #endif + + WP_Message_Initialize(&inboundMessage); + WP_Message_PrepareReception(&inboundMessage); + + WP_Message_Process(&inboundMessage); + + #if (HAL_USE_SERIAL_USB == TRUE) + // pass control to the OS + osThreadYield(); + } + else + { + osDelay(1000); + } + + #elif (HAL_USE_SERIAL == TRUE) + // delay here to give other threads a chance to run + osDelay(100); + #endif + + } + + // this function never returns +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/hard_fault_handler.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/hard_fault_handler.c new file mode 100644 index 00000000..97668a42 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/hard_fault_handler.c @@ -0,0 +1,161 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +//See http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABBGBEC.html +typedef enum { + Reset = 1, + NMI = 2, + HardFault = 3, + MemManage = 4, + BusFault = 5, + UsageFault = 6, +} FaultType; + +#if defined(STM32F4XX) || defined(STM32F7XX) + +void NMI_Handler(void) { + while(1); +} + +#endif + +// dev note: on all the following the variables need to be declared as volatile so they don't get optimized out by the linker +// dev note: the pragma below is to ignore the warning because the variables aren't actually being used despite needing to remain there for debug + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +void HardFault_Handler(void) { + + //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info + struct port_extctx ctx; + + //Get thread context. Contains main registers including PC and LR + memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx)); + (void)ctx; + + //Interrupt status register: Which interrupt have we encountered, e.g. HardFault? + volatile FaultType faultType = (FaultType)__get_IPSR(); + + // these are not available in all the STM32 series +#if defined(STM32F4XX) || defined(STM32F7XX) + + //Flags about hardfault / busfault + //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference + volatile bool isFaultPrecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 1) ? true : false); + volatile bool isFaultImprecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 2) ? true : false); + volatile bool isFaultOnUnstacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 3) ? true : false); + volatile bool isFaultOnStacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 4) ? true : false); + volatile bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 7) ? true : false); + + // Hard Fault Status Register + volatile unsigned long _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ; + + // Debug Fault Status Register + volatile unsigned long _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ; + + // Auxiliary Fault Status Register + volatile unsigned long _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ; + + // Read the Fault Address Registers. These may not contain valid values. + // Check BFARVALID/MMARVALID to see if they are valid values + + // MemManage Fault Address Register + volatile unsigned long _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ; + + //For HardFault/BusFault this is the address that was accessed causing the error + volatile uint32_t faultAddress = SCB->BFAR; + +#endif + + // forces a breakpoint causing the debugger to stop + // if no debugger is attached this is ignored + __asm volatile("BKPT #0\n"); + + // If no debugger connected, just reset the board + NVIC_SystemReset(); +} + +void BusFault_Handler(void) __attribute__((alias("HardFault_Handler"))); + +void UsageFault_Handler(void) { + + //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info + //Get thread context. Contains main registers including PC and LR + struct port_extctx ctx; + memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx)); + (void)ctx; + + //Interrupt status register: Which interrupt have we encountered, e.g. HardFault? + FaultType faultType = (FaultType)__get_IPSR(); + (void)faultType; + + // these are not available in all the STM32 series +#if defined(STM32F4XX) || defined(STM32F7XX) + + //Flags about hardfault / busfault + //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference + volatile bool isUndefinedInstructionFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 0) ? true : false); + volatile bool isEPSRUsageFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 1) ? true : false); + volatile bool isInvalidPCFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 2) ? true : false); + volatile bool isNoCoprocessorFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 3) ? true : false); + volatile bool isUnalignedAccessFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 8) ? true : false); + volatile bool isDivideByZeroFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 9) ? true : false); + +#endif + + // forces a breakpoint causing the debugger to stop + // if no debugger is attached this is ignored + __asm volatile("BKPT #0\n"); + + // If no debugger connected, just reset the board + NVIC_SystemReset(); +} + +void MemManage_Handler(void) { + + //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info + //Get thread context. Contains main registers including PC and LR + struct port_extctx ctx; + memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx)); + (void)ctx; + + //Interrupt status register: Which interrupt have we encountered, e.g. HardFault? + FaultType faultType = (FaultType)__get_IPSR(); + (void)faultType; + + // these are not available in all the STM32 series +#if defined(STM32F4XX) || defined(STM32F7XX) + + //For HardFault/BusFault this is the address that was accessed causing the error + volatile uint32_t faultAddress = SCB->MMFAR; + + //Flags about hardfault / busfault + //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference + volatile bool isInstructionAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 0) ? true : false); + volatile bool isDataAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 1) ? true : false); + volatile bool isExceptionUnstackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 3) ? true : false); + volatile bool isExceptionStackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 4) ? true : false); + volatile bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 7) ? true : false); + +#endif + + // forces a breakpoint causing the debugger to stop + // if no debugger is attached this is ignored + __asm volatile("BKPT #0\n"); + + // If no debugger connected, just reset the board + NVIC_SystemReset(); +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/nanoSupport_CRC32.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/nanoSupport_CRC32.c new file mode 100644 index 00000000..3979ff2a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/nanoSupport_CRC32.c @@ -0,0 +1,26 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include + +#if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ + defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32L0XX) || \ + defined(STM32L1XX) || defined(STM32H7XX) + +// strong implementation of this function specific to the STM32 targets +unsigned int SUPPORT_ComputeCRC(const void* rgBlock, int nLength, unsigned int crc) +{ + crcAquireModule(); + + crc = crcCompute(rgBlock, nLength, crc); + + crcReleaseModule(); + + return crc; +}; + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_BlockStorage.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_BlockStorage.c new file mode 100644 index 00000000..868a5878 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_BlockStorage.c @@ -0,0 +1,22 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// map here the Block Storage Interface to the STM32 driver +IBlockStorageDevice STM32Flash_BlockStorageInterface = +{ + &STM32FlashDriver_InitializeDevice, + &STM32FlashDriver_UninitializeDevice, + &STM32FlashDriver_GetDeviceInfo, + &STM32FlashDriver_Read, + &STM32FlashDriver_Write, + NULL, + &STM32FlashDriver_IsBlockErased, + &STM32FlashDriver_EraseBlock, + NULL, + NULL +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_heap.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_heap.c new file mode 100644 index 00000000..87c648d3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/platform_heap.c @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void* platform_malloc(size_t size) { + return chHeapAlloc(NULL, size); +} + +void platform_free(void* ptr) { + chHeapFree(ptr); +} + +void* platform_realloc(void* ptr, size_t size) { + (void)size; + + return ptr; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules.ld new file mode 100644 index 00000000..4e323fa8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules.ld @@ -0,0 +1,19 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +/* Stack rules inclusion.*/ +INCLUDE rules_stacks.ld + +/* Code rules inclusion.*/ +INCLUDE rules_code.ld + +/* Data rules inclusion.*/ +INCLUDE rules_data.ld + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_clr.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_clr.ld new file mode 100644 index 00000000..80cedd4f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_clr.ld @@ -0,0 +1,21 @@ + SECTIONS +{ + + /* nanoFramework CLR managed heap section at the specified RAM section.*/ + .clr_managed_heap (NOLOAD) : + { + . = ALIGN(8); + __clr_managed_heap_base__ = .; + PROVIDE(HeapBegin = LOADADDR(.clr_managed_heap)); + . = ORIGIN(CLR_MANAGED_HEAP_RAM) + LENGTH(CLR_MANAGED_HEAP_RAM) - LENGTH(ramvt); + . = ALIGN(8); + __clr_managed_heap_end__ = .; + PROVIDE(HeapEnd = .); + } > CLR_MANAGED_HEAP_RAM + + /* RAM space reserved for the vector table */ + .RAMVectorTable (NOLOAD) : ALIGN(4) + { + *(.RAMVectorTable) + } > ramvt +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_code.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_code.ld new file mode 100644 index 00000000..80a49318 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_code.ld @@ -0,0 +1,79 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +__nanoImage_start__ = ORIGIN(flash); +__nanoImage_size__ = LENGTH(flash); +__nanoImage_end__ = __nanoImage_start__ + __nanoImage_size__; +__nanoConfig_start__ = ORIGIN(config); +__nanoConfig_size__ = LENGTH(config); +__nanoConfig_end__ = __nanoConfig_start__ + __nanoConfig_size__; +__deployment_start__ = ORIGIN(deployment); +__deployment_size__ = LENGTH(deployment); +__deployment_end__ = __deployment_start__ + __deployment_size__; + +ENTRY(Reset_Handler) + +SECTIONS +{ + .vectors : ALIGN(16) + { + KEEP(*(.vectors)) + } > VECTORS_FLASH AT > VECTORS_FLASH_LMA + + .xtors : ALIGN(4) + { + __init_array_start = .; + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + __init_array_end = .; + __fini_array_start = .; + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + __fini_array_end = .; + } > XTORS_FLASH AT > XTORS_FLASH_LMA + + .text : ALIGN(16) + { + *(.text) + *(.text.*) + *(.glue_7t) + *(.glue_7) + *(.gcc*) + } > TEXT_FLASH AT > TEXT_FLASH_LMA + + .rodata : ALIGN(4) + { + . = ALIGN(4); + __rodata_base__ = .; + *(.rodata) + *(.rodata.*) + . = ALIGN(4); + __rodata_end__ = .; + } > RODATA_FLASH AT > RODATA_FLASH_LMA + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA + + .eh_frame : ONLY_IF_RO + { + *(.eh_frame) + } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_data.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_data.ld new file mode 100644 index 00000000..18da2784 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_data.ld @@ -0,0 +1,266 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +__ram0_start__ = ORIGIN(ram0); +__ram0_size__ = LENGTH(ram0); +__ram0_end__ = __ram0_start__ + __ram0_size__; +__ram1_start__ = ORIGIN(ram1); +__ram1_size__ = LENGTH(ram1); +__ram1_end__ = __ram1_start__ + __ram1_size__; +__ram2_start__ = ORIGIN(ram2); +__ram2_size__ = LENGTH(ram2); +__ram2_end__ = __ram2_start__ + __ram2_size__; +__ram3_start__ = ORIGIN(ram3); +__ram3_size__ = LENGTH(ram3); +__ram3_end__ = __ram3_start__ + __ram3_size__; +__ram4_start__ = ORIGIN(ram4); +__ram4_size__ = LENGTH(ram4); +__ram4_end__ = __ram4_start__ + __ram4_size__; +__ram5_start__ = ORIGIN(ram5); +__ram5_size__ = LENGTH(ram5); +__ram5_end__ = __ram5_start__ + __ram5_size__; +__ram6_start__ = ORIGIN(ram6); +__ram6_size__ = LENGTH(ram6); +__ram6_end__ = __ram6_start__ + __ram6_size__; +__ram7_start__ = ORIGIN(ram7); +__ram7_size__ = LENGTH(ram7); +__ram7_end__ = __ram7_start__ + __ram7_size__; + +ENTRY(Reset_Handler) + +SECTIONS +{ + .data : ALIGN(4) + { + . = ALIGN(4); + PROVIDE(_textdata = LOADADDR(.data)); + PROVIDE(_data = .); + _textdata_start = LOADADDR(.data); + _data_start = .; + *(.data) + *(.data.*) + *(.ramtext) + . = ALIGN(4); + PROVIDE(_edata = .); + _data_end = .; + } > DATA_RAM AT > DATA_RAM_LMA + + .bss (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + _bss_start = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + _bss_end = .; + PROVIDE(end = .); + } > BSS_RAM + + .ram0_init : ALIGN(4) + { + . = ALIGN(4); + __ram0_init_text__ = LOADADDR(.ram0_init); + __ram0_init__ = .; + KEEP(*(.ram0_init)) + KEEP(*(.ram0_init.*)) + . = ALIGN(4); + } > ram0 AT > RAM_INIT_FLASH_LMA + + .ram0 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram0_clear__ = .; + *(.ram0_clear) + *(.ram0_clear.*) + . = ALIGN(4); + __ram0_noinit__ = .; + *(.ram0) + *(.ram0.*) + . = ALIGN(4); + __ram0_free__ = .; + } > ram0 + + .ram1_init : ALIGN(4) + { + . = ALIGN(4); + __ram1_init_text__ = LOADADDR(.ram1_init); + __ram1_init__ = .; + KEEP(*(.ram1_init)) + KEEP(*(.ram1_init.*)) + . = ALIGN(4); + } > ram1 AT > RAM_INIT_FLASH_LMA + + .ram1 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram1_clear__ = .; + *(.ram1_clear) + *(.ram1_clear.*) + . = ALIGN(4); + __ram1_noinit__ = .; + *(.ram1) + *(.ram1.*) + . = ALIGN(4); + __ram1_free__ = .; + } > ram1 + + .ram2_init : ALIGN(4) + { + . = ALIGN(4); + __ram2_init_text__ = LOADADDR(.ram2_init); + __ram2_init__ = .; + KEEP(*(.ram2_init)) + KEEP(*(.ram2_init.*)) + . = ALIGN(4); + } > ram2 AT > RAM_INIT_FLASH_LMA + + .ram2 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram2_clear__ = .; + *(.ram2_clear) + *(.ram2_clear.*) + . = ALIGN(4); + __ram2_noinit__ = .; + *(.ram2) + *(.ram2.*) + . = ALIGN(4); + __ram2_free__ = .; + } > ram2 + + .ram3_init : ALIGN(4) + { + . = ALIGN(4); + __ram3_init_text__ = LOADADDR(.ram3_init); + __ram3_init__ = .; + KEEP(*(.ram3_init)) + KEEP(*(.ram3_init.*)) + . = ALIGN(4); + } > ram3 AT > RAM_INIT_FLASH_LMA + + .ram3 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram3_clear__ = .; + *(.ram3_clear) + *(.ram3_clear.*) + . = ALIGN(4); + __ram3_noinit__ = .; + *(.ram3) + *(.ram3.*) + . = ALIGN(4); + __ram3_free__ = .; + } > ram3 + + .ram4_init : ALIGN(4) + { + . = ALIGN(4); + __ram4_init_text__ = LOADADDR(.ram4_init); + __ram4_init__ = .; + KEEP(*(.ram4_init)) + KEEP(*(.ram4_init.*)) + . = ALIGN(4); + } > ram4 AT > RAM_INIT_FLASH_LMA + + .ram4 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram4_clear__ = .; + *(.ram4_clear) + *(.ram4_clear.*) + . = ALIGN(4); + __ram4_noinit__ = .; + *(.ram4) + *(.ram4.*) + . = ALIGN(4); + __ram4_free__ = .; + } > ram4 + + .ram5_init : ALIGN(4) + { + . = ALIGN(4); + __ram5_init_text__ = LOADADDR(.ram5_init); + __ram5_init__ = .; + KEEP(*(.ram5_init)) + KEEP(*(.ram5_init.*)) + . = ALIGN(4); + } > ram5 AT > RAM_INIT_FLASH_LMA + + .ram5 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram5_clear__ = .; + *(.ram5_clear) + *(.ram5_clear.*) + . = ALIGN(4); + __ram5_noinit__ = .; + *(.ram5) + *(.ram5.*) + . = ALIGN(4); + __ram5_free__ = .; + } > ram5 + + .ram6_init : ALIGN(4) + { + . = ALIGN(4); + __ram6_init_text__ = LOADADDR(.ram6_init); + __ram6_init__ = .; + KEEP(*(.ram6_init)) + KEEP(*(.ram6_init.*)) + . = ALIGN(4); + } > ram6 AT > RAM_INIT_FLASH_LMA + + .ram6 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram6_clear__ = .; + *(.ram6_clear) + *(.ram6_clear.*) + . = ALIGN(4); + __ram6_noinit__ = .; + *(.ram6) + *(.ram6.*) + . = ALIGN(4); + __ram6_free__ = .; + } > ram6 + + .ram7_init : ALIGN(4) + { + . = ALIGN(4); + __ram7_init_text__ = LOADADDR(.ram7_init); + __ram7_init__ = .; + KEEP(*(.ram7_init)) + KEEP(*(.ram7_init.*)) + . = ALIGN(4); + } > ram7 AT > RAM_INIT_FLASH_LMA + + .ram7 (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __ram7_clear__ = .; + *(.ram7_clear) + *(.ram7_clear.*) + . = ALIGN(4); + __ram7_noinit__ = .; + *(.ram7) + *(.ram7.*) + . = ALIGN(4); + __ram7_free__ = .; + } > ram7 + + /* The default heap uses the (statically) unused part of a RAM section.*/ + .heap (NOLOAD) : + { + . = ALIGN(8); + __heap_base__ = .; + . += __crt_heap_size__; + . = ALIGN(8); + __heap_end__ = .; + } > HEAP_RAM +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_stacks.ld b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_stacks.ld new file mode 100644 index 00000000..227a90c6 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/rules_stacks.ld @@ -0,0 +1,31 @@ +/* +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// +*/ + +SECTIONS +{ + /* Special section for exceptions stack.*/ + .mstack : + { + . = ALIGN(8); + __main_stack_base__ = .; + . += __main_stack_size__; + . = ALIGN(8); + __main_stack_end__ = .; + } > MAIN_STACK_RAM + + /* Special section for process stack.*/ + .pstack : + { + __process_stack_base__ = .; + __main_thread_stack_base__ = .; + . += __process_stack_size__; + . = ALIGN(8); + __process_stack_end__ = .; + __main_thread_stack_end__ = .; + } > PROCESS_STACK_RAM +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL.c new file mode 100644 index 00000000..0088b871 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL.c @@ -0,0 +1,50 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +void HAL_AssertEx() +{ + __BKPT(0); + while(true) { /*nop*/ } +} + +#if !defined(BUILD_RTM) + +void HARD_Breakpoint() +{ + __BKPT(0); + while(true) { /*nop*/ } +}; + +#endif // !defined(BUILD_RTM) + +// Provides information whether the configuration block storage requires erase command before sending the update command +// The 'weak' implementation for ChibiOS targets is true +// If a target implements the store differently it has to provide a 'strong' implementation of this. +__nfweak bool Target_ConfigUpdateRequiresErase() +{ + return true; +}; + +bool Target_HasNanoBooter() +{ + return false; +}; + +// declarations of platform capabilities +uint32_t GetPlatformCapabilities() +{ + return 0; +}; + +// declarations of target capabilities +// If a target has something to declare it has to provide a 'strong' implementation of this. +__nfweak uint32_t GetTargetCapabilities() +{ + return TargetCapabilities_JtagUpdate; +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_ConfigurationManager.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_ConfigurationManager.cpp new file mode 100644 index 00000000..8a84adf0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_ConfigurationManager.cpp @@ -0,0 +1,379 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +// initialization of configuration manager +// provided as weak so it can be replaced at target level, if required because of the target implementing the storage with a mechanism other then saving to flash +__nfweak void ConfigurationManager_Initialize() +{ + // init g_TargetConfiguration + memset(&g_TargetConfiguration, 0, sizeof(HAL_TARGET_CONFIGURATION)); + + // enumerate the blocks + ConfigurationManager_EnumerateConfigurationBlocks(); +}; + +// Enumerates the configuration blocks from the configuration flash sector +// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used +__nfweak void ConfigurationManager_EnumerateConfigurationBlocks() +{ + // start checking if this device has config block + if(((uint32_t)&__nanoConfig_end__ - (uint32_t)&__nanoConfig_start__) > 0) + { + // find network configuration blocks + HAL_CONFIGURATION_NETWORK* networkConfigs = (HAL_CONFIGURATION_NETWORK*)ConfigurationManager_FindNetworkConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__); + + // check network configs count + if(networkConfigs->Count == 0) + { + // there is no network config block available, get a default + HAL_Configuration_NetworkInterface* networkConfig = (HAL_Configuration_NetworkInterface*)platform_malloc(sizeof(HAL_Configuration_NetworkInterface)); + + if(InitialiseNetworkDefaultConfig(networkConfig, 0)) + { + // config block created, store it + ConfigurationManager_StoreConfigurationBlock(networkConfig, DeviceConfigurationOption_Network, 0, sizeof(HAL_Configuration_NetworkInterface), 0); + + // have to enumerate again to pick it up + networkConfigs = (HAL_CONFIGURATION_NETWORK*)ConfigurationManager_FindNetworkConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__); + } + + platform_free(networkConfig); + } + + // find wireless 80211 network configuration blocks + HAL_CONFIGURATION_NETWORK_WIRELESS80211* networkWirelessConfigs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211*)ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__); + + // find X509 certificate blocks + HAL_CONFIGURATION_X509_CERTIFICATE* certificateStore = (HAL_CONFIGURATION_X509_CERTIFICATE*)ConfigurationManager_FindX509CertificateConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__); + + // alloc memory for g_TargetConfiguration + // because this is a struct of structs that use flexible members the memory has to be allocated from the heap + // the malloc size for each struct is computed separately + uint32_t sizeOfNetworkInterfaceConfigs = offsetof(HAL_CONFIGURATION_NETWORK, Configs) + networkConfigs->Count * sizeof(networkConfigs->Configs[0]); + uint32_t sizeOfWireless80211Configs = offsetof(HAL_CONFIGURATION_NETWORK_WIRELESS80211, Configs) + networkWirelessConfigs->Count * sizeof(networkWirelessConfigs->Configs[0]); + uint32_t sizeOfX509CertificateStore = offsetof(HAL_CONFIGURATION_X509_CERTIFICATE, Certificates) + certificateStore->Count * sizeof(certificateStore->Certificates[0]); + + g_TargetConfiguration.NetworkInterfaceConfigs = (HAL_CONFIGURATION_NETWORK*)platform_malloc(sizeOfNetworkInterfaceConfigs); + g_TargetConfiguration.Wireless80211Configs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211*)platform_malloc(sizeOfWireless80211Configs); + g_TargetConfiguration.CertificateStore = (HAL_CONFIGURATION_X509_CERTIFICATE*)platform_malloc(sizeOfX509CertificateStore); + + // copy structs to g_TargetConfiguration + memcpy((HAL_CONFIGURATION_NETWORK*)g_TargetConfiguration.NetworkInterfaceConfigs, networkConfigs, sizeOfNetworkInterfaceConfigs); + memcpy((HAL_CONFIGURATION_NETWORK_WIRELESS80211*)g_TargetConfiguration.Wireless80211Configs, networkWirelessConfigs, sizeOfWireless80211Configs); + memcpy((HAL_CONFIGURATION_X509_CERTIFICATE*)g_TargetConfiguration.CertificateStore, certificateStore, sizeOfX509CertificateStore); + + // now free the memory of the original structs + platform_free(networkConfigs); + platform_free(networkWirelessConfigs); + platform_free(certificateStore); + } + else + { + // no config block + } +} + +// Gets the network configuration block from the configuration flash sector +// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used +__nfweak bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + int sizeOfBlock = 0; + uint8_t* blockAddress = NULL; + + // validate if the requested block exists + // Count has to be non zero + // requested Index has to exist (array index starts at zero, so need to add one) + if(configuration == DeviceConfigurationOption_Network) + { + if( g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count) + { + // the requested config block is beyond the available count + return false; + } + + // set block size + sizeOfBlock = sizeof(HAL_Configuration_NetworkInterface); + + // get block address + blockAddress = (uint8_t*)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex]; + } + else if(configuration == DeviceConfigurationOption_Wireless80211Network) + { + if(g_TargetConfiguration.Wireless80211Configs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count) + { + return FALSE; + } + + // set block size + sizeOfBlock = sizeof(HAL_Configuration_Wireless80211); + + // get block address + blockAddress = (uint8_t*)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex]; + } + else if(configuration == DeviceConfigurationOption_X509CaRootBundle) + { + if(g_TargetConfiguration.CertificateStore->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.CertificateStore->Count) + { + return FALSE; + } + + // get block address + blockAddress = (uint8_t*)g_TargetConfiguration.CertificateStore->Certificates[configurationIndex]; + + // set block size + // because X509 certificate has a variable length need to compute the block size in two steps + sizeOfBlock = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + sizeOfBlock += ((HAL_Configuration_X509CaRootBundle*)blockAddress)->CertificateSize; + } + + // copy the config block content to the pointer in the argument + memcpy(configurationBlock, blockAddress, sizeOfBlock); + + return TRUE; +} + +// Stores the configuration block to the configuration flash sector +// NOTE: because inserting or removing a configuration block it's very 'RAM expensive' we choose not to support those operations +// the host debugger will have to be used to manage these operations on the device configuration collection +// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used +__nfweak bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize, uint32_t offset) +{ + ByteAddress storageAddress = 0; + bool requiresEnumeration = FALSE; + bool success = FALSE; + + if(configuration == DeviceConfigurationOption_Network) + { + if( g_TargetConfiguration.NetworkInterfaceConfigs == NULL || + ( g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 && + configurationIndex == 0 )) + { + // there is no network config block, we are storing the default one + // THIS IS THE ONLY CONFIG BLOCK THAT'S AUTO-CREATED + // OK to continue + // set storage address as the start of the flash configuration sector + storageAddress = (ByteAddress)&__nanoConfig_start__; + } + else + { + // the requested config block is beyond the available count + if((configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count) + { + return FALSE; + } + + // set storage address from block address, plus the requested offset + storageAddress = (ByteAddress)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex] + offset; + } + + // set block size, in case it's not already set + blockSize = sizeof(HAL_Configuration_NetworkInterface); + + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + _ASSERTE(((HAL_Configuration_NetworkInterface*)configurationBlock)->StartupAddressMode > 0); + } + else if(configuration == DeviceConfigurationOption_Wireless80211Network) + { + if( g_TargetConfiguration.Wireless80211Configs == NULL || + (g_TargetConfiguration.Wireless80211Configs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count)) + { + // there is no room for this block, or there are no blocks stored at all + // failing the operation + return FALSE; + } + + // set storage address from block address, plus the requested offset + storageAddress = (ByteAddress)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex] + offset; + + // set block size, in case it's not already set + blockSize = sizeof(HAL_Configuration_Wireless80211); + + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_WIRELESS80211_V1, sizeof(c_MARKER_CONFIGURATION_WIRELESS80211_V1)); + } + else if(configuration == DeviceConfigurationOption_X509CaRootBundle) + { + if( g_TargetConfiguration.Wireless80211Configs == NULL || + (g_TargetConfiguration.CertificateStore->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.CertificateStore->Count)) + { + // there is no room for this block, or there are no blocks stored at all + // failing the operation + return FALSE; + } + + // set storage address from block address, plus the requested offset + storageAddress = (ByteAddress)g_TargetConfiguration.CertificateStore->Certificates[configurationIndex] + offset; + + // set block size, in case it's not already set + // because X509 certificate has a variable length need to compute the block size in two steps + blockSize = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + blockSize += ((HAL_Configuration_X509CaRootBundle*)configurationBlock)->CertificateSize; + + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1, sizeof(c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1)); + } + else if(configuration == DeviceConfigurationOption_All) + { + // particular situation where we are receiving the full configuration block + + // set storage address as the start of the flash configuration sector, plus the requested offset + storageAddress = (ByteAddress)&__nanoConfig_start__ + offset; + + // always enumerate the blocks again after storing it + requiresEnumeration = TRUE; + + // for save all the block size has to be provided, check that + if(blockSize == 0) + { + return FALSE; + } + } + + // copy the config block content to the config block storage + success = STM32FlashDriver_Write(NULL, storageAddress, blockSize, (unsigned char*)configurationBlock, true); + + if(success == TRUE && requiresEnumeration) + { + // free the current allocation(s) + platform_free(g_TargetConfiguration.NetworkInterfaceConfigs); + platform_free(g_TargetConfiguration.Wireless80211Configs); + platform_free(g_TargetConfiguration.CertificateStore); + + // perform enumeration of configuration blocks + ConfigurationManager_EnumerateConfigurationBlocks(); + } + + return success; +} + +// Updates a configuration block in the configuration flash sector +// The flash sector has to be erased before writing the updated block +// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used +__nfweak bool ConfigurationManager_UpdateConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + ByteAddress storageAddress; + uint32_t blockOffset; + uint8_t* blockAddressInCopy; + uint32_t blockSize; + bool success = FALSE; + + // config sector size + int sizeOfConfigSector = (uint32_t)&__nanoConfig_end__ - (uint32_t)&__nanoConfig_start__; + + // allocate memory from CRT heap + uint8_t* configSectorCopy = (uint8_t*)platform_malloc(sizeOfConfigSector); + + if(configSectorCopy != NULL) + { + // copy config sector from flash to RAM + memcpy(configSectorCopy, &__nanoConfig_start__, sizeOfConfigSector); + + // find out the address for the config block to update in the configSectorCopy + // because we are copying back the config block to flash and just replacing the config block content + // the addresses in g_TargetConfiguration will remain the same + // plus we can calculate the offset of the config block from g_TargetConfiguration + if(configuration == DeviceConfigurationOption_Network) + { + // get storage address from block address + storageAddress = (ByteAddress)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex]; + + // set block size, in case it's not already set + blockSize = sizeof(HAL_Configuration_NetworkInterface); + + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + _ASSERTE(((HAL_Configuration_NetworkInterface*)configurationBlock)->StartupAddressMode > 0); + } + else if(configuration == DeviceConfigurationOption_Wireless80211Network) + { + // storage address from block address + storageAddress = (ByteAddress)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex]; + + // set block size, in case it's not already set + blockSize = sizeof(HAL_Configuration_Wireless80211); + + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_WIRELESS80211_V1, sizeof(c_MARKER_CONFIGURATION_WIRELESS80211_V1)); + } + else if(configuration == DeviceConfigurationOption_X509CaRootBundle) + { + // storage address from block address + storageAddress = (ByteAddress)g_TargetConfiguration.CertificateStore->Certificates[configurationIndex]; + + // set block size, in case it's not already set + // because X509 certificate has a variable length need to compute the block size in two steps + blockSize = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + blockSize += ((HAL_Configuration_X509CaRootBundle*)configurationBlock)->CertificateSize; + + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1, sizeof(c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1)); + } + else + { + // this not a valid configuration option to update, quit + // free memory first + platform_free(configSectorCopy); + + return FALSE; + } + + // erase config sector + if(STM32FlashDriver_EraseBlock(NULL, (uint32_t)&__nanoConfig_start__) == TRUE) + { + // flash block is erased + + // subtract the start address of config sector to get the offset + blockOffset = storageAddress - (uint32_t)&__nanoConfig_start__; + + // set pointer to block to udpate + blockAddressInCopy = configSectorCopy + blockOffset; + + // replace config block with new content by replacing memory + memcpy(blockAddressInCopy, configSectorCopy, blockSize); + + // copy the config block copy back to the config block storage + success = STM32FlashDriver_Write(NULL, (uint32_t)&__nanoConfig_start__, sizeOfConfigSector, (unsigned char*)configSectorCopy, true); + } + + // free memory + platform_free(configSectorCopy); + } + + return success; +} + +// Default initialisation for wireless config block +// it's implemented with 'weak' attribute so it can be replaced at target level if different configurations are intended +__nfweak void InitialiseWirelessDefaultConfig(HAL_Configuration_Wireless80211 * pconfig, uint32_t configurationIndex) +{ + (void)pconfig; + (void)configurationIndex; + + // currently empty as no ChibiOS target has Wireless 802.11 interface +} + +// Default initialisation for Network interface config blocks +// it's implemented with 'weak' attribute so it can be replaced at target level if different configurations are intended +__nfweak bool InitialiseNetworkDefaultConfig(HAL_Configuration_NetworkInterface * pconfig, uint32_t configurationIndex) +{ + (void)pconfig; + (void)configurationIndex; + + // can't create a "default" network config because we are lacking definition of a MAC address + return FALSE; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Network.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Network.cpp new file mode 100644 index 00000000..e7b265ca --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Network.cpp @@ -0,0 +1,71 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// This file includes the platform and board specific Network Intialisation + +#include +#include + + +// this is the declaration for the callback implement in nf_sys_arch.c +extern "C" void set_signal_sock_function( void (*funcPtr)() ); + +// +// Callback from lwIP on event +// +void sys_signal_sock_event() +{ + Events_Set(SYSTEM_EVENT_FLAG_SOCKET); +} + +void nanoHAL_Network_Initialize() +{ + // Initialise the lwIP CLR signal callback + set_signal_sock_function( &sys_signal_sock_event ); + + // get network configuration, if available + if(g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0) + { + // there is no networking configuration block, can't proceed + return; + } + + HAL_Configuration_NetworkInterface networkConfig; + + if(ConfigurationManager_GetConfigurationBlock((void *)&networkConfig, DeviceConfigurationOption_Network, 0) == true) + { + // build lwIP configuration + struct lwipthread_opts lwipOptions; + + // grab MAC address + lwipOptions.macaddress = (uint8_t *)networkConfig.MacAddress; + + // static or dinamic address + if(networkConfig.StartupAddressMode == AddressMode_Static) + { + // IPv4 configs + lwipOptions.address = networkConfig.IPv4Address; + lwipOptions.netmask = networkConfig.IPv4NetMask; + lwipOptions.gateway = networkConfig.IPv4GatewayAddress; + } + else if(networkConfig.StartupAddressMode == AddressMode_DHCP) + { + // clear IPv4 configs + lwipOptions.address = 0; + lwipOptions.netmask = 0; + lwipOptions.gateway = 0; + } + + // set address mode option + // our enum follows lwIP defines for address mode + lwipOptions.addrMode = (net_addr_mode_t)networkConfig.StartupAddressMode; + + // we could consider making the device name configurable (or maybe not) + lwipOptions.ourHostName = "nanodevice"; + + // Start lwIP thread in ChibiOS bindings using the above options + lwipInit(&lwipOptions); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Time.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Time.cpp new file mode 100644 index 00000000..4b11d4f0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/common/targetHAL_Time.cpp @@ -0,0 +1,54 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +// Converts CMSIS sysTicks to .NET ticks (100 nanoseconds) +uint64_t HAL_Time_SysTicksToTime(unsigned int sysTicks) +{ + // convert to microseconds from CMSIS SysTicks + // this is a rewrite of ChibiOS TIME_I2US(n) macro because it will overflow if doing the math using uint32_t + // need to convert from microseconds to 100 nanoseconds + return (((sysTicks * (uint64_t)1000000) + (int64_t)CH_CFG_ST_FREQUENCY - 1) / (int64_t)CH_CFG_ST_FREQUENCY) * 10; +} + +// because HAL_Time_SysTicksToTime needs to be called from C we need a proxy to allow it to be called from 'C' code +extern "C" { + + uint64_t HAL_Time_SysTicksToTime_C(unsigned int sysTicks) + { + return HAL_Time_SysTicksToTime(sysTicks); + } +} + +// implementation required for STM Cube package +// Provides a tick value in millisecond. +extern "C" { + +uint32_t HAL_GetTick(void) +{ + return TIME_I2MS(chVTGetSystemTimeX()); +} + +} + +// implementation required for STM Cube package +// This function provides minimum delay (in milliseconds). +extern "C" { + +void HAL_Delay(uint32_t delay) +{ + systime_t start = chVTGetSystemTime(); + systime_t end = start + TIME_MS2I(delay); + + do + { + // do nothing until the timeout expires + chThdYield(); + } + while(chVTIsSystemTimeWithin(start, end)); +} + +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..d88eae23 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append target ChibiOS nanoBooter source files +list(APPEND TARGET_CHIBIOS_NANOBOOTER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_App_Interface.c") +list(APPEND TARGET_CHIBIOS_NANOBOOTER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_MonitorCommands.c") +# make var global +set(TARGET_CHIBIOS_NANOBOOTER_SOURCES ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} CACHE INTERNAL "make global") + +# append include directory for debugger +list(APPEND TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/CLR/Debugger") + +# append target ChibiOS nanoBooter include directory +list(APPEND TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") +# make var global +set(TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_App_Interface.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_App_Interface.c new file mode 100644 index 00000000..d2be2eeb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_App_Interface.c @@ -0,0 +1,118 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +// Initialize to a packet sequence number impossible to encounter +static uint32_t lastPacketSequence = 0x00FEFFFF; + +// defining this array here makes is local helping reduce the image size because of compiler opmitizations +static const CommandHandlerLookup c_Lookup_Request[] = +{ + /*******************************************************************************************************************************************************************/ +#define DEFINE_CMD(cmd) { CLR_DBG_Commands_c_Monitor_##cmd, &Monitor_##cmd } + DEFINE_CMD(Ping ), + DEFINE_CMD(Reboot ), + // // + DEFINE_CMD(ReadMemory ), + DEFINE_CMD(WriteMemory), + DEFINE_CMD(CheckMemory), + DEFINE_CMD(EraseMemory), + DEFINE_CMD(QueryConfiguration), + DEFINE_CMD(UpdateConfiguration), + // // + // DEFINE_CMD(Execute ), + DEFINE_CMD(MemoryMap ), + // // + // DEFINE_CMD(CheckSignature), + // // + DEFINE_CMD(FlashSectorMap), + // DEFINE_CMD(SignatureKeyUpdate), + + DEFINE_CMD(OemInfo), + +#undef DEFINE_CMD + /*******************************************************************************************************************************************************************/ +}; + +//////////////////////////////////////////////////// + +// defining this array here makes is local helping reduce the image size because of compiler opmitizations +static const CommandHandlerLookup c_Lookup_Reply[] = +{ + /*******************************************************************************************************************************************************************/ +#define DEFINE_CMD(cmd) { CLR_DBG_Commands_c_Monitor_##cmd, &Monitor_##cmd } + DEFINE_CMD(Ping), +#undef DEFINE_CMD + /*******************************************************************************************************************************************************************/ +}; + +int WP_App_ProcessHeader(WP_Message* message) +{ + // check for reception buffer overflow + if(message->m_header.m_size > sizeof(receptionBuffer)) + { + return false; + } + + message->m_payload = receptionBuffer; + return true; +} + +int WP_App_ProcessPayload(WP_Message* message) +{ + // Prevent processing duplicate packets + if(message->m_header.m_seq == lastPacketSequence) + { + return false; // Do not even respond to a repeat packet + } + + // save this packet sequence number + lastPacketSequence = message->m_header.m_seq; + + if(message->m_header.m_flags & WP_Flags_c_NACK) + { + // + // Bad packet... + // + return true; + } + + size_t num; + const CommandHandlerLookup* cmd; + + if(message->m_header.m_flags & WP_Flags_c_Reply) + { + num = ARRAYSIZE(c_Lookup_Reply); + cmd = c_Lookup_Reply; + } + else + { + num = ARRAYSIZE(c_Lookup_Request); + cmd = c_Lookup_Request; + } + + while(num--) + { + if(cmd->command == message->m_header.m_cmd) + { + // execute command handler and save the result + int commandHandlerExecuteResult = ((int(*)(WP_Message*))cmd->handler)(message); + + WP_ReplyToCommand(message, commandHandlerExecuteResult, false, NULL, 0); + return true; + } + + cmd++; + } + + WP_ReplyToCommand(message, false, false, NULL, 0); + + return true; +} + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_MonitorCommands.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_MonitorCommands.c new file mode 100644 index 00000000..8c9864b3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoBooter/WireProtocol_MonitorCommands.c @@ -0,0 +1,399 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +// helper functions + +int NanoBooter_GetReleaseInfo(ReleaseInfo* releaseInfo) +{ + releaseInfo->version.usMajor = VERSION_MAJOR; + releaseInfo->version.usMinor = VERSION_MINOR; + releaseInfo->version.usBuild = VERSION_BUILD; + releaseInfo->version.usRevision = VERSION_REVISION; + + memcpy(&releaseInfo->InfoString, OEMSYSTEMINFOSTRING, ARRAYSIZE(OEMSYSTEMINFOSTRING)); + memcpy(&releaseInfo->TargetName, TARGETNAMESTRING, ARRAYSIZE(TARGETNAMESTRING)); + memcpy(&releaseInfo->PlatformName, PLATFORMNAMESTRING, ARRAYSIZE(PLATFORMNAMESTRING)); + + return true; +} + +static int AccessMemory(uint32_t location, uint32_t lengthInBytes, uint8_t* buffer, int32_t mode, uint32_t* errorCode) +{ + // reset error code + *errorCode = AccessMemoryErrorCode_NoError; + + switch(mode) + { + case AccessMemory_Write: + // use FLASH driver to perform write operation + // this requires that HAL_USE_STM32_FLASH is set to TRUE on halconf_nf.h + return stm32FlashWrite(location, lengthInBytes, buffer); + + case AccessMemory_Erase: + // erase using FLASH driver + // this requires that HAL_USE_STM32_FLASH is set to TRUE on halconf_nf.h + return stm32FlashErase(location); + + case AccessMemory_Check: + // use FLASH driver to check is FLASH segment is erased + // this requires that HAL_USE_STM32_FLASH is set to TRUE on halconf_nf.h + return stm32FlashIsErased(location, lengthInBytes); + + case AccessMemory_Read: + // use FLASH driver to perform read operation + // this requires that HAL_USE_STM32_FLASH is set to TRUE on halconf_nf.h + stm32FlashReadBytes(location, lengthInBytes, buffer); + return true; + + default: + // default return is FALSE + return false; + } +} + +//////////////////////////////////////////////////// + +int Monitor_Ping(WP_Message* message) +{ + if((message->m_header.m_flags & WP_Flags_c_Reply) == 0) + { + Monitor_Ping_Reply cmdReply; + cmdReply.m_source = Monitor_Ping_c_Ping_Source_NanoBooter; + cmdReply.m_dbg_flags = 0; + + #if defined(WP_IMPLEMENTS_CRC32) + cmdReply.m_dbg_flags |= Monitor_Ping_c_Ping_WPFlag_SupportsCRC32; + #endif + + // Wire Protocol packet size + #if (WP_PACKET_SIZE == 512) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_0512; + #elif (WP_PACKET_SIZE == 256) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_0256; + #elif (WP_PACKET_SIZE == 128) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_0128; + #elif (WP_PACKET_SIZE == 1024) + cmdReply.m_dbg_flags |= Monitor_Ping_c_PacketSize_1024; + #endif + + + WP_ReplyToCommand(message, true, false, &cmdReply, sizeof(cmdReply)); + } + + return true; +} + +int Monitor_OemInfo(WP_Message* message) +{ + if((message->m_header.m_flags & WP_Flags_c_Reply) == 0) + { + Monitor_OemInfo_Reply cmdReply; + + bool fOK = NanoBooter_GetReleaseInfo(&cmdReply.m_releaseInfo) == true; + + WP_ReplyToCommand(message, fOK, false, &cmdReply, sizeof(cmdReply)); + } + + return true; +} + +int Monitor_ReadMemory(WP_Message* message) +{ + CLR_DBG_Commands_Monitor_ReadMemory* cmd = (CLR_DBG_Commands_Monitor_ReadMemory*)message->m_payload; + + unsigned char buf[ 1024 ]; + unsigned int len = cmd->length; if(len > sizeof(buf)) len = sizeof(buf); + uint32_t errorCode; + + AccessMemory(cmd->address, len, buf, AccessMemory_Read, &errorCode ); + + WP_ReplyToCommand(message, true, false, buf, len); + + return true; +} + +int Monitor_WriteMemory(WP_Message* message) +{ + CLR_DBG_Commands_Monitor_WriteMemory* cmd = (CLR_DBG_Commands_Monitor_WriteMemory*)message->m_payload; + CLR_DBG_Commands_Monitor_WriteMemory_Reply cmdReply; + + + // TODO: not sure if we really need this + // if(!m_signedDataState.VerifyContiguousData(cmd->m_address, cmd->m_length)) + // { + // m_signedDataState.EraseMemoryAndReset(); + + // return false; + // } + + // TODO: not sure if we really need this + // nanoBooter_OnStateChange(State_MemoryWrite, (void*)cmd->m_address); + + // assume at RAM, directly use the original address + AccessMemory(cmd->address, cmd->length, cmd->data, AccessMemory_Write, &cmdReply.ErrorCode); + + WP_ReplyToCommand(message, true, false, &cmdReply, sizeof(cmdReply)); + + return true; +} + +int Monitor_Reboot(WP_Message* message) +{ + Monitor_Reboot_Command* cmd = (Monitor_Reboot_Command*)message->m_payload; + + WP_ReplyToCommand(message, true, false, NULL, 0); + + if(cmd != NULL) + { + // only reset if we are not trying to get into the bootloader + if((cmd->m_flags & Monitor_Reboot_c_EnterBootloader) != Monitor_Reboot_c_EnterBootloader) + { + // RESET CPU + // because ChibiOS relies on CMSIS it's recommended to make use of the CMSIS API + NVIC_SystemReset(); + } + } + + return true; +} + +int Monitor_EraseMemory(WP_Message* message) +{ + CLR_DBG_Commands_Monitor_EraseMemory* cmd = (CLR_DBG_Commands_Monitor_EraseMemory*)message->m_payload; + CLR_DBG_Commands_Monitor_EraseMemory_Reply cmdReply; + + // TODO: not sure if we really need this + // nanoBooter_OnStateChange( State_MemoryErase, (void*)cmd->m_address ); + + AccessMemory(cmd->address, cmd->length, NULL, AccessMemory_Erase, &cmdReply.ErrorCode); + + WP_ReplyToCommand(message, true, false, &cmdReply, sizeof(cmdReply)); + + return true; +} + +int Monitor_QueryConfiguration(WP_Message* message) +{ + bool success = false; + + // include handling of configuration block only if feature is available + #if (HAS_CONFIG_BLOCK == TRUE) + + Monitor_QueryConfiguration_Command *cmd = (Monitor_QueryConfiguration_Command*)message->m_payload; + int size = 0; + + HAL_Configuration_NetworkInterface configNetworkInterface; + HAL_Configuration_Wireless80211 configWireless80211NetworkInterface; + + switch((DeviceConfigurationOption)cmd->Configuration) + { + case DeviceConfigurationOption_Network: + + if(ConfigurationManager_GetConfigurationBlock((void *)&configNetworkInterface, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex) == true) + { + size = sizeof(HAL_Configuration_NetworkInterface); + success = true; + + WP_ReplyToCommand( message, success, false, (uint8_t*)&configNetworkInterface, size ); + } + break; + + case DeviceConfigurationOption_Wireless80211Network: + + if(ConfigurationManager_GetConfigurationBlock((void *)&configWireless80211NetworkInterface, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex) == true) + { + size = sizeof(HAL_Configuration_Wireless80211); + success = true; + + WP_ReplyToCommand( message, success, false, (uint8_t*)&configWireless80211NetworkInterface, size ); + } + break; + + case DeviceConfigurationOption_WirelessNetworkAP: + // TODO missing implementation for now + break; + + default: + break; + } + + if(!success) + { + WP_ReplyToCommand( message, success, false, NULL, size ); + } + + #else + + (void)message; + + #endif // (HAS_CONFIG_BLOCK == TRUE) + + return success; +} + +int Monitor_UpdateConfiguration(WP_Message* message) +{ + bool success = false; + + // include handling of configuration block only if feature is available + #if (HAS_CONFIG_BLOCK == TRUE) + + Monitor_UpdateConfiguration_Command* cmd = (Monitor_UpdateConfiguration_Command*)message->m_payload; + Monitor_UpdateConfiguration_Reply cmdReply; + + switch((DeviceConfigurationOption)cmd->Configuration) + { + case DeviceConfigurationOption_Network: + case DeviceConfigurationOption_Wireless80211Network: + case DeviceConfigurationOption_X509CaRootBundle: + case DeviceConfigurationOption_All: + if(ConfigurationManager_StoreConfigurationBlock(cmd->Data, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex, cmd->Length, cmd->Offset) == true) + { + cmdReply.ErrorCode = 0; + success = true; + } + else + { + cmdReply.ErrorCode = 100; + } + break; + + default: + cmdReply.ErrorCode = 10; + } + + WP_ReplyToCommand(message, success, false, &cmdReply, sizeof(cmdReply)); + + #else + + (void)message; + + #endif // (HAS_CONFIG_BLOCK == TRUE) + + return success; +} + +int Monitor_CheckMemory(WP_Message* message) +{ + bool ret = false; + + CLR_DBG_Commands_Monitor_CheckMemory* cmd = (CLR_DBG_Commands_Monitor_CheckMemory*)message->m_payload; + CLR_DBG_Commands_Monitor_CheckMemory_Reply cmdReply; + uint32_t errorCode; + + ret = AccessMemory(cmd->address, cmd->length, (uint8_t*)&cmdReply.crc, AccessMemory_Check, &errorCode); + + WP_ReplyToCommand(message, ret, false, &cmdReply, sizeof(cmdReply)); + + return ret; +} + +int Monitor_MemoryMap(WP_Message* message) +{ + MemoryMap_Range map[2]; + + // if(m_signedDataState.CheckDirty()) + // { + // m_signedDataState.EraseMemoryAndReset(); + + // return false; + // } + + map[0].m_address = HalSystemConfig.RAM1.Base; + map[0].m_length = HalSystemConfig.RAM1.Size; + map[0].m_flags = Monitor_MemoryMap_c_RAM; + + map[1].m_address = HalSystemConfig.FLASH1.Base; + map[1].m_length = HalSystemConfig.FLASH1.Size; + map[1].m_flags = Monitor_MemoryMap_c_FLASH; + + WP_ReplyToCommand(message, true, false, map, sizeof(map)); + + return true; +} + +int Monitor_FlashSectorMap(WP_Message* message) +{ + + if((message->m_header.m_flags & WP_Flags_c_Reply) == 0) + { + struct Flash_BlockRegionInfo + { + unsigned int StartAddress; + unsigned int NumBlocks; + unsigned int BytesPerBlock; + unsigned int Usage; + + } *pData = NULL; + + unsigned int rangeCount = 0; + unsigned int rangeIndex = 0; + + for(int cnt = 0; cnt < 2; cnt++) + { + BlockStorageDevice* device = BlockStorageList_GetFirstDevice(); + + if(device == NULL) + { + WP_ReplyToCommand(message, true, false, NULL, 0); + return false; + } + + if(cnt == 1) + { + pData = (struct Flash_BlockRegionInfo*)platform_malloc(rangeCount * sizeof(struct Flash_BlockRegionInfo)); + + if(pData == NULL) + { + WP_ReplyToCommand(message, true, false, NULL, 0); + return false; + } + } + + DeviceBlockInfo* deviceInfo = BlockStorageDevice_GetDeviceInfo(device); + + for(unsigned int i = 0; i < deviceInfo->NumRegions; i++) + { + const BlockRegionInfo* pRegion = &deviceInfo->Regions[ i ]; + + for(unsigned int j = 0; j < pRegion->NumBlockRanges; j++) + { + + if(cnt == 0) + { + rangeCount++; + } + else + { + pData[ rangeIndex ].StartAddress = BlockRegionInfo_BlockAddress(pRegion, pRegion->BlockRanges[ j ].StartBlock); + pData[ rangeIndex ].NumBlocks = BlockRange_GetBlockCount(pRegion->BlockRanges[j]); + pData[ rangeIndex ].BytesPerBlock = pRegion->BytesPerBlock; + pData[ rangeIndex ].Usage = pRegion->BlockRanges[ j ].RangeType & BlockRange_USAGE_MASK; + rangeIndex++; + } + } + } + } + + + WP_ReplyToCommand(message, true, false, (void*)pData, rangeCount * sizeof(struct Flash_BlockRegionInfo)); + + platform_free(pData); + } + + return true; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_RT_InteropAssembliesTable.cpp.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_RT_InteropAssembliesTable.cpp.in new file mode 100644 index 00000000..78ae4af5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_RT_InteropAssembliesTable.cpp.in @@ -0,0 +1,23 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#include + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib; +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Native; +@CLR_RT_NativeAssemblyDataDeclarations@ + +const CLR_RT_NativeAssemblyData *g_CLR_InteropAssembliesNativeData[] = +{ + &g_CLR_AssemblyNative_mscorlib, + &g_CLR_AssemblyNative_nanoFramework_Runtime_Native, + @CLR_RT_NativeAssemblyDataTableEntries@ + NULL +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_Startup_Thread.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_Startup_Thread.c new file mode 100644 index 00000000..9e0b66f1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CLR_Startup_Thread.c @@ -0,0 +1,89 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void AssertBlockStorage() +{ + // if the target Device_BlockStorageConfig (and collections) and the linker file have an address mismatch + // the assertions below will cause an exception + // these checks are only included when RTM build option isn't specified + BlockStorageStream stream; + memset(&stream, 0, sizeof(BlockStorageStream)); + + // DEPLOYMENT block + // this one lives in a single block so we are OK with checking start, end and length + BlockStorageStream_Initialize(&stream, BlockUsage_DEPLOYMENT); + ASSERT(stream.BaseAddress == (uint32_t)&__deployment_start__); + //ASSERT(stream.Length == ((uint32_t)&__deployment_end__) - ((uint32_t)&__deployment_start__)); + + // CODE block (CLR) + // this one can be spread accross several blocks so we can only check the start address + memset(&stream, 0, sizeof(BlockStorageStream)); + BlockStorageStream_Initialize(&stream, BlockUsage_CODE); + ASSERT(stream.BaseAddress == (uint32_t)&__nanoImage_start__); + //ASSERT(stream.Length == ((uint32_t)&__nanoImage_end__) - ((uint32_t)&__nanoImage_start__)); + + // CONFIG block + // this one lives in a single block so we are OK with checking start, end and length + memset(&stream, 0, sizeof(BlockStorageStream)); + BlockStorageStream_Initialize(&stream, BlockUsage_CONFIG); + ASSERT(stream.BaseAddress == (uint32_t)&__nanoConfig_start__); + ASSERT(stream.Length == ((uint32_t)&__nanoConfig_end__) - ((uint32_t)&__nanoConfig_start__)); +} + +__attribute__((noreturn)) +void CLRStartupThread(void const * argument) +{ + CLR_SETTINGS* clrSettings = (CLR_SETTINGS*)argument; + + #if (HAL_USE_STM32_CRC == TRUE) + // startup crc + crcStart(NULL); + #endif + + #if (HAL_USE_STM32_ONEWIRE == TRUE) + // startup 1-Wire driver + oneWireStart(); + #endif + + // initialize nanoHAL + nanoHAL_Initialize_C(); + + /////////////////////////////////////////// + // sanity check of block storage addresses + #if !defined(BUILD_RTM) + AssertBlockStorage(); + #endif + /////////////////////////////////////////// + + #if LWIP_NETCONN_SEM_PER_THREAD + // need to create a semaphore for lwIP + semaphore_t *semaphore = chPoolAlloc(NULL); + chSemObjectInit(semaphore, (cnt_t)1); + chSemWaitTimeout(semaphore, 0); + thread_t* currentThread = chThdGetSelfX(); + currentThread->localStorage = semaphore; + #endif + + ClrStartup(*clrSettings); + + // loop until thread receives a request to terminate + while (1) + { + osDelay(500); + } + + // this function never returns +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..824c46e2 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/CMakeLists.txt @@ -0,0 +1,79 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +include(NF_NativeAssemblies) + +# add header file with common target definitions +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_platform.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_platform.h" @ONLY) + +# append nanoHAL +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL.cpp") + +# append target ChibiOS nanoCLR source files +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_App_Interface.c) +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_MonitorCommands.c) +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/CLR_Startup_Thread.c") +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL.c") + +# append target HAL source files +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Power.c") +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Time.cpp") + +# append watchdog only if option is ON +if(HAL_USE_WDG_OPTION) + list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Watchdog.c") +endif() + +# append target PAL source files +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL_Events.cpp") +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL_Time.cpp") + +# append other CLR core files +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Memory.cpp") + +# append nanoCRT +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoCRT.cpp") + +# append files from Runtime.Native +list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp") + +# append TRNG only if option is ON +if(USE_RNG) + + # append random implementation for all series, except F0 + if( ${TARGET_SERIES} STREQUAL "STM32L0xx" OR + ${TARGET_SERIES} STREQUAL "STM32F4xx" OR + ${TARGET_SERIES} STREQUAL "STM32F7xx" OR + ${TARGET_SERIES} STREQUAL "STM32H7xx") + + list(APPEND TARGET_CHIBIOS_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetRandom.cpp") + + else() + # this series doesn't feature hardware TRNG, report + message(ERROR "This CPU doesn't have a Random Number Generation. Please change USE_RNG option to OFF.") + endif() + +endif() + +# add native assemblies +ParseNativeAssemblies() + +# make var global +set(TARGET_CHIBIOS_NANOCLR_SOURCES ${TARGET_CHIBIOS_NANOCLR_SOURCES} CACHE INTERNAL "make global") + +# append target ChibiOS nanoCLR include directory +list(APPEND TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) +list(APPEND TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) +list(APPEND TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) + +# append PAL include directory +list(APPEND TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) + +# append Runtime.Native include directory +list(APPEND TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Runtime.Native) + +# make var global +set(TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Memory.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Memory.cpp new file mode 100644 index 00000000..312e8ce4 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Memory.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +extern "C" { + void HeapLocation_C(unsigned char** baseAddress, unsigned int* sizeInBytes) + { + *baseAddress = (unsigned char*)(unsigned char*) &HeapBegin; + *sizeInBytes = (unsigned int)((size_t)&HeapEnd - (size_t)&HeapBegin); + } +} + +void HeapLocation(unsigned char*& baseAddress, unsigned int& sizeInBytes) +{ + NATIVE_PROFILE_PAL_HEAP(); + + baseAddress = (unsigned char*) &HeapBegin; + sizeInBytes = (unsigned int)((size_t)&HeapEnd - (size_t)&HeapBegin); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp new file mode 100644 index 00000000..ccbe64cb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp @@ -0,0 +1,157 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_dev_dac_native_target.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +// not used, just left here if needed for debugging purposes +static void dacerrorcallback(DACDriver *dacp, dacerror_t err) +{ + (void)dacp; + (void)err; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacChannel::NativeWriteValue___VOID__U2( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* dacController = NULL; + + // we are filling this below with the appropriate DAC port pin config and DAC driver + NF_PAL_DAC_PORT_PIN_CHANNEL dacDefinition; + NF_PAL_DAC* palDac; + + dacsample_t sample; + int channelNumber; + int controllerId; + + // assign the value to the buffer + sample = (dacsample_t)stack.Arg1().NumericByRef().u2; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from _channelNumber field + channelNumber = pThis[FIELD___channelNumber].NumericByRef().s4; + + // need to get the controllerId for the DAC controller of this channel + // get pointer to DacController field + dacController = pThis[FIELD___dacController].Dereference(); + + // get pointer to _controllerId field in DacController + controllerId = dacController[Library_sys_dev_dac_native_System_Devices_Dac_DacController::FIELD___controllerId].NumericByRef().s4; + + // only one DAC controller for now, but check it anyways + if(controllerId == 1) + { + dacDefinition = DacPortPinConfig[channelNumber]; + + // we should remove form the build the DAC controller & channel combinations that aren't implemented + // plus we have to use the default to catch invalid DAC Ids + switch(ENCODED_DAC_REF(dacDefinition.dacIndex, dacDefinition.dacChannel)) + { + #if STM32_DAC_USE_DAC1_CH1 + case 11: + palDac = &Dac1_1_PAL; + break; + #endif + + #if STM32_DAC_USE_DAC1_CH2 + case 12: + palDac = &Dac1_2_PAL; + break; + #endif + + #if STM32_DAC_USE_DAC2_CH1 + case 21: + palDac = &Dac2_1_PAL; + break; + #endif + + #if STM32_DAC_USE_DAC2_CH2 + case 22: + palDac = &Dac2_2_PAL; + break; + #endif + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // perform the conversion + dacPutChannelX(palDac->Driver, palDac->Channel, sample); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacChannel::NativeDispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NF_PAL_DAC_PORT_PIN_CHANNEL dacDefinition; + int channelNumber; + bool disposeController = false; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get disposeController + disposeController = (bool)stack.Arg0().NumericByRef().u1; + + // Get channel from _channelNumber field + channelNumber = pThis[FIELD___channelNumber].NumericByRef().s4; + + if(disposeController) + { + dacDefinition = DacPortPinConfig[channelNumber]; + + switch(ENCODED_DAC_REF(dacDefinition.dacIndex, dacDefinition.dacChannel)) + { + #if STM32_DAC_USE_DAC1_CH1 + case 11: + dacStop(&DACD1); + break; + #endif + + #if STM32_DAC_USE_DAC1_CH2 + case 12: + dacStop(&DACD2); + break; + #endif + + #if STM32_DAC_USE_DAC2_CH1 + case 21: + dacStop(&DACD3); + break; + #endif + + #if STM32_DAC_USE_DAC2_CH2 + case 22: + dacStop(&DACD4); + break; + #endif + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp new file mode 100644 index 00000000..6206f386 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp @@ -0,0 +1,188 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_dev_dac_native_target.h" + +//////////////////////////////////////////////////////////// +// DAC PAL strucs delcared in sys_dev_dac_native_target.h // +//////////////////////////////////////////////////////////// +#if STM32_DAC_USE_DAC1_CH1 +NF_PAL_DAC Dac1_1_PAL; +#endif +#if STM32_DAC_USE_DAC1_CH2 +NF_PAL_DAC Dac1_2_PAL; +#endif +#if STM32_DAC_USE_DAC2_CH1 +NF_PAL_DAC Dac2_1_PAL; +#endif +#if STM32_DAC_USE_DAC2_CH2 +NF_PAL_DAC Dac2_2_PAL; +#endif + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeOpenChannel___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // we are filling this below with the appropriate ADC port pin config and ADC driver + NF_PAL_DAC_PORT_PIN_CHANNEL dacDefinition; + NF_PAL_DAC* palDac; + int controllerId; + + // Get channel from argument + int channel = stack.Arg1().NumericByRef().s4; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get controller ID + controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + // only one DAC controller for now, but check it anyways + if(controllerId == 1) + { + dacDefinition = DacPortPinConfig[channel]; + + switch(ENCODED_DAC_REF(dacDefinition.dacIndex, dacDefinition.dacChannel)) + { + #if STM32_DAC_USE_DAC1_CH1 + case 11: + Dac1_1_PAL.Driver = &DACD1; + palDac = &Dac1_1_PAL; + // unlike STM documentation, ChibiOS uses a 0 index for DAC channels + palDac->Channel = 1 - 1; + break; + #endif + + #if STM32_DAC_USE_DAC1_CH2 + case 12: + Dac1_2_PAL.Driver = &DACD2; + palDac = &Dac1_2_PAL; + // unlike STM documentation, ChibiOS uses a 0 index for DAC channels + palDac->Channel = 2 - 1; + break; + #endif + + #if STM32_DAC_USE_DAC2_CH1 + case 21: + Dac2_1_PAL.Driver = &DACD3; + palDac = &Dac2_1_PAL; + // unlike STM documentation, ChibiOS uses a 0 index for DAC channels + palDac->Channel = 1 - 1; + break; + #endif + + #if STM32_DAC_USE_DAC2_CH2 + case 22: + Dac2_2_PAL.Driver = &DACD4; + palDac = &Dac2_2_PAL; + // unlike STM documentation, ChibiOS uses a 0 index for DAC channels + palDac->Channel = 2 - 1; + break; + #endif + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // start DAC driver if it's not already started + if(palDac->Driver->state < DAC_READY) + { + if(dacDefinition.portId != NULL) + { + palSetPadMode(dacDefinition.portId, dacDefinition.pin, PAL_MODE_INPUT_ANALOG); + } + + // set DAC config: 12 bits data mode, others registers to defaults + memset(&palDac->Config, 0, sizeof(DACConfig)); + + palDac->Config.init = 0; + palDac->Config.datamode = DAC_DHRM_12BIT_RIGHT; + palDac->Config.cr = 0; + + // start DAC + dacStart(palDac->Driver, &palDac->Config); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeGetChannelCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + int channelCount; + int controllerId; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + controllerId = pThis[ FIELD___controllerId ].NumericByRefConst().s4; + + switch(controllerId) + { + case 1: + channelCount = DacChannelCount; + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Return value to the managed application + stack.SetResult_I4(channelCount); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeGetResolutionInBits___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Fixed at 12 bit + stack.SetResult_I4(12); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + int controllerId; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get pointer to _controllerId field in DacController + controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + // all required initialization for DAC is already handled in ChibiOS driver + + switch(controllerId) + { + case 1: + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String("DAC1"); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h new file mode 100644 index 00000000..a237eadb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _SYS_DEV_DAC_NATIVE_TARGET_H_ +#define _SYS_DEV_DAC_NATIVE_TARGET_H_ + +#include +#include + +struct NF_PAL_DAC_PORT_PIN_CHANNEL +{ + // Index of DAC converter + // on most STM32 devices can be converter 1 or 2 + uint8_t dacIndex; + + // DAC channel + // on most STM32 devices can be channel 1 or 2 + uint8_t dacChannel; + + // GPIO port ID + stm32_gpio_t* portId; + + // GPIO pin of the DAC channel + uint8_t pin; +}; + +// struct representing the DAC controller +struct NF_PAL_DAC +{ + DACDriver* Driver; + DACConfig Config; + uint8_t Channel; +}; + +//////////////////////////////////////////// +// declaration of the the DAC PAL strucs // +//////////////////////////////////////////// +#if STM32_DAC_USE_DAC1_CH1 +extern NF_PAL_DAC Dac1_1_PAL; +#endif +#if STM32_DAC_USE_DAC1_CH2 +extern NF_PAL_DAC Dac1_2_PAL; +#endif +#if STM32_DAC_USE_DAC2_CH1 +extern NF_PAL_DAC Dac2_1_PAL; +#endif +#if STM32_DAC_USE_DAC2_CH2 +extern NF_PAL_DAC Dac2_2_PAL; +#endif + + +// there is a driver for each pair DAC converter + channel +// let's code the options with DAC controller on the tens place and the channel on the ones place +// like this: channel 2 of DAC controller 1 being => (1 * 10) + 12 = 12 +#define ENCODED_DAC_REF( dac, channel) (dac * 10 + channel) + + +extern const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[]; +extern const int DacChannelCount; + +#endif //_SYS_DEV_DAC_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp new file mode 100644 index 00000000..9d7d04fa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp @@ -0,0 +1,139 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +// this has to be an array because ChibiOS ADC API expects that +static adcsample_t sampleBuffer[1 * 1]; + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +// not used, just left here if needed for debugging purposes +static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) +{ + (void)adcp; + (void)err; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeReadValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from _channelNumber field + int channelNumber = pThis[FIELD___channelNumber].NumericByRef().s4; + + // need to get the controllerId for the ADC controller of this channel + // get pointer to AdcController field + CLR_RT_HeapBlock* adcController = pThis[FIELD___adcController].Dereference(); + + // get pointer to _controllerId field in AdcController + int controllerId = adcController[Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::FIELD___controllerId].NumericByRef().s4; + + // we are filling this below with the appropriate ADC port pin config and ADC driver + NF_PAL_ADC_PORT_PIN_CHANNEL adcDefinition; + ADCDriver* adcDriver = NULL; + + // only one ADC controller for now, but check it anyways + if(controllerId == 1) + { + adcDefinition = AdcPortPinConfig[channelNumber]; + + // we should remove form the build the ADC options that aren't implemented + // plus we have to use the default to catch invalid ADC Ids + switch(adcDefinition.adcIndex) + { + #if STM32_ADC_USE_ADC1 + case 1: + adcDriver = &ADCD1; + break; + #endif + + #if STM32_ADC_USE_ADC2 + case 2: + adcDriver = &ADCD2; + break; + #endif + + #if STM32_ADC_USE_ADC3 + case 3: + adcDriver = &ADCD3; + break; + #endif + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + bool enableVref = (adcDefinition.adcChannel == ADC_CHANNEL_SENSOR) \ + | (adcDefinition.adcChannel == ADC_CHANNEL_VREFINT) \ + | (adcDefinition.adcChannel == ADC_CHANNEL_VBAT); + + // need to enable VREF? + if(enableVref) + { + adcSTM32EnableTSVREFE(); + + osDelay(10); + } + + // need to setup the conversion group parameters + ADCConversionGroup adcgrpcfg1 = { + FALSE, + 1, + NULL, + NULL, // replace with adcerrorcallback if required for debug + 0, /* CR1 */ + ADC_CR2_SWSTART, /* CR2 */ + ADC_SMPR1_SMP_AN11(ADC_SAMPLE_3), /* SMPR1 */ + 0, /* SMPR2 */ + 0, /* HTR */ + 0, /* LTR */ + 0, /* SQR1 */ + 0, /* SQR2 */ + ADC_SQR3_SQ1_N(adcDefinition.adcChannel) + }; + + // perform the conversion + adcConvert(adcDriver, &adcgrpcfg1, sampleBuffer, 1); + + // need to turn off VREF? + if(enableVref) + { + adcSTM32DisableTSVREFE(); + } + + // set the return result with the conversion value from the array + stack.SetResult_I4(sampleBuffer[0]); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeDisposeChannel___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // left empty on purpose, nothing to do here + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp new file mode 100644 index 00000000..7b9671cc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp @@ -0,0 +1,177 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeOpenChannel___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from argument + int channel = stack.Arg1().NumericByRef().s4; + + // get controller ID + int controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + // we are filling this below with the appropriate ADC port pin config and ADC driver + NF_PAL_ADC_PORT_PIN_CHANNEL adcDefinition; + ADCDriver* adcDriver = NULL; + + // only one ADC controller for now, but check it anyways + if(controllerId == 1) + { + adcDefinition = AdcPortPinConfig[channel]; + + // we should remove form the build the ADC options that aren't implemented + // plus we have to use the default to catch invalid ADC Ids + switch(adcDefinition.adcIndex) + { + #if STM32_ADC_USE_ADC1 + case 1: + adcDriver = &ADCD1; + break; + #endif + + #if STM32_ADC_USE_ADC2 + case 2: + adcDriver = &ADCD2; + break; + #endif + + #if STM32_ADC_USE_ADC3 + case 3: + adcDriver = &ADCD3; + break; + #endif + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if(adcDefinition.portId != NULL) + { + palSetGroupMode(adcDefinition.portId, PAL_PORT_BIT(adcDefinition.pin), 0, PAL_MODE_INPUT_ANALOG); + } + + // start ADC + adcStart(adcDriver, NULL); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetChannelCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int channelCount; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + int controllerId = pThis[ FIELD___controllerId ].NumericByRefConst().s4; + + switch(controllerId) + { + case 1: + channelCount = AdcChannelCount; + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Return value to the managed application + stack.SetResult_I4(channelCount); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMaxValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Currently fixed at 12 bit so return 4095 = ((2^12) - 1) + stack.SetResult_I4(4095); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMinValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + stack.SetResult_I4(0); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeIsChannelModeSupported___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int mode = stack.Arg1().NumericByRef().s4; + + // Only support Single ended mode for now + stack.SetResult_Boolean( (mode == (int)AdcChannelMode::SingleEnded) ) ; + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetResolutionInBits___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Fixed at 12 bit + stack.SetResult_I4(12); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + int controllerId; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get pointer to _controllerId field in AdcController + controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + // all required initialization for ADC is already handled in ChibiOS driver + + switch(controllerId) + { + case 1: + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String("ADC1"); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h new file mode 100644 index 00000000..e2cdb666 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_ADC_NATIVE_TARGET_H_ +#define _WIN_DEV_ADC_NATIVE_TARGET_H_ + +#include +#include + +struct NF_PAL_ADC_PORT_PIN_CHANNEL +{ + uint8_t adcIndex; + stm32_gpio_t* portId; + uint8_t pin; + uint32_t adcChannel; +}; + +extern const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[]; +extern const int AdcChannelCount; + +#endif //_WIN_DEV_ADC_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp new file mode 100644 index 00000000..d6c6623a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp @@ -0,0 +1,86 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_gpio_native.h" + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int16_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + //bool InputMode = (bool)pThis[FIELD___inputMode].NumericByRefConst().u1; + + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeRead___U8__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStart___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + //GpioChangePolarity polarity = (GpioChangePolarity)pThis[ FIELD___Polarity ].NumericByRefConst().s4; + + + // TODO + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStop___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeDispose___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp new file mode 100644 index 00000000..5a5c948a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_gpio_native_target.h" + + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController::get_PinCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // return count ot available GPIO pins + stack.SetResult_I4( 256 ); // Fixme: temporary arbitrary value + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp new file mode 100644 index 00000000..270adcc8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp @@ -0,0 +1,423 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include +#include +#include + +#include +#include "win_dev_gpio_native_target.h" + +// this timer is used to handle the debounce time +static virtual_timer_t debounceTimer; + +volatile uint16_t lastPadValue; + +// this is an utility function to get a ChibiOS PAL IoLine from our "encoded" pin number +ioline_t GetIoLine(int16_t pinNumber) +{ + stm32_gpio_t* port = GPIO_PORT(pinNumber); + int16_t pad = pinNumber % 16; + + return PAL_LINE(port, pad); + +} + +static void debounceTimer_Callback( void* arg ) +{ + CLR_RT_HeapBlock* pThis = (CLR_RT_HeapBlock*)arg; + + if(pThis == NULL) + { + // no Gpio pin here, leave now + chSysUnlockFromISR(); + return; + } + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + // object has been disposed, leave now + chSysUnlockFromISR(); + return; + } + + // get pin number + int16_t pinNumber = pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___pinNumber ].NumericByRefConst().s4; + + // read line + uint16_t currentValue = palReadLine(GetIoLine(pinNumber)); + + // read pad + uint16_t lastPadValue = pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___lastInputValue ].NumericByRef().s4; + + if(lastPadValue == currentValue) + { + // value hasn't change for debounce interval so this is a valid change + + // flag to determine if there are any callbacks registered in managed code + bool callbacksRegistered = (pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___callbacks ].Dereference() != NULL); + + // post a managed event with the current pin value, only if there is anyone listening otherwise don't bother + if(callbacksRegistered) + { + PostManagedEvent( EVENT_GPIO, 0, pinNumber, currentValue ); + } + } +} + +static void GpioEventCallback(void *arg) +{ + CLR_RT_HeapBlock* pThis = (CLR_RT_HeapBlock*)arg; + + NATIVE_INTERRUPT_START + + chSysLockFromISR(); + + //CLR_RT_HeapBlock* pThis = channelPinMapping[channel]; + + if(pThis == NULL) + { + // no Gpio pin here, leave now + chSysUnlockFromISR(); + return; + } + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + // object has been disposed, leave now + chSysUnlockFromISR(); + + NATIVE_INTERRUPT_END + + return; + } + + // get pin number and take the port and pad references from that one + int16_t pinNumber = pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___pinNumber ].NumericByRefConst().s4; + + // get IoLine from pin number + ioline_t ioLine = GetIoLine(pinNumber); + + // check if there is a debounce time set + int64_t debounceTimeoutMilsec = (CLR_INT64_TEMP_CAST) pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___debounceTimeout ].NumericByRefConst().s8 / TIME_CONVERSION__TO_MILLISECONDS; + + if(debounceTimeoutMilsec > 0) + { + // debounce set, need to handle it + + if(chVTIsArmed(&debounceTimer)) + { + // there is a debounce timer already running so this change in pin value should be discarded + chSysUnlockFromISR(); + + NATIVE_INTERRUPT_END + + return; + } + + // read pad + pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___lastInputValue ].NumericByRef().s4 = palReadLine(ioLine); + + // setup timer + chVTSetI(&debounceTimer, TIME_MS2I(debounceTimeoutMilsec), debounceTimer_Callback, pThis); + } + else + { + // read pad + pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___lastInputValue ].NumericByRef().s4 = palReadLine(ioLine); + + // flag to determine if there are any callbacks registered in managed code + bool callbacksRegistered = (pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___callbacks ].Dereference() != NULL); + + // post a managed event with the current pin reading, only if there is anyone listening otherwise don't bother + if(callbacksRegistered) + { + PostManagedEvent( EVENT_GPIO, 0, pinNumber, palReadLine(ioLine) ); + } + } + + chSysUnlockFromISR(); + + NATIVE_INTERRUPT_END + +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Read___WindowsDevicesGpioGpioPinValue( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + stack.SetResult_I4( palReadLine(GetIoLine(pThis[ FIELD___pinNumber ].NumericByRefConst().s4)) ); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Toggle___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // get IoLine from pin number + ioline_t ioLine = GetIoLine(pThis[ FIELD___pinNumber ].NumericByRefConst().s4); + + GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[ FIELD___driveMode ].NumericByRefConst().s4; + + // sanity check for drive mode set to output so we don't mess up writing to an input pin + if ((driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSource) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + palToggleLine(ioLine); + + // store new state + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = (GpioPinValue)(GpioPinValue_High ^ (GpioPinValue)pThis[ FIELD___lastOutputValue ].NumericByRef().s4); + } + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get IoLine from pin number + ioline_t ioLine = GetIoLine(pThis[ FIELD___pinNumber ].NumericByRefConst().s4); + + // disable the EXT interrupt channel + // it's OK to do always this, no matter if it's enabled or not + palDisableLineEvent(ioLine); + + // set pin to input to save power + palSetLineMode(ioLine, PAL_MODE_INPUT); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + GpioPinDriveMode driveMode = (GpioPinDriveMode)stack.Arg1().NumericByRef().s4; + + bool driveModeSupported = false; + + // check if the requested drive mode is support by ChibiOS config + if ((driveMode == GpioPinDriveMode_Input) || + (driveMode == GpioPinDriveMode_InputPullDown) || + (driveMode == GpioPinDriveMode_InputPullUp) || + (driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain)) + { + driveModeSupported = true; + } + + // Return value to the managed application + stack.SetResult_Boolean( driveModeSupported ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // get IoLine from pin number + ioline_t ioLine = GetIoLine(pThis[ FIELD___pinNumber ].NumericByRefConst().s4); + + // it's better cast this this to the appropriate enum + GpioPinDriveMode driveMode = (GpioPinDriveMode)stack.Arg1().NumericByRef().s4; + + // check if drive mode is input + bool driveModeIsInput = false; + + if( driveMode == GpioPinDriveMode_Input || + driveMode == GpioPinDriveMode_InputPullDown || + driveMode == GpioPinDriveMode_InputPullUp) + { + driveModeIsInput = true; + } + + // flag to signal that interrupts need to be setup + bool setupInterrupt = false; + + // flag to determine if there are any callbacks registered in managed code + bool callbacksRegistered = (pThis[ FIELD___callbacks ].Dereference() != NULL); + + switch (driveMode) + { + case GpioPinDriveMode_Input: + palSetLineMode(ioLine, PAL_MODE_INPUT); + setupInterrupt = true; + break; + + case GpioPinDriveMode_InputPullDown: + palSetLineMode(ioLine, PAL_MODE_INPUT_PULLDOWN); + setupInterrupt = true; + break; + + case GpioPinDriveMode_InputPullUp: + palSetLineMode(ioLine, PAL_MODE_INPUT_PULLUP); + setupInterrupt = true; + break; + + case GpioPinDriveMode_Output: + palSetLineMode(ioLine, PAL_MODE_OUTPUT_PUSHPULL); + break; + + case GpioPinDriveMode_OutputOpenDrain: + palSetLineMode(ioLine, PAL_MODE_OUTPUT_OPENDRAIN); + break; + + default: + // all other modes are NOT supported + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // if drive mode is output, read the pad to update the managed field _lastOutputValue + if(!driveModeIsInput) + { + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = palReadLine(ioLine); + } + + if(callbacksRegistered && setupInterrupt) + { + // there are callbacks registered and... + // the drive mode is input so need to setup the interrupt + + // save pin + //channelPinMapping[pad] = pThis; + + palEnableLineEvent(ioLine, PAL_EVENT_MODE_BOTH_EDGES); + palSetLineCallback(ioLine, GpioEventCallback, pThis); + + // protect this from GC so that the callback is where it's supposed to + CLR_RT_ProtectFromGC gc( *pThis ); + + // read pad and store current value to check on debounce callback + lastPadValue = palReadLine(ioLine); + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeInit___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + //int16_t pinNumber = stack.Arg1().NumericByRef().s4; + + // TODO is probably a good idea keep track of the used pins, so we can check that here + // TODO is probably a good idea to check if this pin exists + + // Return value to the managed application + stack.SetResult_Boolean(true ); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDebounceTimeout___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // nothing to do here as the debounce timeout is grabbed from the managed object when required + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::WriteNative___VOID__WindowsDevicesGpioGpioPinValue( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // get IoLine from pin number + ioline_t ioLine = GetIoLine(pThis[ FIELD___pinNumber ].NumericByRefConst().s4); + + GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[ FIELD___driveMode ].NumericByRefConst().s4; + + GpioPinValue state = (GpioPinValue)stack.Arg1().NumericByRef().s4; + + // sanity check for drive mode set to output so we don't mess up writing to an input pin + if ((driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSource) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + palWriteLine(ioLine, state); + + // update the managed field _lastOutputValue + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = state; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetAlternateFunction___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // get IoLine from pin number + ioline_t ioLine = GetIoLine(pThis[ FIELD___pinNumber ].NumericByRefConst().s4); + + // get alternate function argument + int32_t alternateFunction = stack.Arg1().NumericByRef().s4; + + palSetLineMode(ioLine, PAL_MODE_ALTERNATE(alternateFunction)); + + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h new file mode 100644 index 00000000..7666fe1c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_GPIO_NATIVE_TARGET_H_ +#define _WIN_DEV_GPIO_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_DEV_GPIO_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp new file mode 100644 index 00000000..bd2f39fa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp @@ -0,0 +1,537 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include "win_dev_i2c_native_target.h" + +typedef Library_win_dev_i2c_native_Windows_Devices_I2c_I2cConnectionSettings I2cConnectionSettings; + +///////////////////////////////////////////////////// +// I2C PAL strucs declared in win_dev_i2c_native.h // +///////////////////////////////////////////////////// +#if STM32_I2C_USE_I2C1 + NF_PAL_I2C I2C1_PAL; +#endif +#if STM32_I2C_USE_I2C2 + NF_PAL_I2C I2C2_PAL; +#endif +#if STM32_I2C_USE_I2C3 + NF_PAL_I2C I2C3_PAL; +#endif +#if STM32_I2C_USE_I2C4 + NF_PAL_I2C I2C4_PAL; +#endif + + +// ChibiOS I2C working thread +static THD_FUNCTION(I2CWorkingThread, arg) +{ + NF_PAL_I2C* palI2c = (NF_PAL_I2C*)arg; + msg_t result; + int estimatedDurationMiliseconds = palI2c->ByteTime * (palI2c->WriteSize + palI2c->ReadSize + 1); + + if (palI2c->ReadSize != 0 && palI2c->WriteSize != 0) + { + // this is a Write/Read transaction + result = i2cMasterTransmitTimeout(palI2c->Driver, palI2c->Address, palI2c->WriteBuffer, palI2c->WriteSize, palI2c->ReadBuffer, palI2c->ReadSize, TIME_MS2I(estimatedDurationMiliseconds)); + } + else + { + if (palI2c->ReadSize == 0) + { + // this is Write only transaction + + estimatedDurationMiliseconds = palI2c->ByteTime * (palI2c->WriteSize + 1); + + result = i2cMasterTransmitTimeout(palI2c->Driver, palI2c->Address, palI2c->WriteBuffer, palI2c->WriteSize, NULL, 0, TIME_MS2I(estimatedDurationMiliseconds)); + } + else + { + // this is a Read only transaction + + estimatedDurationMiliseconds = palI2c->ByteTime * (palI2c->ReadSize + 1); + + result = i2cMasterReceiveTimeout (palI2c->Driver, palI2c->Address, palI2c->ReadBuffer, palI2c->ReadSize, TIME_MS2I(estimatedDurationMiliseconds)); + } + } + + // fire event for I2C transaction complete + Events_Set(SYSTEM_EVENT_FLAG_I2C_MASTER); + + chThdExit(result); +} + +void GetI2cConfig(CLR_RT_HeapBlock* managedConfig, I2CConfig* llConfig) +{ + I2cBusSpeed busSpeed = (I2cBusSpeed)managedConfig[ I2cConnectionSettings::FIELD___busSpeed ].NumericByRef().s4; + + // set the LL I2C configuration (according to I2C driver version) + #if defined(STM32F1XX) || defined(STM32F4XX) || defined(STM32L1XX) + + llConfig->op_mode = OPMODE_I2C; + llConfig->clock_speed = busSpeed == I2cBusSpeed_StandardMode ? 100000U : 400000U; + llConfig->duty_cycle = busSpeed == I2cBusSpeed_StandardMode ? STD_DUTY_CYCLE : FAST_DUTY_CYCLE_2; + + #endif + + #if defined(STM32F7XX) || defined(STM32F3XX) || defined(STM32F0XX) || \ + defined(STM32L0XX) || defined(STM32L4XX) || \ + defined(STM32H7XX) + + // Standard mode : 100 KHz, Rise time 120 ns, Fall time 25 ns, 54MHz clock source + // Fast mode : 400 KHz, Rise time 120 ns, Fall time 25 ns, 54MHz clock source + // Timing register value calculated by STM32 CubeMx + llConfig->timingr = busSpeed == I2cBusSpeed_StandardMode ? 0x80201721 : 0x00B01B59; + llConfig->cr1 = 0; + llConfig->cr2 = 0; + + #endif + +} + +// estimate the time required to perform the I2C transaction +bool IsLongRunningOperation(uint16_t writeSize, uint16_t readSize, float byteTime, uint32_t& estimatedDurationMiliseconds) +{ + // add an extra byte to account for the address + estimatedDurationMiliseconds = byteTime * (writeSize + readSize + 1); + + if(estimatedDurationMiliseconds > CLR_RT_Thread::c_TimeQuantum_Milliseconds) + { + // total operation time will exceed thread quantum, so this is a long running operation + return true; + } + else + { + return false; + } +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_I2C* palI2c = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed I2C connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the I2cDevice() constructor in managed code for details + uint8_t busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // config GPIO pins used by the I2C peripheral + // init the PAL struct for this I2C bus and assign the respective driver + // all this occurs if not already done + // why do we need to check if this is already done? because several I2cDevice objects can be created associated to the same bus just using different addresses + switch (busIndex) + { + #if STM32_I2C_USE_I2C1 + case 1: + if(I2C1_PAL.Driver == NULL) + { + ConfigPins_I2C1(); + + I2C1_PAL.Driver = &I2CD1; + palI2c = &I2C1_PAL; + } + break; + #endif + #if STM32_I2C_USE_I2C2 + case 2: + if(I2C2_PAL.Driver == NULL) + { + ConfigPins_I2C2(); + + I2C2_PAL.Driver = &I2CD2; + palI2c = &I2C2_PAL; + } + break; + #endif + #if STM32_I2C_USE_I2C3 + case 3: + if(I2C3_PAL.Driver == NULL) + { + ConfigPins_I2C3(); + + I2C3_PAL.Driver = &I2CD3; + palI2c = &I2C3_PAL; + } + break; + #endif + #if STM32_I2C_USE_I2C4 + case 4: + if(I2C4_PAL.Driver == NULL) + { + ConfigPins_I2C4(); + + I2C4_PAL.Driver = &I2CD4; + palI2c = &I2C4_PAL; + } + break; + #endif + + default: + // this I2C bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // Get a general low-level I2C configuration, depending on user's managed parameters + GetI2cConfig(pConfig, &palI2c->Configuration); + + // compute rough estimate on the time to tx/rx a byte (in milliseconds) + if((I2cBusSpeed)pConfig[ I2cConnectionSettings::FIELD___busSpeed ].NumericByRef().s4 == I2cBusSpeed_StandardMode) + { + // 100kbit/s: this is roughly 0.10ms per byte, give or take + palI2c->ByteTime = 0.1; + } + else + { + // 400kbit/s: this is roughly 0.02ms per byte, give or take + palI2c->ByteTime = 0.02; + } + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeDispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t busIndex; + bool disposeController = false; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get disposeController + disposeController = (bool)stack.Arg0().NumericByRef().u1; + + if(disposeController) + { + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the I2cDevice() constructor in managed code for details + busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // get the driver for the I2C bus + switch (busIndex) + { + #if STM32_I2C_USE_I2C1 + case 1 : + // deactivates the I2C peripheral + i2cStop(&I2CD1); + // nulls driver + I2C1_PAL.Driver = NULL; + break; + #endif + + #if STM32_I2C_USE_I2C2 + case 2 : + // deactivates the I2C peripheral + i2cStop(&I2CD2); + // nulls driver + I2C2_PAL.Driver = NULL; + break; + #endif + + #if STM32_I2C_USE_I2C3 + case 3 : + // deactivates the I2C peripheral + i2cStop(&I2CD3); + // nulls driver + I2C3_PAL.Driver = NULL; + break; + #endif + + #if STM32_I2C_USE_I2C4 + case 4 : + // deactivates the I2C peripheral + i2cStop(&I2CD4); + // nulls driver + I2C4_PAL.Driver = NULL; + break; + #endif + + default: + // the requested I2C bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeTransmit___WindowsDevicesI2cI2cTransferResult__SZARRAY_U1__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uint8_t busIndex; + NF_PAL_I2C* palI2c = NULL; + bool isLongRunningOperation = false; + msg_t transactionResult = MSG_OK; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + uint32_t estimatedDurationMiliseconds; + + CLR_RT_HeapBlock_Array* writeBuffer; + CLR_RT_HeapBlock_Array* readBuffer; + CLR_RT_HeapBlock* result; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get pointer to connection settings field + CLR_RT_HeapBlock* connectionSettings = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the I2cDevice() constructor in managed code for details + busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // get the driver for the I2C bus + switch (busIndex) + { + #if STM32_I2C_USE_I2C1 + case 1 : + palI2c = &I2C1_PAL; + break; + #endif + #if STM32_I2C_USE_I2C2 + case 2 : + palI2c = &I2C2_PAL; + break; + #endif + #if STM32_I2C_USE_I2C3 + case 3 : + palI2c = &I2C3_PAL; + break; + #endif + #if STM32_I2C_USE_I2C4 + case 4 : + palI2c = &I2C4_PAL; + break; + #endif + default: + // the requested I2C bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // dereference the write and read buffers from the arguments + writeBuffer = stack.Arg1().DereferenceArray(); + if (writeBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + palI2c->WriteSize = writeBuffer->m_numOfElements; + } + else + { + // nothing to write, have to zero this + palI2c->WriteSize = 0; + } + + readBuffer = stack.Arg2().DereferenceArray(); + if (readBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + palI2c->ReadSize = readBuffer->m_numOfElements; + } + else + { + // nothing to read, have to zero this + palI2c->ReadSize = 0; + } + + // check if this is a long running operation + isLongRunningOperation = IsLongRunningOperation(palI2c->WriteSize, palI2c->ReadSize, palI2c->ByteTime, (uint32_t&)estimatedDurationMiliseconds); + + if(isLongRunningOperation) + { + // if this is a long running operation, set a timeout equal to the estimated transaction duration in milliseconds + // this value has to be in ticks to be properly loaded by SetupTimeoutFromTicks() below + hbTimeout.SetInteger((CLR_INT64)estimatedDurationMiliseconds * TIME_CONVERSION__TO_MILLISECONDS); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // protect the buffers from GC so DMA can find them where they are supposed to be + CLR_RT_ProtectFromGC gcWriteBuffer( *writeBuffer ); + CLR_RT_ProtectFromGC gcReadBuffer( *readBuffer ); + } + + // this is going to be used to check for the right event in case of simultaneous I2C transaction + if(!isLongRunningOperation || stack.m_customState == 1) + { + // get slave address from connection settings field + palI2c->Address = (i2caddr_t)connectionSettings[Library_win_dev_i2c_native_Windows_Devices_I2c_I2cConnectionSettings::FIELD___slaveAddress].NumericByRef().s4; + + // when using I2Cv1 driver the address needs to be loaded in the I2C driver struct + #if defined(STM32F1XX) || defined(STM32F4XX) || defined(STM32L1XX) + palI2c->Driver->addr = palI2c->Address; + #endif + + if (writeBuffer != NULL) + { + palI2c->WriteBuffer = (uint8_t*)writeBuffer->GetFirstElement(); + + // flush DMA buffer to ensure cache coherency + // (only required for Cortex-M7) + cacheBufferFlush(palI2c->WriteBuffer, palI2c->WriteSize); + } + + if (readBuffer != NULL) + { + palI2c->ReadBuffer = (uint8_t*)readBuffer->GetFirstElement(); + } + + // because the bus access is shared, acquire the appropriate bus + i2cAcquireBus(palI2c->Driver); + i2cStart(palI2c->Driver, &palI2c->Configuration); + } + + if(isLongRunningOperation) + { + // this is a long running operation and hasn't started yet + // perform I2C transaction using driver's ASYNC API which is launching a thread to perform it + if(stack.m_customState == 1) + { + // spawn working thread to perform the I2C transaction + palI2c->WorkingThread = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(256), + "I2CWT", NORMALPRIO, I2CWorkingThread, palI2c); + + if(palI2c->WorkingThread == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + } + else + { + // this is NOT a long running operation + // perform I2C transaction using driver's SYNC API + + if (palI2c->ReadSize != 0 && palI2c->WriteSize != 0) + { + // this is a Write/Read transaction + transactionResult = i2cMasterTransmitTimeout(palI2c->Driver, palI2c->Address, palI2c->WriteBuffer, palI2c->WriteSize, palI2c->ReadBuffer, palI2c->ReadSize, TIME_MS2I(20)); + } + else + { + if (palI2c->ReadSize == 0) + { + // this is Write only transaction + transactionResult = i2cMasterTransmitTimeout(palI2c->Driver, palI2c->Address, palI2c->WriteBuffer, palI2c->WriteSize, NULL, 0, TIME_MS2I(20)); + } + else + { + // this is a Read only transaction + transactionResult = i2cMasterReceiveTimeout (palI2c->Driver, palI2c->Address, palI2c->ReadBuffer, palI2c->ReadSize, TIME_MS2I(20)); + } + } + } + + while(eventResult) + { + if(!isLongRunningOperation) + { + // this is not a long running operation so nothing to do here + break; + } + + if(palI2c->WorkingThread->state == CH_STATE_FINAL) + { + // I2C working thread is now complete + break; + } + + // non-blocking wait allowing other threads to run while we wait for the I2C transaction to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_I2cMaster, eventResult )); + } + + if(isLongRunningOperation) + { + // pop timeout heap block from stack + stack.PopValue(); + } + + if(eventResult || !isLongRunningOperation) + { + // event occurred + // OR this is NOT a long running operation + + i2cReleaseBus(palI2c->Driver); + + // create the return object (I2cTransferResult) + // only at this point we are sure that there will be a return from this thread so it's OK to use the managed stack + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_I2cTransferResult)); + result = top.Dereference(); FAULT_ON_NULL(result); + + if(isLongRunningOperation) + { + // ChibiOS requirement: need to call chThdWait for I2C working thread in order to have it's memory released to the heap, otherwise it won't be returned + transactionResult = chThdWait(palI2c->WorkingThread); + } + + // get the result from the working thread execution + if (transactionResult != MSG_OK) + { + // error in transaction + int errors = i2cGetErrors(palI2c->Driver); + + // figure out what was the error and set the status field + switch(errors) + { + case I2C_ACK_FAILURE: + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___status ].SetInteger((CLR_UINT32)I2cTransferStatus_SlaveAddressNotAcknowledged); + break; + + case I2C_TIMEOUT: + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___status ].SetInteger((CLR_UINT32)I2cTransferStatus_ClockStretchTimeout); + break; + + default: + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___status ].SetInteger((CLR_UINT32)I2cTransferStatus_UnknownError); + } + + // set the bytes transferred count to 0 because we don't have a way to know how many bytes were actually sent/received + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___bytesTransferred ].SetInteger(0); + } + else + { + // successfull transaction + // set the result field + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___status ].SetInteger((CLR_UINT32)I2cTransferStatus_FullTransfer); + + // set the bytes transferred field + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___bytesTransferred ].SetInteger((CLR_UINT32)(palI2c->WriteSize + palI2c->ReadSize)); + } + + if(palI2c->ReadSize > 0) + { + // invalidate cache over read buffer to ensure that content from DMA is read + // (only required for Cortex-M7) + cacheBufferInvalidate(palI2c->ReadBuffer, palI2c->ReadSize); + } + } + + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp new file mode 100644 index 00000000..d718a27e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp @@ -0,0 +1,52 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include "win_dev_i2c_native_target.h" + + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "I2C1,I2C2,I2C3,I2C4," + terminator and init with the terminator + char deviceSelectorString[20 + 1] = { 0 }; + + #if STM32_I2C_USE_I2C1 + strcat(deviceSelectorString, "I2C1,"); + #endif + #if STM32_I2C_USE_I2C2 + strcat(deviceSelectorString, "I2C2,"); + #endif + #if STM32_I2C_USE_I2C3 + strcat(deviceSelectorString, "I2C3,"); + #endif + #if STM32_I2C_USE_I2C4 + strcat(deviceSelectorString, "I2C4,"); + #endif + // replace the last comma with a terminator + deviceSelectorString[hal_strlen_s(deviceSelectorString) - 1] = '\0'; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h new file mode 100644 index 00000000..734e1ca2 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h @@ -0,0 +1,63 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_I2C_NATIVE_TARGET_H_ +#define _WIN_DEV_I2C_NATIVE_TARGET_H_ + +#include +#include + +// struct representing the I2C +struct NF_PAL_I2C +{ + I2CDriver* Driver; + I2CConfig Configuration; + thread_t* WorkingThread; + i2caddr_t Address; + float ByteTime; + + uint8_t* WriteBuffer; + uint8_t WriteSize; + + uint8_t* ReadBuffer; + uint8_t ReadSize; +}; + +/////////////////////////////////////////// +// declaration of the the I2C PAL strucs // +/////////////////////////////////////////// +#if STM32_I2C_USE_I2C1 + extern NF_PAL_I2C I2C1_PAL; +#endif +#if STM32_I2C_USE_I2C2 + extern NF_PAL_I2C I2C2_PAL; +#endif +#if STM32_I2C_USE_I2C3 + extern NF_PAL_I2C I2C3_PAL; +#endif +#if STM32_I2C_USE_I2C4 + extern NF_PAL_I2C I2C4_PAL; +#endif + + +// the following macro defines a function that configures the GPIO pins for a STM32 I2C peripheral +// it gets called in the Windows_Devices_I2c_I2cDevice::NativeInit function +// this is required because the I2C peripherals can use multiple GPIO configuration combinations +#define I2C_CONFIG_PINS(num, gpio_port_scl, gpio_port_sda, scl_pin, sda_pin, alternate_function) void ConfigPins_I2C##num() \ +{ \ + palSetPadMode(gpio_port_scl, scl_pin, (PAL_MODE_ALTERNATE(alternate_function) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_OTYPE_OPENDRAIN) ); \ + palSetPadMode(gpio_port_sda, sda_pin, (PAL_MODE_ALTERNATE(alternate_function) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_OTYPE_OPENDRAIN)); \ +} + +////////////////////////////////////////////////////////////////////////////////////////////// +// when an I2C is defined the declarations below will have the real function/configuration // +// in the target folder @ target_windows_devices_i2c_config.cpp // +////////////////////////////////////////////////////////////////////////////////////////////// +void ConfigPins_I2C1(); +void ConfigPins_I2C2(); +void ConfigPins_I2C3(); +void ConfigPins_I2C4(); + +#endif //_WIN_DEV_I2C_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp new file mode 100644 index 00000000..f4ff01b3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp @@ -0,0 +1,161 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include "win_dev_pwm_native_target.h" + +PWMConfig _pwmConfig; + +extern PWMDriver* GetDriver(int timerId); + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MaxFrequency___R8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties + double maxFrequency = 0.0; + +#if defined(STM32F4XX) || defined(STM32F7XX) + int timerId = (int)(pThis[ FIELD___controllerId ].NumericByRef().u4); + + if (timerId == 1 || timerId >= 8) maxFrequency = (double)STM32_PCLK2_MAX; // TIM1, TIM8 and TIM9 on APB2 + else maxFrequency = (double)STM32_PCLK1_MAX; // other timers on APB1 + +#elif defined(STM32F0XX) + + maxFrequency = (double)STM32_PCLK_MAX; // Only APB1 on this MCU + +#endif + stack.SetResult_R8(maxFrequency); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MinFrequency___R8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // FIXME : how can this value be determined ? + stack.SetResult_R8(1.0); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_PinCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int pinCount = 0; +#if defined(STM32F4XX) + pinCount = 42; +#elif defined(STM32F7XX) + //FIXME: arbitrary value, here. Where do I find the information ? + pinCount = 42; +#elif defined(STM32F0XX) + pinCount = 24; +#endif + stack.SetResult_I4(pinCount); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::NativeSetDesiredFrequency___U4__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties + int timerId = (int)(pThis[ FIELD___controllerId ].NumericByRef().u4); + unsigned int desiredFrequency = (unsigned int)stack.Arg1().NumericByRef().u4; + + // Gets the PWM driver associated with the requested timer + PWMDriver * _drv; + _drv = GetDriver(timerId); + + // Sets the period to something able to be precise enough with low and high frequencies + // and that allows the clock frequency parameter to fit in an unsigned int + int period = 1000; + if (desiredFrequency >= 1000) period = 100; + else if (desiredFrequency >= 1000000) period = 10; + + // Build the PWM config structure + PWMConfig pwmConfig = + { + (desiredFrequency * period), // PWM clock frequency + (pwmcnt_t)period, // PWM period + NULL, // No callback + // Enable all channels + { + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_ACTIVE_HIGH, NULL} + }, + 0, + #if STM32_PWM_USE_ADVANCED + 0, + #endif + 0, + }; + + // Starts the pwm driver + pwmStop(_drv); + osDelay(5); + pwmStart(_drv, &pwmConfig); + + stack.SetResult_R8((double)desiredFrequency); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "TIM1,TIM3,TIM4,TIM5,TIM8,TIM9," + terminator and init with the terminator + char deviceSelectorString[ 30 + 1] = { 0 }; + + #if STM32_PWM_USE_TIM1 + strcat(deviceSelectorString, "TIM1,"); + #endif + #if STM32_PWM_USE_TIM2 + strcat(deviceSelectorString, "TIM2,"); + #endif + #if STM32_PWM_USE_TIM3 + strcat(deviceSelectorString, "TIM3,"); + #endif +#ifndef STM32F0XX + #if STM32_PWM_USE_TIM4 + strcat(deviceSelectorString, "TIM4,"); + #endif + #if STM32_PWM_USE_TIM5 + strcat(deviceSelectorString, "TIM5,"); + #endif + #if STM32_PWM_USE_TIM8 + strcat(deviceSelectorString, "TIM8,"); + #endif + #if STM32_PWM_USE_TIM9 + strcat(deviceSelectorString, "TIM9,"); + #endif +#endif + // replace the last comma with a terminator + deviceSelectorString[hal_strlen_s(deviceSelectorString) - 1] = '\0'; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp new file mode 100644 index 00000000..db025708 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp @@ -0,0 +1,975 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include "win_dev_pwm_native_target.h" +#include + +int GetChannel (int pin, int timerId) +{ + int channel = -1; +#if defined(STM32F427xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) + switch (timerId) + { + case 1 : + switch (pin) + { + case 8 : // PA8 + case 4*16+9 : // PE9 + channel = 0; + break; + case 9 : // PA9 + case 4*16+11 : // PE11 + channel = 1; + break; + case 10 : // PA10 + case 4*16+13 : // PE13 + channel = 2; + break; + case 11 : // PA11 + case 4*16+14 : // PE14 + channel = 3; + break; + } + break; + + case 2 : + switch (pin) + { + case 0 : // PA0, PA5, PA15 + case 5 : + case 15 : + channel = 0; + break; + case 1 : // PA1, PB3 + case 1 * 16 + 3 : + channel = 1; + break; + case 2 : // PA2, PB10 + case 1 * 16 + 10 : + channel = 2; + break; + case 3 : // PA3, PB11 + case 1 * 16 + 11 : + channel = 3; + break; + } + break; + + case 3 : + switch (pin) + { + case 0 : + case 5 : + case 15 : + channel = 0; + break; + case 1 : + case 1*16+3 : + channel = 1; + break; + case 2 : + case 1*16+10 : + channel = 2; + break; + case 3 : + case 1*16+11 : + channel = 3; + break; + } + break; + case 4 : + switch (pin) + { + case 1 * 16 + 6 : // PB6, PD12 + case 3 * 16 + 12 : + channel = 0; + break; + case 1 * 16 + 7 : // PB7, PD13 + case 3 * 16 + 13 : + channel = 1; + break; + case 1 * 16 + 8 : // PB8, PD14 + case 3 * 16 + 14 : + channel = 2; + break; + case 1 * 16 + 9 : // PB9, PD15 + case 3 * 16 + 15 : + channel = 3; + break; + } + break; + + case 5 : + switch (pin) + { + case 0 : // PA0, PH10 + case 7 * 16 + 10 : + channel = 0; + break; + case 1 : // PA1, PH11 + case 7 * 16 + 11 : + channel = 1; + break; + case 2 : // PA2, PH12 + case 7 * 16 + 12 : + channel = 2; + break; + case 3 : // PA3, PI0 + case 8 * 16 + 0 : + channel = 3; + break; + } + break; + + case 8 : + switch (pin) + { + case 2 * 16 + 6 : // PC6, PI5 + case 7 * 16 + 5 : + channel = 0; + break; + case 2 * 16 + 7 : // PC7, PI6 + case 7 * 16 + 6 : + channel = 1; + break; + case 2 * 16 + 8 : // PC8, PI7 + case 7 * 16 + 7 : + channel = 2; + break; + case 2 * 16 + 9 : // PC9 + channel = 3; + break; + } + break; + + case 9 : + switch (pin) + { + case 2 * 16 + 6 : // PC6, PI5 + case 7 * 16 + 5 : + channel = 0; + break; + case 2 * 16 + 7 : // PC7, PI6 + case 7 * 16 + 6 : + channel = 1; + break; + case 2 * 16 + 8 : // PC8, PI7 + case 7 * 16 + 7 : + channel = 2; + break; + case 2 * 16 + 9 : // PC9 + channel = 3; + break; + } + break; + + default : + channel = 0xFF; + break; + } +#endif +#if defined(STM32F411xx) || defined(STM32F412xx) || defined(STM32F401xx) +switch (timerId) + { + case 1 : + switch (pin) + { + case 8 : // PA8 + channel = 0; + break; + case 9 : // PA9 + channel = 1; + break; + case 10 : // PA10 + channel = 2; + break; + case 11 : // PA11 + channel = 3; + break; + } + break; + + case 2 : + switch (pin) + { + case 0 : // PA0, PA5, PA15 + case 5 : + case 15 : + channel = 0; + break; + case 1 : // PA1, PB3 + case 1 * 16 + 3 : + channel = 1; + break; + case 2 : // PA2, PB10 + case 1 * 16 + 10 : + channel = 2; + break; + case 3 : // PA3 + channel = 3; + break; + } + break; + case 3 : + switch (pin) + { + case 6 : // PA6, PB4 + case 1 * 16 + 4 : + channel = 0; + break; + case 7 : // PA7, PB5 + case 1 * 16 + 5 : + channel = 1; + break; + case 1 * 16 + 0 : // PB0 + channel = 2; + break; + case 1 * 16 + 1 : // PB1 + channel = 3; + break; + } + break; + case 4 : + switch (pin) + { + case 1 * 16 + 6 : // PB6 + channel = 0; + break; + case 1 * 16 + 7 : // PB7 + channel = 1; + break; + case 1 * 16 + 8 : // PB8 + channel = 2; + break; + case 1 * 16 + 9 : // PB9 + channel = 3; + break; + } + break; + + case 5 : + switch (pin) + { + case 0 : // PA0 + channel = 0; + break; + case 1 : // PA1 + channel = 1; + break; + case 2 : // PA2 + channel = 2; + break; + case 3 : // PA3 + channel = 3; + break; + } + break; + + case 9 : + switch (pin) + { + case 2 : // PA2 + channel = 0; + break; + case 3 : // PA3 + channel = 1; + break; + } + break; + + default : + channel = 0xFF; + break; + } +#endif +#if defined(STM32F746xx) +switch (timerId) + { + case 1 : + switch (pin) + { + case 8 : // PA8, PE9 + case 4*16+9 : + channel = 0; + break; + case 9 : // PA9, PE11 + case 4*16+11 : + channel = 1; + break; + case 10 : // PA10, PE13 + case 4*16+13 : + channel = 2; + break; + case 11 : // PA11, PE14 + case 4*16+14 : + channel = 3; + break; + } + break; + + case 2 : + switch (pin) + { + case 0 : // PA0, PA5, PA15 + case 5 : + case 15 : + channel = 0; + break; + case 1 : // PA1, PB3 + case 1*16+3 : + channel = 1; + break; + case 2 : // PA2, PB10 + case 1*16+10 : + channel = 2; + break; + case 3 : // PA3, PB11 + case 1*16+11 : + channel = 3; + break; + } + break; + case 3 : + switch (pin) + { + case 6 : // PA6, PB4, PC6 + case 1 * 16 + 4 : + case 2 * 16 + 6 : + channel = 0; + break; + case 7 : // PA7, PB5, PC7 + case 1 * 16 + 5 : + case 2 * 16 + 7 : + channel = 1; + break; + case 1 * 16 + 0 : // PB0, PC8 + case 2 * 16 + 8 : + channel = 2; + break; + case 1 * 16 + 1 : // PB1, PC9 + case 2 * 16 + 9 : + channel = 3; + break; + } + break; + case 4 : + switch (pin) + { + case 1*16+6 : // PB6, PD12 + case 3*16+12 : + channel = 0; + break; + case 1*16+7 : // PB7, PD13 + case 3*16+13 : + channel = 1; + break; + case 1*16+8 : // PB8, PD14 + case 3*16+14 : + channel = 2; + break; + case 1*16+9 : // PB9, PD15 + case 3*16+15 : + channel = 3; + break; + } + break; + + case 5 : + switch (pin) + { + case 0 : // PA0 + channel = 0; + break; + case 1 : // PA1 + channel = 1; + break; + case 2 : // PA2 + channel = 2; + break; + case 3 : // PA3 + channel = 3; + break; + } + break; + + case 8 : + switch (pin) + { + case 2*16+6 : // PC6 + channel = 0; + break; + case 2*16+7 : // PC7 + channel = 1; + break; + case 2*16+8 : // PC8 + channel = 2; + break; + case 2*16+9 : // PC9 + channel = 3; + break; + } + break; + + + case 9 : + switch (pin) + { + case 2 : // PA2, PE5 + case 4*16+5 : + channel = 0; + break; + case 3 : // PA3, PE6 + case 4*16+6 : + channel = 1; + break; + } + break; + + default : + channel = 0xFF; + break; + } +#endif +#if defined(STM32F769xx) +switch (timerId) + { + case 1 : + switch (pin) + { + case 8 : // PA8, PE9 + case 4*16+9 : + channel = 0; + break; + case 9 : // PA9, PE11 + case 4*16+11 : + channel = 1; + break; + case 10 : // PA10, PE13 + case 4*16+13 : + channel = 2; + break; + case 11 : // PA11, PE14 + case 4*16+14 : + channel = 3; + break; + } + break; + + case 2 : + switch (pin) + { + case 0 : // PA0, PA5, PA15 + case 5 : + case 15 : + channel = 0; + break; + case 1 : // PA1, PB3 + case 1*16+3 : + channel = 1; + break; + case 2 : // PA2, PB10 + case 1*16+10 : + channel = 2; + break; + case 3 : // PA3, PB11 + case 1*16+11 : + channel = 3; + break; + } + break; + case 3 : + switch (pin) + { + case 6 : // PA6, PB4, PC6 + case 1 * 16 + 4 : + case 2 * 16 + 6 : + channel = 0; + break; + case 7 : // PA7, PB5, PC7 + case 1 * 16 + 5 : + case 2 * 16 + 7 : + channel = 1; + break; + case 1 * 16 + 0 : // PB0, PC8 + case 2 * 16 + 8 : + channel = 2; + break; + case 1 * 16 + 1 : // PB1, PC9 + case 2 * 16 + 9 : + channel = 3; + break; + } + break; + case 4 : + switch (pin) + { + case 1*16+6 : // PB6, PD12 + case 3*16+12 : + channel = 0; + break; + case 1*16+7 : // PB7, PD13 + case 3*16+13 : + channel = 1; + break; + case 1*16+8 : // PB8, PD14 + case 3*16+14 : + channel = 2; + break; + case 1*16+9 : // PB9, PD15 + case 3*16+15 : + channel = 3; + break; + } + break; + + case 5 : + switch (pin) + { + case 0 : // PA0, PH10 + case 7*16+10 : + channel = 0; + break; + case 1 : // PA1, PH11 + case 7*16+11 : + channel = 1; + break; + case 2 : // PA2, PH12 + case 7*16+12 : + channel = 2; + break; + case 3 : // PA3, PI0 + case 8*16+0 : + channel = 3; + break; + } + break; + + case 8 : + switch (pin) + { + case 2*16+6 : // PC6, PI5 + case 8*16+5 : + channel = 0; + break; + case 2*16+7 : // PC7, PI6 + case 8*16+6 : + channel = 1; + break; + case 2*16+8 : // PC8, PI7 + case 8*16+7 : + channel = 2; + break; + case 2*16+9 : // PC9, PI2 + case 8*16+2 : + channel = 3; + break; + } + break; + + + case 9 : + switch (pin) + { + case 2 : // PA2, PE5 + case 4*16+5 : + channel = 0; + break; + case 3 : // PA3, PE6 + case 4*16+6 : + channel = 1; + break; + } + break; + + default : + channel = 0xFF; + break; + } +#endif +#if defined(STM32F091xC) +switch (timerId) + { + case 1 : + switch (pin) + { + case 8 : // PA8 + channel = 0; + break; + case 9 : // PA9 + channel = 1; + break; + case 10 : // PA10 + channel = 2; + break; + case 11 : // PA11 + channel = 3; + break; + } + break; + + case 2 : + switch (pin) + { + case 0 : // PA0, PA5, PA15 + case 5 : + case 15 : + channel = 0; + break; + case 1 : // PA1, PB3 + case 1*16+3 : + channel = 1; + break; + case 2 : // PA2, PB10 + case 1*16+10 : + channel = 2; + break; + case 3 : // PA3, PB11 + case 1*16+11 : + channel = 3; + break; + } + break; + case 3 : + switch (pin) + { + case 6 : // PA6, PB4, PC6 + case 1 * 16 + 4 : + case 2 * 16 + 6 : + channel = 0; + break; + case 7 : // PA7, PB5, PC7 + case 1 * 16 + 5 : + case 2 * 16 + 7 : + channel = 1; + break; + case 1 * 16 + 0 : // PB0, PC8 + case 2 * 16 + 8 : + channel = 2; + break; + case 1 * 16 + 1 : // PB1, PC9 + case 2 * 16 + 9 : + channel = 3; + break; + } + break; + default : + channel = 0xFF; + break; + } +#endif +#if defined(STM32F407xx) || defined(STM32F405xx) + switch (timerId) + { + case 1 : + switch (pin) + { + case 8 : // PA8 + case 4*16+9 : // PE9 + channel = 0; + break; + case 9 : // PA9 + case 4*16+11 : // PE11 + channel = 1; + break; + case 10 : // PA10 + case 4*16+13 : // PE13 + channel = 2; + break; + case 11 : // PA11 + case 4*16+14 : // PE14 + channel = 3; + break; + } + break; + + case 2 : + switch (pin) + { + case 0 : // PA0, PA5, PA15 + case 5 : + case 15 : + channel = 0; + break; + case 1 : // PA1, PB3 + case 1 * 16 + 3 : + channel = 1; + break; + case 2 : // PA2, PB10 + case 1 * 16 + 10 : + channel = 2; + break; + case 3 : // PA3, PB11 + case 1 * 16 + 11 : + channel = 3; + break; + } + break; + + case 3 : + switch (pin) + { + case 6 : + case 1*16+4 : + case 2*16+6 : + channel = 0; + break; + case 7 : + case 1*16+5 : + case 2*16+7 : + channel = 1; + break; + case 1*16+0 : + case 2*16+8 : + channel = 2; + break; + case 1*16+1 : + case 2*16+9 : + channel = 3; + break; + } + break; + case 4 : + switch (pin) + { + case 1 * 16 + 6 : // PB6, PD12 + case 3 * 16 + 12 : + channel = 0; + break; + case 1 * 16 + 7 : // PB7, PD13 + case 3 * 16 + 13 : + channel = 1; + break; + case 1 * 16 + 8 : // PB8, PD14 + case 3 * 16 + 14 : + channel = 2; + break; + case 1 * 16 + 9 : // PB9, PD15 + case 3 * 16 + 15 : + channel = 3; + break; + } + break; + + case 5 : + switch (pin) + { + case 0 : // PA0 + channel = 0; + break; + case 1 : // PA1 + channel = 1; + break; + case 2 : // PA2 + channel = 2; + break; + case 3 : // PA3 + channel = 3; + break; + } + break; + + case 8 : + switch (pin) + { + case 2 * 16 + 6 : // PC6 + channel = 0; + break; + case 2 * 16 + 7 : // PC7 + channel = 1; + break; + case 2 * 16 + 8 : // PC8 + channel = 2; + break; + case 2 * 16 + 9 : // PC9 + channel = 3; + break; + } + break; + + case 9 : + switch (pin) + { + case 2 : // PA2, PE5 + case 4 * 16 + 5 : + channel = 0; + break; + case 3 : // PA3, PE6 + case 4 * 16 + 6 : + channel = 1; + break; + } + break; + + default : + channel = 0xFF; + break; + } +#endif + return channel; +} + +int GetAlternateFunction (int timerId) +{ + if (timerId >= 8) return 3; + if (timerId >= 3) return 2; + return 1; +} + +PWMDriver * GetDriver(int timerId) +{ + PWMDriver * _drv = NULL; + + switch (timerId) + { +#if STM32_PWM_USE_TIM1 + case 1 : _drv = &PWMD1; + break; +#endif +#if STM32_PWM_USE_TIM2 + case 2 : _drv = &PWMD2; + break; +#endif +#if STM32_PWM_USE_TIM3 + case 3 : _drv = &PWMD3; + break; +#endif +#if STM32_PWM_USE_TIM4 + case 4 : _drv = &PWMD4; + break; +#endif +#if STM32_PWM_USE_TIM5 + case 5 : _drv = &PWMD5; + break; +#endif +#if STM32_PWM_USE_TIM8 + case 8 : _drv = &PWMD8; + break; +#endif +#if STM32_PWM_USE_TIM9 + case 9 : _drv = &PWMD9; + break; +#endif + } + + return _drv; +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetActiveDutyCyclePercentage___VOID__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + PWMDriver * _drv; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties or method parameters + int timerId = (int)(pThis[ FIELD___pwmTimer ].NumericByRef().u4); + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + unsigned int dutyCycle = (unsigned int)stack.Arg1().NumericByRef().u4; + + // Gets the PWM driver associated with the requested timer + _drv = GetDriver(timerId); + + // get channel for this pin and timer + int channelId = GetChannel(pinNumber, timerId); + if(channelId < 0) + { + // no channel available for combination pinNumber/timerId provided + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + // Enables the channel associated with the selected pin on that timer + pwmEnableChannel(_drv, channelId ,PWM_PERCENTAGE_TO_WIDTH(_drv, dutyCycle)); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetPolarity___VOID__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStart___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + PWMDriver * _drv; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties or method parameters + int timerId = (int)(pThis[ FIELD___pwmTimer ].NumericByRef().u4); + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + unsigned int dutyCycle = (int)(pThis[ FIELD___dutyCycle ].NumericByRef().u4); + + // Gets the PWM driver associated with the requested timer + _drv = GetDriver(timerId); + + // get channel for this pin and timer + int channelId = GetChannel(pinNumber, timerId); + if(channelId < 0) + { + // no channel available for combination pinNumber/timerId provided + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + // Sets the pin to the correct pwm alternate functin and enables the associated channel + palSetPadMode(GPIO_PORT(pinNumber), pinNumber % 16, PAL_MODE_ALTERNATE(GetAlternateFunction(timerId))); + pwmEnableChannel(_drv, channelId,PWM_PERCENTAGE_TO_WIDTH(_drv, dutyCycle)); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStop___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties or method parameters + int timerId = (int)(pThis[ FIELD___pwmTimer ].NumericByRef().u4); + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + + // get channel for this pin and timer + int channelId = GetChannel(pinNumber, timerId); + if(channelId < 0) + { + // no channel available for combination pinNumber/timerId provided + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + // Stops pwm output on the channel associated with the selected pin + pwmDisableChannel(GetDriver(timerId), channelId); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h new file mode 100644 index 00000000..802c8c78 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_PWM_NATIVE_TARGET_H_ +#define _WIN_DEV_PWM_NATIVE_TARGET_H_ + +#include +#include + +#endif //_WIN_DEV_PWM_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp new file mode 100644 index 00000000..70bdf3cb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp @@ -0,0 +1,1162 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include "win_dev_serial_native_target.h" + +///////////////////////////////////////////////////////// +// UART PAL strucs delcared in win_dev_serial_native.h // +///////////////////////////////////////////////////////// +#if NF_SERIAL_COMM_STM32_UART_USE_USART1 + NF_PAL_UART Uart1_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART2 + NF_PAL_UART Uart2_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART3 + NF_PAL_UART Uart3_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART4 + NF_PAL_UART Uart4_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART5 + NF_PAL_UART Uart5_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART6 + NF_PAL_UART Uart6_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART7 + NF_PAL_UART Uart7_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART8 + NF_PAL_UART Uart8_PAL; +#endif + +// This callback is invoked when a transmission buffer has been completely read by the driver. +static void TxEnd1(UARTDriver *uartp) +{ + (void)uartp; + + NATIVE_INTERRUPT_START + + NF_PAL_UART* palUart; + + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + if (uartp == &UARTD1) + { + palUart = &Uart1_PAL; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + if (uartp == &UARTD2) + { + palUart = &Uart2_PAL; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + if (uartp == &UARTD3) + { + palUart = &Uart3_PAL; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + if (uartp == &UARTD4) + { + palUart = &Uart4_PAL; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + if (uartp == &UARTD5) + { + palUart = &Uart5_PAL; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + if (uartp == &UARTD6) + { + palUart = &Uart6_PAL; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + if (uartp == &UARTD7) + { + palUart = &Uart7_PAL; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + if (uartp == &UARTD8) + { + palUart = &Uart8_PAL; + } + #endif + + // pop elements from ring buffer, just pop + palUart->TxRingBuffer.Pop(palUart->TxOngoingCount); + + // reset Tx ongoing count + palUart->TxOngoingCount = 0; + + Events_Set( SYSTEM_EVENT_FLAG_COM_OUT ); + + NATIVE_INTERRUPT_END +} + +// This callback is invoked when a character is received but the application was not ready to receive it, the character is passed as parameter. +static void RxChar(UARTDriver *uartp, uint16_t c) +{ + NATIVE_INTERRUPT_START + + NF_PAL_UART* palUart; + uint8_t portIndex = 0; + + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + if (uartp == &UARTD1) + { + palUart = &Uart1_PAL; + portIndex = 1; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + if (uartp == &UARTD2) + { + palUart = &Uart2_PAL; + portIndex = 2; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + if (uartp == &UARTD3) + { + palUart = &Uart3_PAL; + portIndex = 3; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + if (uartp == &UARTD4) + { + palUart = &Uart4_PAL; + portIndex = 4; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + if (uartp == &UARTD5) + { + palUart = &Uart5_PAL; + portIndex = 5; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + if (uartp == &UARTD6) + { + palUart = &Uart6_PAL; + portIndex = 6; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + if (uartp == &UARTD7) + { + palUart = &Uart7_PAL; + portIndex = 7; + } + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + if (uartp == &UARTD8) + { + palUart = &Uart8_PAL; + portIndex = 8; + } + #endif + + // store this into the UART Rx buffer + + // push char to ring buffer + // don't care about the success of the operation, if it's full we are droping the char anyway + palUart->RxRingBuffer.Push((uint8_t)c); + + // is there a read operation going on? + if(palUart->RxBytesToRead > 0) + { + // yes + // check if the requested bytes are available in the buffer... + //... or if the watch char was received + if((palUart->RxRingBuffer.Length() >= palUart->RxBytesToRead) || + (c == palUart->WatchChar)) + { + // reset Rx bytes to read count + palUart->RxBytesToRead = 0; + + // fire event for Rx buffer complete + Events_Set(SYSTEM_EVENT_FLAG_COM_IN); + } + } + else + { + // no read operation ongoing, so fire an event + + // post a managed event with the port index and event code (check if this is the watch char or just another another) + // TODO: check if callbacks are registered so this is called only if there is anyone listening otherwise don't bother + // for that to happen ChibiOS callback has to accept arg which we would passing the GpioPin CLR_RT_HeapBlock (see Gpio handler) + // check http://www.chibios.com/forum/viewtopic.php?f=36&t=4798 + PostManagedEvent( EVENT_SERIAL, 0, portIndex, (c == palUart->WatchChar) ? SerialData_WatchChar : SerialData_Chars ); + } + + NATIVE_INTERRUPT_END +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeDispose___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Choose the driver for this SerialDevice + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { + + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + UnInit_UART1(); + // stop UART + uartStop(&UARTD1); + Uart1_PAL.UartDriver = NULL; + break; + #endif + + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + UnInit_UART2(); + // stop UART + uartStop(&UARTD2); + Uart2_PAL.UartDriver = NULL; + break; + #endif + + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + UnInit_UART3(); + // stop UART + uartStop(&UARTD3); + Uart3_PAL.UartDriver = NULL; + break; + #endif + + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + UnInit_UART4(); + // stop UART + uartStop(&UARTD4); + Uart4_PAL.UartDriver = NULL; + break; + #endif + + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + UnInit_UART5(); + // stop UART + uartStop(&UARTD5); + Uart5_PAL.UartDriver = NULL; + break; + #endif + + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + UnInit_UART6(); + // stop UART + uartStop(&UARTD6); + Uart6_PAL.UartDriver = NULL; + break; + #endif + + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + UnInit_UART7(); + // stop UART + uartStop(&UARTD7); + Uart7_PAL.UartDriver = NULL; + break; + #endif + + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + UnInit_UART8(); + // stop UART + uartStop(&UARTD8); + Uart8_PAL.UartDriver = NULL; + break; + #endif + + default: + // this COM port is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_UART* palUart; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Choose the driver for this SerialDevice + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + Init_UART1(); + Uart1_PAL.UartDriver = &UARTD1; + palUart = &Uart1_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + Init_UART2(); + Uart2_PAL.UartDriver = &UARTD2; + palUart = &Uart2_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + Init_UART3(); + Uart3_PAL.UartDriver = &UARTD3; + palUart = &Uart3_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + Init_UART4(); + Uart4_PAL.UartDriver = &UARTD4; + palUart = &Uart4_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + Init_UART5(); + Uart5_PAL.UartDriver = &UARTD5; + palUart = &Uart5_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + Init_UART6(); + Uart6_PAL.UartDriver = &UARTD6; + palUart = &Uart6_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + Init_UART7(); + Uart7_PAL.UartDriver = &UARTD7; + palUart = &Uart7_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + Init_UART8(); + Uart8_PAL.UartDriver = &UARTD8; + palUart = &Uart8_PAL; + break; + #endif + default: + // this COM port is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // configure UART handlers + palUart->Uart_cfg.txend1_cb = TxEnd1; + palUart->Uart_cfg.rxchar_cb = RxChar; + //palUart->Uart_cfg.rxend_cb = RxEnd; + + // call the configure + return NativeConfig___VOID(stack); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeConfig___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_UART* palUart = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Choose the driver for this SerialDevice + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + palUart = &Uart1_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + palUart = &Uart2_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + palUart = &Uart3_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + palUart = &Uart4_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + palUart = &Uart5_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + palUart = &Uart6_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + palUart = &Uart7_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + palUart = &Uart8_PAL; + break; + #endif + } + + // setup configuration + + // data bits @ CR1:M1&M0 + // TODO + + // parity @ CR1:PS + // TODO + + // stop bits @ CR2:STOP1&STOP0 + // clear bits for stop bits setting + palUart->Uart_cfg.cr2 &= ~USART_CR2_STOP; + + switch ((SerialStopBitCount)pThis[ FIELD___stopBits ].NumericByRef().s4) + { + case SerialStopBitCount_One : + // already set with the above + break; + case SerialStopBitCount_OnePointFive : + palUart->Uart_cfg.cr2 |= USART_CR2_STOP_1 + USART_CR2_STOP_0; + break; + case SerialStopBitCount_Two : + palUart->Uart_cfg.cr2 |= USART_CR2_STOP_1; + break; + } + + // baud rate + palUart->Uart_cfg.speed = (int)pThis[ FIELD___baudRate ].NumericByRef().s4; + + // stop UART, better do this before changing configuration + uartStop(palUart->UartDriver); + + // get pointer to PAL UART + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + ConfigPins_UART1(); + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + ConfigPins_UART2(); + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + ConfigPins_UART3(); + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + ConfigPins_UART4(); + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + ConfigPins_UART5(); + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + ConfigPins_UART6(); + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + ConfigPins_UART7(); + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + ConfigPins_UART8(); + break; + #endif + } + + uartStart(palUart->UartDriver, &palUart->Uart_cfg); + uartStopSend(palUart->UartDriver); + uartStopReceive(palUart->UartDriver); + + // null pointers and vars + pThis = NULL; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeWrite___VOID__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_UART* palUart = NULL; + + uint8_t* data; + unsigned int length = 0; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // dereference the data buffer from the argument + CLR_RT_HeapBlock_Array* dataBuffer = stack.Arg1().DereferenceArray(); + + // get a the pointer to the array by using the first element of the array + data = dataBuffer->GetFirstElement(); + + // get the size of the buffer + length = dataBuffer->m_numOfElements; + + // get pointer to PAL UART + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + palUart = &Uart1_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + palUart = &Uart2_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + palUart = &Uart3_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + palUart = &Uart4_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + palUart = &Uart5_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + palUart = &Uart6_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + palUart = &Uart7_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + palUart = &Uart8_PAL; + break; + #endif + } + + // check if there is enough room in the buffer + if(palUart->TxRingBuffer.Capacity() - palUart->TxRingBuffer.Length() < length) + { + // not enough room in the buffer + NANOCLR_SET_AND_LEAVE(CLR_E_BUFFER_TOO_SMALL); + } + + // push data to buffer + size_t bytesWritten = palUart->TxRingBuffer.Push(data, length); + + // check if all requested bytes were written + if(bytesWritten != length) + { + // not sure if this is the best exception to throw here... + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + // need to update the _unstoredBufferLength field in the SerialDeviceOutputStream + // get pointer to outputStream field + CLR_RT_HeapBlock* outputStream = pThis[Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___outputStream].Dereference(); + // get pointer to _unstoredBufferLength field and udpate field value + outputStream[Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDeviceOutputStream::FIELD___unstoredBufferLength].NumericByRef().s4 = palUart->TxRingBuffer.Length(); + + // null pointers and vars + pThis = NULL; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeStore___U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NF_PAL_UART* palUart = NULL; + + size_t length = 0; + + CLR_RT_HeapBlock* writeTimeout; + int64_t* timeoutTicks; + bool eventResult = true; + bool txOk = false; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // Choose the driver for this SerialDevice + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { +#if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + palUart = &Uart1_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + palUart = &Uart2_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + palUart = &Uart3_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + palUart = &Uart4_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + palUart = &Uart5_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + palUart = &Uart6_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + palUart = &Uart7_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + palUart = &Uart8_PAL; + break; +#endif + } + + // get value for _readtimeout field (pointer!) + writeTimeout = &pThis[ Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___writeTimeout ]; + + // setup timeout + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks(*writeTimeout, timeoutTicks)); + + // push dummy length value onto the eval stack + // this is going to be used to store how many bytes where buffered to Tx + if(stack.m_customState == 1) + { + stack.PushValueI4(0); + + // bump custom state so the read value above is pushed only once + stack.m_customState = 2; + } + + // check if there is anything the buffer + if(palUart->TxRingBuffer.Length() > 0) + { + // check if there is a TX operation ongoing + if(palUart->TxOngoingCount == 0) + { + // OK to Tx + txOk = true; + } + else + { + // need to wait for the ongoing operation to complete before starting a new one + } + } + + if(txOk) + { + // optimize buffer for sequential reading + palUart->TxRingBuffer.OptimizeSequence(); + + // get data length available in the buffer + length = palUart->TxRingBuffer.Length(); + + // push to the stack how many bytes bytes where buffered for Tx + stack.m_evalStack[1].NumericByRef().s4 = length; + + // flush DMA buffer to ensure cache coherency + // (only required for Cortex-M7) + cacheBufferFlush(palUart->TxRingBuffer.Reader(), length); + + // set TX ongoing count + palUart->TxOngoingCount = length; + + // because the UART can be accessed from several threads need to get exclusive access to it + uartAcquireBus(palUart->UartDriver); + + // start sending data (DMA will read from the ring buffer) + uartStartSend(palUart->UartDriver, length, (uint8_t*)palUart->TxRingBuffer.Reader()); + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the Tx operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeoutTicks, CLR_RT_ExecutionEngine::c_Event_SerialPortOut, eventResult )); + + // done here, release the UART + uartReleaseBus(palUart->UartDriver); + + if(eventResult) + { + // event occurred + // get from the eval stack how many bytes were buffered to Tx + length = stack.m_evalStack[1].NumericByRef().s4; + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop length heap block from stack + stack.PopValue(); + + // pop timeout heap block from stack + stack.PopValue(); + + stack.SetResult_U4(length); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeRead___U4__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* dataBuffer; + NF_PAL_UART* palUart = NULL; + + uint8_t* data; + size_t dataLength = 0; + + size_t count = 0; + size_t bytesRead = 0; + size_t bytesToRead = 0; + + InputStreamOptions options = InputStreamOptions_None; + + CLR_RT_HeapBlock* readTimeout; + int64_t* timeoutTicks; + bool eventResult = true; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); if(!(pThis)) FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // dereference the data buffer from the argument + dataBuffer = stack.Arg1().DereferenceArray(); + + // get a the pointer to the array by using the first element of the array + data = dataBuffer->GetFirstElement(); + + // get the length of the data buffer + dataLength = dataBuffer->m_numOfElements; + + // get how many bytes are requested to read + count = stack.Arg2().NumericByRef().s4; + + // get the InputStreamOptions option + options = (InputStreamOptions)stack.Arg3().NumericByRef().s4; + + // Choose the driver for this SerialDevice + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { +#if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + palUart = &Uart1_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + palUart = &Uart2_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + palUart = &Uart3_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + palUart = &Uart4_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + palUart = &Uart5_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + palUart = &Uart6_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + palUart = &Uart7_PAL; + break; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + palUart = &Uart8_PAL; + break; +#endif + } + + // get value for _readtimeout field (pointer!) + readTimeout = &pThis[ Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___readTimeout ]; + + // setup timeout from the _readtimeout heap block + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( *readTimeout, timeoutTicks )); + + // figure out what's available in the Rx ring buffer + if(palUart->RxRingBuffer.Length() >= count) + { + // read from Rx ring buffer + bytesToRead = count; + + // is the read ahead option enabled? + if(options == InputStreamOptions_ReadAhead) + { + // yes + // check how many bytes we can store in the buffer argument + if(dataLength < palUart->RxRingBuffer.Length()) + { + // read as many bytes has the buffer can hold + bytesToRead = dataLength; + } + else + { + // read everything that's available in the ring buffer + bytesToRead = palUart->RxRingBuffer.Length(); + } + } + + // we have enough bytes, skip wait for event + eventResult = false; + + // clear event by getting it + Events_Get(SYSTEM_EVENT_FLAG_COM_IN); + } + else + { + if(stack.m_customState == 1) + { + // not enough bytes available, have to read from UART + palUart->RxBytesToRead = count; + + // clear event by getting it + Events_Get(SYSTEM_EVENT_FLAG_COM_IN); + + // don't read anything from the buffer yet + bytesToRead = 0; + } + } + + while(eventResult) + { + if(stack.m_customState == 1) + { + if(bytesToRead > 0) + { + // enough bytes available + eventResult = false; + } + else + { + // need to read from the UART + // update custom state + stack.m_customState = 2; + } + } + else + { + // wait for event + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents(stack.m_owningThread, *timeoutTicks, CLR_RT_ExecutionEngine::c_Event_SerialPortIn, eventResult)); + + if(!eventResult) + { + // event timeout + + // compute how many bytes to read + // considering the InputStreamOptions read ahead option + if(options == InputStreamOptions_ReadAhead) + { + // yes + // check how many bytes we can store in the buffer argument + if(dataLength < palUart->RxRingBuffer.Length()) + { + // read as many bytes has the buffer can hold + bytesToRead = dataLength; + } + else + { + // read everything that's available in the ring buffer + bytesToRead = palUart->RxRingBuffer.Length(); + } + } + else + { + // take InputStreamOptions_Partial as default and read requested quantity or what's available + bytesToRead = count; + + if(count > palUart->RxRingBuffer.Length()) + { + // need to adjust because there aren't enough bytes available + bytesToRead = palUart->RxRingBuffer.Length(); + } + } + } + } + } + + if(bytesToRead > 0) + { + // pop the requested bytes from the ring buffer + bytesRead = palUart->RxRingBuffer.Pop(data, bytesToRead); + } + + // pop timeout heap block from stack + stack.PopValue(); + + // return how many bytes were read + stack.SetResult_U4(bytesRead); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeSetWatchChar___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_UART* palUart; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Choose the driver for this SerialDevice + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + palUart = &Uart1_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + palUart = &Uart2_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + palUart = &Uart3_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + palUart = &Uart4_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + palUart = &Uart5_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + palUart = &Uart6_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + palUart = &Uart7_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + palUart = &Uart8_PAL; + break; + #endif + default: + // this COM port is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // set watch char + palUart->WatchChar = (uint8_t)pThis[ FIELD___watchChar ].NumericByRef().u1; + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::get_BytesToRead___U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_UART* palUart; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Choose the driver for this SerialDevice + switch ((int)pThis[ FIELD___portIndex ].NumericByRef().s4) + { + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + case 1 : + palUart = &Uart1_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + case 2 : + palUart = &Uart2_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + case 3 : + palUart = &Uart3_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + case 4 : + palUart = &Uart4_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + case 5 : + palUart = &Uart5_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + case 6 : + palUart = &Uart6_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + case 7 : + palUart = &Uart7_PAL; + break; + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + case 8 : + palUart = &Uart8_PAL; + break; + #endif + default: + // this COM port is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // get length of Rx ring buffer + stack.SetResult_U4(palUart->RxRingBuffer.Length()); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8," + terminator and init with the terminator + char deviceSelectorString[ 40 + 1] = { 0 }; + + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + strcat(deviceSelectorString, "COM1,"); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + strcat(deviceSelectorString, "COM2,"); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + strcat(deviceSelectorString, "COM3,"); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + strcat(deviceSelectorString, "COM4,"); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + strcat(deviceSelectorString, "COM5,"); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + strcat(deviceSelectorString, "COM6,"); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + strcat(deviceSelectorString, "COM7,"); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + strcat(deviceSelectorString, "COM8,"); + #endif + + // replace the last comma with a terminator + deviceSelectorString[hal_strlen_s(deviceSelectorString) - 1] = '\0'; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h new file mode 100644 index 00000000..57f70acc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h @@ -0,0 +1,182 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_SERIAL_NATIVE_TARGET_H_ +#define _WIN_DEV_SERIAL_NATIVE_TARGET_H_ + +#include +#include +#include + +// struct representing the UART +struct NF_PAL_UART +{ + UARTDriver* UartDriver; + UARTConfig Uart_cfg; + + HAL_RingBuffer TxRingBuffer; + uint8_t* TxBuffer; + uint16_t TxOngoingCount; + + HAL_RingBuffer RxRingBuffer; + uint8_t* RxBuffer; + uint16_t RxBytesToRead; + + uint8_t WatchChar; +}; + + +//////////////////////////////////////////// +// declaration of the the UART PAL strucs // +//////////////////////////////////////////// +#if NF_SERIAL_COMM_STM32_UART_USE_USART1 + extern NF_PAL_UART Uart1_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART2 + extern NF_PAL_UART Uart2_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART3 + extern NF_PAL_UART Uart3_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART4 + extern NF_PAL_UART Uart4_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART5 + extern NF_PAL_UART Uart5_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_USART6 + extern NF_PAL_UART Uart6_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART7 + extern NF_PAL_UART Uart7_PAL; +#endif +#if NF_SERIAL_COMM_STM32_UART_USE_UART8 + extern NF_PAL_UART Uart8_PAL; +#endif + +// the following macro defines a function that configures the GPIO pins for a STM32 UART/USART +// it gets called in the Windows_Devices_SerialCommunication_SerialDevice::NativeConfig function +// this is required because the UART/USART peripherals can use multiple GPIO configuration combinations +#define UART_CONFIG_PINS(num, gpio_port_tx, gpio_port_rx, tx_pin, rx_pin, alternate_function) void ConfigPins_UART##num() { \ + palSetPadMode(gpio_port_tx, tx_pin, PAL_MODE_ALTERNATE(alternate_function)); \ + palSetPadMode(gpio_port_rx, rx_pin, PAL_MODE_ALTERNATE(alternate_function)); \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// when a UART/USART is defined the declarations below will have the real function/configuration +// in the target folder @ target_windows_devices_serialcommunication_config.cpp +/////////////////////////////////////////////////////////////////////////////////////////////////// +void ConfigPins_UART1(); +void ConfigPins_UART2(); +void ConfigPins_UART3(); +void ConfigPins_UART4(); +void ConfigPins_UART5(); +void ConfigPins_UART6(); +void ConfigPins_UART7(); +void ConfigPins_UART8(); + + +///////////////////////////////////// +// UART Tx buffers // +// these live in the target folder // +///////////////////////////////////// +extern uint8_t Uart1_TxBuffer[]; +extern uint8_t Uart2_TxBuffer[]; +extern uint8_t Uart3_TxBuffer[]; +extern uint8_t Uart4_TxBuffer[]; +extern uint8_t Uart5_TxBuffer[]; +extern uint8_t Uart6_TxBuffer[]; +extern uint8_t Uart7_TxBuffer[]; +extern uint8_t Uart8_TxBuffer[]; + + +///////////////////////////////////// +// UART Rx buffers // +// these live in the target folder // +///////////////////////////////////// +extern uint8_t Uart1_RxBuffer[]; +extern uint8_t Uart2_RxBuffer[]; +extern uint8_t Uart3_RxBuffer[]; +extern uint8_t Uart4_RxBuffer[]; +extern uint8_t Uart5_RxBuffer[]; +extern uint8_t Uart6_RxBuffer[]; +extern uint8_t Uart7_RxBuffer[]; +extern uint8_t Uart8_RxBuffer[]; + + +// the following macro defines a function that initializes an UART struct +// it gets called in the Windows_Devices_SerialCommunication_SerialDevice::NativeInit function + +#if defined(STM32F7XX) || defined(STM32F0XX) + +// STM32F7 and STM32F0 use UART driver v2 +#define UART_INIT(num, tx_buffer_size, rx_buffer_size) void Init_UART##num() { \ + Uart##num##_PAL.Uart_cfg.txend2_cb = NULL; \ + Uart##num##_PAL.Uart_cfg.rxend_cb = NULL; \ + Uart##num##_PAL.Uart_cfg.rxerr_cb = NULL; \ + Uart##num##_PAL.Uart_cfg.timeout_cb = NULL; \ + Uart##num##_PAL.Uart_cfg.timeout = 0; \ + Uart##num##_PAL.Uart_cfg.speed = 9600; \ + Uart##num##_PAL.Uart_cfg.cr1 = 0; \ + Uart##num##_PAL.Uart_cfg.cr2 = 0; \ + Uart##num##_PAL.Uart_cfg.cr3 = 0; \ + Uart##num##_PAL.TxBuffer = Uart##num##_TxBuffer; \ + Uart##num##_PAL.TxRingBuffer.Initialize( Uart##num##_PAL.TxBuffer, tx_buffer_size); \ + Uart##num##_PAL.TxOngoingCount = 0; \ + Uart##num##_PAL.RxBuffer = Uart##num##_RxBuffer; \ + Uart##num##_PAL.RxRingBuffer.Initialize( Uart##num##_PAL.RxBuffer, rx_buffer_size); \ + Uart##num##_PAL.WatchChar = 0; \ +} + +#else + +// all other STM32F use UART driver v1 which has a different UARTConfig struct +#define UART_INIT(num, tx_buffer_size, rx_buffer_size) void Init_UART##num() { \ + Uart##num##_PAL.Uart_cfg.txend2_cb = NULL; \ + Uart##num##_PAL.Uart_cfg.rxend_cb = NULL; \ + Uart##num##_PAL.Uart_cfg.rxerr_cb = NULL; \ + Uart##num##_PAL.Uart_cfg.speed = 9600; \ + Uart##num##_PAL.Uart_cfg.cr1 = 0; \ + Uart##num##_PAL.Uart_cfg.cr2 = 0; \ + Uart##num##_PAL.Uart_cfg.cr3 = 0; \ + Uart##num##_PAL.TxBuffer = Uart##num##_TxBuffer; \ + Uart##num##_PAL.TxRingBuffer.Initialize( Uart##num##_PAL.TxBuffer, tx_buffer_size); \ + Uart##num##_PAL.TxOngoingCount = 0; \ + Uart##num##_PAL.RxBuffer = Uart##num##_RxBuffer; \ + Uart##num##_PAL.RxRingBuffer.Initialize( Uart##num##_PAL.RxBuffer, rx_buffer_size); \ + Uart##num##_PAL.WatchChar = 0; \ +} + +#endif + + +// when a UART/USART is defined the declarations below will have the real function/configuration +// in the target folder @ target_windows_devices_serialcommunication_config.cpp +void Init_UART1(); +void Init_UART2(); +void Init_UART3(); +void Init_UART4(); +void Init_UART5(); +void Init_UART6(); +void Init_UART7(); +void Init_UART8(); + + +// the following macro defines a function that un initializes an UART struct +// it gets called in the Windows_Devices_SerialCommunication_SerialDevice::NativeDispose function +#define UART_UNINIT(num) void UnInit_UART##num() { return; } + +// when a UART/USART is defined the declarations below will have the real function/configuration +// in the target folder @ target_windows_devices_serialcommunication_config.cpp +void UnInit_UART1(); +void UnInit_UART2(); +void UnInit_UART3(); +void UnInit_UART4(); +void UnInit_UART5(); +void UnInit_UART6(); +void UnInit_UART7(); +void UnInit_UART8(); + +#endif //_WIN_DEV_SERIAL_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp new file mode 100644 index 00000000..3f777bf7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp @@ -0,0 +1,43 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_spi_native_target.h" + + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MaxClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pArg = &(stack.Arg1()); + + // spiBus is an ASCII string with the bus name in format 'SPIn' + // need to grab 'n' from the string and convert to the integer value from the ASCII code + uint8_t bus = (uint8_t)pArg[0].RecoverString()[3] - 48; + + // According to STM : "At a minimum, the clock frequency should be twice the required communication frequency." + // So maximum useable frequency is CoreClock / 2. + // SPI2 or SPI3 are on APB1, so divide max frequency by four. + stack.SetResult_I4 ((bus == 2 or bus == 3) ? SystemCoreClock >>= 2 : SystemCoreClock >> 1); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MinClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pArg = &(stack.Arg1()); + + // spiBus is an ASCII string with the bus name in format 'SPIn' + // need to grab 'n' from the string and convert to the integer value from the ASCII code + uint8_t bus = (uint8_t)pArg[0].RecoverString()[3] - 48; + + // Max prescaler value = 256 + // SPI2 or SPI3 are on APB1, so divide max frequency by four. + stack.SetResult_I4 ((bus == 2 or bus == 3) ? SystemCoreClock >>= 9 : SystemCoreClock >> 8); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp new file mode 100644 index 00000000..17e41c97 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_spi_native_target.h" + + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "SPI1,SPI2,SPI3,SPI4,SPI5,SPI6," + terminator and init with the terminator + char deviceSelectorString[ 30 + 1] = { 0 }; + + #if STM32_SPI_USE_SPI1 + strcat(deviceSelectorString, "SPI1,"); + #endif + #if STM32_SPI_USE_SPI2 + strcat(deviceSelectorString, "SPI2,"); + #endif + #if STM32_SPI_USE_SPI3 + strcat(deviceSelectorString, "SPI3,"); + #endif + #if STM32_SPI_USE_SPI4 + strcat(deviceSelectorString, "SPI4,"); + #endif + #if STM32_SPI_USE_SPI5 + strcat(deviceSelectorString, "SPI5,"); + #endif + #if STM32_SPI_USE_SPI6 + strcat(deviceSelectorString, "SPI6,"); + #endif + + // replace the last comma with a terminator + deviceSelectorString[hal_strlen_s(deviceSelectorString) - 1] = '\0'; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp new file mode 100644 index 00000000..ebfe4d4a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp @@ -0,0 +1,812 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include +#include +#include +#include +#include +#include +#include "win_dev_spi_native_target.h" + + +// define this type here to make it shorter and improve code readability +typedef Library_win_dev_spi_native_Windows_Devices_Spi_SpiConnectionSettings SpiConnectionSettings; + + +///////////////////////////////////////////////////// +// SPI PAL strucs declared in win_dev_spi_native.h // +///////////////////////////////////////////////////// +#if STM32_SPI_USE_SPI1 +NF_PAL_SPI SPI1_PAL; +#endif +#if STM32_SPI_USE_SPI2 +NF_PAL_SPI SPI2_PAL; +#endif +#if STM32_SPI_USE_SPI3 +NF_PAL_SPI SPI3_PAL; +#endif +#if STM32_SPI_USE_SPI4 +NF_PAL_SPI SPI4_PAL; +#endif +#if STM32_SPI_USE_SPI5 +NF_PAL_SPI SPI5_PAL; +#endif +#if STM32_SPI_USE_SPI6 +NF_PAL_SPI SPI6_PAL; +#endif + +static void SpiCallback(SPIDriver *spip) +{ + (void)spip; + + NATIVE_INTERRUPT_START + + NF_PAL_SPI* palSpi = NULL; + + #if STM32_SPI_USE_SPI1 + if (spip == &SPID1) + { + palSpi = &SPI1_PAL; + } + #endif + #if STM32_SPI_USE_SPI2 + if (spip == &SPID2) + { + palSpi = &SPI2_PAL; + } + #endif + #if STM32_SPI_USE_SPI3 + if (spip == &SPID3) + { + palSpi = &SPI3_PAL; + } + #endif + #if STM32_SPI_USE_SPI4 + if (spip == &SPID4) + { + palSpi = &SPI4_PAL; + } + #endif + #if STM32_SPI_USE_SPI5 + if (spip == &SPID5) + { + palSpi = &SPI5_PAL; + } + #endif + #if STM32_SPI_USE_SPI6 + if (spip == &SPID6) + { + palSpi = &SPI6_PAL; + } + #endif + + // check if there is any Rx operation due + if(palSpi->SequentialTxRx) + { + // yes there is! + // clear flag and... + palSpi->SequentialTxRx = false; + + // ... start it + spiStartReceive(palSpi->Driver, palSpi->ReadSize, palSpi->ReadBuffer); + } + else + { + // all done here! + + spiUnselect(palSpi->Driver); + + // fire event for SPI transaction complete + Events_Set( SYSTEM_EVENT_FLAG_SPI_MASTER ); + } + + NATIVE_INTERRUPT_END +}; + +// Computes the SPI peripheral baud rate according to the requested frequency +uint16_t ComputeBaudRate(uint8_t busIndex, int32_t requestedFrequency, int32_t& actualFrequency) +{ + uint16_t divider = 0; + int32_t maxSpiFrequency; + + #if defined(STM32L0XX) + + // SP1 is feed by APB2 (STM32_PCLK2) + actualFrequency = STM32_PCLK2; + + // SPI2 is feed by APB1 (STM32_PCLK1) + if (busIndex == 1) + { + actualFrequency = STM32_PCLK1; + } + + // from datasheet + maxSpiFrequency = 12000000; + + #elif defined(STM32F0XX) + + (void)busIndex; + + // STM32F0 SPI is always feed by APB1 + actualFrequency = STM32_PCLK1; + + // from datasheet + maxSpiFrequency = 18000000; + + #elif defined(STM32F4XX) || defined(STM32F7XX) + + // SP1, SPI4, SPI5 and SPI6 are feed by APB2 (STM32_PCLK2) + actualFrequency = STM32_PCLK2; + + // SPI2 and SPI3 are feed by APB1 (STM32_PCLK1) + if (busIndex == 2 || busIndex == 3) + { + actualFrequency = STM32_PCLK1; + } + + // this is not really accurate because there are different max SPI clocks depending on which APB clock source if feeding the SPI + // because ChibiOS doesn't offer that we have to go with minimum common denominator + maxSpiFrequency = STM32_SPII2S_MAX; + + #elif defined(STM32H7XX) + + // SP1, SPI4, SPI5 and SPI6 are feed by APB2 (STM32_PCLK2) + actualFrequency = STM32_PCLK2; + maxSpiFrequency = STM32_SPI456_MAX; + + // SPI1, SPI2 and SPI3 are feed by APB1 (STM32_PCLK1) + if (busIndex == 2 || busIndex == 3) + { + actualFrequency = STM32_PCLK1; + maxSpiFrequency = STM32_SPI123_MAX; + } + + #else + + #error "Error setting max SPI frequency. Check if the target series is defined." + + #endif + + + // when requested frequency is 0, means that the developer hasn't set ClockFrequency in SpiConnectionSettings + // default to the max possible SPI frequency + if(requestedFrequency == 0) + { + requestedFrequency = maxSpiFrequency; + } + + for( ; divider < 8; divider++) + { + actualFrequency = actualFrequency / 2; + + if(actualFrequency <= requestedFrequency) + { + // best match for the requested frequency + // just check if it's below the max SPI frequency + if(actualFrequency <= maxSpiFrequency) + { + // we are good with this value + break; + } + } + } + + // the baud rate bits are in the position B5:3 so need to left shit the divider value + return divider << 3; +} + +// Give a complete low-level SPI configuration from user's managed connectionSettings +void GetSPIConfig(int busIndex, CLR_RT_HeapBlock* config, SPIConfig* llConfig, bool bufferIs16bits) +{ + int32_t actualFrequency; + + // clear values + llConfig->cr1 = 0; + llConfig->cr2 = 0; + + // get chip select pin + int csPin = config[ SpiConnectionSettings::FIELD___csLine ].NumericByRef().s4; + + // SPI mode + switch (config[ SpiConnectionSettings::FIELD___spiMode ].NumericByRef().s4) + { + case SpiModes_Mode1: + llConfig->cr1 |= SPI_CR1_CPHA; + break; + + case SpiModes_Mode2: + llConfig->cr1 |= SPI_CR1_CPOL; + break; + + case SpiModes_Mode3: + llConfig->cr1 |= SPI_CR1_CPHA | SPI_CR1_CPOL; + break; + + default: // Default to Mode0 if invalid mode specified + break; + } + + // compute baud rate of SPI peripheral according to the requested frequency + llConfig->cr1 |= ComputeBaudRate(busIndex, config[ SpiConnectionSettings::FIELD___clockFrequency ].NumericByRef().s4, (int32_t&)actualFrequency); + + // set data transfer length according to SPI connection settings and... + // ... buffer data size. Have to use the shortest one. + if (config[ SpiConnectionSettings::FIELD___databitLength ].NumericByRef().s4 == 16) + { + // databitLength is 16bits + + if(bufferIs16bits) + { + // Set data transfer length to 16 bits + #ifdef STM32F4XX + llConfig->cr1 |= SPI_CR1_DFF; + #endif + #ifdef STM32F7XX + llConfig->cr2 = SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; + #endif + // Sets the order of bytes transmission : MSB first or LSB first + int bitOrder = config[ SpiConnectionSettings::FIELD___bitOrder ].NumericByRef().s4; + if (bitOrder == DataBitOrder_LSB) + { + llConfig->cr1 |= SPI_CR1_LSBFIRST; + } + } + else + { + // have to force transfer length to 8bit + #ifdef STM32F4XX + llConfig->cr1 &= ~SPI_CR1_DFF; + #endif + #ifdef STM32F7XX + llConfig->cr2 = SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; + #endif + } + } + else + { + // databitLength is 8bits + + if(bufferIs16bits) + { + // have to force transfer length to 16bit + #ifdef STM32F4XX + llConfig->cr1 |= SPI_CR1_DFF; + #endif + #ifdef STM32F7XX + llConfig->cr2 = SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; + #endif + + } + else + { + // set transfer length to 8bits + #ifdef STM32F4XX + llConfig->cr1 &= ~SPI_CR1_DFF; + #endif + #ifdef STM32F7XX + llConfig->cr2 |= SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; + #endif + } + } + + // Create the low level configuration + #if (SPI_SUPPORTS_CIRCULAR == TRUE) + llConfig->circular = SPI_USE_CIRCULAR; + #endif + llConfig->end_cb = SpiCallback; + llConfig->ssport = GPIO_PORT(csPin); + llConfig->sspad = csPin % 16; +} + +// estimate the time required to perform the SPI transaction +bool IsLongRunningOperation(uint32_t writeSize, uint32_t readSize, bool bufferIs16bits, float byteTime, uint32_t& estimatedDurationMiliseconds) +{ + if(bufferIs16bits) + { + // double the buffers size + writeSize = 2 * writeSize; + readSize = 2 * readSize; + } + + estimatedDurationMiliseconds = byteTime * (writeSize + readSize); + + if(estimatedDurationMiliseconds > CLR_RT_Thread::c_TimeQuantum_Milliseconds) + { + // total operation time will exceed thread quantum, so this is a long running operation + return true; + } + else + { + return false; + } +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + return NativeTransfer( stack, false ); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + return NativeTransfer( stack, true ); +} +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer( CLR_RT_StackFrame& stack, bool bufferIs16bits ) +{ + NANOCLR_HEADER(); + { + NF_PAL_SPI* palSpi = NULL; + uint8_t busIndex; + bool fullDuplex; + bool isLongRunningOperation = false; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + uint32_t estimatedDurationMiliseconds; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details + busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // get the PAL struct for the SPI bus + switch (busIndex) + { + #if STM32_SPI_USE_SPI1 + case 1: + palSpi = &SPI1_PAL; + break; + #endif + #if STM32_SPI_USE_SPI2 + case 2: + palSpi = &SPI2_PAL; + break; + #endif + #if STM32_SPI_USE_SPI3 + case 3: + palSpi = &SPI3_PAL; + break; + #endif + #if STM32_SPI_USE_SPI4 + case 4: + palSpi = &SPI4_PAL; + break; + #endif + #if STM32_SPI_USE_SPI5 + case 5: + palSpi = &SPI5_PAL; + break; + #endif + #if STM32_SPI_USE_SPI6 + case 6: + palSpi = &SPI6_PAL; + break; + #endif + default: + // the requested SPI bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // Are we using SPI full-duplex for transfer? + fullDuplex = (bool)stack.Arg3().NumericByRef().u1; + + // dereference the write and read buffers from the arguments + CLR_RT_HeapBlock_Array* writeBuffer = stack.Arg1().DereferenceArray(); + if (writeBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + palSpi->WriteSize = writeBuffer->m_numOfElements; + } + + CLR_RT_HeapBlock_Array* readBuffer = stack.Arg2().DereferenceArray(); + if (readBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + palSpi->ReadSize = readBuffer->m_numOfElements; + } + + // check if this is a long running operation + isLongRunningOperation = IsLongRunningOperation(palSpi->WriteSize, palSpi->ReadSize, bufferIs16bits, palSpi->ByteTime, (uint32_t&)estimatedDurationMiliseconds); + + if(isLongRunningOperation) + { + // if this is a long running operation, set a timeout equal to the estimated transaction duration in milliseconds + // this value has to be in ticks to be properly loaded by SetupTimeoutFromTicks() below + hbTimeout.SetInteger((CLR_INT64)estimatedDurationMiliseconds * TIME_CONVERSION__TO_MILLISECONDS); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // protect the buffers from GC so DMA can find them where they are supposed to be + CLR_RT_ProtectFromGC gcWriteBuffer( *writeBuffer ); + CLR_RT_ProtectFromGC gcReadBuffer( *readBuffer ); + } + + // setup the operation and init buffers + if(!isLongRunningOperation || stack.m_customState == 1) + { + // get the LL SPI configuration, depending on user's managed parameters and buffer element size + GetSPIConfig(busIndex, pConfig, &palSpi->Configuration, bufferIs16bits); + + // if this is not a long run operation we'll be using the async API thus operations are sequencial + // need to remove the callback from the SPI LL config + if(!isLongRunningOperation) + { + palSpi->Configuration.end_cb = NULL; + } + + if (writeBuffer != NULL) + { + // set DMA write buffer + if(bufferIs16bits) + { + // buffer data width is 16bits + // get the pointer to the write buffer as UINT16 because it's really an UINT16 (2 bytes) + palSpi->WriteBuffer = (uint8_t*)writeBuffer->GetFirstElementUInt16(); + + // flush DMA buffer to ensure cache coherency + // (only required for Cortex-M7) + cacheBufferFlush(palSpi->WriteBuffer, (palSpi->WriteSize * 2)); + } + else + { + // buffer data width is 8bits + // get the pointer to the write buffer as BYTE + palSpi->WriteBuffer = (uint8_t*)writeBuffer->GetFirstElement(); + + // flush DMA buffer to ensure cache coherency + // (only required for Cortex-M7) + cacheBufferFlush(palSpi->WriteBuffer, palSpi->WriteSize); + } + } + + if (readBuffer != NULL) + { + // set DMA read buffer + if(palSpi->ReadSize > 0) + { + if(bufferIs16bits) + { + // buffer data width is 16bits + palSpi->ReadBuffer = (uint8_t*)readBuffer->GetFirstElementUInt16(); + } + else + { + // buffer data width is 8bits + // get the pointer to the read buffer as BYTE + palSpi->ReadBuffer = (uint8_t*)readBuffer->GetFirstElement(); + } + } + } + + // because the bus access is shared, acquire and select the appropriate bus + spiAcquireBus(palSpi->Driver); + spiStart(palSpi->Driver, &palSpi->Configuration); + + // just to satisfy the driver ceremony, no actual implementation for STM32 + spiSelect(palSpi->Driver); + } + + if(isLongRunningOperation) + { + // this is a long running operation and hasn't started yet + // perform SPI operation using driver's ASYNC API + if(stack.m_customState == 1) + { + if (palSpi->WriteSize != 0 && palSpi->ReadSize != 0) + { + // Transmit+Receive + if (fullDuplex) + { + // Full duplex + // single operation, clear flag + palSpi->SequentialTxRx = false; + + // Uses the largest buffer size as transfer size + spiStartExchange(palSpi->Driver, palSpi->WriteSize > palSpi->ReadSize ? palSpi->WriteSize : palSpi->ReadSize, palSpi->WriteBuffer, palSpi->ReadBuffer); + } + else + { + // flag that an Rx is required after the Tx operation completes + palSpi->SequentialTxRx = true; + + // start send operation + spiStartSend(palSpi->Driver, palSpi->WriteSize, palSpi->WriteBuffer); + // receive operation will be started in the callback after the above completes + } + } + else + { + // Transmit only or Receive only + if (palSpi->ReadSize != 0) + { + // single operation, clear flag + palSpi->SequentialTxRx = false; + + // start receive + spiStartReceive(palSpi->Driver, palSpi->ReadSize, palSpi->ReadBuffer); + } + else + { + // single operation, clear flag + palSpi->SequentialTxRx = false; + + // start send + spiStartSend(palSpi->Driver, palSpi->WriteSize, palSpi->WriteBuffer); + } + } + + // bump custom state + stack.m_customState = 2; + } + } + else + { + // this is NOT a long running operation + // perform SPI operation using driver's SYNC API + if (palSpi->WriteSize != 0 && palSpi->ReadSize != 0) + { + // Transmit+Receive + if (fullDuplex) + { + // Full duplex + // Uses the largest buffer size as transfer size + spiExchange(palSpi->Driver, palSpi->WriteSize > palSpi->ReadSize ? palSpi->WriteSize : palSpi->ReadSize, palSpi->WriteBuffer, palSpi->ReadBuffer); + } + else + { + // send operation + spiSend(palSpi->Driver, palSpi->WriteSize, palSpi->WriteBuffer); + // receive operation + spiReceive(palSpi->Driver, palSpi->ReadSize, palSpi->ReadBuffer); + } + } + else + { + // Transmit only or Receive only + if (palSpi->ReadSize != 0) + { + // receive + spiReceive(palSpi->Driver, palSpi->ReadSize, palSpi->ReadBuffer); + } + else + { + // send + spiSend(palSpi->Driver, palSpi->WriteSize, palSpi->WriteBuffer); + } + } + + // just to satisfy the driver ceremony, no actual implementation for STM32 + spiUnselect(palSpi->Driver); + + // Release the bus + spiReleaseBus(palSpi->Driver); + } + + while(eventResult) + { + if(!isLongRunningOperation) + { + // this is not a long running operation so nothing to do here + break; + } + + if(palSpi->Driver->state == SPI_READY) + { + // SPI driver is ready meaning that the SPI transaction(s) is(are) completed + break; + } + + // non-blocking wait allowing other threads to run while we wait for the Spi transaction to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_SpiMaster, eventResult )); + } + + if(isLongRunningOperation) + { + // pop timeout heap block from stack + stack.PopValue(); + } + + if(eventResult) + { + spiReleaseBus(palSpi->Driver); + + // event occurred + if(palSpi->ReadSize > 0) + { + // because this was a Read transaction, need to copy from DMA buffer to managed buffer + if(bufferIs16bits) + { + // buffer data width is 16bits + + // invalidate cache over read buffer to ensure that content from DMA is read + // (only required for Cortex-M7) + // get the pointer to the read buffer as UINT16 because it's really an UINT16 (2 bytes) + cacheBufferInvalidate(palSpi->ReadBuffer, (palSpi->ReadSize * 2)); + } + else + { + // buffer data width is 8bits + + // invalidate cache over read buffer to ensure that content from DMA is read + // (only required for Cortex-M7) + // get the pointer to the read buffer as BYTE + cacheBufferInvalidate(palSpi->ReadBuffer, palSpi->ReadSize); + } + } + } + + // null pointers and vars + pThis = NULL; + pConfig = NULL; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_SPI* palSpi = NULL; + int32_t actualFrequency; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details + uint8_t busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // init the PAL struct for this SPI bus and assign the respective driver + // all this occurs if not already done + // why do we need this? because several SPIDevice objects can be created associated to the same bus + switch (busIndex) + { + #if STM32_SPI_USE_SPI1 + case 1: + if(SPI1_PAL.Driver == NULL) + { + SPI1_PAL.Driver = &SPID1; + palSpi = &SPI1_PAL; + } + break; + #endif + #if STM32_SPI_USE_SPI2 + case 2: + if(SPI2_PAL.Driver == NULL) + { + SPI2_PAL.Driver = &SPID2; + palSpi = &SPI2_PAL; + } + break; + #endif + #if STM32_SPI_USE_SPI3 + case 3: + if(SPI3_PAL.Driver == NULL) + { + SPI3_PAL.Driver = &SPID3; + palSpi = &SPI3_PAL; + } + break; + #endif + #if STM32_SPI_USE_SPI4 + case 4: + if(SPI4_PAL.Driver == NULL) + { + SPI4_PAL.Driver = &SPID4; + palSpi = &SPI4_PAL; + } + break; + #endif + #if STM32_SPI_USE_SPI5 + case 5: + if(SPI5_PAL.Driver == NULL) + { + SPI5_PAL.Driver = &SPID5; + palSpi = &SPI5_PAL; + } + break; + #endif + #if STM32_SPI_USE_SPI6 + case 6: + if(SPI6_PAL.Driver == NULL) + { + SPI6_PAL.Driver = &SPID6; + palSpi = &SPI6_PAL; + } + break; + #endif + default: + // this SPI bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // compute rough estimate on the time to tx/rx a byte (in milliseconds) + ComputeBaudRate(busIndex, pConfig[ SpiConnectionSettings::FIELD___clockFrequency ].NumericByRef().s4, (int32_t&)actualFrequency); + palSpi->ByteTime = (1.0 / actualFrequency) * 1000; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t busIndex; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details + busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // get the PAL struct for the SPI bus + switch (busIndex) + { + #if STM32_SPI_USE_SPI1 + case 1: + spiStop(&SPID1); + SPI1_PAL.Driver = NULL; + break; + #endif + + #if STM32_SPI_USE_SPI2 + case 2: + spiStop(&SPID2); + SPI2_PAL.Driver = NULL; + break; + #endif + + #if STM32_SPI_USE_SPI3 + case 3: + spiStop(&SPID3); + SPI3_PAL.Driver = NULL; + break; + #endif + + #if STM32_SPI_USE_SPI4 + case 4: + spiStop(&SPID4); + SPI4_PAL.Driver = NULL; + break; + #endif + + #if STM32_SPI_USE_SPI5 + case 5: + spiStop(&SPID5); + SPI5_PAL.Driver = NULL; + break; + #endif + + #if STM32_SPI_USE_SPI6 + case 6: + spiStop(&SPID6); + SPI6_PAL.Driver = NULL; + break; + #endif + + default: + // the requested SPI bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h new file mode 100644 index 00000000..3176688b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_SPI_NATIVE_TARGET_H_ +#define _WIN_DEV_SPI_NATIVE_TARGET_H_ + +#include +#include + +// struct representing the SPI +struct NF_PAL_SPI +{ + SPIDriver* Driver; + SPIConfig Configuration; + float ByteTime; + bool SequentialTxRx; + + uint8_t* WriteBuffer; + uint16_t WriteSize; + + uint8_t* ReadBuffer; + uint16_t ReadSize; +}; + +/////////////////////////////////////////// +// declaration of the the SPI PAL strucs // +/////////////////////////////////////////// +#if STM32_SPI_USE_SPI1 + extern NF_PAL_SPI SPI1_PAL; +#endif +#if STM32_SPI_USE_SPI2 + extern NF_PAL_SPI SPI2_PAL; +#endif +#if STM32_SPI_USE_SPI3 + extern NF_PAL_SPI SPI3_PAL; +#endif +#if STM32_SPI_USE_SPI4 + extern NF_PAL_SPI SPI4_PAL; +#endif +#if STM32_SPI_USE_SPI5 + extern NF_PAL_SPI SPI5_PAL; +#endif +#if STM32_SPI_USE_SPI6 + extern NF_PAL_SPI SPI6_PAL; +#endif + +#endif //_WIN_DEV_SPI_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp new file mode 100644 index 00000000..ceba4d66 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp @@ -0,0 +1,593 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_net_sockets_native_target.h" + +// TODO - Check if required, for now just ignore +#define SwapEndianIfBEc16(x) (x) + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::socket___STATIC__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_INT32 family = stack.Arg0().NumericByRef().s4; + CLR_INT32 type = stack.Arg1().NumericByRef().s4; + CLR_INT32 protocol = stack.Arg2().NumericByRef().s4; + + CLR_INT32 nonBlocking = 1; + CLR_INT32 sock = SOCK_socket( family, type, protocol ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, sock )); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, SOCK_ioctl( sock, SOCK_FIONBIO, &nonBlocking ) )); + + stack.SetResult_I4( sock ); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::bind___STATIC__VOID__OBJECT__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + return BindConnectHelper( stack, true ); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::connect___STATIC__VOID__OBJECT__SZARRAY_U1__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + return BindConnectHelper( stack, false ); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::send___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::recv___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::close___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_INT32 handle, ret; + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); FAULT_ON_NULL(socket); + + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + ret = SOCK_close( handle ); + + //If a socket gets closed, we need to make sure to wake up any threads that are waiting on it. + Events_Set( SYSTEM_EVENT_FLAG_SOCKET ); + + stack.SetResult_I4( ret ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::listen___STATIC__VOID__OBJECT__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 backlog = stack.Arg1().NumericByRef().s4; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + ret = SOCK_listen( handle, backlog ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::accept___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 ret; + CLR_INT32 nonBlocking = 1; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + + /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see + * if our handle has been shutdown before continuing. */ + if (handle == DISPOSED_HANDLE) + { + ThrowError(stack, CLR_E_OBJECT_DISPOSED); + NANOCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION); + } + + ret = SOCK_accept( handle, NULL, NULL ); + + if(ret != SOCK_SOCKET_ERROR) + { + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, SOCK_ioctl( ret, SOCK_FIONBIO, &nonBlocking ) )); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + stack.SetResult_I4( ret ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::shutdown___STATIC__VOID__OBJECT__I4__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::sendto___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::recvfrom___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getpeername___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getsockname___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::setsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::poll___STATIC__BOOLEAN__OBJECT__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::ioctl___STATIC__VOID__OBJECT__U4__BYREF_U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + + + +//--// + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::BindConnectHelper( CLR_RT_StackFrame& stack, bool fBind ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + SOCK_sockaddr addr; + CLR_UINT32 addrLen = sizeof(addr); + CLR_INT32 ret; + bool fThrowOnWouldBlock = false; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, stack.Arg1() )); + + if(fBind) + { + ret = SOCK_bind( handle, &addr, addrLen ); + } + else + { + ret = SOCK_connect( handle, &addr, addrLen ); + + fThrowOnWouldBlock = (stack.Arg2().NumericByRefConst().s4 != 0); + + if(!fThrowOnWouldBlock && SOCK_getlasterror() == SOCK_EWOULDBLOCK) + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::MarshalSockAddress( CLR_RT_HeapBlock& blkDst, const struct SOCK_sockaddr* addrSrc, CLR_UINT32 addrLenSrc ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* arr = NULL; + + CLR_RT_HeapBlock blkArr; blkArr.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( blkArr ); + SOCK_sockaddr_in* dst; + SOCK_sockaddr_in* src = (SOCK_sockaddr_in*)addrSrc; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( blkArr, addrLenSrc, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + arr = blkArr.DereferenceArray(); + + _ASSERTE(arr); + + dst = (SOCK_sockaddr_in*)arr->GetFirstElement(); + + dst->sin_family = SwapEndianIfBEc16(src->sin_family); + dst->sin_port = src->sin_port; + dst->sin_addr.S_un.S_addr = src->sin_addr.S_un.S_addr; + + memcpy(dst->sin_zero, src->sin_zero, sizeof(dst->sin_zero)); + + _ASSERTE(blkDst.DataType() == DATATYPE_BYREF || blkDst.DataType() == DATATYPE_ARRAY_BYREF); + + NANOCLR_CHECK_HRESULT(blkArr.StoreToReference( blkDst, 0 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::MarshalSockAddress( struct SOCK_sockaddr* addrDst, CLR_UINT32& addrLen, const CLR_RT_HeapBlock& blkSockAddress ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* ptrSockAddress; + SOCK_sockaddr_in* dst = (SOCK_sockaddr_in*)addrDst; + SOCK_sockaddr_in* src; + + ptrSockAddress = blkSockAddress.DereferenceArray(); + FAULT_ON_NULL(ptrSockAddress); + + if(ptrSockAddress->m_numOfElements > addrLen) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + src = (SOCK_sockaddr_in*)ptrSockAddress->GetFirstElement(); + + dst->sin_family = SwapEndianIfBEc16(src->sin_family); + dst->sin_port = src->sin_port; + dst->sin_addr.S_un.S_addr = src->sin_addr.S_un.S_addr; //already in network byte order + + memcpy(dst->sin_zero, src->sin_zero, sizeof(dst->sin_zero)); + + addrLen = ptrSockAddress->m_numOfElements; + + NANOCLR_NOCLEANUP(); +} + +// HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::SendRecvHelper( CLR_RT_StackFrame& stack, bool fSend, bool fAddress ) +// { +// NATIVE_PROFILE_CLR_NETWORK(); +// NANOCLR_HEADER(); + +// CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); +// CLR_INT32 handle; +// CLR_RT_HeapBlock_Array* arrData = stack.Arg1().DereferenceArray(); +// CLR_UINT32 offset = stack.Arg2().NumericByRef().u4; +// CLR_UINT32 count = stack.Arg3().NumericByRef().u4; +// CLR_INT32 flags = stack.Arg4().NumericByRef().s4; +// CLR_INT32 timeout_ms = stack.Arg5().NumericByRef().s4; +// CLR_RT_HeapBlock hbTimeout; + +// CLR_INT64* timeout; +// CLR_UINT8* buf; +// bool fRes = true; +// CLR_INT32 totReadWrite; +// CLR_INT32 ret = 0; + +// FAULT_ON_NULL(socket); +// FAULT_ON_NULL(arrData); + +// handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + +// /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see +// * if our handle has been shutdown before continuing. */ +// if (handle == DISPOSED_HANDLE) +// { +// ThrowError( stack, CLR_E_OBJECT_DISPOSED ); +// NANOCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION); +// } + +// if(offset + count > arrData->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); + + +// hbTimeout.SetInteger( timeout_ms ); + +// NANOCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout )); + +// // +// // Push "totReadWrite" onto the eval stack. +// // +// if(stack.m_customState == 1) +// { +// stack.PushValueI4( 0 ); + +// stack.m_customState = 2; +// } + +// totReadWrite = stack.m_evalStack[ 1 ].NumericByRef().s4; + +// buf = arrData->GetElement( offset + totReadWrite ); +// count -= totReadWrite; + +// while(count > 0) +// { +// CLR_INT32 bytes = 0; + +// // first make sure we have data to read or ability to write +// while(fRes) +// { +// ret = Helper__SelectSocket( handle, fSend ? 1 : 0 ); + +// if(ret != 0) break; + +// // non-blocking - allow other threads to run while we wait for handle activity +// NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); +// } + +// // timeout expired +// if(!fRes) +// { +// ret = SOCK_SOCKET_ERROR; + +// ThrowError( stack, SOCK_ETIMEDOUT ); + +// NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); +// } + +// // socket is in the excepted state, so let's bail out +// if(SOCK_SOCKET_ERROR == ret) +// { +// break; +// } + +// if(fAddress) +// { +// struct SOCK_sockaddr addr; +// CLR_UINT32 addrLen = sizeof(addr); +// CLR_RT_HeapBlock& blkAddr = stack.Arg6(); + +// if(fSend) +// { +// NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, blkAddr )); + +// bytes = SOCK_sendto( handle, (const char*)buf, count, flags, &addr, addrLen ); +// } +// else +// { +// CLR_RT_HeapBlock* pBlkAddr = blkAddr.Dereference(); + +// NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, *pBlkAddr )); + +// bytes = SOCK_recvfrom( handle, (char*)buf, count, flags, &addr, (int*)&addrLen ); + +// if(bytes != SOCK_SOCKET_ERROR) +// { +// NANOCLR_CHECK_HRESULT(MarshalSockAddress( blkAddr, &addr, addrLen )); +// } +// } +// } +// else +// { +// if(fSend) +// { +// bytes = SOCK_send( handle, (const char*)buf, count, flags ); +// } +// else +// { +// bytes = SOCK_recv( handle, (char*)buf, count, flags ); +// } +// } + +// // send/recv/sendto/recvfrom failed +// if(bytes == SOCK_SOCKET_ERROR) +// { +// CLR_INT32 err = SOCK_getlasterror(); + +// if(err != SOCK_EWOULDBLOCK) +// { +// ret = SOCK_SOCKET_ERROR; +// break; +// } + +// continue; +// } +// // zero recv bytes indicates the handle has been closed. +// else if(!fSend && (bytes == 0)) +// { +// break; +// } + +// buf += bytes; +// totReadWrite += bytes; +// count -= bytes; + +// stack.m_evalStack[ 1 ].NumericByRef().s4 = totReadWrite; + +// // receive returns immediately after receiving bytes. +// if(!fSend && (totReadWrite > 0)) +// { +// break; +// } + +// } + +// stack.PopValue(); // totReadWrite +// stack.PopValue(); // Timeout + +// NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + +// stack.SetResult_I4( totReadWrite ); + +// NANOCLR_NOCLEANUP(); +// } + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::SockOptHelper( CLR_RT_StackFrame& stack, bool fGet ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 level = stack.Arg1().NumericByRef().s4; + CLR_INT32 optname = stack.Arg2().NumericByRef().s4; + CLR_RT_HeapBlock_Array* arrOpt = stack.Arg3().DereferenceArray(); + char* optval; + CLR_INT32 optlen; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + FAULT_ON_NULL(arrOpt); + + optval = (char*)arrOpt->GetFirstElement(); + optlen = arrOpt->m_numOfElements; + + if(fGet) + { + ret = SOCK_getsockopt( handle, level, optname, optval, &optlen ); + _ASSERTE( optlen <= (CLR_INT32)arrOpt->m_numOfElements ); + } + else + { + ret = SOCK_setsockopt( handle, level, optname, optval, optlen ); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::SockNameHelper( CLR_RT_StackFrame& stack, bool fPeer ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 ret; + + struct SOCK_sockaddr addr; + CLR_INT32 addrLen = sizeof(addr); + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + if(fPeer) + { + ret = SOCK_getpeername( handle, &addr, &addrLen ); + } + else + { + ret = SOCK_getsockname( handle, &addr, &addrLen ); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_CHECK_HRESULT(MarshalSockAddress( stack.Arg1(), &addr, addrLen )); + + NANOCLR_NOCLEANUP(); +} + + + + +void Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::ThrowError( CLR_RT_StackFrame& stack, CLR_INT32 errorCode ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + // CLR_RT_HeapBlock& res = stack.m_owningThread->m_currentException; + + // if((Library_corlib_native_System_Exception::CreateInstance( res, g_CLR_RT_WellKnownTypes.m_SocketException, CLR_E_FAIL, &stack )) == S_OK) + // { + // res.Dereference()[ Library_system_sockets_System_Net_Sockets_SocketException::FIELD___errorCode ].SetInteger( errorCode ); + // } +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::ThrowOnError( CLR_RT_StackFrame& stack, CLR_INT32 res ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + if(res == SOCK_SOCKET_ERROR) + { + CLR_INT32 err = SOCK_getlasterror(); + + ThrowError( stack, err ); + + NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); + } + + NANOCLR_NOCLEANUP(); +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h new file mode 100644 index 00000000..90131221 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +//--------------------------------------------------------------------------- + +#ifndef _WIN_NET_SOCKETS_NATIVE_TARGET_H_ +#define _WIN_NET_SOCKETS_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_NET_SOCKETS_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp new file mode 100644 index 00000000..4c10bd7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_storage_native_target.h" + +HRESULT Library_win_storage_native_Windows_Storage_Devices_SDCard::MountMMCNative___STATIC__VOID__BOOLEAN(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + (void)stack; + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_storage_native_Windows_Storage_Devices_SDCard::MountSpiNative___STATIC__VOID__I4__I4(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + (void)stack; + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_win_storage_native_Windows_Storage_Devices_SDCard::UnmountNative___STATIC__VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + (void)stack; + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp new file mode 100644 index 00000000..983b9c9b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp @@ -0,0 +1,1104 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#if (HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE) +#include +#endif +#include "win_storage_native_target.h" +#include +#include + +#if (HAL_USBH_USE_MSD == TRUE) +#include "usbh/dev/msd.h" +#endif +#if (USE_SPIFFS_FOR_STORAGE == TRUE) +#include +#endif + +// defining these types here to make it shorter and improve code readability +typedef Library_win_storage_native_Windows_Storage_StorageFolder StorageFolder; +typedef Library_win_storage_native_Windows_Storage_StorageFile StorageFile; + +////////////////////////////////////////// +enum FileOperationResult +{ + FileOperationResult_OK = 0, + FileOperationResult_Error = 10, + FileOperationResult_NoFile = 20, + FileOperationResult_InvalidDrive = 30, +}; + +////////////////////////////////////////// + +struct FileOperation +{ + #if (HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE) + FIL* FatFile; + #endif + #if USE_SPIFFS_FOR_STORAGE + spiffs_file* SpiffsFile; + #endif + char* Content; + uint32_t ContentLength; +}; + +// this is the FileIO working thread +// because FatFS is supposed to be atomic we won't have any concurrent threads +static thread_t* fileIoWorkingThread; + +// ReadText working thread +static THD_FUNCTION(ReadTextWorkingThread, arg) +{ + FileOperationResult opResult = FileOperationResult_OK; + + FileOperation* fileIoOperation = (FileOperation*)arg; + + // need an extra one for the terminator + uint32_t readLength = fileIoOperation->ContentLength + 1; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + if(fileIoOperation->FatFile != NULL) + { + // read string + if(f_gets((TCHAR*)fileIoOperation->Content, readLength, fileIoOperation->FatFile)) + { + // operation succesfull + } + else + { + switch((FRESULT)f_error(fileIoOperation->FatFile)) + { + case FR_NO_FILE: + opResult = FileOperationResult_NoFile; + break; + + case FR_INVALID_DRIVE: + opResult = FileOperationResult_InvalidDrive; + break; + + default: + opResult = FileOperationResult_Error; + break; + } + } + + // close file + f_close(fileIoOperation->FatFile); + + // free memory + platform_free(fileIoOperation->FatFile); + + } + #endif + #if USE_SPIFFS_FOR_STORAGE + if(fileIoOperation->SpiffsFile != NULL) + { + uint32_t bytesRead = SPIFFS_read(&fs, *fileIoOperation->SpiffsFile, fileIoOperation->Content, fileIoOperation->ContentLength); + + if (bytesRead == fileIoOperation->ContentLength) + { + // expected number of bytes read + } + else + { + // failed to read expected number of bytes + opResult = FileOperationResult_Error; + } + + // close file + SPIFFS_close(&fs, *fileIoOperation->SpiffsFile); + + // free memory + platform_free(fileIoOperation->SpiffsFile); + } + #endif + + // free memory + platform_free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + chThdExit((msg_t)opResult); +} + +// WriteText working thread +static THD_FUNCTION(WriteTextWorkingThread, arg) +{ + FileOperationResult opResult = FileOperationResult_OK; + + FileOperation* fileIoOperation = (FileOperation*)arg; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + if(fileIoOperation->FatFile != NULL) + { + if(f_puts(fileIoOperation->Content, fileIoOperation->FatFile) == (int)fileIoOperation->ContentLength) + { + // expected number of bytes written + } + else + { + switch((FRESULT)f_error(fileIoOperation->FatFile)) + { + case FR_NO_FILE: + opResult = FileOperationResult_NoFile; + break; + + case FR_INVALID_DRIVE: + opResult = FileOperationResult_InvalidDrive; + break; + + default: + opResult = FileOperationResult_Error; + break; + } + } + + // close file + f_close(fileIoOperation->FatFile); + + // free memory + platform_free(fileIoOperation->FatFile); + + } + #endif + #if USE_SPIFFS_FOR_STORAGE + if(fileIoOperation->SpiffsFile != NULL) + { + if (SPIFFS_write(&fs, *fileIoOperation->SpiffsFile, fileIoOperation->Content, fileIoOperation->ContentLength) < 0) + { + // failed to write expected number of bytes + opResult = FileOperationResult_Error; + } + + // close file + SPIFFS_close(&fs, *fileIoOperation->SpiffsFile); + + // free memory + platform_free(fileIoOperation->SpiffsFile); + } + #endif + + platform_free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + chThdExit((msg_t)opResult); +} + +// WriteBinary working thread +static THD_FUNCTION(WriteBinaryWorkingThread, arg) +{ + FileOperationResult opResult = FileOperationResult_OK; + + FileOperation* fileIoOperation = (FileOperation*)arg; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + if(fileIoOperation->FatFile != NULL) + { + UINT bytesWritten; + + FRESULT operationResult = f_write(fileIoOperation->FatFile, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesWritten); + + if( (operationResult == FR_OK) && + (bytesWritten == fileIoOperation->ContentLength)) + { + // expected number of bytes written + } + else + { + switch((FRESULT)f_error(fileIoOperation->FatFile)) + { + case FR_NO_FILE: + opResult = FileOperationResult_NoFile; + break; + + case FR_INVALID_DRIVE: + opResult = FileOperationResult_InvalidDrive; + break; + + default: + opResult = FileOperationResult_Error; + break; + } + } + + // close file + f_close(fileIoOperation->FatFile); + + // free memory + platform_free(fileIoOperation->FatFile); + + } + #endif + #if USE_SPIFFS_FOR_STORAGE + if(fileIoOperation->SpiffsFile != NULL) + { + if (SPIFFS_write(&fs, *fileIoOperation->SpiffsFile, fileIoOperation->Content, fileIoOperation->ContentLength) < 0) + { + // failed to write expected number of bytes + opResult = FileOperationResult_Error; + } + + // close file + SPIFFS_close(&fs, *fileIoOperation->SpiffsFile); + + // free memory + platform_free(fileIoOperation->SpiffsFile); + } + #endif + + // free memory + platform_free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + chThdExit((msg_t)opResult); +} + +// ReadBinary working thread +static THD_FUNCTION(ReadBinaryWorkingThread, arg) +{ + FileOperationResult opResult = FileOperationResult_OK; + + FileOperation* fileIoOperation = (FileOperation*)arg; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + if(fileIoOperation->FatFile != NULL) + { + UINT bytesRead; + + FileOperation* fileIoOperation = (FileOperation*)arg; + + FRESULT operationResult = f_read(fileIoOperation->FatFile, fileIoOperation->Content, fileIoOperation->ContentLength, &bytesRead); + + if( (operationResult == FR_OK) && + (bytesRead == fileIoOperation->ContentLength)) + { + // expected number of bytes read + } + else + { + switch((FRESULT)f_error(fileIoOperation->FatFile)) + { + case FR_NO_FILE: + opResult = FileOperationResult_NoFile; + break; + + case FR_INVALID_DRIVE: + opResult = FileOperationResult_InvalidDrive; + break; + + default: + opResult = FileOperationResult_Error; + break; + } + } + + // close file + f_close(fileIoOperation->FatFile); + + // free memory + platform_free(fileIoOperation->FatFile); + + } + #endif + #if USE_SPIFFS_FOR_STORAGE + if(fileIoOperation->SpiffsFile != NULL) + { + uint32_t bytesRead = SPIFFS_read(&fs, *fileIoOperation->SpiffsFile, fileIoOperation->Content, fileIoOperation->ContentLength); + + if (bytesRead == fileIoOperation->ContentLength) + { + // expected number of bytes read + } + else + { + // failed to read expected number of bytes + opResult = FileOperationResult_Error; + } + + // close file + SPIFFS_close(&fs, *fileIoOperation->SpiffsFile); + + // free memory + platform_free(fileIoOperation->SpiffsFile); + } + #endif + + // free memory + platform_free(fileIoOperation); + + // fire event for FileIO operation complete + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + + chThdExit((msg_t)opResult); +} + +//////////////////////////////////////////////// +// Developer notes: +// Depending on the content size these operations have the potential to be a long running ones as the string or buffer is written to the storage. +// Despite we are not (yet!) async this is better handled by spawning a thread where the actual data transfer occurs and not blocking the execution. +// The underlying RTOS inheritably takes care of making this happen "in the background". +// When the operation is completed a CLR event is fired and the thread execution resumes. +// Being hard to estimate the expected duration of the operation (depends on storage hardware, CPU clock, transfer speed, etc) +// the timeout is set to an infinite timeout +// the catch is that the working thread MUST ALWAYS return at some point +//////////////////////////////////////////////// + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__VOID__WindowsStorageIStorageFile__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* bufferArray; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + char workingDrive[DRIVE_LETTER_LENGTH]; + const char* filePath; + char* workingBuffer = NULL; + FileOperation* fileIoOperation; + + char* buffer; + uint32_t bufferLength; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + FIL* fatFile = NULL; + FRESULT operationResult; + #endif + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + spiffs_file* spiffsFile = NULL; + #endif + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the buffer + bufferArray = stack.Arg1().DereferenceArray(); + + buffer = (char*)bufferArray->GetFirstElement(); + + bufferLength = bufferArray->m_numOfElements; + + // get a pointer to the file path + filePath = pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + if(stack.m_customState == 1) + { + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); + + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // SPIFFS drive workflow + + // create file struct + spiffsFile = (spiffs_file*)platform_malloc(sizeof(spiffs_file)); + // check allocation + if(spiffsFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // get file name removing the drive letter + workingBuffer = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + memcpy(workingBuffer, (filePath + 3), SPIFFS_OBJ_NAME_LEN - 3); + + *spiffsFile = SPIFFS_open(&fs, workingBuffer, SPIFFS_TRUNC | SPIFFS_RDWR, 0); + if(*spiffsFile < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + #endif + } + else + { + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // FatFS workflow + + // create file struct + fatFile = (FIL*)platform_malloc(sizeof(FIL)); + // check allocation + if(fatFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // open file (which is supposed to already exist) + // need to use FA_OPEN_ALWAYS because we are writting the file content from start + operationResult = f_open(fatFile, filePath, FA_OPEN_ALWAYS | FA_WRITE); + + if(operationResult != FR_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + #endif + } + + // protect the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcContent( *bufferArray ); + + // setup FileIO operation + fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + fileIoOperation->FatFile = fatFile; + #endif + #if USE_SPIFFS_FOR_STORAGE + fileIoOperation->SpiffsFile = spiffsFile; + #endif + + fileIoOperation->Content = buffer; + fileIoOperation->ContentLength = bufferLength; + + // spawn working thread to perform the write transaction + fileIoWorkingThread = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2048), + "STWT", NORMALPRIO, WriteBinaryWorkingThread, fileIoOperation); + + if(fileIoWorkingThread == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + + // ChibiOS requirement: need to call chThdWait on working thread in order to have it's memory released to the heap, otherwise it won't be returned + FileOperationResult result = (FileOperationResult)chThdWait(fileIoWorkingThread); + + if(result == FileOperationResult_Error) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(result == FileOperationResult_NoFile) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(result == FileOperationResult_InvalidDrive) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__VOID__WindowsStorageIStorageFile__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_String* content; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + char workingDrive[DRIVE_LETTER_LENGTH]; + const char* filePath; + char* workingBuffer = NULL; + FileOperation* fileIoOperation; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + FIL* fatFile = NULL; + FRESULT operationResult; + #endif + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + spiffs_file* spiffsFile = NULL; + #endif + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the content + content = stack.Arg1().DereferenceString(); + + // get a pointer to the file path + filePath = pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + if(stack.m_customState == 1) + { + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); + + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // SPIFFS drive workflow + + // create file struct + spiffsFile = (spiffs_file*)platform_malloc(sizeof(spiffs_file)); + // check allocation + if(spiffsFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // get file name removing the drive letter + workingBuffer = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + memcpy(workingBuffer, (filePath + 3), SPIFFS_OBJ_NAME_LEN - 3); + + *spiffsFile = SPIFFS_open(&fs, workingBuffer, SPIFFS_TRUNC | SPIFFS_RDWR, 0); + if(*spiffsFile < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + #endif + } + else + { + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // FatFS workflow + + // create file struct + fatFile = (FIL*)platform_malloc(sizeof(FIL)); + // check allocation + if(fatFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // open file (which is supposed to already exist) + // need to use FA_OPEN_ALWAYS because we are writting the file content from start + operationResult = f_open(fatFile, filePath, FA_OPEN_ALWAYS | FA_WRITE); + + if(operationResult != FR_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + #endif + } + + // protect the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcContent( *content ); + + // setup FileIO operation + fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + fileIoOperation->FatFile = fatFile; + #endif + #if USE_SPIFFS_FOR_STORAGE + fileIoOperation->SpiffsFile = spiffsFile; + #endif + + fileIoOperation->Content = (char*)content->StringText(); + fileIoOperation->ContentLength = hal_strlen_s(fileIoOperation->Content); + + // spawn working thread to perform the write transaction + fileIoWorkingThread = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2048), + "STWT", NORMALPRIO, WriteTextWorkingThread, fileIoOperation); + + if(fileIoWorkingThread == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + + // ChibiOS requirement: need to call chThdWait on working thread in order to have it's memory released to the heap, otherwise it won't be returned + FileOperationResult result = (FileOperationResult)chThdWait(fileIoWorkingThread); + + if(result == FileOperationResult_Error) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(result == FileOperationResult_NoFile) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(result == FileOperationResult_InvalidDrive) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + uint32_t fileSize; + + char workingDrive[DRIVE_LETTER_LENGTH]; + const char* filePath; + char* workingBuffer = NULL; + FileOperation* fileIoOperation; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + FIL* fatFile = NULL; + FRESULT operationResult; + #endif + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + spiffs_file* spiffsFile = NULL; + #endif + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // get a pointer to the file path + filePath = pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + if(stack.m_customState == 1) + { + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); + + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // SPIFFS drive workflow + + // create file struct + spiffsFile = (spiffs_file*)platform_malloc(sizeof(spiffs_file)); + // check allocation + if(spiffsFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // get file name removing the drive letter + workingBuffer = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + memcpy(workingBuffer, (filePath + 3), SPIFFS_OBJ_NAME_LEN - 3); + + *spiffsFile = SPIFFS_open(&fs, workingBuffer, SPIFFS_RDONLY, 0); + if(*spiffsFile < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + // get file details + spiffs_stat fileInfo; + SPIFFS_stat(&fs, workingBuffer, &fileInfo); + + // we are only interested in the file size + fileSize = fileInfo.size; + + #endif + } + else + { + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // FatFS workflow + + // create file struct + fatFile = (FIL*)platform_malloc(sizeof(FIL)); + // check allocation + if(fatFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // open file (which is supposed to already exist) + operationResult = f_open(fatFile, filePath, FA_OPEN_EXISTING | FA_READ); + + if(operationResult != FR_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + // get file details + FILINFO fileInfo; + f_stat(filePath, &fileInfo); + + // we are only interested in the file size + fileSize = fileInfo.fsize; + + #endif + } + + CLR_RT_HeapBlock buffer; + buffer.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc2( buffer ); + + // create a new byte array with the appropriate size (and type) + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( buffer, (CLR_INT32)fileSize, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + // store this to the argument passed byref + NANOCLR_CHECK_HRESULT(buffer.StoreToReference( stack.Arg1(), 0 )); + + // get a pointer to the buffer array to improve readability on the code ahead + CLR_RT_HeapBlock_Array* bufferArray = buffer.DereferenceArray(); + + // setup FileIO operation + fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + fileIoOperation->FatFile = fatFile; + #endif + #if USE_SPIFFS_FOR_STORAGE + fileIoOperation->SpiffsFile = spiffsFile; + #endif + + fileIoOperation->Content = (char*)bufferArray->GetFirstElement(); + fileIoOperation->ContentLength = bufferArray->m_numOfElements; + + // spawn working thread to perform the read transaction + fileIoWorkingThread = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2048), + "STRB", NORMALPRIO, ReadBinaryWorkingThread, fileIoOperation); + + if(fileIoWorkingThread == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + + // ChibiOS requirement: need to call chThdWait on working thread in order to have it's memory released to the heap, otherwise it won't be returned + FileOperationResult result = (FileOperationResult)chThdWait(fileIoWorkingThread); + + if(result == FileOperationResult_Error) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(result == FileOperationResult_NoFile) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(result == FileOperationResult_InvalidDrive) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadTextNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + uint32_t fileSize = 0; + + char workingDrive[DRIVE_LETTER_LENGTH]; + const char* filePath; + char* workingBuffer = NULL; + FileOperation* fileIoOperation; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + FIL* fatFile = NULL; + FRESULT operationResult; + #endif + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + spiffs_file* spiffsFile = NULL; + #endif + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // get a pointer to the file path + filePath = pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + if(stack.m_customState == 1) + { + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); + + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // SPIFFS drive workflow + + // create file struct + spiffsFile = (spiffs_file*)platform_malloc(sizeof(spiffs_file)); + // check allocation + if(spiffsFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // get file name removing the drive letter + workingBuffer = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + memcpy(workingBuffer, (filePath + 3), SPIFFS_OBJ_NAME_LEN - 3); + + *spiffsFile = SPIFFS_open(&fs, workingBuffer, SPIFFS_RDONLY, 0); + if(*spiffsFile < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + // get file details + spiffs_stat fileInfo; + SPIFFS_stat(&fs, workingBuffer, &fileInfo); + + // we are only interested in the file size + fileSize = fileInfo.size; + + #endif + } + else + { + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // FatFS workflow + + // create file struct + fatFile = (FIL*)platform_malloc(sizeof(FIL)); + // check allocation + if(fatFile == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // open file (which is supposed to already exist) + operationResult = f_open(fatFile, filePath, FA_OPEN_EXISTING | FA_READ); + + if(operationResult != FR_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + // get file details + FILINFO fileInfo; + f_stat(filePath, &fileInfo); + + // we are only interested in the file size + fileSize = fileInfo.fsize; + + #endif + } + + // create a new string object with the appropriate size + CLR_RT_HeapBlock hbText; + hbText.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( hbText ); + + CLR_RT_HeapBlock_String* textString = CLR_RT_HeapBlock_String::CreateInstance( hbText, (CLR_UINT32)fileSize ); + FAULT_ON_NULL(textString); + + // store this to the argument passed byref + NANOCLR_CHECK_HRESULT(hbText.StoreToReference( stack.Arg1(), 0 )); + + // get a pointer to the buffer array to improve readability on the code ahead + hbText.DereferenceString(); + + // setup FileIO operation + fileIoOperation = (FileOperation*)platform_malloc(sizeof(FileOperation)); + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + fileIoOperation->FatFile = fatFile; + #endif + #if USE_SPIFFS_FOR_STORAGE + fileIoOperation->SpiffsFile = spiffsFile; + #endif + + fileIoOperation->Content = (char*)textString->StringText(); + fileIoOperation->ContentLength = fileSize; + + // spawn working thread to perform the read transaction + fileIoWorkingThread = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2048), + "STRT", NORMALPRIO, ReadTextWorkingThread, fileIoOperation); + + if(fileIoWorkingThread == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + + // ChibiOS requirement: need to call chThdWait on working thread in order to have it's memory released to the heap, otherwise it won't be returned + FileOperationResult result = (FileOperationResult)chThdWait(fileIoWorkingThread); + + if(result == FileOperationResult_Error) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(result == FileOperationResult_NoFile) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(result == FileOperationResult_InvalidDrive) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + + NANOCLR_CLEANUP_END(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp new file mode 100644 index 00000000..dbb07cfc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp @@ -0,0 +1,325 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#if (HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE) +#include +#endif +#include "win_storage_native_target.h" +#include +#include + +#if (HAL_USBH_USE_MSD == TRUE) +#include "usbh/dev/msd.h" +#endif +#if (USE_SPIFFS_FOR_STORAGE == TRUE) +#include +#endif + +extern SYSTEMTIME GetDateTime(uint16_t date, uint16_t time); + +HRESULT Library_win_storage_native_Windows_Storage_StorageFile::DeleteFileNative___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + char workingDrive[DRIVE_LETTER_LENGTH]; + const char* workingPath; + char* workingBuffer = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path].DereferenceString()->StringText(); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, workingPath, DRIVE_LETTER_LENGTH); + + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // SPIFFS drive workflow + + // get file name removing the drive letter + workingBuffer = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + memcpy(workingBuffer, (workingPath + 3), SPIFFS_OBJ_NAME_LEN - 3); + + if(SPIFFS_remove(&fs, workingBuffer) < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + #endif + } + else + { + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // FatFS workflow + + // Delete folder + FRESULT operationResult = f_unlink(workingPath); + if (operationResult != FR_OK) + { + // folder doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + #endif + } + + NANOCLR_CLEANUP(); + + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFile::RenameFileNative___VOID__STRING(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + char workingDrive[DRIVE_LETTER_LENGTH]; + const char* workingPath; + const char* desiredPath; + char* workingBuffer = NULL; + char* workingBuffer1 = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path].DereferenceString()->StringText(); + + // get a pointer to the desired folder path + desiredPath = stack.Arg1().DereferenceString()->StringText(); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, workingPath, DRIVE_LETTER_LENGTH); + + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // SPIFFS drive workflow + + // get origin and desired file names removing the drive letter + // need to malloc these + workingBuffer = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + workingBuffer1 = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + // sanity check for successfull malloc + if( (workingBuffer == NULL) || + (workingBuffer1 == NULL)) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + memcpy(workingBuffer, (workingPath + 3), SPIFFS_OBJ_NAME_LEN - 3); + memcpy(workingBuffer1, (desiredPath + 3), SPIFFS_OBJ_NAME_LEN - 3); + + if(SPIFFS_rename(&fs, workingBuffer, workingBuffer1) < 0) + { + switch(SPIFFS_errno(&fs)) + { + case SPIFFS_ERR_NOT_FOUND: + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + break; + } + } + + #endif + } + else + { + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // FatFS workflow + + // rename folder + FRESULT operationResult = f_rename(workingPath, desiredPath); + if (operationResult == FR_INVALID_NAME) + { + // invalid path + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + else if (operationResult != FR_OK) + { + // folder doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + #endif + } + + NANOCLR_CLEANUP(); + + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + if(workingBuffer1 != NULL) + { + platform_free(workingBuffer1); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFile::GetFileFromPathNative___STATIC__WindowsStorageStorageFile__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFileTypeDef; + CLR_RT_HeapBlock* storageFile; + + char workingDrive[DRIVE_LETTER_LENGTH]; + char* workingBuffer = NULL; + const char* filePath; + const char* fileName; + + // get a pointer to the file path + filePath = stack.Arg0().DereferenceString()->StringText(); + + // get a pointer to the file name + fileName = stack.Arg1().DereferenceString()->StringText(); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, filePath, DRIVE_LETTER_LENGTH); + + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // SPIFFS drive workflow + + // get file name removing the drive letter + // need to malloc this + workingBuffer = (char*)platform_malloc(SPIFFS_OBJ_NAME_LEN); + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + memcpy(workingBuffer, (filePath + 3), SPIFFS_OBJ_NAME_LEN - 3); + + spiffs_file file = SPIFFS_open(&fs, workingBuffer, SPIFFS_RDONLY, 0); + if(file < 0) + { + switch(SPIFFS_errno(&fs)) + { + case SPIFFS_ERR_NOT_FOUND: + SPIFFS_close(&fs, file); + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + break; + + default: + SPIFFS_close(&fs, file); + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + break; + } + } + + SPIFFS_close(&fs, file); + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFile", "Windows.Storage", storageFileTypeDef); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name], fileName)); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path], filePath)); + + // SPIFFS files don't have date information so we are done here + + #endif + } + else + { + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // FatFS workflow + + FILINFO fileInfo; + SYSTEMTIME fileInfoTime; + + FRESULT fr = f_stat(filePath, &fileInfo); + if(fr == FR_OK) + { + // is this a file? + if ( !(fileInfo.fattrib & AM_DIR) ) + { + // path represents a file, we are good + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFile", "Windows.Storage", storageFileTypeDef); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name], fileName)); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path], filePath)); + + // get the date time details and fill in the managed field + // compute directory date + fileInfoTime = GetDateTime(fileInfo.fdate, fileInfo.ftime); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it with the fileInfoTime + *pRes = HAL_Time_ConvertFromSystemTime( &fileInfoTime ); + } + else + { + // path exists but it's a folder + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + } + else if(fr == FR_NO_FILE) + { + // file doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + else + { + // IO error + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + + #endif + } + + NANOCLR_CLEANUP(); + + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + + NANOCLR_CLEANUP_END(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp new file mode 100644 index 00000000..4a2bdb29 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp @@ -0,0 +1,1625 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#if (HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE) +#include +#endif +#include "win_storage_native_target.h" +#include +#include +#include + +#if (HAL_USBH_USE_MSD == TRUE) +#include "usbh/dev/msd.h" +#endif +#if (USE_SPIFFS_FOR_STORAGE == TRUE) +#include +#endif + +// flags for file system ready +#if (HAL_USE_SDC == TRUE) +extern bool sdCardFileSystemReady; +#endif +#if (HAL_USBH_USE_MSD == TRUE) +extern bool usbMsdFileSystemReady; +#endif +#if (USE_SPIFFS_FOR_STORAGE == TRUE) +extern bool spiffsFileSystemReady; +extern spiffs fs; +#endif + +void CombinePath(char * outpath, const char * path1, const char * path2) +{ + strcat(outpath, path1); + + // Add "\" to path if required + if (outpath[hal_strlen_s(outpath) - 1] != '\\') + { + strcat(outpath, "\\"); + } + strcat(outpath, path2); +} + +SYSTEMTIME GetDateTime(uint16_t date, uint16_t time) +{ + SYSTEMTIME fileTime; + + memset(&fileTime, 0, sizeof(SYSTEMTIME)); + + // date (bit15:9) Year origin from 1980 (0..127) + fileTime.wYear = (date >> 9) + 1980; + // date (bit8:5) Month (1..12) + fileTime.wMonth = (date >> 5) & 0x000F; + // date (bit4:0) Day (1..31) + fileTime.wDay = date & 0x001F; + + // time (bit15:11) Hour (0..23) + fileTime.wHour = (time >> 11) & 0x001F; + // time (bit10:5) Minute (0..59) + fileTime.wMinute = (time >> 5) & 0x003F; + // time (bit4:0) Second / 2 (0..29) + fileTime.wSecond = time & 0x001F; + + return fileTime; +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + char* stringBuffer; + uint32_t driveCount = 0; + char workingDrive[sizeof(DRIVE_PATH_LENGTH)]; + uint16_t driveIterator = 0; + + CLR_RT_HeapBlock* storageFolder; + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* hbObj; + CLR_RT_HeapBlock& top = stack.PushValue(); + + #if HAL_USE_SDC + bool sdCardEnumerated = false; + #endif + + #if HAL_USE_SDC + // is the SD card file system ready? + if(sdCardFileSystemReady) + { + // add count + driveCount++; + } + #endif + + #if HAL_USBH_USE_MSD + bool usbMsdEnumerated = false; + + // is the USB mass storage device file system ready? + if(usbMsdFileSystemReady) + { + // add count + driveCount++; + } + #endif + + // start composing the reply + // find type definition, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, driveCount, storageFolderTypeDef )); + + #if (HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE) + + if(driveCount > 0) + { + // there are driver present and enumerated + + // get a pointer to the first object in the array (which is of type ) + storageFolder = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFolder, storageFolderTypeDef)); + + // loop until we've loaded all the possible drives + // because we are iterating through an enum, need to use its integer values + for(; driveIterator < driveCount; driveIterator++ ) + { + // fill the folder name and path + + #if HAL_USE_SDC + // is the SD card file system ready? + if(sdCardFileSystemReady && !sdCardEnumerated) + { + memcpy(workingDrive, INDEX0_DRIVE_PATH, DRIVE_PATH_LENGTH); + + // flag as enumerated + sdCardEnumerated = true; + } + #endif + + #if HAL_USBH_USE_MSD + // is the USB mass storage device file system ready? + if(usbMsdFileSystemReady && !usbMsdEnumerated) + { + memcpy(workingDrive, INDEX1_DRIVE_PATH, DRIVE_PATH_LENGTH); + + // flag as enumerated + usbMsdEnumerated = true; + } + #endif + + // dereference the object in order to reach its fields + hbObj = storageFolder->Dereference(); + + // set the managed fields + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], workingDrive )); + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], workingDrive )); + + // malloc stringBuffer to work with FS + stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(stringBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + else + { + // clear buffer + memset(stringBuffer, 0, FF_LFN_BUF + 1); + + // read the drive volume label + // don't bother checking the result, if anything goes wrong we'll end up with an empty string which is OK + f_getlabel(workingDrive, stringBuffer, NULL); + + // add the driver letter separated it with an empty space, if the volume label isn't empty + if(*stringBuffer != '\0') + { + strcat(stringBuffer, " "); + } + strcat(stringBuffer, "("); + strcat(stringBuffer, workingDrive); + strcat(stringBuffer, ")"); + + // set the field with the volume label + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], stringBuffer )); + + + // free stringBuffer + platform_free(stringBuffer); + } + + // move pointer to the next folder item + storageFolder++; + } + } + + #endif + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetInternalStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + uint32_t driveCount = 0; + char workingDrive[sizeof(DRIVE_PATH_LENGTH)]; + + CLR_RT_HeapBlock* storageFolder; + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* hbObj; + CLR_RT_HeapBlock& top = stack.PushValue(); + + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + // is the SPIFFS file system available and mounted? + if(spiffsFileSystemReady) + { + // add count + driveCount++; + } + #endif + + // start composing the reply + // find type definition, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, driveCount, storageFolderTypeDef )); + + if(driveCount > 0) + { + // SPIFFS is mounted + // currently there is support for a single SPIFFS instance + + // get a pointer to the first object in the array (which is of type ) + storageFolder = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFolder, storageFolderTypeDef)); + + // fill the folder name and path + memcpy(workingDrive, INTERNAL_DRIVE_PATH, DRIVE_PATH_LENGTH); + + // dereference the object in order to reach its fields + hbObj = storageFolder->Dereference(); + + // set the managed fields + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], workingDrive )); + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], workingDrive )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* storageFolder; + CLR_RT_HeapBlock* hbObj; + SYSTEMTIME fileInfoTime; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + + const char* workingPath; + char workingDrive[DRIVE_LETTER_LENGTH]; + + DIR currentDirectory; + FRESULT operationResult; + static FILINFO fileInfo; + uint16_t directoryCount = 0; + char* stringBuffer = NULL; + char* workingBuffer = NULL; + + CLR_RT_HeapBlock& top = stack.PushValue(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(), DRIVE_LETTER_LENGTH); + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // open directory + operationResult = f_opendir(¤tDirectory, workingPath); + + if(operationResult != FR_OK) + { + if(operationResult == FR_INVALID_DRIVE) + { + // failed to change drive + + // check if the working drive is the SPIFFS drive + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + // this is the SPIFFS drive, + // do nothing here and return an empty collection because folders aren't supported in SPIFFS + } + else + { + #else + { + #endif + // invalid drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + } + + // error or directory empty + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, directoryCount, storageFolderTypeDef )); + } + else + { + // need to perform this in two steps + // 1st: count the directory objects + // 2nd: create the array items with each directory object + + // perform 1st pass + for (;;) + { + // read next directory item + operationResult = f_readdir(¤tDirectory, &fileInfo); + + // break on error or at end of dir + if (operationResult != FR_OK || fileInfo.fname[0] == 0) + { + break; + } + + // check if this is a directory + // but skip if: + // - has system attribute set + // - has hidden attribute set + if ((fileInfo.fattrib & AM_DIR) && + !(fileInfo.fattrib & AM_SYS) && + !(fileInfo.fattrib & AM_HID)) + { + directoryCount++; + } + } + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, directoryCount, storageFolderTypeDef )); + + // get a pointer to the first object in the array (which is of type ) + storageFolder = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + if(directoryCount > 0) + { + // allocate memory for buffers + stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); + workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(stringBuffer == NULL || workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // perform 2nd pass + // need to rewind the directory read index first + f_readdir(¤tDirectory, NULL); + + for (;;) + { + // read next directory item + operationResult = f_readdir(¤tDirectory, &fileInfo); + + // break on error or at end of dir + if (operationResult != FR_OK || fileInfo.fname[0] == 0) + { + break; + } + + // check if this is a directory + // but skip if: + // - has system attribute set + // - has hidden attribute set + if ((fileInfo.fattrib & AM_DIR) && + !(fileInfo.fattrib & AM_SYS) && + !(fileInfo.fattrib & AM_HID)) + { + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFolder, storageFolderTypeDef)); + + // dereference the object in order to reach its fields + hbObj = storageFolder->Dereference(); + + // directory name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], fileInfo.fname )); + + // clear working buffer + memset(workingBuffer, 0, 2 * FF_LFN_BUF + 1); + + // compose directory path + CombinePath(workingBuffer, workingPath, fileInfo.fname); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], workingBuffer )); + + // compute directory date + fileInfoTime = GetDateTime(fileInfo.fdate, fileInfo.ftime); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it with the fileInfoTime + *pRes = HAL_Time_ConvertFromSystemTime( &fileInfoTime ); + + // move the storage folder pointer to the next item in the array + storageFolder++; + } + } + } + } + + #elif (USE_SPIFFS_FOR_STORAGE == TRUE) + + // SPIFFS doesn't support folders so return an empty collection + CLR_RT_HeapBlock& top = stack.PushValue(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, directoryCount, storageFolderTypeDef )); + + #endif + + NANOCLR_CLEANUP(); + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // close directory + f_closedir(¤tDirectory); + + // free buffers memory, if allocated + if(stringBuffer != NULL) + { + platform_free(stringBuffer); + } + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + #endif + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFilesNative___SZARRAY_WindowsStorageStorageFile__U4__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFileTypeDef; + CLR_RT_HeapBlock* storageFile; + CLR_RT_HeapBlock* hbObj; + SYSTEMTIME fileInfoTime; + + const char* workingPath; + char workingDrive[DRIVE_LETTER_LENGTH]; + + uint32_t startIndex; + uint32_t maxItemsToRetrieve; + uint32_t itemIndex = 0; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + + DIR currentDirectory; + FRESULT operationResult; + static FILINFO fileInfo; + uint16_t fileCount = 0; + char* stringBuffer = NULL; + char* workingBuffer = NULL; + + CLR_RT_HeapBlock& top = stack.PushValue(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get start index + startIndex = stack.Arg1().NumericByRef().u4; + + // get max items to retrieve + maxItemsToRetrieve = stack.Arg2().NumericByRef().u4; + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(), DRIVE_LETTER_LENGTH); + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // change drive + if(f_chdrive(workingDrive) == FR_OK) + { + // open directory + operationResult = f_opendir(¤tDirectory, workingPath); + + if(operationResult != FR_OK) + { + // error or directory empty + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, fileCount, storageFileTypeDef )); + } + else + { + // need to perform this in two steps + // 1st: count the file objects + // 2nd: create the array items with each file object + + // perform 1st pass + for (;;) + { + // read next directory item + operationResult = f_readdir(¤tDirectory, &fileInfo); + + // break on error or at end of dir + if (operationResult != FR_OK || fileInfo.fname[0] == 0) + { + break; + } + + // check if this is a file + // but skip if: + // - has system attribute set + // - has hidden attribute set + if ((fileInfo.fattrib & AM_ARC) && + !(fileInfo.fattrib & AM_SYS) && + !(fileInfo.fattrib & AM_HID)) + { + // check if this file is within the requested parameters + if( (itemIndex >= startIndex) && + (fileCount < maxItemsToRetrieve)) + { + fileCount++; + } + + itemIndex++; + } + } + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, fileCount, storageFileTypeDef )); + + // get a pointer to the first object in the array (which is of type ) + storageFile = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + if(fileCount > 0) + { + // allocate memory for buffers + stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); + workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(stringBuffer == NULL || workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // perform 2nd pass + // need to rewind the directory read index first + f_readdir(¤tDirectory, NULL); + + // and reset the file iterator vars too + itemIndex = 0; + fileCount = 0; + + + for (;;) + { + // read next directory item + operationResult = f_readdir(¤tDirectory, &fileInfo); + + // break on error or at end of dir + if (operationResult != FR_OK || fileInfo.fname[0] == 0) + { + break; + } + + // check if this is a file + // but skip if: + // - has system attribute set + // - has hidden attribute set + if ((fileInfo.fattrib & AM_ARC) && + !(fileInfo.fattrib & AM_SYS) && + !(fileInfo.fattrib & AM_HID)) + { + // check if this file is within the requested parameters + if( (itemIndex >= startIndex) && + (fileCount < maxItemsToRetrieve)) + { + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFile, storageFileTypeDef)); + + // dereference the object in order to reach its fields + hbObj = storageFile->Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], fileInfo.fname )); + + // clear working buffer + memset(workingBuffer, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(workingBuffer, workingPath, fileInfo.fname); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], workingBuffer )); + + // compute directory date + fileInfoTime = GetDateTime(fileInfo.fdate, fileInfo.ftime); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it with the fileInfoTime + *pRes = HAL_Time_ConvertFromSystemTime( &fileInfoTime ); + + // move the storage folder pointer to the next item in the array + storageFile++; + + // update iterator var + fileCount++; + } + + // update iterator var + itemIndex++; + } + } + } + else + { + // empty directory + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, fileCount, storageFileTypeDef )); + } + } + } + else + { + // check if the working drive is the SPIFFS drive and... + // ... that the path is the drive root (because SPIFFS doesn't support folders) + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + if( (WORKING_DRIVE_IS_INTERNAL_DRIVE) && + (hal_strlen_s(workingPath) == DRIVE_PATH_LENGTH - 1)) + { + // this is the SPIFFS drive + spiffs_DIR drive; + struct spiffs_dirent e; + struct spiffs_dirent *pe = &e; + + // need to perform this in two steps + // 1st: count the file objects + // 2nd: create the array items with each file object + + // perform 1st pass + SPIFFS_opendir(&fs, "/", &drive); + while ((pe = SPIFFS_readdir(&drive, pe))) + { + fileCount++; + } + + // have to close dir + SPIFFS_closedir(&drive); + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, fileCount, storageFileTypeDef )); + + // get a pointer to the first object in the array (which is of type ) + storageFile = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + if(fileCount > 0) + { + // allocate memory for buffer + workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // perform 2nd pass + // need to open the directory again + SPIFFS_opendir(&fs, "/", &drive); + + // and reset the file iterator vars too + itemIndex = 0; + fileCount = 0; + pe = &e; + + while ((pe = SPIFFS_readdir(&drive, pe))) + { + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFile, storageFileTypeDef)); + + // dereference the object in order to reach its fields + hbObj = storageFile->Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], (const char*)pe->name )); + + // clear working buffer + memset(workingBuffer, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(workingBuffer, workingPath, (const char*)pe->name); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], workingBuffer )); + + // SPIFFS files don't have date information + + // move the storage folder pointer to the next item in the array + storageFile++; + } + + // done here, close dir + SPIFFS_closedir(&drive); + } + } + else + { + #else + { + #endif + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + } + + #elif (USE_SPIFFS_FOR_STORAGE == TRUE) + + CLR_RT_HeapBlock& top = stack.PushValue(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + spiffs_DIR drive; + struct spiffs_dirent e; + struct spiffs_dirent *pe = &e; + + // need to perform this in two steps + // 1st: count the file objects + // 2nd: create the array items with each file object + + // perform 1st pass + SPIFFS_opendir(&fs, "/", &drive); + while ((pe = SPIFFS_readdir(&drive, pe))) + { + fileCount++; + } + + // have to close dir + SPIFFS_closedir(&drive); + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, fileCount, storageFileTypeDef )); + + // get a pointer to the first object in the array (which is of type ) + storageFile = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + if(fileCount > 0) + { + // allocate memory for buffer + workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // perform 2nd pass + // need to open the directory again + SPIFFS_opendir(&fs, "/", &drive); + + // and reset the file iterator vars too + itemIndex = 0; + fileCount = 0; + + while ((pe = SPIFFS_readdir(&drive, pe))) + { + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFile, storageFileTypeDef)); + + // dereference the object in order to reach its fields + hbObj = storageFile->Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], (const char*)pe->name )); + + // clear working buffer + memset(workingBuffer, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(workingBuffer, workingPath, (const char*)pe->name); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], workingBuffer )); + + // SPIFFS files don't have date information + + // move the storage folder pointer to the next item in the array + storageFile++; + } + + // done here, close dir + SPIFFS_closedir(&drive); + } + #endif + + NANOCLR_CLEANUP(); + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + // close directory + f_closedir(¤tDirectory); + #endif + + // free buffers memory, if allocated + if(stringBuffer != NULL) + { + platform_free(stringBuffer); + } + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFileNative___WindowsStorageStorageFile__STRING__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFileTypeDef; + CLR_RT_HeapBlock* storageFile; + + const char* fileName; + const char* workingPath; + char workingDrive[DRIVE_LETTER_LENGTH]; + + CreationCollisionOption options; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + + FIL file; + static FILINFO fileInfo; + SYSTEMTIME fileInfoTime; + FRESULT operationResult; + uint8_t modeFlags = 0; + char* filePath = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(), DRIVE_LETTER_LENGTH); + + // get creation collision options + options = (CreationCollisionOption)stack.Arg2().NumericByRef().u4; + + // get a pointer to the StorageFolder path in managed field + workingPath = pThis[ Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // get a pointer to the desired file name + fileName = stack.Arg1().DereferenceString()->StringText(); + + // setup file path + filePath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(filePath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(filePath, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(filePath, workingPath, fileName); + + // change directory + operationResult = f_chdir(workingPath); + + if(operationResult != FR_OK) + { + if(operationResult == FR_INVALID_DRIVE) + { + // check if the working drive is the SPIFFS drive + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + // this is the SPIFFS drive + // proceed to create the file + + // compute mode flags from CreationCollisionOption + switch (options) + { + case CreationCollisionOption_ReplaceExisting: + modeFlags = SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR; + break; + + case CreationCollisionOption_FailIfExists: + modeFlags = SPIFFS_RDWR; + break; + + case CreationCollisionOption_OpenIfExists: + modeFlags = SPIFFS_CREAT | SPIFFS_RDWR; + break; + + case CreationCollisionOption_GenerateUniqueName: + // this operation is not supported in nanoFramework + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + + default: + break; + } + + spiffs_file fd = SPIFFS_open(&fs, fileName, modeFlags, 0); + if (fd < 0) + { + int32_t error = SPIFFS_errno(&fs); + + // process operation result according to creation options + if( (error == SPIFFS_ERR_FILE_EXISTS) && + (options == CreationCollisionOption_FailIfExists)) + { + // file already exists + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + } + if(options == CreationCollisionOption_OpenIfExists) + { + // file doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + // failed to create the file + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + else + { + // file created (or opened) succesfully + // OK to close it + SPIFFS_close(&fs, fd); + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], fileName )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], filePath )); + + // SPIFFS don't have date time details, so we are done here + } + } + else + { + #else + { + #endif + // invalid drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + } + else + { + // error opening the directoty + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + } + else + { + // compute mode flags from CreationCollisionOption + switch (options) + { + case CreationCollisionOption_ReplaceExisting: + modeFlags = FA_CREATE_ALWAYS; + break; + + case CreationCollisionOption_FailIfExists: + modeFlags = FA_CREATE_NEW; + break; + + case CreationCollisionOption_OpenIfExists: + modeFlags = FA_OPEN_EXISTING; + break; + + case CreationCollisionOption_GenerateUniqueName: + // this operation is not supported in nanoFramework + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + + default: + break; + } + + // open file + operationResult = f_open(&file, filePath, modeFlags); + + // process operation result according to creation options + if( (operationResult == FR_EXIST) && + (options == CreationCollisionOption_FailIfExists)) + { + // file already exists + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + } + if( (operationResult == FR_NO_FILE) && + (options == CreationCollisionOption_OpenIfExists)) + { + // file doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + if(operationResult == FR_OK) + { + // file created (or opened) succesfully + // OK to close it + f_close(&file); + + // now get the details + f_stat(fileName, &fileInfo); + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], fileName )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], filePath )); + + // get the date time details and fill in the managed field + // compute directory date + fileInfoTime = GetDateTime(fileInfo.fdate, fileInfo.ftime); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it with the fileInfoTime + *pRes = HAL_Time_ConvertFromSystemTime( &fileInfoTime ); + } + else + { + // failed to create the file + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + } + + #elif (USE_SPIFFS_FOR_STORAGE == TRUE) + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(), DRIVE_LETTER_LENGTH); + + // get creation collision options + options = (CreationCollisionOption)stack.Arg2().NumericByRef().u4; + + // get a pointer to the StorageFolder path in managed field + workingPath = pThis[ Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // get a pointer to the desired file name + fileName = stack.Arg1().DereferenceString()->StringText(); + + // setup file path + filePath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(filePath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(filePath, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(filePath, workingPath, fileName); + + // compute mode flags from CreationCollisionOption + switch (options) + { + case CreationCollisionOption_ReplaceExisting: + modeFlags = SPIFFS_CREAT | SPIFFS_TRUNC; + break; + + case CreationCollisionOption_FailIfExists: + modeFlags = 0; + break; + + case CreationCollisionOption_OpenIfExists: + modeFlags = SPIFFS_CREAT; + break; + + case CreationCollisionOption_GenerateUniqueName: + // this operation is not supported in nanoFramework + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + + default: + break; + } + + spiffs_file fd = SPIFFS_open(&fs, filePath, modeFlags, 0); + if (fd < 0) + { + int32_t error = SPIFFS_errno(&fs); + + // process operation result according to creation options + if( (error == SPIFFS_ERR_FILE_EXISTS) && + (options == CreationCollisionOption_FailIfExists)) + { + // file already exists + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + } + if(options == CreationCollisionOption_OpenIfExists) + { + // file doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + // failed to create the file + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + else + { + // file created (or opened) succesfully + // OK to close it + SPIFFS_close(&fs, fd); + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], fileName )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], filePath )); + + // SPIFFS don't have date time details, so we are done here + } + #endif + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if(filePath != NULL) + { + platform_free(filePath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNative___WindowsStorageStorageFolder__STRING__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* storageFolder; + + const char* folderName; + const char* workingPath; + char workingDrive[DRIVE_LETTER_LENGTH]; + + CreationCollisionOption options; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + + static FILINFO fileInfo; + SYSTEMTIME fileInfoTime; + FRESULT operationResult; + char* folderPath = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(), DRIVE_LETTER_LENGTH); + + // get creation collision options + options = (CreationCollisionOption)stack.Arg2().NumericByRef().u4; + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // get a pointer to the desired folder name + folderName = stack.Arg1().DereferenceString()->StringText(); + + folderPath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(folderPath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(folderPath, 0, 2 * FF_LFN_BUF + 1); + + // compose folder path + CombinePath(folderPath, workingPath, folderName); + + // check if folder exists + operationResult = f_stat(folderPath, &fileInfo); + + // folder doesn't exist + if (operationResult == FR_NO_FILE) + { + if (options == CreationCollisionOption_OpenIfExists) + { + // folder doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + else + { + // create directory + operationResult = f_mkdir(folderPath); + + if(operationResult == FR_OK) + { + operationResult = f_stat(folderPath, &fileInfo); + } + else + { + // failed to create the folder + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + } + } + else + { + if (options == CreationCollisionOption_FailIfExists) + { + // folder already exists + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + } + } + + if(operationResult == FR_OK) + { + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFolderTypeDef)); + + // get a handle to the storage folder + storageFolder = stack.TopValue().Dereference(); + + // folder name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], folderName )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], folderPath )); + + // get the date time details and fill in the managed field + // compute directory date + fileInfoTime = GetDateTime(fileInfo.fdate, fileInfo.ftime); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it with the fileInfoTime + *pRes = HAL_Time_ConvertFromSystemTime( &fileInfoTime ); + } + else + { + // failed to get folder details + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + + #elif (USE_SPIFFS_FOR_STORAGE == TRUE) + + // throw not supported exception because folders aren't supported in SPIFFS + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + #endif + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if(folderPath != NULL) + { + platform_free(folderPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::DeleteFolderNative___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + const char* workingPath; + // need extra room for the change dir command + char workingDrive[DRIVE_LETTER_LENGTH + 2]; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + + FRESULT operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path].DereferenceString()->StringText(); + + // remove folder + operationResult = f_unlink(workingPath); + if (operationResult == FR_INVALID_NAME) + { + // Invalid path + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + else if (operationResult == FR_DENIED) + { + // this could be because the folder is not empty or because it's the current folder + + // change directory to the parent directory using f_chdir("2:..") + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(), DRIVE_LETTER_LENGTH); + // make sure there is a terminator + workingDrive[2] = '\0'; + strcat(workingDrive, ".."); + + // change dir to parent + operationResult = f_chdir(workingDrive); + + // try remove again + operationResult = f_unlink(workingPath); + + if (operationResult == FR_DENIED) + { + // folder not empty + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_EMPTY); + } + else if (operationResult != FR_OK) + { + // something else is failing + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + } + else if (operationResult != FR_OK) + { + // folder doesn't exist + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + // this is the SPIFFS drive + // throw not supported exception because folders aren't supported in SPIFFS + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + else + { + #else + { + #endif + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + } + + #elif (USE_SPIFFS_FOR_STORAGE == TRUE) + + // throw not supported exception because folders aren't supported in SPIFFS + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + #endif + + NANOCLR_CLEANUP(); + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::RenameFolderNative___VOID__STRING(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + const char* workingPath; + const char* desiredPath; + char workingDrive[DRIVE_LETTER_LENGTH]; + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + + FRESULT operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // copy the first 2 letters of the path for the drive + // path is 'D:\folder\file.txt', so we need 'D:' + memcpy(workingDrive, pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(), DRIVE_LETTER_LENGTH); + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path].DereferenceString()->StringText(); + + // get a pointer to the desired folder name + desiredPath = stack.Arg1().DereferenceString()->StringText(); + + // rename folder + operationResult = f_rename(workingPath, desiredPath); + if (operationResult == FR_INVALID_NAME) + { + // invalid path + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + else if (operationResult != FR_OK) + { + // folder doesn't exist + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + // this is the SPIFFS drive + // throw not supported exception because folders aren't supported in SPIFFS + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + else + { + #else + { + #endif + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + } + + #elif (USE_SPIFFS_FOR_STORAGE == TRUE) + + // throw not supported exception because folders aren't supported in SPIFFS + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + #endif + + NANOCLR_CLEANUP(); + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetFolderNative___WindowsStorageStorageFolder__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* storageFolder; + + const char* folderName; + const char* workingPath; + char* folderPath = NULL; + + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + char workingDrive[DRIVE_LETTER_LENGTH]; + #endif + + #if ((HAL_USE_SDC == TRUE) || (HAL_USBH_USE_MSD == TRUE)) + + FILINFO fileInfo; + SYSTEMTIME fileInfoTime; + + FRESULT operationResult; + + CLR_INT64* pRes; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + workingPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path].DereferenceString()->StringText(); + + // get a pointer to the desired folder name + folderName = stack.Arg1().DereferenceString()->StringText(); + + folderPath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if (folderPath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(folderPath, 0, 2 * FF_LFN_BUF + 1); + + // compose folder path + CombinePath(folderPath, workingPath, folderName); + + // check if directory exists + operationResult = f_stat(folderPath, &fileInfo); + if (operationResult != FR_OK) + { + // folder doesn't exist + #if (USE_SPIFFS_FOR_STORAGE == TRUE) + if(WORKING_DRIVE_IS_INTERNAL_DRIVE) + { + // this is the SPIFFS drive + // throw not supported exception because folders aren't supported in SPIFFS + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + else + { + #else + { + #endif + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + } + else + { + // is this a file? + if ( !(fileInfo.fattrib & AM_DIR) ) + { + // Path represents a file + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + else + { + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFolder", "Windows.Storage", storageFolderTypeDef); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFolderTypeDef)); + + // get a handle to the storage folder + storageFolder = stack.TopValue().Dereference(); + + // folder name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name], folderName)); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path], folderPath)); + + // get the date time details and fill in the managed field + // compute directory date + fileInfoTime = GetDateTime(fileInfo.fdate, fileInfo.ftime); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___dateCreated]; + pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it with the fileInfoTime + *pRes = HAL_Time_ConvertFromSystemTime(&fileInfoTime); + } + } + + #elif (USE_SPIFFS_FOR_STORAGE == TRUE) + + // throw not supported exception because folders aren't supported in SPIFFS + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + #endif + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (folderPath != NULL) + { + platform_free(folderPath); + } + + NANOCLR_CLEANUP_END(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_target.h new file mode 100644 index 00000000..ac692517 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/Windows.Storage/win_storage_native_target.h @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_STORAGE_NATIVE_TARGET_H_ +#define _WIN_STORAGE_NATIVE_TARGET_H_ + +#include +#include + +#define WORKING_DRIVE_IS_INTERNAL_DRIVE memcmp(workingDrive, INTERNAL_DRIVE_LETTER, sizeof(INTERNAL_DRIVE_LETTER) - 1) == 0 + +#endif //_WIN_STORAGE_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_App_Interface.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_App_Interface.c new file mode 100644 index 00000000..7582fbfc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_App_Interface.c @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +// declaration for wrapper function +extern int CLR_Messaging_ProcessPayload(WP_Message* msg); + +//////////////////////////////////////////////////// + +int WP_App_ProcessHeader(WP_Message* message) +{ + // check for reception buffer overflow + if(message->m_header.m_size > sizeof(receptionBuffer)) + { + return false; + } + + message->m_payload = receptionBuffer; + return true; +} + +int WP_App_ProcessPayload(WP_Message* message) +{ + return CLR_Messaging_ProcessPayload(message); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_MonitorCommands.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_MonitorCommands.c new file mode 100644 index 00000000..3a3646b0 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/WireProtocol_MonitorCommands.c @@ -0,0 +1,7 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// file empty on purpose +// in nanoCLR the MonitorCommands are implemented in Debugger diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/mbedtls_entropy_hardware_pool.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/mbedtls_entropy_hardware_pool.c new file mode 100644 index 00000000..99a8416a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/mbedtls_entropy_hardware_pool.c @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// Get len bytes of entropy from the hardware RNG. +int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen ) +{ + (void)data; + + // start random generator + rngStart(); + + for(size_t i = 0; i < len; i++) + { + // our generator returns 32bits numbers + *output = rngGenerateRandomNumber(); + + output++; + } + + // callers require this to be set + *olen = len; + + // stop random generator + rngStop(); + + return 0; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoCRT.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoCRT.cpp new file mode 100644 index 00000000..10f90972 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoCRT.cpp @@ -0,0 +1,205 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +//--// +/* STDIO stubs */ +//--// + +#if !defined(BUILD_RTM) + +void hal_fprintf_SetLoggingCallback( LOGGING_CALLBACK fpn ) +{ + (void)fpn; + NATIVE_PROFILE_PAL_CRT(); + +} + +#endif + +//--// + +#if defined(PLATFORM_EMULATED_FLOATINGPOINT) + +// no floating point, fixed point + +int hal_snprintf_float( char* buffer, size_t len, const char* format, int32_t f ) +{ + NATIVE_PROFILE_PAL_CRT(); + + uint32_t i ; + uint32_t dec; + + if ( f < 0 ) + { + // negative number + i = (uint32_t) -f ; + dec = i & (( 1<>HAL_FLOAT_SHIFT); + + if (dec !=0) dec = (dec * (uint32_t)HAL_FLOAT_PRECISION + (1<< (HAL_FLOAT_SHIFT-1))) >>HAL_FLOAT_SHIFT; + + return hal_snprintf( buffer, len, "-%d.%03u", i, (uint32_t)dec); + + } + else + { + // positive number + i = (uint32_t) f ; + dec = f & (( 1<>HAL_FLOAT_SHIFT); + + if (dec !=0) dec = (dec * (uint32_t)HAL_FLOAT_PRECISION + (1<< (HAL_FLOAT_SHIFT-1))) >>HAL_FLOAT_SHIFT; + + return hal_snprintf( buffer, len, "%d.%03u", i, (uint32_t)dec); + } +} + +int hal_snprintf_double( char* buffer, size_t len, const char* format, int64_t& d ) +{ + NATIVE_PROFILE_PAL_CRT(); + + uint64_t i; + uint32_t dec; // 32 bit is enough for decimal part + + if ( d < 0 ) + { + // negative number + i = (uint64_t)-d; + + i += ((1 << (HAL_DOUBLE_SHIFT-1)) / HAL_DOUBLE_PRECISION); // add broad part of rounding increment before split + + dec = i & (( 1<> HAL_DOUBLE_SHIFT ; + + if (dec !=0) dec = (dec * HAL_DOUBLE_PRECISION + ((1 << (HAL_DOUBLE_SHIFT-1)) % HAL_DOUBLE_PRECISION)) >> HAL_DOUBLE_SHIFT; + + return hal_snprintf( buffer, len, "-%lld.%04u", (int64_t)i, (uint32_t)dec); + + } + else + { + + // positive number + i = (uint64_t)d; + + i += ((1 << (HAL_DOUBLE_SHIFT-1)) / HAL_DOUBLE_PRECISION); // add broad part of rounding increment before split + + dec = i & (( 1<> HAL_DOUBLE_SHIFT; + + if (dec !=0) dec = (dec * HAL_DOUBLE_PRECISION + ((1 << (HAL_DOUBLE_SHIFT-1)) % HAL_DOUBLE_PRECISION)) >> HAL_DOUBLE_SHIFT; + + return hal_snprintf( buffer, len, "%lld.%04u", (int64_t)i, (uint32_t)dec); + } +} + +#else + +#endif + +// because debug_printf needs to be called in both C and C++ we need a proxy to allow it to be called in 'C' +extern "C" { + +#if !defined(BUILD_RTM) + + void debug_printf(const char* format, ...) + { + char buffer[256]; + va_list arg_ptr; + + va_start( arg_ptr, format ); + + int len = vsnprintf( buffer, sizeof(buffer)-1, format, arg_ptr ); + + DebuggerPort_Write( HalSystemConfig.stdio, buffer, len, 0 ); // skip null terminator + + va_end( arg_ptr ); + } + +#else + __inline void debug_printf( const char *format, ... ) {} +#endif // !defined(BUILD_RTM) +} + +int hal_strcpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strcpy + + size_t len; + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + len = hal_strlen_s(strSrc); + if(sizeInBytes < len + 1) {_ASSERTE(FALSE); return 1;} + + strcpy( strDst, strSrc ); + return 0; + +#define strcpy DoNotUse_*strcpy [] +} + +int hal_strncpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc, size_t count ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strncpy + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + if (sizeInBytes < count + 1) + { + _ASSERTE(FALSE); + strDst[0] = 0; + return 1; + } + + strDst[count] = 0; + strncpy( strDst, strSrc, count ); + return 0; + +#define strncpy DoNotUse_*strncpy [] +} + +size_t hal_strlen_s (const char * str) +{ + NATIVE_PROFILE_PAL_CRT(); + + const char *eos = str; + while( *eos++ ) ; + return( eos - str - 1 ); +} + +int hal_strncmp_s ( const char* str1, const char* str2, size_t num ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strncmp + if(str1 == NULL || str2 == NULL) {_ASSERTE(FALSE); return 1;} + + return strncmp( str1, str2, num ); + +#define strncmp DoNotUse_*strncmp [] +} + +// Compares 2 ASCII strings case insensitive. Does not take locale into account. +int hal_stricmp( const char * dst, const char * src ) +{ + int f = 0, l = 0; + + do + { + if ( ((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z') ) + { + f -= 'A' - 'a'; + } + if ( ((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z') ) + { + l -= 'A' - 'a'; + } + } + while ( f && (f == l) ); + + return(f - l); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_nanoFramework_Devices_Can_CanController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_nanoFramework_Devices_Can_CanController.cpp new file mode 100644 index 00000000..798fa59a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_nanoFramework_Devices_Can_CanController.cpp @@ -0,0 +1,460 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_devices_can_native_target.h" + +// define these types here to make it shorter and improve code readability +typedef Library_nf_devices_can_native_nanoFramework_Devices_Can_CanSettings CanSettings; +typedef Library_nf_devices_can_native_nanoFramework_Devices_Can_CanMessage ManagedCanMessage; + +static void RxMessage(CANDriver *canp, uint32_t flags) +{ + NATIVE_INTERRUPT_START + + NF_PAL_CAN* palCan; + uint8_t controllerId = 0; + CANRxFrame rxMsg; + + (void)flags; + + #if STM32_CAN_USE_CAN1 + if (canp == &CAND1) + { + palCan = &Can1_PAL; + controllerId = 1; + } + #endif + #if STM32_CAN_USE_CAN2 + if (canp == &CAND2) + { + palCan = &Can2_PAL; + controllerId = 2; + } + #endif + #if STM32_CAN_USE_CAN3 + if (canp == &CAND3) + { + palCan = &Can3_PAL; + controllerId = 3; + } + #endif + + while (canReceiveTimeout(palCan->Driver, CAN_ANY_MAILBOX, &rxMsg, TIME_IMMEDIATE) == MSG_OK) + { + // got message + + // store message in the CAN buffer + // don't care about the success of the operation, if it's full we are droping the message anyway + palCan->MsgRingBuffer.Push(rxMsg); + + // fire event for CAN message received + PostManagedEvent( EVENT_CAN, 0, controllerId, CanEvent_MessageReceived ); + } + + NATIVE_INTERRUPT_END +} + +///////////////////////////////////////////////////////// +// CAN PAL strucs delcared in nf_devices_can_native.h // +///////////////////////////////////////////////////////// +#if STM32_CAN_USE_CAN1 + NF_PAL_CAN Can1_PAL; +#endif +#if STM32_CAN_USE_CAN2 + NF_PAL_CAN Can2_PAL; +#endif +#if STM32_CAN_USE_CAN3 + NF_PAL_CAN Can3_PAL; +#endif + +HRESULT Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::WriteMessage___VOID__nanoFrameworkDevicesCanCanMessage( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uint32_t id; + CanMessageIdType msgIdType; + CanMessageFrameType msgFrameType; + CLR_RT_HeapBlock_Array* message; + CANTxFrame txmsg; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + CLR_RT_HeapBlock* pMessage = stack.Arg1().Dereference(); + + // get controller index + uint8_t controllerIndex = (uint8_t)(pThis[ FIELD___controllerId ].NumericByRef().s4); + + // dereference message fields + id = (uint32_t)(pMessage[ Library_nf_devices_can_native_nanoFramework_Devices_Can_CanMessage::FIELD___id ].NumericByRef().u4); + msgIdType = (CanMessageIdType)(pMessage[ Library_nf_devices_can_native_nanoFramework_Devices_Can_CanMessage::FIELD___identifierType ].NumericByRefConst().u1); + msgFrameType = (CanMessageFrameType)(pMessage[ Library_nf_devices_can_native_nanoFramework_Devices_Can_CanMessage::FIELD___frameType ].NumericByRefConst().u1); + + // get message to transmite + message = pMessage[ Library_nf_devices_can_native_nanoFramework_Devices_Can_CanMessage::FIELD___message ].DereferenceArray(); + + // message max length is 8 bytes + if(message->m_numOfElements > 8) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + // compose the transmite packet to send + if(message != NULL) + { + // copy message to structure + memcpy(txmsg.data8, (uint8_t*)message->GetFirstElement(), message->m_numOfElements); + } + // message id according to it's type + if(msgIdType == CanMessageIdType_SID) + { + txmsg.IDE = CAN_IDE_STD; + txmsg.SID = id; + } + else + { + txmsg.IDE = CAN_IDE_EXT; + txmsg.EID = id; + } + // remote transmission request + txmsg.RTR = msgFrameType == CanMessageFrameType_Data ? CAN_RTR_DATA : CAN_RTR_REMOTE; + // data length + txmsg.DLC = message->m_numOfElements; + + switch (controllerIndex) + { + #if STM32_CAN_USE_CAN1 + case 1: + canTransmit(Can1_PAL.Driver, CAN_ANY_MAILBOX, &txmsg, TIME_MS2I(100)); + break; + #endif + #if STM32_CAN_USE_CAN2 + case 2: + canTransmit(Can2_PAL.Driver, CAN_ANY_MAILBOX, &txmsg, TIME_MS2I(100)); + break; + #endif + #if STM32_CAN_USE_CAN3 + case 3: + canTransmit(Can3_PAL.Driver, CAN_ANY_MAILBOX, &txmsg, TIME_MS2I(100)); + break; + #endif + default: + // this CAN bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::GetMessage___nanoFrameworkDevicesCanCanMessage( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index canMessageTypeDef; + CLR_RT_HeapBlock* canMessage = NULL; + + CANRxFrame canFrame; + NF_PAL_CAN* palCan; + uint8_t controllerIndex; + size_t messageCount = 0; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get controller index + controllerIndex = (uint8_t)(pThis[ FIELD___controllerId ].NumericByRef().s4); + + // get the PAL struct for this CAN bus + switch (controllerIndex) + { + + #if STM32_CAN_USE_CAN1 + case 1: + palCan = &Can1_PAL; + + break; + #endif + + #if STM32_CAN_USE_CAN2 + case 2: + palCan = &Can2_PAL; + + break; + #endif + + #if STM32_CAN_USE_CAN3 + case 3: + palCan = &Can3_PAL; + + break; + #endif + + default: + // this CAN bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // get next CAN frame from ring buffer + messageCount = palCan->MsgRingBuffer.Pop(&canFrame, 1); + + // find type, don't bother checking the result as the type exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "CanMessage", "nanoFramework.Devices.Can", canMessageTypeDef ); + + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), canMessageTypeDef)); + + canMessage = stack.TopValue().Dereference(); + + if(messageCount == 1) + { + // we have a message + + // get pointer to each managed field and set appropriate value + CLR_RT_HeapBlock& identifierTypeFieldRef = canMessage[ ManagedCanMessage::FIELD___identifierType ]; + CLR_RT_HeapBlock& frameTypeFieldRef = canMessage[ ManagedCanMessage::FIELD___frameType ]; + + // get message frame type + uint8_t* fr = (uint8_t*)&frameTypeFieldRef.NumericByRef().u1; + *fr = canFrame.RTR; + + // get message id type + uint8_t* idType = (uint8_t*)&identifierTypeFieldRef.NumericByRef().u1; + *idType = canFrame.IDE; + + // get message id + CLR_RT_HeapBlock& idFieldRef = canMessage[ ManagedCanMessage::FIELD___id ]; + uint32_t* id = (uint32_t*)&idFieldRef.NumericByRef().u4; + + if(canFrame.IDE == 0) + { + *id = canFrame.SID; + } + else + { + *id = canFrame.EID; + } + + // get data if any + if(canFrame.data8) + { + CLR_RT_HeapBlock& dataArrayField = canMessage[ ManagedCanMessage::FIELD___message ]; + // create an array of + NANOCLR_CHECK_HRESULT( CLR_RT_HeapBlock_Array::CreateInstance( dataArrayField, 8, g_CLR_RT_WellKnownTypes.m_UInt8 ) ); + + // get a pointer to the first object in the array + CLR_UINT8* dataBuffer = (CLR_UINT8*)(dataArrayField.DereferenceArray()->GetFirstElement()); + memcpy(dataBuffer, &canFrame.data8[0], 8); + } + } + else + { + // no more messages, return null + stack.SetResult_Object(NULL); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t controllerIndex; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get controller index + controllerIndex = (uint8_t)(pThis[ FIELD___controllerId ].NumericByRef().s4); + + // init the PAL struct for this CAN bus and assign the respective driver + // all this occurs if not already done + switch (controllerIndex) + { + #if STM32_CAN_USE_CAN1 + case 1: + Can1_PAL.Driver = NULL; + // stop CAN + canStop(&CAND1); + break; + #endif + + #if STM32_CAN_USE_CAN2 + case 2: + Can2_PAL.Driver = NULL; + // stop CAN + canStop(&CAND2); + break; + #endif + + #if STM32_CAN_USE_CAN3 + case 3: + Can3_PAL.Driver = NULL; + // stop CAN + canStop(&CAND3); + break; + #endif + + default: + // this CAN bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_CAN* palCan = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___settings ].Dereference(); + + // get controller index + uint8_t controllerIndex = (uint8_t)(pThis[ FIELD___controllerId ].NumericByRef().s4); + + // init the PAL struct for this CAN bus and assign the respective driver + // all this occurs if not already done + switch (controllerIndex) + { + #if STM32_CAN_USE_CAN1 + case 1: + Init_Can1(); + ConfigPins_CAN1(); + Can1_PAL.Driver = &CAND1; + palCan = &Can1_PAL; + break; + #endif + #if STM32_CAN_USE_CAN2 + case 2: + Init_Can2(); + ConfigPins_CAN2(); + Can2_PAL.Driver = &CAND2; + palCan = &Can2_PAL; + break; + #endif + #if STM32_CAN_USE_CAN3 + case 3: + Init_Can3(); + ConfigPins_CAN3(); + Can3_PAL.Driver = &CAND3; + palCan = &Can3_PAL; + break; + #endif + default: + // this CAN bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // get config + palCan->Configuration = { + CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP, + (uint32_t)( + CAN_BTR_SJW((uint8_t)pConfig[ CanSettings::FIELD___syncJumpWidth ].NumericByRef().u1) | + CAN_BTR_TS2((uint8_t)pConfig[ CanSettings::FIELD___phaseSegment2 ].NumericByRef().u1) | + CAN_BTR_TS1((uint8_t)pConfig[ CanSettings::FIELD___phaseSegment1 ].NumericByRef().u1) | + CAN_BTR_BRP((uint8_t)pConfig[ CanSettings::FIELD___baudRatePrescaler ].NumericByRef().u1) + ) + }; + + // start CAN + canStart(palCan->Driver, &palCan->Configuration); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::NativeUpdateCallbacks___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NF_PAL_CAN* palCan = NULL; + bool callbacksRegistered; + uint8_t controllerIndex; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get controller index + controllerIndex = (uint8_t)(pThis[ FIELD___controllerId ].NumericByRef().s4); + + // flag to determine if there are any callbacks registered in managed code + callbacksRegistered = (pThis[ FIELD___callbacks ].Dereference() != NULL); + + switch (controllerIndex) + { + #if STM32_CAN_USE_CAN1 + case 1: + palCan = &Can1_PAL; + break; + #endif + #if STM32_CAN_USE_CAN2 + case 2: + palCan = &Can2_PAL; + break; + #endif + #if STM32_CAN_USE_CAN3 + case 3: + palCan = &Can3_PAL; + break; + #endif + default: + // this CAN bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // need to start CAN again + // it's safe to stop first + canStop(palCan->Driver); + + if(callbacksRegistered) + { + // there is someone listening on the managed end + palCan->Driver->rxfull_cb = RxMessage; + } + else + { + // no one listening, OK to remove + palCan->Driver->rxfull_cb = NULL; + } + + // start CAN + canStart(palCan->Driver, &palCan->Configuration); + + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_can_native_nanoFramework_Devices_Can_CanController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "SPI1,SPI2,SPI3,SPI4,SPI5,SPI6," + terminator and init with the terminator + char deviceSelectorString[ 30 + 1] = { 0 }; + + #if STM32_CAN_USE_CAN1 + strcat(deviceSelectorString, "CAN1,"); + #endif + #if STM32_CAN_USE_CAN2 + strcat(deviceSelectorString, "CAN2,"); + #endif + #if STM32_CAN_USE_CAN3 + strcat(deviceSelectorString, "CAN3,"); + #endif + + // replace the last comma with a terminator + deviceSelectorString[hal_strlen_s(deviceSelectorString) - 1] = '\0'; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_target.h new file mode 100644 index 00000000..44211206 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.Can/nf_devices_can_native_target.h @@ -0,0 +1,77 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _NF_DEVICES_CAN_NATIVE_TARGET_H_ +#define _NF_DEVICES_CAN_NATIVE_TARGET_H_ + +#include +#include "target_nf_devices_can_config.h" +#include + + +// struct representing the CAN +struct NF_PAL_CAN +{ + CANDriver* Driver; + CANConfig Configuration; + thread_t* ReceiverThread; + + HAL_RingBuffer MsgRingBuffer; + CANRxFrame* MsgBuffer; +}; + +/////////////////////////////////////////// +// declaration of the CAN PAL strucs // +/////////////////////////////////////////// +#if STM32_CAN_USE_CAN1 + extern NF_PAL_CAN Can1_PAL; +#endif +#if STM32_CAN_USE_CAN2 + extern NF_PAL_CAN Can2_PAL; +#endif +#if STM32_CAN_USE_CAN3 + extern NF_PAL_CAN Can3_PAL; +#endif + +// the following macro defines a function that configures the GPIO pins for a STM32 CAN +// it gets called in the can_lld_start function// this is required because the CAN peripherals can use multiple GPIO configuration combinations +#define CAN_CONFIG_PINS(num, gpio_port_tx, gpio_port_rx, tx_pin, rx_pin, alternate_function) void ConfigPins_CAN##num() { \ + palSetPadMode(gpio_port_tx, tx_pin, PAL_MODE_ALTERNATE(alternate_function) | PAL_STM32_OTYPE_PUSHPULL \ + | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_MODE_ALTERNATE); \ + palSetPadMode(gpio_port_rx, rx_pin, PAL_MODE_ALTERNATE(alternate_function) | PAL_STM32_OTYPE_PUSHPULL \ + | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_MODE_ALTERNATE); \ +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// when a CAN is defined the declarations below will have the real function/configuration +// in the target folder @ target_nf_devices_can_config.cpp +/////////////////////////////////////////////////////////////////////////////////////////// +void ConfigPins_CAN1(); +void ConfigPins_CAN2(); +void ConfigPins_CAN3(); + + +///////////////////////////////////// +// CAN Msg buffers // +// these live in the target folder // +///////////////////////////////////// +extern CANRxFrame Can1_MsgBuffer[]; +extern CANRxFrame Can2_MsgBuffer[]; +extern CANRxFrame Can3_MsgBuffer[]; + +// +#define CAN_INIT(num, buffer_size) void Init_Can##num() { \ + Can##num##_PAL.MsgBuffer = Can##num##_MsgBuffer; \ + Can##num##_PAL.MsgRingBuffer.Initialize( Can##num##_PAL.MsgBuffer, buffer_size); \ +} + +// when a CAN is defined the declarations below will have the real function/configuration +// in the target folder @ target_nf_devices_can_config.cpp +void Init_Can1(); +void Init_Can2(); +void Init_Can3(); + +#endif //_NF_DEVICES_CAN_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp new file mode 100644 index 00000000..08345362 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp @@ -0,0 +1,261 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_devices_onewire_native_target.h" + +// working thread to execute long running 1-Wire operations +static thread_t* OneWireWorkingThread; + +// struct for working threads +OneWireFindStruct FindStruct; + +// ChibiOS OneWire working thread +static THD_FUNCTION(OneWireFindFirstWorkingThread, arg) +{ + msg_t deviceFound; + + OneWireFindStruct* findStruct = (OneWireFindStruct*)arg; + + deviceFound = oneWireFindFirst(findStruct->DoReset, findStruct->AlarmOnly); + + // fire event for 1-Wire operarion completed + Events_Set(SYSTEM_EVENT_FLAG_ONEWIRE_MASTER); + + chThdExit(deviceFound); +} + +static THD_FUNCTION(OneWireFindNextWorkingThread, arg) +{ + msg_t deviceFound; + + OneWireFindStruct* findStruct = (OneWireFindStruct*)arg; + + deviceFound = oneWireFindNext(findStruct->DoReset, findStruct->AlarmOnly); + + // fire event for 1-Wire operarion completed + Events_Set(SYSTEM_EVENT_FLAG_ONEWIRE_MASTER); + + chThdExit(deviceFound); +} + + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchReset___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + volatile bool reset = oneWireTouchReset(); + stack.SetResult_Boolean( reset ) ; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchBit___BOOLEAN__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + bool value = stack.Arg1().NumericByRefConst().u1 != 0; + + stack.SetResult_Boolean( oneWireTouchBit(value) ) ; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchByte___U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t value = (uint8_t)stack.Arg1().NumericByRefConst().u1; + uint8_t result = oneWireTouchByte(value); + stack.SetResult_U1( result ) ; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::WriteByte___U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t cmd = (uint8_t)stack.Arg1().NumericByRefConst().u1; + uint8_t result = oneWireWriteByte(cmd); + stack.SetResult_U1( result ) ; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::ReadByte___U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t result = oneWireReadByte(); + stack.SetResult_U1( result ) ; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::FindFirstDevice___BOOLEAN__BOOLEAN__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t* serialNumberPointer; + msg_t oneWireOperationResult = FALSE; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + // set an infinite timeout to wait forever for the operation to complete + // this value has to be in ticks to be properly loaded by SetupTimeoutFromTicks() below + hbTimeout.SetInteger((CLR_INT64)-1); + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // this is going to be used to check for the right event in case of simultaneous 1-Wire operations + if(stack.m_customState == 1) + { + FindStruct.DoReset = stack.Arg1().NumericByRefConst().u1 != 0; + FindStruct.AlarmOnly = stack.Arg2().NumericByRefConst().u1 != 0; + + // because the 1-Wire bus is shared, acquire the module + oneWireAcquireModule(); + + // spawn working thread to perform the 1-Wire operations + OneWireWorkingThread = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(256), + "OWWT", NORMALPRIO, OneWireFindFirstWorkingThread, &FindStruct); + + // bump custom state + stack.m_customState = 2; + } + + while(eventResult) + { + if(OneWireWorkingThread->state == CH_STATE_FINAL) + { + // OneWire working thread is now complete + break; + } + + // non-blocking wait allowing other threads to run while we wait for the 1-Wire operations to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_OneWireMaster, eventResult )); + } + + if(eventResult) + { + // event occurred + + // ChibiOS requirement: need to call chThdWait for working thread in order to have it's memory released to the heap, otherwise it won't be returned + oneWireOperationResult = chThdWait(OneWireWorkingThread); + + oneWireReleaseModule(); + + // get the result from the working thread execution + if(oneWireOperationResult) + { + // if a device was found update serialNumber field in managed class + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the serial number field in the OneWireController instance + CLR_RT_HeapBlock_Array* serialNumberField = pThis[ FIELD___serialNumber ].DereferenceArray(); + + _ASSERTE(serialNumberField->m_numOfElements == 8); + + // get a pointer to the first element of the byte array + serialNumberPointer = (uint8_t*)serialNumberField->GetFirstElement(); + + oneWireSerialNum(serialNumberPointer, TRUE); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + // set result + stack.SetResult_Boolean( oneWireOperationResult ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::FindNextDevice___BOOLEAN__BOOLEAN__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t* serialNumberPointer; + msg_t oneWireOperationResult = FALSE; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + // set an infinite timeout to wait forever for the operation to complete + // this value has to be in ticks to be properly loaded by SetupTimeoutFromTicks() below + hbTimeout.SetInteger((CLR_INT64)-1); + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // this is going to be used to check for the right event in case of simultaneous 1-Wire operations + if(stack.m_customState == 1) + { + FindStruct.DoReset = stack.Arg1().NumericByRefConst().u1 != 0; + FindStruct.AlarmOnly = stack.Arg2().NumericByRefConst().u1 != 0; + + // because the 1-Wire bus is shared, acquire the module + oneWireAcquireModule(); + + // spawn working thread to perform the 1-Wire operations + OneWireWorkingThread = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(256), + "OWWT", NORMALPRIO, OneWireFindNextWorkingThread, &FindStruct); + + // bump custom state + stack.m_customState = 2; + } + + while(eventResult) + { + if(OneWireWorkingThread->state == CH_STATE_FINAL) + { + // OneWire working thread is now complete + break; + } + + // non-blocking wait allowing other threads to run while we wait for the 1-Wire operations to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_OneWireMaster, eventResult )); + } + + if(eventResult) + { + // event occurred + + // ChibiOS requirement: need to call chThdWait for working thread in order to have it's memory released to the heap, otherwise it won't be returned + oneWireOperationResult = chThdWait(OneWireWorkingThread); + + oneWireReleaseModule(); + + // get the result from the working thread execution + if(oneWireOperationResult) + { + // update serialNumber field + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the serial number field in the OneWireController instance + CLR_RT_HeapBlock_Array* serialNumberField = pThis[ FIELD___serialNumber ].DereferenceArray(); + + _ASSERTE(serialNumberField->m_numOfElements == 8); + + // get a pointer to the first element of the byte array + serialNumberPointer = (uint8_t*)serialNumberField->GetFirstElement(); + + oneWireSerialNum(serialNumberPointer, TRUE); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + // set result + stack.SetResult_Boolean( oneWireOperationResult ); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h new file mode 100644 index 00000000..f89b8d1c --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_DEVICES_ONEWIRE_NATIVE_TARGET_H_ +#define _NF_DEVICES_ONEWIRE_NATIVE_TARGET_H_ + +#include +#include +#include + +// struct with parameters for 1-Wire working thread +struct OneWireFindStruct +{ + bool DoReset; + bool AlarmOnly; +}; + +// the following macro defines a function that configures the GPIO pins for a STM32 UART/USART +// it gets called in the oneWire_lld_start function +// this is required because the UART/USART peripherals can use multiple GPIO configuration combinations +#define UART_CONFIG_PINS(num, gpio_port_tx, tx_pin, alternate_function) void ConfigPins_UART##num() { \ + palSetPadMode(gpio_port_tx, tx_pin, PAL_MODE_ALTERNATE(alternate_function) | PAL_STM32_OTYPE_OPENDRAIN \ + | PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_MODE_ALTERNATE); \ +} + +#endif //_NF_DEVICES_ONEWIRE_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.cpp new file mode 100644 index 00000000..d6a2cd9a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.cpp @@ -0,0 +1,62 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_hardware_stm32_native.h" +#include + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::get_WakeupReason___STATIC__nanoFrameworkHardwareStm32PowerWakeupReasonType, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::DisableWakeupPin___STATIC__VOID__nanoFrameworkHardwareStm32PowerWakeupPin, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::EnableWakeupPin___STATIC__VOID__nanoFrameworkHardwareStm32PowerWakeupPin, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::NativeEnterStandbyMode___STATIC__VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::ReadBytes___STATIC__VOID__U4__SZARRAY_U1, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::WriteBytes___STATIC__VOID__U4__SZARRAY_U1, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::GetSize___STATIC__I4, + NULL, + NULL, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC::GetAlarm___STATIC__mscorlibSystemDateTime, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC::Native_RTC_SetAlarm___STATIC__VOID__U1__U1__U1__U1, + NULL, + NULL, + NULL, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities::NativeGetDeviceUniqueId___STATIC__VOID__SZARRAY_U1, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities::NativeGetDeviceId___STATIC__U4, + Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities::NativeGetDeviceRevisionId___STATIC__U4, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Hardware_Stm32 = +{ + "nanoFramework.Hardware.Stm32", + 0x3E87EA8A, + method_lookup, + { 100, 0, 4, 3 } +}; diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.h new file mode 100644 index 00000000..d14ea279 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_HARDWARE_STM32_NATIVE_H_ +#define _NF_HARDWARE_STM32_NATIVE_H_ + +#include +#include +#include + +struct Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power +{ + NANOCLR_NATIVE_DECLARE(get_WakeupReason___STATIC__nanoFrameworkHardwareStm32PowerWakeupReasonType); + NANOCLR_NATIVE_DECLARE(DisableWakeupPin___STATIC__VOID__nanoFrameworkHardwareStm32PowerWakeupPin); + NANOCLR_NATIVE_DECLARE(EnableWakeupPin___STATIC__VOID__nanoFrameworkHardwareStm32PowerWakeupPin); + NANOCLR_NATIVE_DECLARE(NativeEnterStandbyMode___STATIC__VOID); + + //--// + +}; + +struct Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory +{ + static const int FIELD_STATIC___size = 0; + + NANOCLR_NATIVE_DECLARE(ReadBytes___STATIC__VOID__U4__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(WriteBytes___STATIC__VOID__U4__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(GetSize___STATIC__I4); + + //--// + + // need to address the fact that the majority of the series have 32 bits wide registers and F1 has 16bits wide. + // the backup size is calculated with the number of available backup registers and their size (in bytes) + static const int BACKUP_SIZE = RTC_BKP_NUMBER * sizeof(RTC_BKP0R_Msk); +}; + +struct Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC +{ + NANOCLR_NATIVE_DECLARE(GetAlarm___STATIC__mscorlibSystemDateTime); + NANOCLR_NATIVE_DECLARE(Native_RTC_SetAlarm___STATIC__VOID__U1__U1__U1__U1); + + //--// + +}; + +struct Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities +{ + static const int FIELD_STATIC___deviceUniqueId = 1; + static const int FIELD_STATIC___deviceId = 2; + static const int FIELD_STATIC___deviceRevisionId = 3; + + NANOCLR_NATIVE_DECLARE(NativeGetDeviceUniqueId___STATIC__VOID__SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(NativeGetDeviceId___STATIC__U4); + NANOCLR_NATIVE_DECLARE(NativeGetDeviceRevisionId___STATIC__U4); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Hardware_Stm32; + +#endif //_NF_HARDWARE_STM32_NATIVE_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory.cpp new file mode 100644 index 00000000..d75a399d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory.cpp @@ -0,0 +1,245 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_hardware_stm32_native.h" + + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::ReadBytes___STATIC__VOID__U4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint32_t position = stack.Arg0().NumericByRef().u4; + + // dereference the data buffer from the argument + CLR_RT_HeapBlock_Array* buffer = stack.Arg1().DereferenceArray(); + // get a the pointer to the byffer by using the first element of the array + uint8_t* data = buffer->GetFirstElement(); + // get the length of the data buffer + uint32_t dataLength = buffer->m_numOfElements; + + // address of bkp register 0 + __IO uint32_t* baseAddress = &(RTC->BKP0R); + uint8_t* storeAddress = ((uint8_t*)baseAddress + position); + uint32_t* registerAddress = NULL; + uint32_t tempRegisterValue; + uint32_t counter = 0; + uint32_t remainder; + int32_t index = 3; + + // sanity check for out of range position + if(position > (BACKUP_SIZE - 1) ) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + // sanity check for over sized data buffer + if( (position + dataLength) > BACKUP_SIZE) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + // check if the store address is starting at a register address boundary + remainder = (uint32_t)((uint32_t*)storeAddress) % sizeof(RTC_BKP0R_Msk); + + if(remainder > 0) + { + // read register + registerAddress = (uint32_t*)(storeAddress - remainder); + tempRegisterValue = *registerAddress; + + // adjust remainder to the amount of bytes to move + remainder = 4 - remainder; + + do + { + *data = (uint8_t)(tempRegisterValue >> ( (remainder - 1) * 8)); + data++; + remainder--; + counter++; + } + while(remainder && (counter < dataLength)); + registerAddress++; + } + + // keep reading into the buffer if there enough bytes + if( (dataLength - counter) >= 4) + { + // load register + tempRegisterValue = *registerAddress; + + do + { + *data = (uint8_t)(tempRegisterValue >> (index-- * 8)); + data++; + counter++; + + if(index < 0) + { + index = 3; + registerAddress++; + + // is there enough data in buffer for another round + if( (dataLength - counter) < 4) + { + // no, exit loop + break; + } + + // load register + tempRegisterValue = *registerAddress; + } + } + while(1); + } + + // now read the remaining bytes, if any + if((dataLength - counter) > 0) + { + remainder = dataLength - counter; + + // read register + tempRegisterValue = *registerAddress; + + // adjust remainder to the amount of bytes to move + remainder = 4 - remainder; + + do + { + *data = (uint8_t)(tempRegisterValue >> (remainder * 8)); + remainder--; + data++; + counter++; + } + while(remainder); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::WriteBytes___STATIC__VOID__U4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // get position to write to + uint32_t position = stack.Arg0().NumericByRef().u4; + + // dereference the data buffer from the argument + CLR_RT_HeapBlock_Array* buffer = stack.Arg1().DereferenceArray(); + // get a the pointer to the byffer by using the first element of the array + uint8_t* data = buffer->GetFirstElement(); + // get the length of the data buffer + uint32_t dataLength = buffer->m_numOfElements; + + // address of bkp register 0 + __IO uint32_t* baseAddress = &(RTC->BKP0R); + uint8_t* storeAddress = ((uint8_t*)baseAddress + position); + uint32_t* registerAddress = NULL; + uint32_t tempRegisterValue; + uint32_t counter = 0; + uint32_t remainder; + int32_t index = 3; + + // sanity check for out of range position + if(position > (BACKUP_SIZE - 1) ) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + // sanity check for over sized data buffer + if( (position + dataLength) > BACKUP_SIZE) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + // write has to be done register wide, so if a write address is "in the middle" of a register, need to read it first and overwrite as required + // this can happen at the begining and/or at the end of the buffer + + // check if the store address is starting at a register address boundary + remainder = (uint32_t)((uint32_t*)storeAddress) % sizeof(RTC_BKP0R_Msk); + + if(remainder > 0) + { + // read register + registerAddress = (uint32_t*)(storeAddress - remainder); + tempRegisterValue = *registerAddress; + + // adjust remainder to the amount of bytes to move + remainder = 4 - remainder; + + // clear the bytes we'll be filling + tempRegisterValue &= (uint32_t)(0xFFFFFF00 << ( (remainder - 1) * 8)); + + do + { + tempRegisterValue |= (uint32_t)((uint32_t)*data << ( (remainder - 1) * 8)); + remainder--; + data++; + counter++; + } + while(remainder && (counter < dataLength)); + + // write back register + *registerAddress = tempRegisterValue; + registerAddress++; + } + + // keep processing the buffer if there enough bytes + if( (dataLength - counter) >= 4) + { + // clear register + *registerAddress = 0; + + do + { + *registerAddress |= (uint32_t)((uint32_t)*data << (index-- * 8)); + data++; + counter++; + + if(index < 0) + { + index = 3; + registerAddress++; + + // is there enough data in buffer for another round + if( (dataLength - counter) < 4) + { + // no, exit loop + break; + } + + // clear register + *registerAddress = 0; + } + } + while(1); + } + + // take care of the remaining bytes, if any + if((dataLength - counter) > 0) + { + remainder = dataLength - counter; + + // read register + tempRegisterValue = *registerAddress; + + // clear the bytes we'll be filling + tempRegisterValue &= (uint32_t)(0x00FFFFFF >> ( (remainder - 1) * 8)); + + // adjust remainder to the amount of bytes to move + remainder = 4 - remainder; + + do + { + tempRegisterValue |= (uint32_t)((uint32_t)*data << (remainder * 8)); + remainder--; + data++; + counter++; + } + while(remainder); + + // write back register + *registerAddress = tempRegisterValue; + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_BackupMemory::GetSize___STATIC__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + stack.SetResult_I4(BACKUP_SIZE); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp new file mode 100644 index 00000000..83854bb6 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power.cpp @@ -0,0 +1,251 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_hardware_stm32_native.h" +#include + +///////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Hardware.Stm32.Power.WakeupPin (in managed code) !!! // +///////////////////////////////////////////////////////////////////////////////////////////////// +enum WakeupPin +{ + WakeupPin_Pin1 = 1, + WakeupPin_Pin2, + WakeupPin_Pin3 +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Hardware.Stm32.Power.WakeupReason (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////////////////// +enum WakeupReason +{ + WakeupReason_Undetermined = 0, + WakeupReason_FromStandby, + WakeupReason_FromPin +}; + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::get_WakeupReason___STATIC__nanoFrameworkHardwareStm32PowerWakeupReasonType( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + stack.SetResult_U4( WakeupReasonStore ); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::DisableWakeupPin___STATIC__VOID__nanoFrameworkHardwareStm32PowerWakeupPin( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint32_t wakeUpPin; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + switch((WakeupPin)stack.Arg0().NumericByRef().u4) + { + #if defined(PWR_CSR_EWUP) + case WakeupPin_Pin1: + wakeUpPin = PWR_CSR_EWUP; + break; + #elif defined(PWR_CSR_EWUP1) + case WakeupPin_Pin1: + wakeUpPin = PWR_CSR_EWUP1; + break; + #elif defined(PWR_CSR2_EWUP1) + case WakeupPin_Pin1: + wakeUpPin = PWR_CSR2_EWUP1; + break; + #else + #error "missing include for STM32 target PAL" + #endif + + #if defined(PWR_CSR_EWUP2) + case WakeupPin_Pin2: + wakeUpPin = PWR_CSR_EWUP2; + break; + #elif defined(PWR_CSR2_EWUP2) + case WakeupPin_Pin2: + wakeUpPin = PWR_CSR2_EWUP2; + break; + #endif + + #if defined(PWR_CSR_EWUP3) + case WakeupPin_Pin3: + wakeUpPin = PWR_CSR_EWUP3; + break; + #elif defined(PWR_CSR2_EWUP3) + case WakeupPin_Pin3: + wakeUpPin = PWR_CSR2_EWUP3; + break; + #endif + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // disable the wake up pin + #if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ + defined(STM32F3XX) ||defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L1XX) + + CLEAR_BIT(PWR->CSR, wakeUpPin); + + #endif + + #if defined(STM32F7XX) || defined(STM32H7XX) || defined(STM32L4XX) + + CLEAR_BIT(PWR->CSR2, wakeUpPin); + + #endif + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::EnableWakeupPin___STATIC__VOID__nanoFrameworkHardwareStm32PowerWakeupPin( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint32_t wakeUpPin; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + switch((WakeupPin)stack.Arg0().NumericByRef().u4) + { + #if defined(PWR_CSR_EWUP) + + case WakeupPin_Pin1: + wakeUpPin = PWR_CSR_EWUP; + + // need to config the respective EXTI line (PA0) + EXTI->IMR |= EXTI_IMR_IM0; + EXTI->RTSR |= EXTI_RTSR_TR0; + + break; + + #elif defined(PWR_CSR_EWUP1) + + case WakeupPin_Pin1: + wakeUpPin = PWR_CSR_EWUP1; + // need to config the respective EXTI line (PA0) + EXTI->IMR |= EXTI_IMR_IM0; + EXTI->RTSR |= EXTI_RTSR_TR0; + break; + + #elif defined(PWR_CSR2_EWUP1) + + case WakeupPin_Pin1: + wakeUpPin = PWR_CSR2_EWUP1; + + // need to config the respective EXTI line (PA0) + EXTI->IMR |= EXTI_IMR_IM0; + EXTI->RTSR |= EXTI_RTSR_TR0; + + break; + + #else + #error "missing include for STM32 target PAL" + #endif + + #if defined(PWR_CSR_EWUP2) + + case WakeupPin_Pin2: + wakeUpPin = PWR_CSR_EWUP2; + + // need to config the respective EXTI line (PA2) + EXTI->IMR |= EXTI_IMR_IM2; + EXTI->RTSR |= EXTI_RTSR_TR2; + break; + + #elif defined(PWR_CSR2_EWUP2) + + case WakeupPin_Pin2: + wakeUpPin = PWR_CSR2_EWUP2; + + // need to config the respective EXTI line (PA2) + EXTI->IMR |= EXTI_IMR_IM2; + EXTI->RTSR |= EXTI_RTSR_TR2; + + break; + + #endif + + #if defined(PWR_CSR_EWUP3) + + case WakeupPin_Pin3: + wakeUpPin = PWR_CSR_EWUP3; + + // need to config the respective EXTI line (PC1) + EXTI->IMR |= EXTI_IMR_IM1; + EXTI->RTSR |= EXTI_RTSR_TR1; + + break; + + #elif defined(PWR_CSR2_EWUP3) + + case WakeupPin_Pin3: + wakeUpPin = PWR_CSR2_EWUP3; + + // need to config the respective EXTI line (PC1) + EXTI->IMR |= EXTI_IMR_IM1; + EXTI->RTSR |= EXTI_RTSR_TR1; + + break; + + #endif + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // according to the STM32 documentation it's highly recommended to first disable and then enable the wake-up source + + #if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ + defined(STM32F3XX) ||defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L1XX) + // clear PWR wake up Flag + PWR->CR |= PWR_CSR_WUF; + + // disable the wake up pin + CLEAR_BIT(PWR->CSR, wakeUpPin); + + // enable the wake up pin + SET_BIT(PWR->CSR, wakeUpPin); + + #endif + + #if defined(STM32F7XX) || defined(STM32H7XX) || defined(STM32L4XX) + + // enable the wake up pin + SET_BIT(PWR->CSR2, wakeUpPin); + + #endif + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Power::NativeEnterStandbyMode___STATIC__VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + (void)stack; + + // set flags to stop debug... + CLR_EE_DBG_SET( RebootPending ); + // ... reboot CLR so execution ends gracefully ... + CLR_EE_REBOOT_CLR; + // ... and set power level to OFF + g_CLR_HW_Hardware.m_powerLevel = PowerLevel__Off; + + ////////////////////////////////////////////////////////// + // developer notes: + // - the "goto sleep" is actually handled in ClrStartup() loop when calling CPU_SetPowerMode() + // - the execution engine has to exit the current thread execution to be able to check the reboot flags set above and shutdown gracefully + // - a clean approach to accomplish this is to add a Thread.Sleep(Inifinite) in the caller + ////////////////////////////////////////////////////////// + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp new file mode 100644 index 00000000..09f5f6c6 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC.cpp @@ -0,0 +1,202 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_hardware_stm32_native.h" + +// we are using always Alarm 0 (alarm A, if there are two alarms) +#define ALARM_ID 0 + + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC::Native_RTC_SetAlarm___STATIC__VOID__U1__U1__U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + #if (HAL_USE_RTC == TRUE) + + RTCAlarm alarmTime; + + uint32_t value = 0; + uint32_t alarmRegister = 0; + + #if defined(STM32F7XX) || defined(STM32F3XX) || defined(STM32F0XX) || \ + defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L4XX) || \ + defined(STM32H7XX) + + // these series are using driver RTCv2 + // the alarm is set on a register with the various values BCD coded + // to keep the configuration simple, it's assumed that + // it's only possible to set seconds, minutes, hours and date (day) + + // to set the alarm, it has to be stoped first (in case there is one already set) + rtcSetAlarm(&RTCD1, ALARM_ID, NULL); + + // alarm date (day) tens and units + value = stack.Arg0().NumericByRef().u1; + alarmRegister |= ((value % 10) << RTC_ALRMAR_DU_Pos); + value /= 10; + alarmRegister |= ((value % 10) << RTC_ALRMAR_DT_Pos); + + // alarm hours tens and units + value = stack.Arg1().NumericByRef().u1; + alarmRegister |= ((value % 10) << RTC_ALRMAR_HU_Pos); + value /= 10; + alarmRegister |= ((value % 10) << RTC_ALRMAR_HT_Pos); + + // alarm minutes tens and units + value = stack.Arg2().NumericByRef().u1; + alarmRegister |= ((value % 10) << RTC_ALRMAR_MNU_Pos); + value /= 10; + alarmRegister |= ((value % 10) << RTC_ALRMAR_MNT_Pos); + + // alarm seconds tens and units + value = stack.Arg3().NumericByRef().u1; + alarmRegister |= ((value % 10) << RTC_ALRMAR_SU_Pos); + value /= 10; + alarmRegister |= ((value % 10) << RTC_ALRMAR_ST_Pos); + + alarmTime.alrmr = alarmRegister; + + #else + #error "Setting an alarm for this series in not supported. Care to look into it and submit a PR?" + #endif + + #if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ + defined(STM32F3XX) ||defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L1XX) + // clear PWR wake up Flag + PWR->CR |= PWR_CSR_WUF; + #endif + + #if defined(STM32F7XX) || defined(STM32H7XX) || defined(STM32L4XX) + + CLEAR_BIT(RTC->CR, RTC_CR_ALRAIE); + CLEAR_BIT(RTC->ISR, RTC_ISR_ALRAF); + + #endif + + rtcSetAlarm(&RTCD1, ALARM_ID, &alarmTime); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + + (void)stack; + + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + NANOCLR_NOCLEANUP(); + + #endif // (HAL_USE_RTC == TRUE) + +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_RTC::GetAlarm___STATIC__mscorlibSystemDateTime( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + #if (HAL_USE_RTC == TRUE) + + RTCAlarm alarmValue; + RTCDateTime currentTime; + SYSTEMTIME alarmTime; + uint32_t value; + + rtcGetAlarm(&RTCD1, ALARM_ID, &alarmValue); + + #if defined(STM32F7XX) || defined(STM32F3XX) || defined(STM32F0XX) || \ + defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L4XX) || \ + defined(STM32H7XX) + + // these series are using driver RTCv2 + // the alarm is set on a register with the various values BCD coded + // to keep the configuration simple, it's assumed that + // it's only possible to set seconds, minutes, hours and date (day) + + // convert from BCD assuming the alarm is always set for a future date/time + + // get current time from RTC + rtcGetTime(&RTCD1, ¤tTime); + + // fill in alarmTime struct + alarmTime.wYear = (unsigned short) (currentTime.year + 1980); // ChibiOS is counting years since 1980 + alarmTime.wMonth = (unsigned short) currentTime.month; + + // date (day) tens and units + value = alarmValue.alrmr & RTC_ALRMAR_DT_Msk; + value = value >> RTC_ALRMAR_DT_Pos; + alarmTime.wDay = value * 10; + + value = alarmValue.alrmr & RTC_ALRMAR_DU_Msk; + value = value >> RTC_ALRMAR_DU_Pos; + alarmTime.wDay += value; + + // alarm hours tens and units + value = alarmValue.alrmr & RTC_ALRMAR_HT_Msk; + value = value >> RTC_ALRMAR_HT_Pos; + alarmTime.wHour = value * 10; + + value = alarmValue.alrmr & RTC_ALRMAR_HU_Msk; + value = value >> RTC_ALRMAR_HU_Pos; + alarmTime.wHour += value; + + // alarm minutes tens and units + value = alarmValue.alrmr & RTC_ALRMAR_MNT_Msk; + value = value >> RTC_ALRMAR_MNT_Pos; + alarmTime.wMinute = value * 10; + + value = alarmValue.alrmr & RTC_ALRMAR_MNU_Msk; + value = value >> RTC_ALRMAR_MNU_Pos; + alarmTime.wMinute += value; + + // alarm seconds tens and units + value = alarmValue.alrmr & RTC_ALRMAR_ST_Msk; + value = value >> RTC_ALRMAR_ST_Pos; + alarmTime.wSecond = value * 10; + + value = alarmValue.alrmr & RTC_ALRMAR_SU_Msk; + value = value >> RTC_ALRMAR_SU_Pos; + alarmTime.wSecond += value; + + // clear unused fields + alarmTime.wMilliseconds = 0; + alarmTime.wDayOfWeek = 0; + + // if alarm day is lower than the current day, means that the alarm was set for a date on the next month + if(alarmTime.wDay < currentTime.day) + { + alarmTime.wMonth++; + + // check for December + 1 + if(alarmTime.wMonth > 12) + { + // adjust to January + alarmTime.wMonth = 1; + } + } + + #else + #error "Setting an alarm for this series in not supported. Care to look into it and submit a PR?" + #endif + + CLR_RT_HeapBlock& ref = stack.PushValue(); + + ref.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_DATETIME, 0, 1) ); + ref.ClearData(); + + CLR_INT64* pRes = (CLR_INT64*)&ref.NumericByRef().s8; + *pRes = HAL_Time_ConvertFromSystemTime( &alarmTime ); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + + (void)stack; + + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + NANOCLR_NOCLEANUP(); + + #endif // (HAL_USE_RTC == TRUE) + +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities.cpp new file mode 100644 index 00000000..4d2d2525 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Hardware.Stm32/nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities.cpp @@ -0,0 +1,49 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_hardware_stm32_native.h" + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities::NativeGetDeviceUniqueId___STATIC__VOID__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // dereference the data buffer from the argument + CLR_RT_HeapBlock_Array* buffer = stack.Arg0().DereferenceArray(); + + // get a the pointer to the byffer by using the first element of the array + uint8_t* data = buffer->GetFirstElement(); + + // 96 bit unique device ID => 12 bytes + // memory copy from the address pointed by UID_BASE define (from STM32 HAL) + memcpy(data, ((uint8_t *)UID_BASE), 12); + + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities::NativeGetDeviceId___STATIC__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // this ID is provided by debug MCU register + uint32_t deviceId = READ_BIT(DBGMCU->IDCODE, DBGMCU_IDCODE_DEV_ID); + + stack.SetResult_U4(deviceId); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nf_hardware_stm32_native_nanoFramework_Hardware_Stm32_Utilities::NativeGetDeviceRevisionId___STATIC__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // this ID is provided by debug MCU register + // need to right shift 16 bits because it shows as 0xFFFF0000 + uint32_t deviceRevisionId = (READ_BIT(DBGMCU->IDCODE, DBGMCU_IDCODE_REV_ID) >> DBGMCU_IDCODE_REV_ID_Pos); + + stack.SetResult_U4(deviceRevisionId); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp new file mode 100644 index 00000000..735f3323 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp @@ -0,0 +1,56 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include "nf_rt_native.h" + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// these functions are the real implementation of the 'weak' ones declared at src\CLR\Runtime.Native\nf_rt_native_nanoFramework_Runtime_Native_Rtc_stubs.cpp // +// the stubs for this class are generated by nanoFramework.Runtime.Native // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// for all these to work we need the RTC to be enabled +#if !defined(HAL_USE_RTC) + #error "Need the RTC to be enabled. Please set CMake option NF_FEATURE_RTC to ON." +#endif + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_Rtc::Native_RTC_SetSystemTime___STATIC__BOOLEAN__I4__U1__U1__U1__U1__U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + #if (HAL_USE_RTC == TRUE) + + RTCDateTime newTime; + + newTime.year = stack.Arg0().NumericByRef().s4 - 1980; // ChibiOS time base is 1980-01-01 + newTime.month = (uint8_t)stack.Arg1().NumericByRef().u1; + newTime.day = stack.Arg2().NumericByRef().u1; + newTime.dayofweek = stack.Arg3().NumericByRef().u1; + newTime.millisecond = ((((uint32_t)stack.Arg4().NumericByRef().u1 * 3600) + + ((uint32_t)stack.Arg5().NumericByRef().u1 * 60) + + (uint32_t)stack.Arg6().NumericByRef().u1) * 1000); + + // set RTC time + rtcSetTime(&RTCD1, &newTime); + + // Return value to the managed application + stack.SetResult_Boolean(true); + + NANOCLR_NOCLEANUP_NOLABEL(); + + #else + + (void)stack; + + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + NANOCLR_NOCLEANUP(); + + #endif // (HAL_USE_RTC == TRUE) + +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp new file mode 100644 index 00000000..0e0abb90 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL.cpp @@ -0,0 +1,212 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +// global mutex protecting the internal state of the interpreter, including event flags +//mutex_t interpreterGlobalMutex; + +// because nanoHAL_Initialize/Uninitialize needs to be called in both C and C++ we need a proxy to allow it to be called in 'C' +extern "C" { + + void nanoHAL_Initialize_C() + { + nanoHAL_Initialize(); + } + + void nanoHAL_Uninitialize_C() + { + nanoHAL_Uninitialize(); + } +} + +void nanoHAL_Initialize() +{ + // initialize global mutex + //chMtxObjectInit(&interpreterGlobalMutex); + + HAL_CONTINUATION::InitializeList(); + HAL_COMPLETION ::InitializeList(); + + BlockStorageList_Initialize(); + + // initialize block storage devices + BlockStorage_AddDevices(); + + BlockStorageList_InitializeDevices(); + + // clear managed heap region + unsigned char* heapStart = NULL; + unsigned int heapSize = 0; + + ::HeapLocation( heapStart, heapSize ); + memset(heapStart, 0, heapSize); + + ConfigurationManager_Initialize(); + + Events_Initialize(); + + // no PAL events required until now + //PalEvent_Initialize(); + + // Initialise Network Stack + Network_Initialize(); +} + +void nanoHAL_Uninitialize() +{ + // release the global mutex, just in case it's locked somewhere + //chMtxUnlock(&interpreterGlobalMutex); + + // TODO check for s_rebootHandlers + // for(int i = 0; i< ARRAYSIZE(s_rebootHandlers); i++) + // { + // if(s_rebootHandlers[i] != NULL) + // { + // s_rebootHandlers[i](); + // } + // else + // { + // break; + // } + // } + + SOCKETS_CloseConnections(); + + #if !defined(HAL_REDUCESIZE) + // TODO need to call this but it's preventing the debug session from starting + //Network_Uninitialize(); + #endif + + BlockStorageList_UnInitializeDevices(); + + // need to be sure that all mutexes for drivers that use them are released +#if (HAL_USE_SPI == TRUE) + + #if STM32_SPI_USE_SPI1 + spiReleaseBus(&SPID1); + #endif + #if STM32_SPI_USE_SPI2 + spiReleaseBus(&SPID2); + #endif + #if STM32_SPI_USE_SPI3 + spiReleaseBus(&SPID3); + #endif + #if STM32_SPI_USE_SPI4 + spiReleaseBus(&SPID4); + #endif + #if STM32_SPI_USE_SPI5 + spiReleaseBus(&SPID5); + #endif + #if STM32_SPI_USE_SPI6 + spiReleaseBus(&SPID6); + #endif + +#endif + +#if (HAL_USE_I2C == TRUE) + + #if STM32_I2C_USE_I2C1 + i2cReleaseBus(&I2CD1); + #endif + #if STM32_I2C_USE_I2C2 + i2cReleaseBus(&I2CD2); + #endif + #if STM32_I2C_USE_I2C3 + i2cReleaseBus(&I2CD3); + #endif + #if STM32_I2C_USE_I2C4 + i2cReleaseBus(&I2CD4); + #endif + +#endif + +#if (HAL_USE_UART == TRUE) + + #if NF_SERIAL_COMM_STM32_UART_USE_USART1 + uartReleaseBus(&UARTD1); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART2 + uartReleaseBus(&UARTD2); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART3 + uartReleaseBus(&UARTD3); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART4 + uartReleaseBus(&UARTD4); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART5 + uartReleaseBus(&UARTD5); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_USART6 + uartReleaseBus(&UARTD6); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART7 + uartReleaseBus(&UARTD7); + #endif + #if NF_SERIAL_COMM_STM32_UART_USE_UART8 + uartReleaseBus(&UARTD8); + #endif + +#endif + + Events_Uninitialize(); + + HAL_CONTINUATION::Uninitialize(); + HAL_COMPLETION ::Uninitialize(); +} + +volatile int32_t SystemStates[SYSTEM_STATE_TOTAL_STATES]; + +void SystemState_SetNoLock(SYSTEM_STATE_type state) +{ + SystemStates[state]++; +} + +void SystemState_ClearNoLock(SYSTEM_STATE_type state) +{ + SystemStates[state]--; +} + +bool SystemState_QueryNoLock(SYSTEM_STATE_type state) +{ + return (SystemStates[state] > 0) ? true : false; +} + +void SystemState_Set(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + SystemState_SetNoLock(state); + + GLOBAL_UNLOCK(); +} + +void SystemState_Clear(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + SystemState_ClearNoLock(state ); + + GLOBAL_UNLOCK(); +} + +bool SystemState_Query(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + bool systemStateCopy = SystemState_QueryNoLock(state); + + GLOBAL_UNLOCK(); + + return systemStateCopy; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c new file mode 100644 index 00000000..766376de --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Power.c @@ -0,0 +1,166 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include + +#if (HAL_USE_FSMC == TRUE) +#include +#include +#endif + +uint32_t WakeupReasonStore; + +inline void CPU_Reset() +{ + NVIC_SystemReset(); +}; + +inline bool CPU_IsSoftRebootSupported() +{ + return true; +}; + +// CPU sleep is not currently implemented in this target +inline void CPU_Sleep(SLEEP_LEVEL_type level, uint64_t wakeEvents) +{ + (void)level; + (void)wakeEvents; + +}; + +void CPU_SetPowerMode(PowerLevel_type powerLevel) +{ + // default to false + bool success = false; + + switch(powerLevel) + { + case PowerLevel__Off: + // stop watchdog + wdgStop(&WDGD1); + + #if (HAL_USE_FSMC == TRUE) + // shutdown memory + #if (STM32_USE_FSMC_SDRAM == TRUE) + fsmcSdramStop(&SDRAMD); + #endif + #if (STM32_USE_FSMC_SRAM == TRUE) + #if (STM32_SRAM_USE_FSMC_SRAM1 == TRUE) + fsmcSramStop(&SRAMD1); + #endif + #if (STM32_SRAM_USE_FSMC_SRAM2 == TRUE) + fsmcSramStop(&SRAMD2); + #endif + #if (STM32_SRAM_USE_FSMC_SRAM3 == TRUE) + fsmcSramStop(&SRAMD3); + #endif + #if (STM32_SRAM_USE_FSMC_SRAM4 == TRUE) + fsmcSramStop(&SRAMD4); + #endif + #endif + #endif + + // gracefully shutdown everything + nanoHAL_Uninitialize_C(); + + chSysDisable(); + + ///////////////////////////////////////////////////////////////////////// + // stop the idependent watchdog, for series where the option is available + #if defined(STM32L4XX) + + (void)success; + // TODO FIXME this code needs to follow the same workflow as the STM32F7 + CLEAR_BIT(FLASH->OPTR, FLASH_OPTR_IWDG_STDBY); + + #elif defined(STM32F7XX) + + // only need to change this option bit if not already done + if((FLASH->OPTCR & FLASH_OPTCR_IWDG_STDBY)) + { + // developer notes: + // follow workflow recommended @ 3.4.2 Option bytes programming (from programming manual) + // Authorizes the Option Byte register programming + FLASH->OPTKEYR = FLASH_OPT_KEY1; + FLASH->OPTKEYR = FLASH_OPT_KEY2; + + // wait 500ms for any flash operation to be completed + success = FLASH_WaitForLastOperation(500); + + if(success) + { + // write option value (clear the FLASH_OPTCR_IWDG_STDBY) + CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_IWDG_STDBY); + + // set the option start bit + FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT; + + // Data synchronous Barrier, forcing the CPU to respect the sequence of instruction without optimization + __DSB(); + + // wait 100ms for the flash operation to be completed + success = FLASH_WaitForLastOperation(100); + } + + // Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access + FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; + } + (void)success; + + #elif defined(STM32H7XX) + + (void)success; + // TODO FIXME this code needs to follow the same workflow as the STM32F7 + CLEAR_BIT(FLASH->OPTSR, FLASH_OPTSR_FZ_IWDG_SDBY); + + #else + (void)success; + #endif + + /////////////////////////////////////////////////////// + // set alarm interrupt enable + // set power control register to: power down deep sleep + /////////////////////////////////////////////////////// + + #if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F2XX) || \ + defined(STM32F3XX) ||defined(STM32F4XX) || defined(STM32L0XX) || defined(STM32L1XX) + SET_BIT(RTC->CR, RTC_CR_ALRAIE); + SET_BIT(PWR->CR, PWR_CR_PDDS); + #endif + + #if defined(STM32F7XX) + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // workaround recommended in section 2.2.2 at STM32F77xxx errata document (DM00257543 - ES0334 Rev 5) // + PWR->CSR1 |= PWR_CSR1_EIWUP; + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + SET_BIT(PWR->CR1, PWR_CR1_PDDS); + + #endif + + #if defined(STM32H7XX) + SET_BIT(PWR->CR1, PWR_CR1_PDDS); + #endif + + // set SLEEPDEEP bit of Cortex SCR + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + // wait for interrupt, and the execution dies here + __WFI(); + + break; + + default: + // all the other power modes are unsupported here + break; + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Time.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Time.cpp new file mode 100644 index 00000000..de1fa4a9 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Time.cpp @@ -0,0 +1,172 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include + +// Returns the current date time from the system tick or from the RTC if it's available (this depends on the respective configuration option) +uint64_t HAL_Time_CurrentDateTime(bool datePartOnly) +{ + #if (HAL_USE_RTC == TRUE) + + // use RTC to get date time + SYSTEMTIME st; + RTCDateTime _dateTime; + + rtcGetTime(&RTCD1, &_dateTime); + + st.wDay = (unsigned short) _dateTime.day; + st.wMonth = (unsigned short) _dateTime.month; + st.wYear = (unsigned short) (_dateTime.year + 1980); // ChibiOS is counting years since 1980 + st.wDayOfWeek = (unsigned short) _dateTime.dayofweek; + + // zero 'time' fields if date part only is required + if(datePartOnly) + { + st.wMilliseconds = 0; + st.wSecond = 0; + st.wMinute = 0; + st.wHour = 0; + } + else + { + // full date&time required, fill in 'time' fields too + + st.wMilliseconds =(unsigned short) (_dateTime.millisecond % 1000); + _dateTime.millisecond /= 1000; + st.wSecond = (unsigned short) (_dateTime.millisecond % 60); + _dateTime.millisecond /= 60; + st.wMinute = (unsigned short) (_dateTime.millisecond % 60); + _dateTime.millisecond /= 60; + st.wHour = (unsigned short) (_dateTime.millisecond % 24); + } + + return HAL_Time_ConvertFromSystemTime( &st ); + + #else + + if (datePartOnly) + { + SYSTEMTIME st; + HAL_Time_ToSystemTime(HAL_Time_CurrentTime(), &st); + + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + return HAL_Time_ConvertFromSystemTime(&st); + } + else + { + return HAL_Time_CurrentTime(); + } + + #endif +}; + +void HAL_Time_SetUtcTime(uint64_t utcTime) +{ + SYSTEMTIME systemTime; + + HAL_Time_ToSystemTime(utcTime, &systemTime); + + #if (HAL_USE_RTC == TRUE) + + // set RTC + RTCDateTime newTime; + + newTime.year = systemTime.wYear - 1980; // ChibiOS time base is 1980-01-01 + newTime.month = systemTime.wMonth; + newTime.day = systemTime.wDay; + newTime.dayofweek = systemTime.wDayOfWeek; + newTime.millisecond = ((((uint32_t)systemTime.wHour * 3600) + + ((uint32_t)systemTime.wMinute * 60) + + (uint32_t)systemTime.wSecond) * 1000); + + // set RTC time + rtcSetTime(&RTCD1, &newTime); + + #else + + // TODO FIXME + // need to add implementation when RTC is not being used + // can't mess with the systicks because the scheduling can fail + + #endif +} + +bool HAL_Time_TimeSpanToStringEx( const int64_t& ticks, char*& buf, size_t& len ) +{ + uint64_t ticksAbs; + uint64_t rest; + + if(ticks < 0) + { + ticksAbs = -ticks; + + CLR_SafeSprintf( buf, len, "-" ); + } + else + { + ticksAbs = ticks; + } + + rest = ticksAbs % ( 1000 * TIME_CONVERSION__TICKUNITS); + ticksAbs = ticksAbs / ( 1000 * TIME_CONVERSION__TICKUNITS); // Convert to seconds. + + if(ticksAbs > TIME_CONVERSION__ONEDAY) // More than one day. + { + CLR_SafeSprintf( buf, len, "%d.", (int32_t)(ticksAbs / TIME_CONVERSION__ONEDAY) ); ticksAbs %= TIME_CONVERSION__ONEDAY; + } + + CLR_SafeSprintf( buf, len, "%02d:", (int32_t)(ticksAbs / TIME_CONVERSION__ONEHOUR) ); ticksAbs %= TIME_CONVERSION__ONEHOUR ; + CLR_SafeSprintf( buf, len, "%02d:", (int32_t)(ticksAbs / TIME_CONVERSION__ONEMINUTE)); ticksAbs %= TIME_CONVERSION__ONEMINUTE; + CLR_SafeSprintf( buf, len, "%02d" , (int32_t)(ticksAbs / TIME_CONVERSION__ONESECOND)); ticksAbs %= TIME_CONVERSION__ONESECOND; + + ticksAbs = (uint32_t)rest; + if(ticksAbs) + { + CLR_SafeSprintf( buf, len, ".%07d", (uint32_t)ticksAbs ); + } + + return len != 0; +} + +bool DateTimeToString(const uint64_t& time, char*& buf, size_t& len ) +{ + SYSTEMTIME st; + + HAL_Time_ToSystemTime( time, &st ); + + return CLR_SafeSprintf(buf, len, "%4d/%02d/%02d %02d:%02d:%02d.%03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ); +} + +char* DateTimeToString(const uint64_t& time) +{ + static char rgBuffer[128]; + char* szBuffer = rgBuffer; + size_t iBuffer = ARRAYSIZE(rgBuffer); + + DateTimeToString( time, szBuffer, iBuffer ); + + return rgBuffer; +} + +const char* HAL_Time_CurrentDateTimeToString() +{ + return DateTimeToString(HAL_Time_CurrentDateTime(false)); +} + +uint64_t CPU_MillisecondsToTicks(uint64_t ticks) +{ + // this is a rewrite of ChibiOS TIME_MS2I(n) macro because it will overflow if doing the math using uint32_t + return (((ticks * (uint64_t)CH_CFG_ST_FREQUENCY) + 999) / (uint64_t)1000); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Watchdog.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Watchdog.c new file mode 100644 index 00000000..ae40f26d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetHAL_Watchdog.c @@ -0,0 +1,86 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +// LSI clock value (series dependent) +#if defined(STM32L0xx_MCUCONF) +#define LSI_CLK_TYPICAL 38000 +#elif defined(STM32F0xx_MCUCONF) +#define LSI_CLK_TYPICAL 40000 +#elif defined(STM32F4xx_MCUCONF) || defined(STM32F7xx_MCUCONF) || defined(STM32H7xx_MCUCONF) +#define LSI_CLK_TYPICAL 32000 +#else +#error "The LSI value for this STM32 series hasn't been defined." +#endif + + +//Watchdog configuration structure required by ChibiOS +#if (STM32_IWDG_IS_WINDOWED == TRUE) + static WDGConfig wdgConfig = {STM32_IWDG_PR_256, STM32_IWDG_RL(0xFFF), 0x0FFF}; //default is max +#else + static WDGConfig wdgConfig = {STM32_IWDG_PR_256, STM32_IWDG_RL(0xFFF)}; //default is max +#endif + +/** +* Method to initialize the watchdog. In ChibiOS, the watchdog sub-system is +* initialized when halInit() is called. In this method, we perform +* further specific initializations and also start the watchdog +*/ +void Watchdog_Init() +{ + //setup required watchdog timeout...(for IWATCHDOG_TIMEOUT_MILLIS) + /* + There are minor variations in STM32 LSI clock across models (e.g STM32F091 has 40KHz LSI + and STM32F401 has 32 KHz). Also, across the same model, due to manufacturing differences + the LSI clock has a minimum and maximum range. Therefore, the timeout is always an approximation + and not exact + */ + uint32_t ticksForTimeout=0; + + uint16_t prescaler[] = {STM32_IWDG_PR_4,STM32_IWDG_PR_8,STM32_IWDG_PR_16, + STM32_IWDG_PR_32,STM32_IWDG_PR_64,STM32_IWDG_PR_128, + STM32_IWDG_PR_256}; + + uint8_t length = (sizeof(prescaler)/sizeof(prescaler[0])); + + uint16_t divisor= 4; + + for(uint8_t index=0; index < length;index++) + { + divisor = 4 << prescaler[index]; + ticksForTimeout = (LSI_CLK_TYPICAL / divisor) * (IWATCHDOG_TIMEOUT_MILLIS/1000) - 1; + + if(ticksForTimeout <= 0xFFF) + { + // the max reload register value + + wdgConfig.pr = prescaler[index]; + wdgConfig.rlr = ticksForTimeout; + break; + } + } + + wdgStart(&WDGD1,&wdgConfig); + + #if !defined(BUILD_RTM) + // these are required to stop the watchdog peripheral when stopping the core + // useful for debugging without the watchdog triggering + DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP; + DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_WWDG_STOP; + #endif +} + +/** + * Reset the watchdog. If not done within the timout period, + * the watchdog will trigger and MCU will reset + */ +void Watchdog_Reset() +{ + wdgReset(&WDGD1); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL.c new file mode 100644 index 00000000..8c63f2e7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL.c @@ -0,0 +1,40 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +#if defined(STM32L0XX) || defined(STM32F0XX) || defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32H7XX) + +stm32_gpio_t* gpioPort[] = { GPIOA, GPIOB +#if STM32_HAS_GPIOC +, GPIOC +#endif +#if STM32_HAS_GPIOD +, GPIOD +#endif +#if STM32_HAS_GPIOE +, GPIOE +#endif +#if STM32_HAS_GPIOF +, GPIOF +#endif +#if STM32_HAS_GPIOG +, GPIOG +#endif +#if STM32_HAS_GPIOH +, GPIOH +#endif +#if STM32_HAS_GPIOI +, GPIOI +#endif +#if STM32_HAS_GPIOJ +, GPIOJ +#endif +#if STM32_HAS_GPIOK +, GPIOK +#endif +}; + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Events.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Events.cpp new file mode 100644 index 00000000..da69a771 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Events.cpp @@ -0,0 +1,170 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +uint64_t CPU_MillisecondsToTicks(uint64_t ticks); + +// timer for bool events +static virtual_timer_t boolEventsTimer; +uint32_t systemEvents; + +set_Event_Callback g_Event_Callback = NULL; +void* g_Event_Callback_Arg = NULL; + +bool Events_Initialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // init events + GLOBAL_LOCK(); + systemEvents = 0; + GLOBAL_UNLOCK(); + + return true; +} + +bool Events_Uninitialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + chVTResetI(&boolEventsTimer); + + return true; +} + +void Events_Set( uint32_t events ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // set events + GLOBAL_LOCK(); + systemEvents |= events; + GLOBAL_UNLOCK(); + + if( g_Event_Callback != NULL ) + { + g_Event_Callback( g_Event_Callback_Arg ); + } +} + +uint32_t Events_Get( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // get the requested flags from system events state and... + uint32_t returnEvents = (systemEvents & eventsOfInterest); + + // ... clear the requested flags atomically + GLOBAL_LOCK(); + systemEvents &= ~eventsOfInterest; + GLOBAL_UNLOCK(); + + // give the caller notice of just the events they asked for ( and were cleared already ) + return returnEvents; +} + +uint32_t Events_MaskedRead( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + return (systemEvents & eventsOfInterest); +} + +static void local_Events_SetBoolTimer_Callback( void* arg ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + bool* timerCompleteFlag = (bool*)arg; + + *timerCompleteFlag = true; +} + +void Events_SetCallback( set_Event_Callback pfn, void* arg ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + g_Event_Callback = pfn; + g_Event_Callback_Arg = arg; +} + +void Events_SetBoolTimer( bool* timerCompleteFlag, uint32_t millisecondsFromNow ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + if(timerCompleteFlag != NULL) + { + // no need to stop the timer even if it's running because the API does it anyway + chVTSetI(&boolEventsTimer, TIME_MS2I(millisecondsFromNow), local_Events_SetBoolTimer_Callback, timerCompleteFlag); + } +} + +uint32_t Events_WaitForEvents( uint32_t powerLevel, uint32_t wakeupSystemEvents, uint32_t timeoutMilliseconds ) +{ + // schedule an interrupt for this far in the future + // timeout is in milliseconds, need to convert to ticks + uint64_t countsRemaining = CPU_MillisecondsToTicks( timeoutMilliseconds ); + +#if defined(HAL_PROFILE_ENABLED) + Events_WaitForEvents_Calls++; +#endif + + uint64_t expireTimeInTicks = HAL_Time_CurrentTime() + countsRemaining; + bool runContinuations = true; + + while(true) + { + EVENTS_HEART_BEAT; + + uint32_t events = Events_MaskedRead( wakeupSystemEvents ); + if(events) + { + return events; + } + + if(expireTimeInTicks <= HAL_Time_CurrentTime()) + { + break; + } + + // first check and possibly run any continuations + // but only if we have slept after stalling + if(runContinuations && !SystemState_QueryNoLock(SYSTEM_STATE_NO_CONTINUATIONS)) + { + // if we stall on time, don't check again until after we sleep + runContinuations = HAL_CONTINUATION::Dequeue_And_Execute(); + } + else + { + // try stalled continuations again after sleeping + runContinuations = true; + + HAL_COMPLETION::WaitForInterrupts(expireTimeInTicks, powerLevel, wakeupSystemEvents ); + } + + // no events, pass control to the OS + osThreadYield(); + + // check if reboot or exit flags were set when the other OS threads executed + if(CLR_EE_DBG_IS(RebootPending) || CLR_EE_DBG_IS(ExitPending)) + { + break; + } + } + + return 0; +} + +void FreeManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2) +{ + (void)category; + (void)subCategory; + (void)data1; + (void)data2; + + NATIVE_PROFILE_PAL_EVENTS(); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Time.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Time.cpp new file mode 100644 index 00000000..1009fc55 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetPAL_Time.cpp @@ -0,0 +1,71 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + + +// timer for next event +static virtual_timer_t nextEventTimer; +void* nextEventCallbackDummyArg = NULL; + +static void NextEventTimer_Callback( void* arg ) +{ + (void)arg; + + // this call also schedules the next one, if there is one + HAL_COMPLETION::DequeueAndExec(); +} + +HRESULT Time_Initialize() +{ + // need to setup the timer at boot, but stoped + chVTSet(&nextEventTimer, TIME_INFINITE, NextEventTimer_Callback, nextEventCallbackDummyArg); + + return S_OK; +} + +HRESULT Time_Uninitialize() +{ + chVTReset(&nextEventTimer); + + // nothing to do here has time management is handled by ChibiOS + return S_OK; +} + +void Time_SetCompare ( uint64_t compareValueTicks ) +{ + if(compareValueTicks == 0) + { + // compare value is 0 so dequeue and schedule immediately + // can't call chVTSet with 'immidiate delay value', so use value 1 to get it executed ASAP + chVTSet(&nextEventTimer, 1, NextEventTimer_Callback, nextEventCallbackDummyArg); + } + else if(compareValueTicks == HAL_COMPLETION_IDLE_VALUE) + { + // wait for infinity, don't need to do anything here + } + else + { + if (HAL_Time_CurrentTime() >= compareValueTicks) + { + // already missed the event, dequeue and execute immediately + // can't call chVTSet with 'immidiate delay value', so use value 1 to get it executed ASAP + chVTSet(&nextEventTimer, 1, NextEventTimer_Callback, nextEventCallbackDummyArg); + } + else + { + // compareValueTicks is the time (in sys ticks) that is being requested to fire an HAL_COMPLETION::DequeueAndExec() + // need to subtract the current system time to set when the timer will fire + compareValueTicks -= HAL_Time_CurrentTime(); + + // no need to stop the timer if it's running because the API does it anyway + // need to convert from nF ticks to milliseconds and then to ChibiOS sys ticks to load the timer + chVTSet(&nextEventTimer, TIME_MS2I(compareValueTicks/ TIME_CONVERSION__TO_MILLISECONDS), NextEventTimer_Callback, nextEventCallbackDummyArg); + } + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetRandom.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetRandom.cpp new file mode 100644 index 00000000..1b5aa12f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/targetRandom.cpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#include "Core.h" +#include +#include + +void CLR_RT_Random::Initialize() +{ + rngStart(); +} + +void CLR_RT_Random::Initialize( int seed ) +{ + (void)seed; + + rngStart(); +} + +uint32_t CLR_RT_Random::Next() +{ + return rngGenerateRandomNumber(); +} + +double CLR_RT_Random::NextDouble() +{ + // the hardware generator returns a value between 0 - 0xFFFFFFFF + return ((double)rngGenerateRandomNumber()) / ((double)0xFFFFFFFF); +} + +void CLR_RT_Random::NextBytes(unsigned char* buffer, unsigned int count) +{ + unsigned int i; + + for(i = 0; i < count; i++) + { + buffer[i] = (unsigned char)rngGenerateRandomNumber(); + } +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/target_platform.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/target_platform.h.in new file mode 100644 index 00000000..08b5aa2e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nanoCLR/target_platform.h.in @@ -0,0 +1,58 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_CHIBIOS_NANOCLR_H_ +#define _TARGET_CHIBIOS_NANOCLR_H_ + +// enable SPIFFS +#define NF_FEATURE_USE_SPIFFS @NF_FEATURE_USE_SPIFFS_OPTION@ + +// set preference to enable (or not) the RTC subsystem +#define HAL_USE_RTC @HAL_USE_RTC_OPTION@ + +// takes care of enabling the HAL subsystems required for API options + +// enable SPI +#define HAL_USE_SPI @HAL_USE_SPI_OPTION@ + +// enable I2C +#define HAL_USE_I2C @HAL_USE_I2C_OPTION@ + +// enable PWM +#define HAL_USE_PWM @HAL_USE_PWM_OPTION@ + +// enable ADC +#define HAL_USE_ADC @HAL_USE_ADC_OPTION@ + +// enable DAC +#define HAL_USE_DAC @HAL_USE_DAC_OPTION@ + +// enable UART subsystem +#define HAL_USE_UART @HAL_USE_UART_OPTION@ + +// set when networking is enabled +#define HAL_USE_MAC @HAL_USE_MAC_OPTION@ + +// set when filesystem is enabled +#define HAL_USE_SDC @HAL_USE_SDC_OPTION@ + +// set when watchod is enabled +#define HAL_USE_WDG @HAL_USE_WDG_OPTION@ + +// enable CAN +#define HAL_USE_CAN @HAL_USE_CAN_OPTION@ + +// enable STM32 ONEWIRE (from nf overlay) +#define HAL_USE_STM32_ONEWIRE @HAL_USE_STM32_ONEWIRE_OPTION@ + +// enable USB MSD (from ChibiOS Contrib) + #define HAL_USBH_USE_MSD @HAL_USBH_USE_MSDC_OPTION@ + +#endif /* _TARGET_CHIBIOS_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/README.md new file mode 100644 index 00000000..460e0849 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/README.md @@ -0,0 +1,23 @@ +# **nanoFramework** overlay for ChibiOS + +This folder contains code that _extends_ ChibiOS features/functionalities for the purpose of **nanoFramework**. +ChibiOS core code is architecture to include seamless integration of third party code (HAL drivers, boards, etc). That is explained [here](http://wiki.chibios.org/dokuwiki/doku.php?id=chibios:community:guides:community_overlay). +The structure below this folder mimics the structure and organization of ChibiOS Community overlay. +Note that this is designed in a way that in order to use a specific driver, the only thing that a developer has to do is enable the corresponding define in the HAL configuration file at the target folder e.g. HAL_USE_STM32_FLASH in order to enable the flash driver. + + +## Adding components to **nanoFramework** overlay + +When adding HAL components, drivers, boards or any other code to the **nanoFramework** overlay make sure you follow the following guide. + +- Add the required source code to the appropriate folder below this one. Follow the existing structure and make sure it follows the one established by ChibiOS. It makes it easier to maintain and for newcomers to better understand it. In particular try to follow (if it makes sense) the design approach of providing a 'main' driver and a low level driver. +- Add a compiler define following the pattern HAL_USE_NNNN for the component and add any required includes in [hal_community.h](os/hal/include/hal_community.h). +- If it requires an initialization function add a call to it wrapped in the appropriate compiler define in [hal_community.c](os/hal/src/hal_community.c). +- Add an entry for each source file (both main and low level driver) and include directories to the CMake module [FindChibiOSnfOverlay.cmake](../../../../CMake/Modules/FindChibiOSnfOverlay.cmake). + + +## **nanoFramework** overlay components + +Follows a list of available components in **nanoFramework** overlay. + +- [Driver for internal flash of STM32 parts](stm32-internal-flash-driver.md) (supports F0, F4 and F7 series) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/asmdefs.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/asmdefs.h new file mode 100644 index 00000000..c2a6f973 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/asmdefs.h @@ -0,0 +1,229 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +//***************************************************************************** +// +// asmdefs.h - Macros to allow assembly code be portable among toolchains. +// +//***************************************************************************** + +#ifndef __ASMDEFS_H__ +#define __ASMDEFS_H__ + +//***************************************************************************** +// +// The defines required for code_red. +// +//***************************************************************************** +#ifdef codered + +// +// The assembly code preamble required to put the assembler into the correct +// configuration. +// + .syntax unified + .thumb + +// +// Section headers. +// +#define __LIBRARY__ @ +#define __TEXT__ .text +#define __DATA__ .data +#define __BSS__ .bss +#define __TEXT_NOROOT__ .text + +// +// Assembler nmenonics. +// +#define __ALIGN__ .balign 4 +#define __END__ .end +#define __EXPORT__ .globl +#define __IMPORT__ .extern +#define __LABEL__ : +#define __STR__ .ascii +#define __THUMB_LABEL__ .thumb_func +#define __WORD__ .word +#define __INLINE_DATA__ + +#endif // codered + +//***************************************************************************** +// +// The defines required for EW-ARM. +// +//***************************************************************************** +#ifdef ewarm + +// +// Section headers. +// +#define __LIBRARY__ module +#define __TEXT__ rseg CODE:CODE(2) +#define __DATA__ rseg DATA:DATA(2) +#define __BSS__ rseg DATA:DATA(2) +#define __TEXT_NOROOT__ rseg CODE:CODE:NOROOT(2) + +// +// Assembler nmenonics. +// +#define __ALIGN__ alignrom 2 +#define __END__ end +#define __EXPORT__ export +#define __IMPORT__ import +#define __LABEL__ +#define __STR__ dcb +#define __THUMB_LABEL__ thumb +#define __WORD__ dcd +#define __INLINE_DATA__ data + +#endif // ewarm + +//***************************************************************************** +// +// The defines required for GCC. +// +//***************************************************************************** +#if defined(gcc) + +// +// The assembly code preamble required to put the assembler into the correct +// configuration. +// + .syntax unified + .thumb + +// +// Section headers. +// +#define __LIBRARY__ @ +#define __TEXT__ .text +#define __DATA__ .data +#define __BSS__ .bss +#define __TEXT_NOROOT__ .text + +// +// Assembler nmenonics. +// +#define __ALIGN__ .balign 4 +#define __END__ .end +#define __EXPORT__ .globl +#define __IMPORT__ .extern +#define __LABEL__ : +#define __STR__ .ascii +#define __THUMB_LABEL__ .thumb_func +#define __WORD__ .word +#define __INLINE_DATA__ + +#endif // gcc + +//***************************************************************************** +// +// The defines required for RV-MDK. +// +//***************************************************************************** +#ifdef rvmdk + +// +// The assembly code preamble required to put the assembler into the correct +// configuration. +// + thumb + require8 + preserve8 + +// +// Section headers. +// +#define __LIBRARY__ ; +#define __TEXT__ area ||.text||, code, readonly, align=2 +#define __DATA__ area ||.data||, data, align=2 +#define __BSS__ area ||.bss||, noinit, align=2 +#define __TEXT_NOROOT__ area ||.text||, code, readonly, align=2 + +// +// Assembler nmenonics. +// +#define __ALIGN__ align 4 +#define __END__ end +#define __EXPORT__ export +#define __IMPORT__ import +#define __LABEL__ +#define __STR__ dcb +#define __THUMB_LABEL__ +#define __WORD__ dcd +#define __INLINE_DATA__ + +#endif // rvmdk + +//***************************************************************************** +// +// The defines required for Sourcery G++. +// +//***************************************************************************** +#if defined(sourcerygxx) + +// +// The assembly code preamble required to put the assembler into the correct +// configuration. +// + .syntax unified + .thumb + +// +// Section headers. +// +#define __LIBRARY__ @ +#define __TEXT__ .text +#define __DATA__ .data +#define __BSS__ .bss +#define __TEXT_NOROOT__ .text + +// +// Assembler nmenonics. +// +#define __ALIGN__ .balign 4 +#define __END__ .end +#define __EXPORT__ .globl +#define __IMPORT__ .extern +#define __LABEL__ : +#define __STR__ .ascii +#define __THUMB_LABEL__ .thumb_func +#define __WORD__ .word +#define __INLINE_DATA__ + +#endif // sourcerygxx + +#endif // __ASMDEF_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_adc.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_adc.h new file mode 100644 index 00000000..525ce905 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_adc.h @@ -0,0 +1,888 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_ADC_H__ +#define __HW_ADC_H__ + +//***************************************************************************** +// +// The following are defines for the ADC register offsets. +// +//***************************************************************************** +#define ADC_O_ADC_CTRL 0x00000000 // ADC control register. +#define ADC_O_adc_ch0_gain 0x00000004 // Channel 0 gain setting +#define ADC_O_adc_ch1_gain 0x00000008 // Channel 1 gain setting +#define ADC_O_adc_ch2_gain 0x0000000C // Channel 2 gain setting +#define ADC_O_adc_ch3_gain 0x00000010 // Channel 3 gain setting +#define ADC_O_adc_ch4_gain 0x00000014 // Channel 4 gain setting +#define ADC_O_adc_ch5_gain 0x00000018 // Channel 5 gain setting +#define ADC_O_adc_ch6_gain 0x0000001C // Channel 6 gain setting +#define ADC_O_adc_ch7_gain 0x00000020 // Channel 7 gain setting +#define ADC_O_adc_ch0_irq_en 0x00000024 // Channel 0 interrupt enable + // register +#define ADC_O_adc_ch1_irq_en 0x00000028 // Channel 1 interrupt enable + // register +#define ADC_O_adc_ch2_irq_en 0x0000002C // Channel 2 interrupt enable + // register +#define ADC_O_adc_ch3_irq_en 0x00000030 // Channel 3 interrupt enable + // register +#define ADC_O_adc_ch4_irq_en 0x00000034 // Channel 4 interrupt enable + // register +#define ADC_O_adc_ch5_irq_en 0x00000038 // Channel 5 interrupt enable + // register +#define ADC_O_adc_ch6_irq_en 0x0000003C // Channel 6 interrupt enable + // register +#define ADC_O_adc_ch7_irq_en 0x00000040 // Channel 7 interrupt enable + // register +#define ADC_O_adc_ch0_irq_status \ + 0x00000044 // Channel 0 interrupt status + // register + +#define ADC_O_adc_ch1_irq_status \ + 0x00000048 // Channel 1 interrupt status + // register + +#define ADC_O_adc_ch2_irq_status \ + 0x0000004C + +#define ADC_O_adc_ch3_irq_status \ + 0x00000050 // Channel 3 interrupt status + // register + +#define ADC_O_adc_ch4_irq_status \ + 0x00000054 // Channel 4 interrupt status + // register + +#define ADC_O_adc_ch5_irq_status \ + 0x00000058 + +#define ADC_O_adc_ch6_irq_status \ + 0x0000005C // Channel 6 interrupt status + // register + +#define ADC_O_adc_ch7_irq_status \ + 0x00000060 // Channel 7 interrupt status + // register + +#define ADC_O_adc_dma_mode_en 0x00000064 // DMA mode enable register +#define ADC_O_adc_timer_configuration \ + 0x00000068 // ADC timer configuration register + +#define ADC_O_adc_timer_current_count \ + 0x00000070 // ADC timer current count register + +#define ADC_O_channel0FIFODATA 0x00000074 // CH0 FIFO DATA register +#define ADC_O_channel1FIFODATA 0x00000078 // CH1 FIFO DATA register +#define ADC_O_channel2FIFODATA 0x0000007C // CH2 FIFO DATA register +#define ADC_O_channel3FIFODATA 0x00000080 // CH3 FIFO DATA register +#define ADC_O_channel4FIFODATA 0x00000084 // CH4 FIFO DATA register +#define ADC_O_channel5FIFODATA 0x00000088 // CH5 FIFO DATA register +#define ADC_O_channel6FIFODATA 0x0000008C // CH6 FIFO DATA register +#define ADC_O_channel7FIFODATA 0x00000090 // CH7 FIFO DATA register +#define ADC_O_adc_ch0_fifo_lvl 0x00000094 // channel 0 FIFO Level register +#define ADC_O_adc_ch1_fifo_lvl 0x00000098 // Channel 1 interrupt status + // register +#define ADC_O_adc_ch2_fifo_lvl 0x0000009C +#define ADC_O_adc_ch3_fifo_lvl 0x000000A0 // Channel 3 interrupt status + // register +#define ADC_O_adc_ch4_fifo_lvl 0x000000A4 // Channel 4 interrupt status + // register +#define ADC_O_adc_ch5_fifo_lvl 0x000000A8 +#define ADC_O_adc_ch6_fifo_lvl 0x000000AC // Channel 6 interrupt status + // register +#define ADC_O_adc_ch7_fifo_lvl 0x000000B0 // Channel 7 interrupt status + // register + +#define ADC_O_ADC_CH_ENABLE 0x000000B8 + +//****************************************************************************** +// +// The following are defines for the bit fields in the ADC_O_ADC_CTRL register. +// +//****************************************************************************** +#define ADC_ADC_CTRL_adc_cap_scale \ + 0x00000020 // ADC CAP SCALE. + +#define ADC_ADC_CTRL_adc_buf_bypass \ + 0x00000010 // ADC ANA CIO buffer bypass. + // Signal is modelled in ANA TOP. + // When '1': ADC buffer is bypassed. + +#define ADC_ADC_CTRL_adc_buf_en 0x00000008 // ADC ANA buffer enable. When 1: + // ADC buffer is enabled. +#define ADC_ADC_CTRL_adc_core_en \ + 0x00000004 // ANA ADC core en. This signal act + // as glbal enable to ADC CIO. When + // 1: ADC core is enabled. + +#define ADC_ADC_CTRL_adc_soft_reset \ + 0x00000002 // ADC soft reset. When '1' : reset + // ADC internal logic. + +#define ADC_ADC_CTRL_adc_en 0x00000001 // ADC global enable. When set ADC + // module is enabled +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch0_gain register. +// +//****************************************************************************** +#define ADC_adc_ch0_gain_adc_channel0_gain_M \ + 0x00000003 // gain setting for ADC channel 0. + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch0_gain_adc_channel0_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch1_gain register. +// +//****************************************************************************** +#define ADC_adc_ch1_gain_adc_channel1_gain_M \ + 0x00000003 // gain setting for ADC channel 1. + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch1_gain_adc_channel1_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch2_gain register. +// +//****************************************************************************** +#define ADC_adc_ch2_gain_adc_channel2_gain_M \ + 0x00000003 // gain setting for ADC channel 2. + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch2_gain_adc_channel2_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch3_gain register. +// +//****************************************************************************** +#define ADC_adc_ch3_gain_adc_channel3_gain_M \ + 0x00000003 // gain setting for ADC channel 3. + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch3_gain_adc_channel3_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch4_gain register. +// +//****************************************************************************** +#define ADC_adc_ch4_gain_adc_channel4_gain_M \ + 0x00000003 // gain setting for ADC channel 4 + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch4_gain_adc_channel4_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch5_gain register. +// +//****************************************************************************** +#define ADC_adc_ch5_gain_adc_channel5_gain_M \ + 0x00000003 // gain setting for ADC channel 5. + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch5_gain_adc_channel5_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch6_gain register. +// +//****************************************************************************** +#define ADC_adc_ch6_gain_adc_channel6_gain_M \ + 0x00000003 // gain setting for ADC channel 6 + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch6_gain_adc_channel6_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch7_gain register. +// +//****************************************************************************** +#define ADC_adc_ch7_gain_adc_channel7_gain_M \ + 0x00000003 // gain setting for ADC channel 7. + // when "00": 1x when "01: 2x when + // "10":3x when "11" 4x + +#define ADC_adc_ch7_gain_adc_channel7_gain_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch0_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch0_irq_en_adc_channel0_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch0_irq_en_adc_channel0_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch1_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch1_irq_en_adc_channel1_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch1_irq_en_adc_channel1_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch2_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch2_irq_en_adc_channel2_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch2_irq_en_adc_channel2_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch3_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch3_irq_en_adc_channel3_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch3_irq_en_adc_channel3_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch4_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch4_irq_en_adc_channel4_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch4_irq_en_adc_channel4_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch5_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch5_irq_en_adc_channel5_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch5_irq_en_adc_channel5_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch6_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch6_irq_en_adc_channel6_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch6_irq_en_adc_channel6_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch7_irq_en register. +// +//****************************************************************************** +#define ADC_adc_ch7_irq_en_adc_channel7_irq_en_M \ + 0x0000000F // interrupt enable register for + // per ADC channel bit 3: when '1' + // -> enable FIFO overflow interrupt + // bit 2: when '1' -> enable FIFO + // underflow interrupt bit 1: when + // "1' -> enable FIFO empty + // interrupt bit 0: when "1" -> + // enable FIFO full interrupt + +#define ADC_adc_ch7_irq_en_adc_channel7_irq_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch0_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch0_irq_status_adc_channel0_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch0_irq_status_adc_channel0_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch1_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch1_irq_status_adc_channel1_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch1_irq_status_adc_channel1_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch2_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch2_irq_status_adc_channel2_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch2_irq_status_adc_channel2_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch3_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch3_irq_status_adc_channel3_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch3_irq_status_adc_channel3_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch4_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch4_irq_status_adc_channel4_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch4_irq_status_adc_channel4_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch5_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch5_irq_status_adc_channel5_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch5_irq_status_adc_channel5_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch6_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch6_irq_status_adc_channel6_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch6_irq_status_adc_channel6_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch7_irq_status register. +// +//****************************************************************************** +#define ADC_adc_ch7_irq_status_adc_channel7_irq_status_M \ + 0x0000000F // interrupt status register for + // per ADC channel. Interrupt status + // can be cleared on write. bit 3: + // when value '1' is written -> + // would clear FIFO overflow + // interrupt status in the next + // cycle. if same interrupt is set + // in the same cycle then interurpt + // would be set and clear command + // will be ignored. bit 2: when + // value '1' is written -> would + // clear FIFO underflow interrupt + // status in the next cycle. bit 1: + // when value '1' is written -> + // would clear FIFO empty interrupt + // status in the next cycle. bit 0: + // when value '1' is written -> + // would clear FIFO full interrupt + // status in the next cycle. + +#define ADC_adc_ch7_irq_status_adc_channel7_irq_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_dma_mode_en register. +// +//****************************************************************************** +#define ADC_adc_dma_mode_en_DMA_MODEenable_M \ + 0x000000FF // this register enable DMA mode. + // when '1' respective ADC channel + // is enabled for DMA. When '0' only + // interrupt mode is enabled. Bit 0: + // channel 0 DMA mode enable. Bit 1: + // channel 1 DMA mode enable. Bit 2: + // channel 2 DMA mode enable. Bit 3: + // channel 3 DMA mode enable. bit 4: + // channel 4 DMA mode enable. bit 5: + // channel 5 DMA mode enable. bit 6: + // channel 6 DMA mode enable. bit 7: + // channel 7 DMA mode enable. + +#define ADC_adc_dma_mode_en_DMA_MODEenable_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_timer_configuration register. +// +//****************************************************************************** +#define ADC_adc_timer_configuration_timeren \ + 0x02000000 // when '1' timer is enabled. + +#define ADC_adc_timer_configuration_timerreset \ + 0x01000000 // when '1' reset timer. + +#define ADC_adc_timer_configuration_timercount_M \ + 0x00FFFFFF // Timer count configuration. 17 + // bit counter is supported. Other + // MSB's are redundent. + +#define ADC_adc_timer_configuration_timercount_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_timer_current_count register. +// +//****************************************************************************** +#define ADC_adc_timer_current_count_timercurrentcount_M \ + 0x0001FFFF // Timer count configuration + +#define ADC_adc_timer_current_count_timercurrentcount_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel0FIFODATA register. +// +//****************************************************************************** +#define ADC_channel0FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel0FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel1FIFODATA register. +// +//****************************************************************************** +#define ADC_channel1FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel1FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel2FIFODATA register. +// +//****************************************************************************** +#define ADC_channel2FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel2FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel3FIFODATA register. +// +//****************************************************************************** +#define ADC_channel3FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel3FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel4FIFODATA register. +// +//****************************************************************************** +#define ADC_channel4FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel4FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel5FIFODATA register. +// +//****************************************************************************** +#define ADC_channel5FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel5FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel6FIFODATA register. +// +//****************************************************************************** +#define ADC_channel6FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel6FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_channel7FIFODATA register. +// +//****************************************************************************** +#define ADC_channel7FIFODATA_FIFO_RD_DATA_M \ + 0xFFFFFFFF // read to this register would + // return ADC data along with time + // stamp information in following + // format: bits [13:0] : ADC sample + // bits [31:14]: : time stamp per + // ADC sample + +#define ADC_channel7FIFODATA_FIFO_RD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch0_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch0_fifo_lvl_adc_channel0_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch0_fifo_lvl_adc_channel0_fifo_lvl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch1_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch1_fifo_lvl_adc_channel1_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch1_fifo_lvl_adc_channel1_fifo_lvl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch2_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch2_fifo_lvl_adc_channel2_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch2_fifo_lvl_adc_channel2_fifo_lvl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch3_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch3_fifo_lvl_adc_channel3_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch3_fifo_lvl_adc_channel3_fifo_lvl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch4_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch4_fifo_lvl_adc_channel4_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch4_fifo_lvl_adc_channel4_fifo_lvl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch5_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch5_fifo_lvl_adc_channel5_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch5_fifo_lvl_adc_channel5_fifo_lvl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch6_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch6_fifo_lvl_adc_channel6_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch6_fifo_lvl_adc_channel6_fifo_lvl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// ADC_O_adc_ch7_fifo_lvl register. +// +//****************************************************************************** +#define ADC_adc_ch7_fifo_lvl_adc_channel7_fifo_lvl_M \ + 0x00000007 // This register shows current FIFO + // level. FIFO is 4 word wide. + // Possible supported levels are : + // 0x0 to 0x3 + +#define ADC_adc_ch7_fifo_lvl_adc_channel7_fifo_lvl_S 0 + + + +#endif // __HW_ADC_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_aes.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_aes.h new file mode 100644 index 00000000..3ab0398b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_aes.h @@ -0,0 +1,802 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_AES_H__ +#define __HW_AES_H__ + +//***************************************************************************** +// +// The following are defines for the AES_P register offsets. +// +//***************************************************************************** +#define AES_O_KEY2_6 0x00000000 // XTS second key / CBC-MAC third + // key +#define AES_O_KEY2_7 0x00000004 // XTS second key (MSW for 256-bit + // key) / CBC-MAC third key (MSW) +#define AES_O_KEY2_4 0x00000008 // XTS / CCM second key / CBC-MAC + // third key (LSW) +#define AES_O_KEY2_5 0x0000000C // XTS second key (MSW for 192-bit + // key) / CBC-MAC third key +#define AES_O_KEY2_2 0x00000010 // XTS / CCM / CBC-MAC second key / + // Hash Key input +#define AES_O_KEY2_3 0x00000014 // XTS second key (MSW for 128-bit + // key) + CCM/CBC-MAC second key + // (MSW) / Hash Key input (MSW) +#define AES_O_KEY2_0 0x00000018 // XTS / CCM / CBC-MAC second key + // (LSW) / Hash Key input (LSW) +#define AES_O_KEY2_1 0x0000001C // XTS / CCM / CBC-MAC second key / + // Hash Key input +#define AES_O_KEY1_6 0x00000020 // Key (LSW for 256-bit key) +#define AES_O_KEY1_7 0x00000024 // Key (MSW for 256-bit key) +#define AES_O_KEY1_4 0x00000028 // Key (LSW for 192-bit key) +#define AES_O_KEY1_5 0x0000002C // Key (MSW for 192-bit key) +#define AES_O_KEY1_2 0x00000030 // Key +#define AES_O_KEY1_3 0x00000034 // Key (MSW for 128-bit key) +#define AES_O_KEY1_0 0x00000038 // Key (LSW for 128-bit key) +#define AES_O_KEY1_1 0x0000003C // Key +#define AES_O_IV_IN_0 0x00000040 // Initialization Vector input + // (LSW) +#define AES_O_IV_IN_1 0x00000044 // Initialization vector input +#define AES_O_IV_IN_2 0x00000048 // Initialization vector input +#define AES_O_IV_IN_3 0x0000004C // Initialization Vector input + // (MSW) +#define AES_O_CTRL 0x00000050 // register determines the mode of + // operation of the AES Engine +#define AES_O_C_LENGTH_0 0x00000054 // Crypto data length registers + // (LSW and MSW) store the + // cryptographic data length in + // bytes for all modes. Once + // processing with this context is + // started@@ this length decrements + // to zero. Data lengths up to (2^61 + // – 1) bytes are allowed. For GCM@@ + // any value up to 2^36 - 32 bytes + // can be used. This is because a + // 32-bit counter mode is used; the + // maximum number of 128-bit blocks + // is 2^32 – 2@@ resulting in a + // maximum number of bytes of 2^36 - + // 32. A write to this register + // triggers the engine to start + // using this context. This is valid + // for all modes except GCM and CCM. + // Note that for the combined + // modes@@ this length does not + // include the authentication only + // data; the authentication length + // is specified in the + // AES_AUTH_LENGTH register below. + // All modes must have a length > 0. + // For the combined modes@@ it is + // allowed to have one of the + // lengths equal to zero. For the + // basic encryption modes + // (ECB/CBC/CTR/ICM/CFB128) it is + // allowed to program zero to the + // length field; in that case the + // length is assumed infinite. All + // data must be byte (8-bit) + // aligned; bit aligned data streams + // are not supported by the AES + // Engine. For a Host read + // operation@@ these registers + // return all-zeroes. +#define AES_O_C_LENGTH_1 0x00000058 // Crypto data length registers + // (LSW and MSW) store the + // cryptographic data length in + // bytes for all modes. Once + // processing with this context is + // started@@ this length decrements + // to zero. Data lengths up to (2^61 + // – 1) bytes are allowed. For GCM@@ + // any value up to 2^36 - 32 bytes + // can be used. This is because a + // 32-bit counter mode is used; the + // maximum number of 128-bit blocks + // is 2^32 – 2@@ resulting in a + // maximum number of bytes of 2^36 - + // 32. A write to this register + // triggers the engine to start + // using this context. This is valid + // for all modes except GCM and CCM. + // Note that for the combined + // modes@@ this length does not + // include the authentication only + // data; the authentication length + // is specified in the + // AES_AUTH_LENGTH register below. + // All modes must have a length > 0. + // For the combined modes@@ it is + // allowed to have one of the + // lengths equal to zero. For the + // basic encryption modes + // (ECB/CBC/CTR/ICM/CFB128) it is + // allowed to program zero to the + // length field; in that case the + // length is assumed infinite. All + // data must be byte (8-bit) + // aligned; bit aligned data streams + // are not supported by the AES + // Engine. For a Host read + // operation@@ these registers + // return all-zeroes. +#define AES_O_AUTH_LENGTH 0x0000005C // AAD data length. The + // authentication length register + // store the authentication data + // length in bytes for combined + // modes only (GCM or CCM) Supported + // AAD-lengths for CCM are from 0 to + // (2^16 - 2^8) bytes. For GCM any + // value up to (2^32 - 1) bytes can + // be used. Once processing with + // this context is started@@ this + // length decrements to zero. A + // write to this register triggers + // the engine to start using this + // context for GCM and CCM. For XTS + // this register is optionally used + // to load ‘j’. Loading of ‘j’ is + // only required if ‘j’ != 0. ‘j’ is + // a 28-bit value and must be + // written to bits [31-4] of this + // register. ‘j’ represents the + // sequential number of the 128-bit + // block inside the data unit. For + // the first block in a unit@@ this + // value is zero. It is not required + // to provide a ‘j’ for each new + // data block within a unit. Note + // that it is possible to start with + // a ‘j’ unequal to zero; refer to + // Table 4 for more details. For a + // Host read operation@@ these + // registers return all-zeroes. +#define AES_O_DATA_IN_0 0x00000060 // Data register to read and write + // plaintext/ciphertext (MSW) +#define AES_O_DATA_IN_1 0x00000064 // Data register to read and write + // plaintext/ciphertext +#define AES_O_DATA_IN_2 0x00000068 // Data register to read and write + // plaintext/ciphertext +#define AES_O_DATA_IN_3 0x0000006C // Data register to read and write + // plaintext/ciphertext (LSW) +#define AES_O_TAG_OUT_0 0x00000070 +#define AES_O_TAG_OUT_1 0x00000074 +#define AES_O_TAG_OUT_2 0x00000078 +#define AES_O_TAG_OUT_3 0x0000007C +#define AES_O_REVISION 0x00000080 // Register AES_REVISION +#define AES_O_SYSCONFIG 0x00000084 // Register AES_SYSCONFIG.This + // register configures the DMA + // signals and controls the IDLE and + // reset logic +#define AES_O_SYSSTATUS 0x00000088 +#define AES_O_IRQSTATUS 0x0000008C // This register indicates the + // interrupt status. If one of the + // interrupt bits is set the + // interrupt output will be asserted +#define AES_O_IRQENABLE 0x00000090 // This register contains an enable + // bit for each unique interrupt + // generated by the module. It + // matches the layout of + // AES_IRQSTATUS register. An + // interrupt is enabled when the bit + // in this register is set to ‘1’. + // An interrupt that is enabled is + // propagated to the SINTREQUEST_x + // output. All interrupts need to be + // enabled explicitly by writing + // this register. + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_6 register. +// +//****************************************************************************** +#define AES_KEY2_6_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_6_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_7 register. +// +//****************************************************************************** +#define AES_KEY2_7_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_7_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_4 register. +// +//****************************************************************************** +#define AES_KEY2_4_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_4_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_5 register. +// +//****************************************************************************** +#define AES_KEY2_5_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_5_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_2 register. +// +//****************************************************************************** +#define AES_KEY2_2_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_2_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_3 register. +// +//****************************************************************************** +#define AES_KEY2_3_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_3_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_0 register. +// +//****************************************************************************** +#define AES_KEY2_0_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_0_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY2_1 register. +// +//****************************************************************************** +#define AES_KEY2_1_KEY_M 0xFFFFFFFF // key data +#define AES_KEY2_1_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_6 register. +// +//****************************************************************************** +#define AES_KEY1_6_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_6_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_7 register. +// +//****************************************************************************** +#define AES_KEY1_7_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_7_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_4 register. +// +//****************************************************************************** +#define AES_KEY1_4_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_4_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_5 register. +// +//****************************************************************************** +#define AES_KEY1_5_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_5_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_2 register. +// +//****************************************************************************** +#define AES_KEY1_2_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_2_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_3 register. +// +//****************************************************************************** +#define AES_KEY1_3_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_3_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_0 register. +// +//****************************************************************************** +#define AES_KEY1_0_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_0_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_KEY1_1 register. +// +//****************************************************************************** +#define AES_KEY1_1_KEY_M 0xFFFFFFFF // key data +#define AES_KEY1_1_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_IV_IN_0 register. +// +//****************************************************************************** +#define AES_IV_IN_0_DATA_M 0xFFFFFFFF // IV data +#define AES_IV_IN_0_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_IV_IN_1 register. +// +//****************************************************************************** +#define AES_IV_IN_1_DATA_M 0xFFFFFFFF // IV data +#define AES_IV_IN_1_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_IV_IN_2 register. +// +//****************************************************************************** +#define AES_IV_IN_2_DATA_M 0xFFFFFFFF // IV data +#define AES_IV_IN_2_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_IV_IN_3 register. +// +//****************************************************************************** +#define AES_IV_IN_3_DATA_M 0xFFFFFFFF // IV data +#define AES_IV_IN_3_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_CTRL register. +// +//****************************************************************************** +#define AES_CTRL_CONTEXT_READY \ + 0x80000000 // If ‘1’@@ this read-only status + // bit indicates that the context + // data registers can be overwritten + // and the host is permitted to + // write the next context. + +#define AES_CTRL_SVCTXTRDY \ + 0x40000000 // If ‘1’@@ this read-only status + // bit indicates that an AES + // authentication TAG and/or IV + // block(s) is/are available for the + // host to retrieve. This bit is + // only asserted if the + // ‘save_context’ bit is set to ‘1’. + // The bit is mutual exclusive with + // the ‘context_ready’ bit. + +#define AES_CTRL_SAVE_CONTEXT 0x20000000 // This bit is used to indicate + // that an authentication TAG or + // result IV needs to be stored as a + // result context. If this bit is + // set@@ context output DMA and/or + // interrupt will be asserted if the + // operation is finished and related + // signals are enabled. +#define AES_CTRL_CCM_M 0x01C00000 // Defines “M” that indicated the + // length of the authentication + // field for CCM operations; the + // authentication field length + // equals two times (the value of + // CCM-M plus one). Note that the + // AES Engine always returns a + // 128-bit authentication field@@ of + // which the M least significant + // bytes are valid. All values are + // supported. +#define AES_CTRL_CCM_S 22 +#define AES_CTRL_CCM_L_M 0x00380000 // Defines “L” that indicated the + // width of the length field for CCM + // operations; the length field in + // bytes equals the value of CMM-L + // plus one. Supported values for L + // are (programmed value): 2 (1)@@ 4 + // (3) and 8 (7). +#define AES_CTRL_CCM_L_S 19 +#define AES_CTRL_CCM 0x00040000 // AES-CCM is selected@@ this is a + // combined mode@@ using AES for + // both authentication and + // encryption. No additional mode + // selection is required. 0 Other + // mode selected 1 ccm mode selected +#define AES_CTRL_GCM_M 0x00030000 // AES-GCM mode is selected.this is + // a combined mode@@ using the + // Galois field multiplier GF(2^128) + // for authentication and AES-CTR + // mode for encryption@@ the bits + // specify the GCM mode. 0x0 No + // operation 0x1 GHASH with H loaded + // and Y0-encrypted forced to zero + // 0x2 GHASH with H loaded and + // Y0-encrypted calculated + // internally 0x3 Autonomous GHASH + // (both H and Y0-encrypted + // calculated internally) +#define AES_CTRL_GCM_S 16 +#define AES_CTRL_CBCMAC 0x00008000 // AES-CBC MAC is selected@@ the + // Direction bit must be set to ‘1’ + // for this mode. 0 Other mode + // selected 1 cbcmac mode selected +#define AES_CTRL_F9 0x00004000 // AES f9 mode is selected@@ the + // AES key size must be set to + // 128-bit for this mode. 0 Other + // mode selected 1 f9 selected +#define AES_CTRL_F8 0x00002000 // AES f8 mode is selected@@ the + // AES key size must be set to + // 128-bit for this mode. 0 Other + // mode selected 1 f8 selected +#define AES_CTRL_XTS_M 0x00001800 // AES-XTS operation is selected; + // the bits specify the XTS mode.01 + // = Previous/intermediate tweak + // value and ‘j’ loaded (value is + // loaded via IV@@ j is loaded via + // the AAD length register) 0x0 No + // operation 0x1 + // Previous/intermediate tweak value + // and ‘j’ loaded (value is loaded + // via IV@@ j is loaded via the AAD + // length register) 0x2 Key2@@ i and + // j loaded (i is loaded via IV@@ j + // is loaded via the AAD length + // register) 0x3 Key2 and i loaded@@ + // j=0 (i is loaded via IV) +#define AES_CTRL_XTS_S 11 +#define AES_CTRL_CFB 0x00000400 // full block AES cipher feedback + // mode (CFB128) is selected. 0 + // other mode selected 1 cfb + // selected +#define AES_CTRL_ICM 0x00000200 // AES integer counter mode (ICM) + // is selected@@ this is a counter + // mode with a 16-bit wide counter. + // 0 Other mode selected. 1 ICM mode + // selected +#define AES_CTRL_CTR_WIDTH_M 0x00000180 // Specifies the counter width for + // AES-CTR mode 0x0 Counter is 32 + // bits 0x1 Counter is 64 bits 0x2 + // Counter is 128 bits 0x3 Counter + // is 192 bits +#define AES_CTRL_CTR_WIDTH_S 7 +#define AES_CTRL_CTR 0x00000040 // Tthis bit must also be set for + // GCM and CCM@@ when + // encryption/decryption is + // required. 0 Other mode selected 1 + // Counter mode +#define AES_CTRL_MODE 0x00000020 // ecb/cbc mode 0 ecb mode 1 cbc + // mode +#define AES_CTRL_KEY_SIZE_M 0x00000018 // key size 0x0 reserved 0x1 Key is + // 128 bits. 0x2 Key is 192 bits 0x3 + // Key is 256 +#define AES_CTRL_KEY_SIZE_S 3 +#define AES_CTRL_DIRECTION 0x00000004 // If set to ‘1’ an encrypt + // operation is performed. If set to + // ‘0’ a decrypt operation is + // performed. Read 0 decryption is + // selected Read 1 Encryption is + // selected +#define AES_CTRL_INPUT_READY 0x00000002 // If ‘1’@@ this read-only status + // bit indicates that the 16-byte + // input buffer is empty@@ and the + // host is permitted to write the + // next block of data. +#define AES_CTRL_OUTPUT_READY 0x00000001 // If ‘1’@@ this read-only status + // bit indicates that an AES output + // block is available for the host + // to retrieve. +//****************************************************************************** +// +// The following are defines for the bit fields in the +// AES_O_C_LENGTH_0 register. +// +//****************************************************************************** +//****************************************************************************** +// +// The following are defines for the bit fields in the +// AES_O_C_LENGTH_1 register. +// +//****************************************************************************** +#define AES_C_LENGTH_1_LENGTH_M \ + 0x1FFFFFFF // Data length (MSW) length + // registers (LSW and MSW) store the + // cryptographic data length in + // bytes for all modes. Once + // processing with this context is + // started@@ this length decrements + // to zero. Data lengths up to (2^61 + // – 1) bytes are allowed. For GCM@@ + // any value up to 2^36 - 32 bytes + // can be used. This is because a + // 32-bit counter mode is used; the + // maximum number of 128-bit blocks + // is 2^32 – 2@@ resulting in a + // maximum number of bytes of 2^36 - + // 32. A write to this register + // triggers the engine to start + // using this context. This is valid + // for all modes except GCM and CCM. + // Note that for the combined + // modes@@ this length does not + // include the authentication only + // data; the authentication length + // is specified in the + // AES_AUTH_LENGTH register below. + // All modes must have a length > 0. + // For the combined modes@@ it is + // allowed to have one of the + // lengths equal to zero. For the + // basic encryption modes + // (ECB/CBC/CTR/ICM/CFB128) it is + // allowed to program zero to the + // length field; in that case the + // length is assumed infinite. All + // data must be byte (8-bit) + // aligned; bit aligned data streams + // are not supported by the AES + // Engine. For a Host read + // operation@@ these registers + // return all-zeroes. + +#define AES_C_LENGTH_1_LENGTH_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// AES_O_AUTH_LENGTH register. +// +//****************************************************************************** +#define AES_AUTH_LENGTH_AUTH_M \ + 0xFFFFFFFF // data + +#define AES_AUTH_LENGTH_AUTH_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_DATA_IN_0 register. +// +//****************************************************************************** +#define AES_DATA_IN_0_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt +#define AES_DATA_IN_0_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_DATA_IN_1 register. +// +//****************************************************************************** +#define AES_DATA_IN_1_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt +#define AES_DATA_IN_1_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_DATA_IN_2 register. +// +//****************************************************************************** +#define AES_DATA_IN_2_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt +#define AES_DATA_IN_2_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_DATA_IN_3 register. +// +//****************************************************************************** +#define AES_DATA_IN_3_DATA_M 0xFFFFFFFF // Data to encrypt/decrypt +#define AES_DATA_IN_3_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_TAG_OUT_0 register. +// +//****************************************************************************** +#define AES_TAG_OUT_0_HASH_M 0xFFFFFFFF // Hash result (MSW) +#define AES_TAG_OUT_0_HASH_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_TAG_OUT_1 register. +// +//****************************************************************************** +#define AES_TAG_OUT_1_HASH_M 0xFFFFFFFF // Hash result (MSW) +#define AES_TAG_OUT_1_HASH_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_TAG_OUT_2 register. +// +//****************************************************************************** +#define AES_TAG_OUT_2_HASH_M 0xFFFFFFFF // Hash result (MSW) +#define AES_TAG_OUT_2_HASH_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_TAG_OUT_3 register. +// +//****************************************************************************** +#define AES_TAG_OUT_3_HASH_M 0xFFFFFFFF // Hash result (LSW) +#define AES_TAG_OUT_3_HASH_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_REVISION register. +// +//****************************************************************************** +#define AES_REVISION_SCHEME_M 0xC0000000 +#define AES_REVISION_SCHEME_S 30 +#define AES_REVISION_FUNC_M 0x0FFF0000 // Function indicates a software + // compatible module family. If + // there is no level of software + // compatibility a new Func number + // (and hence REVISION) should be + // assigned. +#define AES_REVISION_FUNC_S 16 +#define AES_REVISION_R_RTL_M 0x0000F800 // RTL Version (R)@@ maintained by + // IP design owner. RTL follows a + // numbering such as X.Y.R.Z which + // are explained in this table. R + // changes ONLY when: (1) PDS + // uploads occur which may have been + // due to spec changes (2) Bug fixes + // occur (3) Resets to '0' when X or + // Y changes. Design team has an + // internal 'Z' (customer invisible) + // number which increments on every + // drop that happens due to DV and + // RTL updates. Z resets to 0 when R + // increments. +#define AES_REVISION_R_RTL_S 11 +#define AES_REVISION_X_MAJOR_M \ + 0x00000700 // Major Revision (X)@@ maintained + // by IP specification owner. X + // changes ONLY when: (1) There is a + // major feature addition. An + // example would be adding Master + // Mode to Utopia Level2. The Func + // field (or Class/Type in old PID + // format) will remain the same. X + // does NOT change due to: (1) Bug + // fixes (2) Change in feature + // parameters. + +#define AES_REVISION_X_MAJOR_S 8 +#define AES_REVISION_CUSTOM_M 0x000000C0 +#define AES_REVISION_CUSTOM_S 6 +#define AES_REVISION_Y_MINOR_M \ + 0x0000003F // Minor Revision (Y)@@ maintained + // by IP specification owner. Y + // changes ONLY when: (1) Features + // are scaled (up or down). + // Flexibility exists in that this + // feature scalability may either be + // represented in the Y change or a + // specific register in the IP that + // indicates which features are + // exactly available. (2) When + // feature creeps from Is-Not list + // to Is list. But this may not be + // the case once it sees silicon; in + // which case X will change. Y does + // NOT change due to: (1) Bug fixes + // (2) Typos or clarifications (3) + // major functional/feature + // change/addition/deletion. Instead + // these changes may be reflected + // via R@@ S@@ X as applicable. Spec + // owner maintains a + // customer-invisible number 'S' + // which changes due to: (1) + // Typos/clarifications (2) Bug + // documentation. Note that this bug + // is not due to a spec change but + // due to implementation. + // Nevertheless@@ the spec tracks + // the IP bugs. An RTL release (say + // for silicon PG1.1) that occurs + // due to bug fix should document + // the corresponding spec number + // (X.Y.S) in its release notes. + +#define AES_REVISION_Y_MINOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_SYSCONFIG register. +// +//****************************************************************************** +#define AES_SYSCONFIG_MACONTEXT_OUT_ON_DATA_OUT \ + 0x00000200 // If set to '1' the two context + // out requests + // (dma_req_context_out_en@@ Bit [8] + // above@@ and context_out interrupt + // enable@@ Bit [3] of AES_IRQENABLE + // register) are mapped on the + // corresponding data output request + // bit. In this case@@ the original + // ‘context out’ bit values are + // ignored. + +#define AES_SYSCONFIG_DMA_REQ_CONTEXT_OUT_EN \ + 0x00000100 // If set to ‘1’@@ the DMA context + // output request is enabled (for + // context data out@@ e.g. TAG for + // authentication modes). 0 Dma + // disabled 1 Dma enabled + +#define AES_SYSCONFIG_DMA_REQ_CONTEXT_IN_EN \ + 0x00000080 // If set to ‘1’@@ the DMA context + // request is enabled. 0 Dma + // disabled 1 Dma enabled + +#define AES_SYSCONFIG_DMA_REQ_DATA_OUT_EN \ + 0x00000040 // If set to ‘1’@@ the DMA output + // request is enabled. 0 Dma + // disabled 1 Dma enabled + +#define AES_SYSCONFIG_DMA_REQ_DATA_IN_EN \ + 0x00000020 // If set to ‘1’@@ the DMA input + // request is enabled. 0 Dma + // disabled 1 Dma enabled + +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_SYSSTATUS register. +// +//****************************************************************************** +#define AES_SYSSTATUS_RESETDONE \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_IRQSTATUS register. +// +//****************************************************************************** +#define AES_IRQSTATUS_CONTEXT_OUT \ + 0x00000008 // This bit indicates + // authentication tag (and IV) + // interrupt(s) is/are active and + // triggers the interrupt output. + +#define AES_IRQSTATUS_DATA_OUT \ + 0x00000004 // This bit indicates data output + // interrupt is active and triggers + // the interrupt output. + +#define AES_IRQSTATUS_DATA_IN 0x00000002 // This bit indicates data input + // interrupt is active and triggers + // the interrupt output. +#define AES_IRQSTATUS_CONTEX_IN \ + 0x00000001 // This bit indicates context + // interrupt is active and triggers + // the interrupt output. + +//****************************************************************************** +// +// The following are defines for the bit fields in the AES_O_IRQENABLE register. +// +//****************************************************************************** +#define AES_IRQENABLE_CONTEXT_OUT \ + 0x00000008 // This bit indicates + // authentication tag (and IV) + // interrupt(s) is/are active and + // triggers the interrupt output. + +#define AES_IRQENABLE_DATA_OUT \ + 0x00000004 // This bit indicates data output + // interrupt is active and triggers + // the interrupt output. + +#define AES_IRQENABLE_DATA_IN 0x00000002 // This bit indicates data input + // interrupt is active and triggers + // the interrupt output. +#define AES_IRQENABLE_CONTEX_IN \ + 0x00000001 // This bit indicates context + // interrupt is active and triggers + // the interrupt output. + + + + +#endif // __HW_AES_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_config.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_config.h new file mode 100644 index 00000000..b8789b98 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_config.h @@ -0,0 +1,747 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + + +#ifndef __HW_APPS_CONFIG_H__ +#define __HW_APPS_CONFIG_H__ + +//***************************************************************************** +// +// The following are defines for the APPS_CONFIG register offsets. +// +//***************************************************************************** +#define APPS_CONFIG_O_PATCH_TRAP_ADDR_REG \ + 0x00000000 // Patch trap address Register + // array + +#define APPS_CONFIG_O_PATCH_TRAP_EN_REG \ + 0x00000078 + +#define APPS_CONFIG_O_FAULT_STATUS_REG \ + 0x0000007C + +#define APPS_CONFIG_O_MEMSS_WR_ERR_CLR_REG \ + 0x00000080 + +#define APPS_CONFIG_O_MEMSS_WR_ERR_ADDR_REG \ + 0x00000084 + +#define APPS_CONFIG_O_DMA_DONE_INT_MASK \ + 0x0000008C + +#define APPS_CONFIG_O_DMA_DONE_INT_MASK_SET \ + 0x00000090 + +#define APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR \ + 0x00000094 + +#define APPS_CONFIG_O_DMA_DONE_INT_STS_CLR \ + 0x00000098 + +#define APPS_CONFIG_O_DMA_DONE_INT_ACK \ + 0x0000009C + +#define APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED \ + 0x000000A0 + +#define APPS_CONFIG_O_DMA_DONE_INT_STS_RAW \ + 0x000000A4 + +#define APPS_CONFIG_O_FAULT_STATUS_CLR_REG \ + 0x000000A8 + +#define APPS_CONFIG_O_RESERVD_REG_0 \ + 0x000000AC + +#define APPS_CONFIG_O_GPT_TRIG_SEL \ + 0x000000B0 + +#define APPS_CONFIG_O_TOP_DIE_SPARE_DIN_REG \ + 0x000000B4 + +#define APPS_CONFIG_O_TOP_DIE_SPARE_DOUT_REG \ + 0x000000B8 + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_PATCH_TRAP_ADDR_REG register. +// +//****************************************************************************** +#define APPS_CONFIG_PATCH_TRAP_ADDR_REG_PATCH_TRAP_ADDR_M \ + 0xFFFFFFFF // When PATCH_TRAP_EN[n] is set bus + // fault is generated for the + // address + // PATCH_TRAP_ADDR_REG[n][31:0] from + // Idcode bus. The exception routine + // should take care to jump to the + // location where the patch + // correspond to this address is + // kept. + +#define APPS_CONFIG_PATCH_TRAP_ADDR_REG_PATCH_TRAP_ADDR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_PATCH_TRAP_EN_REG register. +// +//****************************************************************************** +#define APPS_CONFIG_PATCH_TRAP_EN_REG_PATCH_TRAP_EN_M \ + 0x3FFFFFFF // When PATCH_TRAP_EN[n] is set bus + // fault is generated for the + // address PATCH_TRAP_ADD[n][31:0] + // from Idcode bus. The exception + // routine should take care to jump + // to the location where the patch + // correspond to this address is + // kept. + +#define APPS_CONFIG_PATCH_TRAP_EN_REG_PATCH_TRAP_EN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_FAULT_STATUS_REG register. +// +//****************************************************************************** +#define APPS_CONFIG_FAULT_STATUS_REG_PATCH_ERR_INDEX_M \ + 0x0000003E // This field shows because of + // which patch trap address the + // bus_fault is generated. If the + // PATCH_ERR bit is set, then it + // means the bus fault is generated + // because of + // PATCH_TRAP_ADDR_REG[2^PATCH_ERR_INDEX] + +#define APPS_CONFIG_FAULT_STATUS_REG_PATCH_ERR_INDEX_S 1 +#define APPS_CONFIG_FAULT_STATUS_REG_PATCH_ERR \ + 0x00000001 // This bit is set when there is a + // bus fault because of patched + // address access to the Apps boot + // rom. Write 0 to clear this + // register. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_MEMSS_WR_ERR_CLR_REG register. +// +//****************************************************************************** +#define APPS_CONFIG_MEMSS_WR_ERR_CLR_REG_MEMSS_WR_ERR_CLR \ + 0x00000001 // This bit is set when there is a + // an error in memss write access. + // And the address causing this + // error is captured in + // MEMSS_ERR_ADDR_REG. To capture + // the next error address one have + // to clear this bit. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_MEMSS_WR_ERR_ADDR_REG register. +// +//****************************************************************************** +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_DMA_DONE_INT_MASK register. +// +//****************************************************************************** +#define APPS_CONFIG_DMA_DONE_INT_MASK_ADC_WR_DMA_DONE_INT_MASK_M \ + 0x0000F000 // 1= disable corresponding + // interrupt;0 = interrupt enabled + // bit 14: ADC channel 7 interrupt + // enable/disable bit 13: ADC + // channel 5 interrupt + // enable/disable bit 12: ADC + // channel 3 interrupt + // enable/disable bit 11: ADC + // channel 1 interrupt + // enable/disable + +#define APPS_CONFIG_DMA_DONE_INT_MASK_ADC_WR_DMA_DONE_INT_MASK_S 12 +#define APPS_CONFIG_DMA_DONE_INT_MASK_MCASP_WR_DMA_DONE_INT_MASK \ + 0x00000800 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_MCASP_RD_DMA_DONE_INT_MASK \ + 0x00000400 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CAM_FIFO_EMPTY_DMA_DONE_INT_MASK \ + 0x00000200 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CAM_THRESHHOLD_DMA_DONE_INT_MASK \ + 0x00000100 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SHSPI_WR_DMA_DONE_INT_MASK \ + 0x00000080 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SHSPI_RD_DMA_DONE_INT_MASK \ + 0x00000040 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_HOSTSPI_WR_DMA_DONE_INT_MASK \ + 0x00000020 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_HOSTSPI_RD_DMA_DONE_INT_MASK \ + 0x00000010 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_APPS_SPI_WR_DMA_DONE_INT_MASK \ + 0x00000008 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_APPS_SPI_RD_DMA_DONE_INT_MASK \ + 0x00000004 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SDIOM_WR_DMA_DONE_INT_MASK \ + 0x00000002 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SDIOM_RD_DMA_DONE_INT_MASK \ + 0x00000001 // 1= disable corresponding + // interrupt;0 = interrupt enabled + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_DMA_DONE_INT_MASK_SET register. +// +//****************************************************************************** +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_ADC_WR_DMA_DONE_INT_MASK_SET_M \ + 0x0000F000 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect bit 14: ADC channel 7 DMA + // Done IRQ bit 13: ADC channel 5 + // DMA Done IRQ bit 12: ADC channel + // 3 DMA Done IRQ bit 11: ADC + // channel 1 DMA Done IRQ + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_ADC_WR_DMA_DONE_INT_MASK_SET_S 12 +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_MCASP_WR_DMA_DONE_INT_MASK_SET \ + 0x00000800 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_MCASP_RD_DMA_DONE_INT_MASK_SET \ + 0x00000400 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_CAM_FIFO_EMPTY_DMA_DONE_INT_MASK_SET \ + 0x00000200 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_CAM_THRESHHOLD_DMA_DONE_INT_MASK_SET \ + 0x00000100 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SHSPI_WR_DMA_DONE_INT_MASK_SET \ + 0x00000080 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SHSPI_RD_DMA_DONE_INT_MASK_SET \ + 0x00000040 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_HOSTSPI_WR_DMA_DONE_INT_MASK_SET \ + 0x00000020 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_HOSTSPI_RD_DMA_DONE_INT_MASK_SET \ + 0x00000010 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_APPS_SPI_WR_DMA_DONE_INT_MASK_SET \ + 0x00000008 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_APPS_SPI_RD_DMA_DONE_INT_MASK_SET \ + 0x00000004 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SDIOM_WR_DMA_DONE_INT_MASK_SET \ + 0x00000002 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_SET_SDIOM_RD_DMA_DONE_INT_MASK_SET \ + 0x00000001 // write 1 to set mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR register. +// +//****************************************************************************** +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_ADC_WR_DMA_DONE_INT_MASK_CLR_M \ + 0x0000F000 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect bit 14: ADC channel 7 DMA + // Done IRQ mask bit 13: ADC channel + // 5 DMA Done IRQ mask bit 12: ADC + // channel 3 DMA Done IRQ mask bit + // 11: ADC channel 1 DMA Done IRQ + // mask + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_ADC_WR_DMA_DONE_INT_MASK_CLR_S 12 +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_MACASP_WR_DMA_DONE_INT_MASK_CLR \ + 0x00000800 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_MCASP_RD_DMA_DONE_INT_MASK_CLR \ + 0x00000400 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_CAM_FIFO_EMPTY_DMA_DONE_INT_MASK_CLR \ + 0x00000200 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_CAM_THRESHHOLD_DMA_DONE_INT_MASK_CLR \ + 0x00000100 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SHSPI_WR_DMA_DONE_INT_MASK_CLR \ + 0x00000080 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SHSPI_RD_DMA_DONE_INT_MASK_CLR \ + 0x00000040 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_HOSTSPI_WR_DMA_DONE_INT_MASK_CLR \ + 0x00000020 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_HOSTSPI_RD_DMA_DONE_INT_MASK_CLR \ + 0x00000010 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_APPS_SPI_WR_DMA_DONE_INT_MASK_CLR \ + 0x00000008 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_APPS_SPI_RD_DMA_DONE_INT_MASK_CLR \ + 0x00000004 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SDIOM_WR_DMA_DONE_INT_MASK_CLR \ + 0x00000002 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +#define APPS_CONFIG_DMA_DONE_INT_MASK_CLR_SDIOM_RD_DMA_DONE_INT_MASK_CLR \ + 0x00000001 // write 1 to clear mask of the + // corresponding DMA DONE IRQ;0 = no + // effect + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_DMA_DONE_INT_STS_CLR register. +// +//****************************************************************************** +#define APPS_CONFIG_DMA_DONE_INT_STS_CLR_DMA_INT_STS_CLR_M \ + 0xFFFFFFFF // write 1 or 0 to clear all + // DMA_DONE interrupt; + +#define APPS_CONFIG_DMA_DONE_INT_STS_CLR_DMA_INT_STS_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_DMA_DONE_INT_ACK register. +// +//****************************************************************************** +#define APPS_CONFIG_DMA_DONE_INT_ACK_ADC_WR_DMA_DONE_INT_ACK_M \ + 0x0000F000 // write 1 to clear corresponding + // interrupt; 0 = no effect; bit 14: + // ADC channel 7 DMA Done IRQ bit + // 13: ADC channel 5 DMA Done IRQ + // bit 12: ADC channel 3 DMA Done + // IRQ bit 11: ADC channel 1 DMA + // Done IRQ + +#define APPS_CONFIG_DMA_DONE_INT_ACK_ADC_WR_DMA_DONE_INT_ACK_S 12 +#define APPS_CONFIG_DMA_DONE_INT_ACK_MCASP_WR_DMA_DONE_INT_ACK \ + 0x00000800 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_MCASP_RD_DMA_DONE_INT_ACK \ + 0x00000400 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_CAM_FIFO_EMPTY_DMA_DONE_INT_ACK \ + 0x00000200 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_CAM_THRESHHOLD_DMA_DONE_INT_ACK \ + 0x00000100 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_SHSPI_WR_DMA_DONE_INT_ACK \ + 0x00000080 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_SHSPI_RD_DMA_DONE_INT_ACK \ + 0x00000040 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_HOSTSPI_WR_DMA_DONE_INT_ACK \ + 0x00000020 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_HOSTSPI_RD_DMA_DONE_INT_ACK \ + 0x00000010 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_APPS_SPI_WR_DMA_DONE_INT_ACK \ + 0x00000008 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_APPS_SPI_RD_DMA_DONE_INT_ACK \ + 0x00000004 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_SDIOM_WR_DMA_DONE_INT_ACK \ + 0x00000002 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +#define APPS_CONFIG_DMA_DONE_INT_ACK_SDIOM_RD_DMA_DONE_INT_ACK \ + 0x00000001 // write 1 to clear corresponding + // interrupt; 0 = no effect; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED register. +// +//****************************************************************************** +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_ADC_WR_DMA_DONE_INT_STS_MASKED_M \ + 0x0000F000 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask bit 14: ADC + // channel 7 DMA Done IRQ bit 13: + // ADC channel 5 DMA Done IRQ bit + // 12: ADC channel 3 DMA Done IRQ + // bit 11: ADC channel 1 DMA Done + // IRQ + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_ADC_WR_DMA_DONE_INT_STS_MASKED_S 12 +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_MCASP_WR_DMA_DONE_INT_STS_MASKED \ + 0x00000800 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_MCASP_RD_DMA_DONE_INT_STS_MASKED \ + 0x00000400 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_CAM_FIFO_EMPTY_DMA_DONE_INT_STS_MASKED \ + 0x00000200 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_CAM_THRESHHOLD_DMA_DONE_INT_STS_MASKED \ + 0x00000100 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SHSPI_WR_DMA_DONE_INT_STS_MASKED \ + 0x00000080 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SHSPI_RD_DMA_DONE_INT_STS_MASKED \ + 0x00000040 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_HOSTSPI_WR_DMA_DONE_INT_STS_MASKED \ + 0x00000020 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_HOSTSPI_RD_DMA_DONE_INT_STS_MASKED \ + 0x00000010 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_APPS_SPI_WR_DMA_DONE_INT_STS_MASKED \ + 0x00000008 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_APPS_SPI_RD_DMA_DONE_INT_STS_MASKED \ + 0x00000004 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SDIOM_WR_DMA_DONE_INT_STS_MASKED \ + 0x00000002 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +#define APPS_CONFIG_DMA_DONE_INT_STS_MASKED_SDIOM_RD_DMA_DONE_INT_STS_MASKED \ + 0x00000001 // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by DMA_DONE_INT mask + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_DMA_DONE_INT_STS_RAW register. +// +//****************************************************************************** +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_ADC_WR_DMA_DONE_INT_STS_RAW_M \ + 0x0000F000 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive bit 14: ADC channel 7 + // DMA Done IRQ bit 13: ADC channel + // 5 DMA Done IRQ bit 12: ADC + // channel 3 DMA Done IRQ bit 11: + // ADC channel 1 DMA Done IRQ + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_ADC_WR_DMA_DONE_INT_STS_RAW_S 12 +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_MCASP_WR_DMA_DONE_INT_STS_RAW \ + 0x00000800 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_MCASP_RD_DMA_DONE_INT_STS_RAW \ + 0x00000400 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_CAM_EPMTY_FIFO_DMA_DONE_INT_STS_RAW \ + 0x00000200 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_CAM_THRESHHOLD_DMA_DONE_INT_STS_RAW \ + 0x00000100 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SHSPI_WR_DMA_DONE_INT_STS_RAW \ + 0x00000080 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SHSPI_RD_DMA_DONE_INT_STS_RAW \ + 0x00000040 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_HOSTSPI_WR_DMA_DONE_INT_STS_RAW \ + 0x00000020 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_HOSTSPI_RD_DMA_DONE_INT_STS_RAW \ + 0x00000010 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_APPS_SPI_WR_DMA_DONE_INT_STS_RAW \ + 0x00000008 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_APPS_SPI_RD_DMA_DONE_INT_STS_RAW \ + 0x00000004 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SDIOM_WR_DMA_DONE_INT_STS_RAW \ + 0x00000002 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define APPS_CONFIG_DMA_DONE_INT_STS_RAW_SDIOM_RD_DMA_DONE_INT_STS_RAW \ + 0x00000001 // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_FAULT_STATUS_CLR_REG register. +// +//****************************************************************************** +#define APPS_CONFIG_FAULT_STATUS_CLR_REG_PATCH_ERR_CLR \ + 0x00000001 // Write 1 to clear the LSB of + // FAULT_STATUS_REG + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_RESERVD_REG_0 register. +// +//****************************************************************************** +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_GPT_TRIG_SEL register. +// +//****************************************************************************** +#define APPS_CONFIG_GPT_TRIG_SEL_GPT_TRIG_SEL_M \ + 0x000000FF // This bit is implemented for GPT + // trigger mode select. GPT IP + // support 2 modes: RTC mode and + // external trigger. When this bit + // is set to logic '1': enable + // external trigger mode for APPS + // GPT CP0 and CP1 pin. bit 0: when + // set '1' enable external GPT + // trigger 0 on GPIO0 CP0 pin else + // RTC mode is selected. bit 1: when + // set '1' enable external GPT + // trigger 1 on GPIO0 CP1 pin else + // RTC mode is selected. bit 2: when + // set '1' enable external GPT + // trigger 2 on GPIO1 CP0 pin else + // RTC mode is selected. bit 3: when + // set '1' enable external GPT + // trigger 3 on GPIO1 CP1 pin else + // RTC mode is selected. bit 4: when + // set '1' enable external GPT + // trigger 4 on GPIO2 CP0 pin else + // RTC mode is selected. bit 5: when + // set '1' enable external GPT + // trigger 5 on GPIO2 CP1 pin else + // RTC mode is selected. bit 6: when + // set '1' enable external GPT + // trigger 6 on GPIO3 CP0 pin else + // RTC mode is selected. bit 7: when + // set '1' enable external GPT + // trigger 7 on GPIO3 CP1 pin else + // RTC mode is selected. + +#define APPS_CONFIG_GPT_TRIG_SEL_GPT_TRIG_SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_TOP_DIE_SPARE_DIN_REG register. +// +//****************************************************************************** +#define APPS_CONFIG_TOP_DIE_SPARE_DIN_REG_D2D_SPARE_DIN_M \ + 0x00000007 // Capture data from d2d_spare pads + +#define APPS_CONFIG_TOP_DIE_SPARE_DIN_REG_D2D_SPARE_DIN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_CONFIG_O_TOP_DIE_SPARE_DOUT_REG register. +// +//****************************************************************************** +#define APPS_CONFIG_TOP_DIE_SPARE_DOUT_REG_D2D_SPARE_DOUT_M \ + 0x00000007 // Send data to d2d_spare pads - + // eventually this will get + // registered in top die + +#define APPS_CONFIG_TOP_DIE_SPARE_DOUT_REG_D2D_SPARE_DOUT_S 0 + + + +#endif // __HW_APPS_CONFIG_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_rcm.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_rcm.h new file mode 100644 index 00000000..edb52d26 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_apps_rcm.h @@ -0,0 +1,1506 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_APPS_RCM_H__ +#define __HW_APPS_RCM_H__ + +//***************************************************************************** +// +// The following are defines for the APPS_RCM register offsets. +// +//***************************************************************************** +#define APPS_RCM_O_CAMERA_CLK_GEN \ + 0x00000000 + +#define APPS_RCM_O_CAMERA_CLK_GATING \ + 0x00000004 + +#define APPS_RCM_O_CAMERA_SOFT_RESET \ + 0x00000008 + +#define APPS_RCM_O_MCASP_CLK_GATING \ + 0x00000014 + +#define APPS_RCM_O_MCASP_SOFT_RESET \ + 0x00000018 + +#define APPS_RCM_O_MMCHS_CLK_GEN \ + 0x00000020 + +#define APPS_RCM_O_MMCHS_CLK_GATING \ + 0x00000024 + +#define APPS_RCM_O_MMCHS_SOFT_RESET \ + 0x00000028 + +#define APPS_RCM_O_MCSPI_A1_CLK_GEN \ + 0x0000002C + +#define APPS_RCM_O_MCSPI_A1_CLK_GATING \ + 0x00000030 + +#define APPS_RCM_O_MCSPI_A1_SOFT_RESET \ + 0x00000034 + +#define APPS_RCM_O_MCSPI_A2_CLK_GEN \ + 0x00000038 + +#define APPS_RCM_O_MCSPI_A2_CLK_GATING \ + 0x00000040 + +#define APPS_RCM_O_MCSPI_A2_SOFT_RESET \ + 0x00000044 + +#define APPS_RCM_O_UDMA_A_CLK_GATING \ + 0x00000048 + +#define APPS_RCM_O_UDMA_A_SOFT_RESET \ + 0x0000004C + +#define APPS_RCM_O_GPIO_A_CLK_GATING \ + 0x00000050 + +#define APPS_RCM_O_GPIO_A_SOFT_RESET \ + 0x00000054 + +#define APPS_RCM_O_GPIO_B_CLK_GATING \ + 0x00000058 + +#define APPS_RCM_O_GPIO_B_SOFT_RESET \ + 0x0000005C + +#define APPS_RCM_O_GPIO_C_CLK_GATING \ + 0x00000060 + +#define APPS_RCM_O_GPIO_C_SOFT_RESET \ + 0x00000064 + +#define APPS_RCM_O_GPIO_D_CLK_GATING \ + 0x00000068 + +#define APPS_RCM_O_GPIO_D_SOFT_RESET \ + 0x0000006C + +#define APPS_RCM_O_GPIO_E_CLK_GATING \ + 0x00000070 + +#define APPS_RCM_O_GPIO_E_SOFT_RESET \ + 0x00000074 + +#define APPS_RCM_O_WDOG_A_CLK_GATING \ + 0x00000078 + +#define APPS_RCM_O_WDOG_A_SOFT_RESET \ + 0x0000007C + +#define APPS_RCM_O_UART_A0_CLK_GATING \ + 0x00000080 + +#define APPS_RCM_O_UART_A0_SOFT_RESET \ + 0x00000084 + +#define APPS_RCM_O_UART_A1_CLK_GATING \ + 0x00000088 + +#define APPS_RCM_O_UART_A1_SOFT_RESET \ + 0x0000008C + +#define APPS_RCM_O_GPT_A0_CLK_GATING \ + 0x00000090 + +#define APPS_RCM_O_GPT_A0_SOFT_RESET \ + 0x00000094 + +#define APPS_RCM_O_GPT_A1_CLK_GATING \ + 0x00000098 + +#define APPS_RCM_O_GPT_A1_SOFT_RESET \ + 0x0000009C + +#define APPS_RCM_O_GPT_A2_CLK_GATING \ + 0x000000A0 + +#define APPS_RCM_O_GPT_A2_SOFT_RESET \ + 0x000000A4 + +#define APPS_RCM_O_GPT_A3_CLK_GATING \ + 0x000000A8 + +#define APPS_RCM_O_GPT_A3_SOFT_RESET \ + 0x000000AC + +#define APPS_RCM_O_MCASP_FRAC_CLK_CONFIG0 \ + 0x000000B0 + +#define APPS_RCM_O_MCASP_FRAC_CLK_CONFIG1 \ + 0x000000B4 + +#define APPS_RCM_O_CRYPTO_CLK_GATING \ + 0x000000B8 + +#define APPS_RCM_O_CRYPTO_SOFT_RESET \ + 0x000000BC + +#define APPS_RCM_O_MCSPI_S0_CLK_GATING \ + 0x000000C8 + +#define APPS_RCM_O_MCSPI_S0_SOFT_RESET \ + 0x000000CC + +#define APPS_RCM_O_MCSPI_S0_CLKDIV_CFG \ + 0x000000D0 + +#define APPS_RCM_O_I2C_CLK_GATING \ + 0x000000D8 + +#define APPS_RCM_O_I2C_SOFT_RESET \ + 0x000000DC + +#define APPS_RCM_O_APPS_LPDS_REQ \ + 0x000000E4 + +#define APPS_RCM_O_APPS_TURBO_REQ \ + 0x000000EC + +#define APPS_RCM_O_APPS_DSLP_WAKE_CONFIG \ + 0x00000108 + +#define APPS_RCM_O_APPS_DSLP_WAKE_TIMER_CFG \ + 0x0000010C + +#define APPS_RCM_O_APPS_RCM_SLP_WAKE_ENABLE \ + 0x00000110 + +#define APPS_RCM_O_APPS_SLP_WAKETIMER_CFG \ + 0x00000114 + +#define APPS_RCM_O_APPS_TO_NWP_WAKE_REQUEST \ + 0x00000118 + +#define APPS_RCM_O_APPS_RCM_INTERRUPT_STATUS \ + 0x00000120 + +#define APPS_RCM_O_APPS_RCM_INTERRUPT_ENABLE \ + 0x00000124 + + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_CAMERA_CLK_GEN register. +// +//****************************************************************************** +#define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_OFF_TIME_M \ + 0x00000700 // Configuration of OFF-TIME for + // dividing PLL clk (240 MHz) in + // generation of Camera func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_OFF_TIME_S 8 +#define APPS_RCM_CAMERA_CLK_GEN_NU1_M \ + 0x000000F8 + +#define APPS_RCM_CAMERA_CLK_GEN_NU1_S 3 +#define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_ON_TIME_M \ + 0x00000007 // Configuration of ON-TIME for + // dividing PLL clk (240 MHz) in + // generation of Camera func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_CAMERA_CLK_GEN_CAMERA_PLLCKDIV_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_CAMERA_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_CAMERA_CLK_GATING_NU1_M \ + 0x00FE0000 + +#define APPS_RCM_CAMERA_CLK_GATING_NU1_S 17 +#define APPS_RCM_CAMERA_CLK_GATING_CAMERA_DSLP_CLK_ENABLE \ + 0x00010000 // 0 - Disable camera clk during + // deep-sleep mode + +#define APPS_RCM_CAMERA_CLK_GATING_NU2_M \ + 0x0000FE00 + +#define APPS_RCM_CAMERA_CLK_GATING_NU2_S 9 +#define APPS_RCM_CAMERA_CLK_GATING_CAMERA_SLP_CLK_ENABLE \ + 0x00000100 // 1- Enable camera clk during + // sleep mode ; 0- Disable camera + // clk during sleep mode + +#define APPS_RCM_CAMERA_CLK_GATING_NU3_M \ + 0x000000FE + +#define APPS_RCM_CAMERA_CLK_GATING_NU3_S 1 +#define APPS_RCM_CAMERA_CLK_GATING_CAMERA_RUN_CLK_ENABLE \ + 0x00000001 // 1- Enable camera clk during run + // mode ; 0- Disable camera clk + // during run mode + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_CAMERA_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_CAMERA_SOFT_RESET_CAMERA_ENABLED_STATUS \ + 0x00000002 // 1 - Camera clocks/resets are + // enabled ; 0 - Camera + // clocks/resets are disabled + +#define APPS_RCM_CAMERA_SOFT_RESET_CAMERA_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for Camera-core + // ; 0 - De-assert reset for + // Camera-core + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCASP_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_MCASP_CLK_GATING_NU1_M \ + 0x00FE0000 + +#define APPS_RCM_MCASP_CLK_GATING_NU1_S 17 +#define APPS_RCM_MCASP_CLK_GATING_MCASP_DSLP_CLK_ENABLE \ + 0x00010000 // 0 - Disable MCASP clk during + // deep-sleep mode + +#define APPS_RCM_MCASP_CLK_GATING_NU2_M \ + 0x0000FE00 + +#define APPS_RCM_MCASP_CLK_GATING_NU2_S 9 +#define APPS_RCM_MCASP_CLK_GATING_MCASP_SLP_CLK_ENABLE \ + 0x00000100 // 1- Enable MCASP clk during sleep + // mode ; 0- Disable MCASP clk + // during sleep mode + +#define APPS_RCM_MCASP_CLK_GATING_NU3_M \ + 0x000000FE + +#define APPS_RCM_MCASP_CLK_GATING_NU3_S 1 +#define APPS_RCM_MCASP_CLK_GATING_MCASP_RUN_CLK_ENABLE \ + 0x00000001 // 1- Enable MCASP clk during run + // mode ; 0- Disable MCASP clk + // during run mode + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCASP_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_MCASP_SOFT_RESET_MCASP_ENABLED_STATUS \ + 0x00000002 // 1 - MCASP Clocks/resets are + // enabled ; 0 - MCASP Clocks/resets + // are disabled + +#define APPS_RCM_MCASP_SOFT_RESET_MCASP_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for MCASP-core + // ; 0 - De-assert reset for + // MCASP-core + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MMCHS_CLK_GEN register. +// +//****************************************************************************** +#define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_OFF_TIME_M \ + 0x00000700 // Configuration of OFF-TIME for + // dividing PLL clk (240 MHz) in + // generation of MMCHS func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_OFF_TIME_S 8 +#define APPS_RCM_MMCHS_CLK_GEN_NU1_M \ + 0x000000F8 + +#define APPS_RCM_MMCHS_CLK_GEN_NU1_S 3 +#define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_ON_TIME_M \ + 0x00000007 // Configuration of ON-TIME for + // dividing PLL clk (240 MHz) in + // generation of MMCHS func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MMCHS_CLK_GEN_MMCHS_PLLCKDIV_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MMCHS_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_MMCHS_CLK_GATING_NU1_M \ + 0x00FE0000 + +#define APPS_RCM_MMCHS_CLK_GATING_NU1_S 17 +#define APPS_RCM_MMCHS_CLK_GATING_MMCHS_DSLP_CLK_ENABLE \ + 0x00010000 // 0 - Disable MMCHS clk during + // deep-sleep mode + +#define APPS_RCM_MMCHS_CLK_GATING_NU2_M \ + 0x0000FE00 + +#define APPS_RCM_MMCHS_CLK_GATING_NU2_S 9 +#define APPS_RCM_MMCHS_CLK_GATING_MMCHS_SLP_CLK_ENABLE \ + 0x00000100 // 1- Enable MMCHS clk during sleep + // mode ; 0- Disable MMCHS clk + // during sleep mode + +#define APPS_RCM_MMCHS_CLK_GATING_NU3_M \ + 0x000000FE + +#define APPS_RCM_MMCHS_CLK_GATING_NU3_S 1 +#define APPS_RCM_MMCHS_CLK_GATING_MMCHS_RUN_CLK_ENABLE \ + 0x00000001 // 1- Enable MMCHS clk during run + // mode ; 0- Disable MMCHS clk + // during run mode + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MMCHS_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_MMCHS_SOFT_RESET_MMCHS_ENABLED_STATUS \ + 0x00000002 // 1 - MMCHS Clocks/resets are + // enabled ; 0 - MMCHS Clocks/resets + // are disabled + +#define APPS_RCM_MMCHS_SOFT_RESET_MMCHS_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for MMCHS-core + // ; 0 - De-assert reset for + // MMCHS-core + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_A1_CLK_GEN register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_BAUD_CLK_SEL \ + 0x00010000 // 0 - XTAL clk is used as baud clk + // for MCSPI_A1 ; 1 - PLL divclk is + // used as baud clk for MCSPI_A1. + +#define APPS_RCM_MCSPI_A1_CLK_GEN_NU1_M \ + 0x0000F800 + +#define APPS_RCM_MCSPI_A1_CLK_GEN_NU1_S 11 +#define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_OFF_TIME_M \ + 0x00000700 // Configuration of OFF-TIME for + // dividing PLL clk (240 MHz) in + // generation of MCSPI_A1 func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_OFF_TIME_S 8 +#define APPS_RCM_MCSPI_A1_CLK_GEN_NU2_M \ + 0x000000F8 + +#define APPS_RCM_MCSPI_A1_CLK_GEN_NU2_S 3 +#define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_ON_TIME_M \ + 0x00000007 // Configuration of ON-TIME for + // dividing PLL clk (240 MHz) in + // generation of MCSPI_A1 func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MCSPI_A1_CLK_GEN_MCSPI_A1_PLLCLKDIV_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_A1_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_A1_CLK_GATING_NU1_M \ + 0x00FE0000 + +#define APPS_RCM_MCSPI_A1_CLK_GATING_NU1_S 17 +#define APPS_RCM_MCSPI_A1_CLK_GATING_MCSPI_A1_DSLP_CLK_ENABLE \ + 0x00010000 // 0 - Disable MCSPI_A1 clk during + // deep-sleep mode + +#define APPS_RCM_MCSPI_A1_CLK_GATING_NU2_M \ + 0x0000FE00 + +#define APPS_RCM_MCSPI_A1_CLK_GATING_NU2_S 9 +#define APPS_RCM_MCSPI_A1_CLK_GATING_MCSPI_A1_SLP_CLK_ENABLE \ + 0x00000100 // 1- Enable MCSPI_A1 clk during + // sleep mode ; 0- Disable MCSPI_A1 + // clk during sleep mode + +#define APPS_RCM_MCSPI_A1_CLK_GATING_NU3_M \ + 0x000000FE + +#define APPS_RCM_MCSPI_A1_CLK_GATING_NU3_S 1 +#define APPS_RCM_MCSPI_A1_CLK_GATING_MCSPI_A1_RUN_CLK_ENABLE \ + 0x00000001 // 1- Enable MCSPI_A1 clk during + // run mode ; 0- Disable MCSPI_A1 + // clk during run mode + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_A1_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_A1_SOFT_RESET_MCSPI_A1_ENABLED_STATUS \ + 0x00000002 // 1 - MCSPI_A1 Clocks/Resets are + // enabled ; 0 - MCSPI_A1 + // Clocks/Resets are disabled + +#define APPS_RCM_MCSPI_A1_SOFT_RESET_MCSPI_A1_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for + // MCSPI_A1-core ; 0 - De-assert + // reset for MCSPI_A1-core + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_A2_CLK_GEN register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_BAUD_CLK_SEL \ + 0x00010000 // 0 - XTAL clk is used as baud-clk + // for MCSPI_A2 ; 1 - PLL divclk is + // used as baud-clk for MCSPI_A2 + +#define APPS_RCM_MCSPI_A2_CLK_GEN_NU1_M \ + 0x0000F800 + +#define APPS_RCM_MCSPI_A2_CLK_GEN_NU1_S 11 +#define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_OFF_TIME_M \ + 0x00000700 // Configuration of OFF-TIME for + // dividing PLL clk (240 MHz) in + // generation of MCSPI_A2 func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_OFF_TIME_S 8 +#define APPS_RCM_MCSPI_A2_CLK_GEN_NU2_M \ + 0x000000F8 + +#define APPS_RCM_MCSPI_A2_CLK_GEN_NU2_S 3 +#define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_ON_TIME_M \ + 0x00000007 // Configuration of OFF-TIME for + // dividing PLL clk (240 MHz) in + // generation of MCSPI_A2 func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MCSPI_A2_CLK_GEN_MCSPI_A2_PLLCKDIV_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_A2_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_A2_CLK_GATING_NU1_M \ + 0x00FE0000 + +#define APPS_RCM_MCSPI_A2_CLK_GATING_NU1_S 17 +#define APPS_RCM_MCSPI_A2_CLK_GATING_MCSPI_A2_DSLP_CLK_ENABLE \ + 0x00010000 // 0 - Disable MCSPI_A2 clk during + // deep-sleep mode + +#define APPS_RCM_MCSPI_A2_CLK_GATING_NU2_M \ + 0x0000FE00 + +#define APPS_RCM_MCSPI_A2_CLK_GATING_NU2_S 9 +#define APPS_RCM_MCSPI_A2_CLK_GATING_MCSPI_A2_SLP_CLK_ENABLE \ + 0x00000100 // 1- Enable MCSPI_A2 clk during + // sleep mode ; 0- Disable MCSPI_A2 + // clk during sleep mode + +#define APPS_RCM_MCSPI_A2_CLK_GATING_NU3_M \ + 0x000000FE + +#define APPS_RCM_MCSPI_A2_CLK_GATING_NU3_S 1 +#define APPS_RCM_MCSPI_A2_CLK_GATING_MCSPI_A2_RUN_CLK_ENABLE \ + 0x00000001 // 1- Enable MCSPI_A2 clk during + // run mode ; 0- Disable MCSPI_A2 + // clk during run mode + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_A2_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_A2_SOFT_RESET_MCSPI_A2_ENABLED_STATUS \ + 0x00000002 // 1 - MCSPI_A2 Clocks/Resets are + // enabled ; 0 - MCSPI_A2 + // Clocks/Resets are disabled + +#define APPS_RCM_MCSPI_A2_SOFT_RESET_MCSPI_A2_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for + // MCSPI_A2-core ; 0 - De-assert + // reset for MCSPI_A2-core + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_UDMA_A_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_UDMA_A_CLK_GATING_UDMA_A_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable UDMA_A clk during + // deep-sleep mode 0 - Disable + // UDMA_A clk during deep-sleep mode + // ; + +#define APPS_RCM_UDMA_A_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_UDMA_A_CLK_GATING_NU1_S 9 +#define APPS_RCM_UDMA_A_CLK_GATING_UDMA_A_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable UDMA_A clk during + // sleep mode 0 - Disable UDMA_A clk + // during sleep mode ; + +#define APPS_RCM_UDMA_A_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_UDMA_A_CLK_GATING_NU2_S 1 +#define APPS_RCM_UDMA_A_CLK_GATING_UDMA_A_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable UDMA_A clk during run + // mode 0 - Disable UDMA_A clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_UDMA_A_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_UDMA_A_SOFT_RESET_UDMA_A_ENABLED_STATUS \ + 0x00000002 // 1 - UDMA_A Clocks/Resets are + // enabled ; 0 - UDMA_A + // Clocks/Resets are disabled + +#define APPS_RCM_UDMA_A_SOFT_RESET_UDMA_A_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for DMA_A ; 0 - + // De-assert reset for DMA_A + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_A_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_A_CLK_GATING_GPIO_A_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable GPIO_A clk during + // deep-sleep mode 0 - Disable + // GPIO_A clk during deep-sleep mode + // ; + +#define APPS_RCM_GPIO_A_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPIO_A_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPIO_A_CLK_GATING_GPIO_A_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable GPIO_A clk during + // sleep mode 0 - Disable GPIO_A clk + // during sleep mode ; + +#define APPS_RCM_GPIO_A_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPIO_A_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPIO_A_CLK_GATING_GPIO_A_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable GPIO_A clk during run + // mode 0 - Disable GPIO_A clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_A_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_A_SOFT_RESET_GPIO_A_ENABLED_STATUS \ + 0x00000002 // 1 - GPIO_A Clocks/Resets are + // enabled ; 0 - GPIO_A + // Clocks/Resets are disabled + +#define APPS_RCM_GPIO_A_SOFT_RESET_GPIO_A_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for GPIO_A ; 0 + // - De-assert reset for GPIO_A + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_B_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_B_CLK_GATING_GPIO_B_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable GPIO_B clk during + // deep-sleep mode 0 - Disable + // GPIO_B clk during deep-sleep mode + // ; + +#define APPS_RCM_GPIO_B_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPIO_B_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPIO_B_CLK_GATING_GPIO_B_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable GPIO_B clk during + // sleep mode 0 - Disable GPIO_B clk + // during sleep mode ; + +#define APPS_RCM_GPIO_B_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPIO_B_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPIO_B_CLK_GATING_GPIO_B_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable GPIO_B clk during run + // mode 0 - Disable GPIO_B clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_B_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_B_SOFT_RESET_GPIO_B_ENABLED_STATUS \ + 0x00000002 // 1 - GPIO_B Clocks/Resets are + // enabled ; 0 - GPIO_B + // Clocks/Resets are disabled + +#define APPS_RCM_GPIO_B_SOFT_RESET_GPIO_B_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for GPIO_B ; 0 + // - De-assert reset for GPIO_B + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_C_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_C_CLK_GATING_GPIO_C_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable GPIO_C clk during + // deep-sleep mode 0 - Disable + // GPIO_C clk during deep-sleep mode + // ; + +#define APPS_RCM_GPIO_C_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPIO_C_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPIO_C_CLK_GATING_GPIO_C_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable GPIO_C clk during + // sleep mode 0 - Disable GPIO_C clk + // during sleep mode ; + +#define APPS_RCM_GPIO_C_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPIO_C_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPIO_C_CLK_GATING_GPIO_C_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable GPIO_C clk during run + // mode 0 - Disable GPIO_C clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_C_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_C_SOFT_RESET_GPIO_C_ENABLED_STATUS \ + 0x00000002 // 1 - GPIO_C Clocks/Resets are + // enabled ; 0 - GPIO_C + // Clocks/Resets are disabled + +#define APPS_RCM_GPIO_C_SOFT_RESET_GPIO_C_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for GPIO_C ; 0 + // - De-assert reset for GPIO_C + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_D_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_D_CLK_GATING_GPIO_D_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable GPIO_D clk during + // deep-sleep mode 0 - Disable + // GPIO_D clk during deep-sleep mode + // ; + +#define APPS_RCM_GPIO_D_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPIO_D_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPIO_D_CLK_GATING_GPIO_D_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable GPIO_D clk during + // sleep mode 0 - Disable GPIO_D clk + // during sleep mode ; + +#define APPS_RCM_GPIO_D_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPIO_D_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPIO_D_CLK_GATING_GPIO_D_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable GPIO_D clk during run + // mode 0 - Disable GPIO_D clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_D_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_D_SOFT_RESET_GPIO_D_ENABLED_STATUS \ + 0x00000002 // 1 - GPIO_D Clocks/Resets are + // enabled ; 0 - GPIO_D + // Clocks/Resets are disabled + +#define APPS_RCM_GPIO_D_SOFT_RESET_GPIO_D_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for GPIO_D ; 0 + // - De-assert reset for GPIO_D + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_E_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_E_CLK_GATING_GPIO_E_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable GPIO_E clk during + // deep-sleep mode 0 - Disable + // GPIO_E clk during deep-sleep mode + // ; + +#define APPS_RCM_GPIO_E_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPIO_E_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPIO_E_CLK_GATING_GPIO_E_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable GPIO_E clk during + // sleep mode 0 - Disable GPIO_E clk + // during sleep mode ; + +#define APPS_RCM_GPIO_E_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPIO_E_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPIO_E_CLK_GATING_GPIO_E_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable GPIO_E clk during run + // mode 0 - Disable GPIO_E clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPIO_E_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPIO_E_SOFT_RESET_GPIO_E_ENABLED_STATUS \ + 0x00000002 // 1 - GPIO_E Clocks/Resets are + // enabled ; 0 - GPIO_E + // Clocks/Resets are disabled + +#define APPS_RCM_GPIO_E_SOFT_RESET_GPIO_E_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for GPIO_E ; 0 + // - De-assert reset for GPIO_E + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_WDOG_A_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_BAUD_CLK_SEL_M \ + 0x03000000 // "00" - Sysclk ; "01" - REF_CLK + // (38.4 MHz) ; "10/11" - Slow_clk + +#define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_BAUD_CLK_SEL_S 24 +#define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable WDOG_A clk during + // deep-sleep mode 0 - Disable + // WDOG_A clk during deep-sleep mode + // ; + +#define APPS_RCM_WDOG_A_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_WDOG_A_CLK_GATING_NU1_S 9 +#define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable WDOG_A clk during + // sleep mode 0 - Disable WDOG_A clk + // during sleep mode ; + +#define APPS_RCM_WDOG_A_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_WDOG_A_CLK_GATING_NU2_S 1 +#define APPS_RCM_WDOG_A_CLK_GATING_WDOG_A_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable WDOG_A clk during run + // mode 0 - Disable WDOG_A clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_WDOG_A_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_WDOG_A_SOFT_RESET_WDOG_A_ENABLED_STATUS \ + 0x00000002 // 1 - WDOG_A Clocks/Resets are + // enabled ; 0 - WDOG_A + // Clocks/Resets are disabled + +#define APPS_RCM_WDOG_A_SOFT_RESET_WDOG_A_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for WDOG_A ; 0 + // - De-assert reset for WDOG_A + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_UART_A0_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_UART_A0_CLK_GATING_UART_A0_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable UART_A0 clk during + // deep-sleep mode 0 - Disable + // UART_A0 clk during deep-sleep + // mode ; + +#define APPS_RCM_UART_A0_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_UART_A0_CLK_GATING_NU1_S 9 +#define APPS_RCM_UART_A0_CLK_GATING_UART_A0_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable UART_A0 clk during + // sleep mode 0 - Disable UART_A0 + // clk during sleep mode ; + +#define APPS_RCM_UART_A0_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_UART_A0_CLK_GATING_NU2_S 1 +#define APPS_RCM_UART_A0_CLK_GATING_UART_A0_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable UART_A0 clk during + // run mode 0 - Disable UART_A0 clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_UART_A0_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_UART_A0_SOFT_RESET_UART_A0_ENABLED_STATUS \ + 0x00000002 // 1 - UART_A0 Clocks/Resets are + // enabled ; 0 - UART_A0 + // Clocks/Resets are disabled + +#define APPS_RCM_UART_A0_SOFT_RESET_UART_A0_SOFT_RESET \ + 0x00000001 // 1 - Assert reset for UART_A0 ; 0 + // - De-assert reset for UART_A0 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_UART_A1_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_UART_A1_CLK_GATING_UART_A1_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable UART_A1 clk during + // deep-sleep mode 0 - Disable + // UART_A1 clk during deep-sleep + // mode ; + +#define APPS_RCM_UART_A1_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_UART_A1_CLK_GATING_NU1_S 9 +#define APPS_RCM_UART_A1_CLK_GATING_UART_A1_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable UART_A1 clk during + // sleep mode 0 - Disable UART_A1 + // clk during sleep mode ; + +#define APPS_RCM_UART_A1_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_UART_A1_CLK_GATING_NU2_S 1 +#define APPS_RCM_UART_A1_CLK_GATING_UART_A1_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable UART_A1 clk during + // run mode 0 - Disable UART_A1 clk + // during run mode ; + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_UART_A1_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_UART_A1_SOFT_RESET_UART_A1_ENABLED_STATUS \ + 0x00000002 // 1 - UART_A1 Clocks/Resets are + // enabled ; 0 - UART_A1 + // Clocks/Resets are disabled + +#define APPS_RCM_UART_A1_SOFT_RESET_UART_A1_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // UART_A1 ; 0 - De-assert the soft + // reset for UART_A1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A0_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A0_CLK_GATING_GPT_A0_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable the GPT_A0 clock + // during deep-sleep ; 0 - Disable + // the GPT_A0 clock during + // deep-sleep + +#define APPS_RCM_GPT_A0_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPT_A0_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPT_A0_CLK_GATING_GPT_A0_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable the GPT_A0 clock + // during sleep ; 0 - Disable the + // GPT_A0 clock during sleep + +#define APPS_RCM_GPT_A0_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPT_A0_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPT_A0_CLK_GATING_GPT_A0_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable the GPT_A0 clock + // during run ; 0 - Disable the + // GPT_A0 clock during run + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A0_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A0_SOFT_RESET_GPT_A0_ENABLED_STATUS \ + 0x00000002 // 1 - GPT_A0 clocks/resets are + // enabled ; 0 - GPT_A0 + // clocks/resets are disabled + +#define APPS_RCM_GPT_A0_SOFT_RESET_GPT_A0_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // GPT_A0 ; 0 - De-assert the soft + // reset for GPT_A0 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A1_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A1_CLK_GATING_GPT_A1_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable the GPT_A1 clock + // during deep-sleep ; 0 - Disable + // the GPT_A1 clock during + // deep-sleep + +#define APPS_RCM_GPT_A1_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPT_A1_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPT_A1_CLK_GATING_GPT_A1_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable the GPT_A1 clock + // during sleep ; 0 - Disable the + // GPT_A1 clock during sleep + +#define APPS_RCM_GPT_A1_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPT_A1_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPT_A1_CLK_GATING_GPT_A1_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable the GPT_A1 clock + // during run ; 0 - Disable the + // GPT_A1 clock during run + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A1_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A1_SOFT_RESET_GPT_A1_ENABLED_STATUS \ + 0x00000002 // 1 - GPT_A1 clocks/resets are + // enabled ; 0 - GPT_A1 + // clocks/resets are disabled + +#define APPS_RCM_GPT_A1_SOFT_RESET_GPT_A1_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // GPT_A1 ; 0 - De-assert the soft + // reset for GPT_A1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A2_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A2_CLK_GATING_GPT_A2_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable the GPT_A2 clock + // during deep-sleep ; 0 - Disable + // the GPT_A2 clock during + // deep-sleep + +#define APPS_RCM_GPT_A2_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPT_A2_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPT_A2_CLK_GATING_GPT_A2_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable the GPT_A2 clock + // during sleep ; 0 - Disable the + // GPT_A2 clock during sleep + +#define APPS_RCM_GPT_A2_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPT_A2_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPT_A2_CLK_GATING_GPT_A2_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable the GPT_A2 clock + // during run ; 0 - Disable the + // GPT_A2 clock during run + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A2_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A2_SOFT_RESET_GPT_A2_ENABLED_STATUS \ + 0x00000002 // 1 - GPT_A2 clocks/resets are + // enabled ; 0 - GPT_A2 + // clocks/resets are disabled + +#define APPS_RCM_GPT_A2_SOFT_RESET_GPT_A2_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // GPT_A2 ; 0 - De-assert the soft + // reset for GPT_A2 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A3_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A3_CLK_GATING_GPT_A3_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable the GPT_A3 clock + // during deep-sleep ; 0 - Disable + // the GPT_A3 clock during + // deep-sleep + +#define APPS_RCM_GPT_A3_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_GPT_A3_CLK_GATING_NU1_S 9 +#define APPS_RCM_GPT_A3_CLK_GATING_GPT_A3_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable the GPT_A3 clock + // during sleep ; 0 - Disable the + // GPT_A3 clock during sleep + +#define APPS_RCM_GPT_A3_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_GPT_A3_CLK_GATING_NU2_S 1 +#define APPS_RCM_GPT_A3_CLK_GATING_GPT_A3_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable the GPT_A3 clock + // during run ; 0 - Disable the + // GPT_A3 clock during run + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_GPT_A3_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_GPT_A3_SOFT_RESET_GPT_A3_ENABLED_STATUS \ + 0x00000002 // 1 - GPT_A3 Clocks/resets are + // enabled ; 0 - GPT_A3 + // Clocks/resets are disabled + +#define APPS_RCM_GPT_A3_SOFT_RESET_GPT_A3_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // GPT_A3 ; 0 - De-assert the soft + // reset for GPT_A3 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCASP_FRAC_CLK_CONFIG0 register. +// +//****************************************************************************** +#define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_DIVISOR_M \ + 0x03FF0000 + +#define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_DIVISOR_S 16 +#define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_FRACTION_M \ + 0x0000FFFF + +#define APPS_RCM_MCASP_FRAC_CLK_CONFIG0_MCASP_FRAC_DIV_FRACTION_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCASP_FRAC_CLK_CONFIG1 register. +// +//****************************************************************************** +#define APPS_RCM_MCASP_FRAC_CLK_CONFIG1_MCASP_FRAC_DIV_SOFT_RESET \ + 0x00010000 // 1 - Assert the reset for MCASP + // Frac-clk div; 0 - Donot assert + // the reset for MCASP frac clk-div + +#define APPS_RCM_MCASP_FRAC_CLK_CONFIG1_MCASP_FRAC_DIV_PERIOD_M \ + 0x000003FF + +#define APPS_RCM_MCASP_FRAC_CLK_CONFIG1_MCASP_FRAC_DIV_PERIOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_CRYPTO_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_CRYPTO_CLK_GATING_CRYPTO_DSLP_CLK_ENABLE \ + 0x00010000 // 0 - Disable the Crypto clock + // during deep-sleep + +#define APPS_RCM_CRYPTO_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_CRYPTO_CLK_GATING_NU1_S 9 +#define APPS_RCM_CRYPTO_CLK_GATING_CRYPTO_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable the Crypto clock + // during sleep ; 0 - Disable the + // Crypto clock during sleep + +#define APPS_RCM_CRYPTO_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_CRYPTO_CLK_GATING_NU2_S 1 +#define APPS_RCM_CRYPTO_CLK_GATING_CRYPTO_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable the Crypto clock + // during run ; 0 - Disable the + // Crypto clock during run + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_CRYPTO_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_CRYPTO_SOFT_RESET_CRYPTO_ENABLED_STATUS \ + 0x00000002 // 1 - Crypto clocks/resets are + // enabled ; 0 - Crypto + // clocks/resets are disabled + +#define APPS_RCM_CRYPTO_SOFT_RESET_CRYPTO_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // Crypto ; 0 - De-assert the soft + // reset for Crypto + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_S0_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_S0_CLK_GATING_MCSPI_S0_DSLP_CLK_ENABLE \ + 0x00010000 // 0 - Disable the MCSPI_S0 clock + // during deep-sleep + +#define APPS_RCM_MCSPI_S0_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_MCSPI_S0_CLK_GATING_NU1_S 9 +#define APPS_RCM_MCSPI_S0_CLK_GATING_MCSPI_S0_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable the MCSPI_S0 clock + // during sleep ; 0 - Disable the + // MCSPI_S0 clock during sleep + +#define APPS_RCM_MCSPI_S0_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_MCSPI_S0_CLK_GATING_NU2_S 1 +#define APPS_RCM_MCSPI_S0_CLK_GATING_MCSPI_S0_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable the MCSPI_S0 clock + // during run ; 0 - Disable the + // MCSPI_S0 clock during run + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_S0_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_S0_SOFT_RESET_MCSPI_S0_ENABLED_STATUS \ + 0x00000002 // 1 - MCSPI_S0 Clocks/Resets are + // enabled ; 0 - MCSPI_S0 + // Clocks/resets are disabled + +#define APPS_RCM_MCSPI_S0_SOFT_RESET_MCSPI_S0_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // MCSPI_S0 ; 0 - De-assert the soft + // reset for MCSPI_S0 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_MCSPI_S0_CLKDIV_CFG register. +// +//****************************************************************************** +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_BAUD_CLK_SEL \ + 0x00010000 // 0 - XTAL clk is used as baud-clk + // for MCSPI_S0 ; 1 - PLL divclk is + // used as buad-clk for MCSPI_S0 + +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU1_M \ + 0x0000F800 + +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU1_S 11 +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_OFF_TIME_M \ + 0x00000700 // Configuration of OFF-TIME for + // dividing PLL clk (240 MHz) in + // generation of MCSPI_S0 func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_OFF_TIME_S 8 +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU2_M \ + 0x000000F8 + +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_NU2_S 3 +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_ON_TIME_M \ + 0x00000007 // Configuration of ON-TIME for + // dividing PLL clk (240 MHz) in + // generation of MCSPI_S0 func-clk : + // "000" - 1 "001" - 2 "010" - 3 + // "011" - 4 "100" - 5 "101" - 6 + // "110" - 7 "111" - 8 + +#define APPS_RCM_MCSPI_S0_CLKDIV_CFG_MCSPI_S0_PLLCLKDIV_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_I2C_CLK_GATING register. +// +//****************************************************************************** +#define APPS_RCM_I2C_CLK_GATING_I2C_DSLP_CLK_ENABLE \ + 0x00010000 // 1 - Enable the I2C Clock during + // deep-sleep 0 - Disable the I2C + // clock during deep-sleep + +#define APPS_RCM_I2C_CLK_GATING_NU1_M \ + 0x0000FE00 + +#define APPS_RCM_I2C_CLK_GATING_NU1_S 9 +#define APPS_RCM_I2C_CLK_GATING_I2C_SLP_CLK_ENABLE \ + 0x00000100 // 1 - Enable the I2C clock during + // sleep ; 0 - Disable the I2C clock + // during sleep + +#define APPS_RCM_I2C_CLK_GATING_NU2_M \ + 0x000000FE + +#define APPS_RCM_I2C_CLK_GATING_NU2_S 1 +#define APPS_RCM_I2C_CLK_GATING_I2C_RUN_CLK_ENABLE \ + 0x00000001 // 1 - Enable the I2C clock during + // run ; 0 - Disable the I2C clock + // during run + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_I2C_SOFT_RESET register. +// +//****************************************************************************** +#define APPS_RCM_I2C_SOFT_RESET_I2C_ENABLED_STATUS \ + 0x00000002 // 1 - I2C Clocks/Resets are + // enabled ; 0 - I2C clocks/resets + // are disabled + +#define APPS_RCM_I2C_SOFT_RESET_I2C_SOFT_RESET \ + 0x00000001 // 1 - Assert the soft reset for + // Shared-I2C ; 0 - De-assert the + // soft reset for Shared-I2C + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_LPDS_REQ register. +// +//****************************************************************************** +#define APPS_RCM_APPS_LPDS_REQ_APPS_LPDS_REQ \ + 0x00000001 // 1 - Request for LPDS + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_TURBO_REQ register. +// +//****************************************************************************** +#define APPS_RCM_APPS_TURBO_REQ_APPS_TURBO_REQ \ + 0x00000001 // 1 - Request for TURBO + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_DSLP_WAKE_CONFIG register. +// +//****************************************************************************** +#define APPS_RCM_APPS_DSLP_WAKE_CONFIG_DSLP_WAKE_FROM_NWP_ENABLE \ + 0x00000002 // 1 - Enable the NWP to wake APPS + // from deep-sleep ; 0 - Disable NWP + // to wake APPS from deep-sleep + +#define APPS_RCM_APPS_DSLP_WAKE_CONFIG_DSLP_WAKE_TIMER_ENABLE \ + 0x00000001 // 1 - Enable deep-sleep wake timer + // in APPS RCM for deep-sleep; 0 - + // Disable deep-sleep wake timer in + // APPS RCM + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_DSLP_WAKE_TIMER_CFG register. +// +//****************************************************************************** +#define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_OPP_CFG_M \ + 0xFFFF0000 // Configuration (in slow_clks) + // which says when to request for + // OPP during deep-sleep exit + +#define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_OPP_CFG_S 16 +#define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_WAKE_CFG_M \ + 0x0000FFFF // Configuration (in slow_clks) + // which says when to request for + // WAKE during deep-sleep exit + +#define APPS_RCM_APPS_DSLP_WAKE_TIMER_CFG_DSLP_WAKE_TIMER_WAKE_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_RCM_SLP_WAKE_ENABLE register. +// +//****************************************************************************** +#define APPS_RCM_APPS_RCM_SLP_WAKE_ENABLE_SLP_WAKE_FROM_NWP_ENABLE \ + 0x00000002 // 1- Enable the sleep wakeup due + // to NWP request. 0- Disable the + // sleep wakeup due to NWP request + +#define APPS_RCM_APPS_RCM_SLP_WAKE_ENABLE_SLP_WAKE_TIMER_ENABLE \ + 0x00000001 // 1- Enable the sleep wakeup due + // to sleep-timer; 0-Disable the + // sleep wakeup due to sleep-timer + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_SLP_WAKETIMER_CFG register. +// +//****************************************************************************** +#define APPS_RCM_APPS_SLP_WAKETIMER_CFG_SLP_WAKE_TIMER_CFG_M \ + 0xFFFFFFFF // Configuration (number of + // sysclks-80MHz) for the Sleep + // wakeup timer + +#define APPS_RCM_APPS_SLP_WAKETIMER_CFG_SLP_WAKE_TIMER_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_TO_NWP_WAKE_REQUEST register. +// +//****************************************************************************** +#define APPS_RCM_APPS_TO_NWP_WAKE_REQUEST_APPS_TO_NWP_WAKEUP_REQUEST \ + 0x00000001 // When 1 => APPS generated a wake + // request to NWP (When NWP is in + // any of its low-power modes : + // SLP/DSLP/LPDS) + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// APPS_RCM_O_APPS_RCM_INTERRUPT_STATUS register. +// +//****************************************************************************** +#define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_deep_sleep_timer_wake \ + 0x00000008 // 1 - Indicates that deep-sleep + // timer expiry had caused the + // wakeup from deep-sleep + +#define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_sleep_timer_wake \ + 0x00000004 // 1 - Indicates that sleep timer + // expiry had caused the wakeup from + // sleep + +#define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_deep_sleep_wake_from_nwp \ + 0x00000002 // 1 - Indicates that NWP had + // caused the wakeup from deep-sleep + +#define APPS_RCM_APPS_RCM_INTERRUPT_STATUS_apps_sleep_wake_from_nwp \ + 0x00000001 // 1 - Indicates that NWP had + // caused the wakeup from Sleep + + + + +#endif // __HW_APPS_RCM_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_camera.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_camera.h new file mode 100644 index 00000000..4461a284 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_camera.h @@ -0,0 +1,519 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_CAMERA_H__ +#define __HW_CAMERA_H__ + +//***************************************************************************** +// +// The following are defines for the CAMERA register offsets. +// +//***************************************************************************** +#define CAMERA_O_CC_REVISION 0x00000000 // This register contains the IP + // revision code ( Parallel Mode) +#define CAMERA_O_CC_SYSCONFIG 0x00000010 // This register controls the + // various parameters of the OCP + // interface (CCP and Parallel Mode) +#define CAMERA_O_CC_SYSSTATUS 0x00000014 // This register provides status + // information about the module + // excluding the interrupt status + // information (CCP and Parallel + // Mode) +#define CAMERA_O_CC_IRQSTATUS 0x00000018 // The interrupt status regroups + // all the status of the module + // internal events that can generate + // an interrupt (CCP & Parallel + // Mode) +#define CAMERA_O_CC_IRQENABLE 0x0000001C // The interrupt enable register + // allows to enable/disable the + // module internal sources of + // interrupt on an event-by-event + // basis (CCP & Parallel Mode) +#define CAMERA_O_CC_CTRL 0x00000040 // This register controls the + // various parameters of the Camera + // Core block (CCP & Parallel Mode) +#define CAMERA_O_CC_CTRL_DMA 0x00000044 // This register controls the DMA + // interface of the Camera Core + // block (CCP & Parallel Mode) +#define CAMERA_O_CC_CTRL_XCLK 0x00000048 // This register control the value + // of the clock divisor used to + // generate the external clock + // (Parallel Mode) +#define CAMERA_O_CC_FIFO_DATA 0x0000004C // This register allows to write to + // the FIFO and read from the FIFO + // (CCP & Parallel Mode) +#define CAMERA_O_CC_TEST 0x00000050 // This register shows the status + // of some important variables of + // the camera core module (CCP & + // Parallel Mode) +#define CAMERA_O_CC_GEN_PAR 0x00000054 // This register shows the values + // of the generic parameters of the + // module + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_REVISION register. +// +//****************************************************************************** +#define CAMERA_CC_REVISION_REV_M \ + 0x000000FF // IP revision [7:4] Major revision + // [3:0] Minor revision Examples: + // 0x10 for 1.0 0x21 for 2.1 + +#define CAMERA_CC_REVISION_REV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_SYSCONFIG register. +// +//****************************************************************************** +#define CAMERA_CC_SYSCONFIG_S_IDLE_MODE_M \ + 0x00000018 // Slave interface power management + // req/ack control """00"" + // Force-idle. An idle request is + // acknoledged unconditionally" + // """01"" No-idle. An idle request + // is never acknowledged" """10"" + // reserved (Smart-idle not + // implemented)" + +#define CAMERA_CC_SYSCONFIG_S_IDLE_MODE_S 3 +#define CAMERA_CC_SYSCONFIG_SOFT_RESET \ + 0x00000002 // Software reset. Set this bit to + // 1 to trigger a module reset. The + // bit is automatically reset by the + // hardware. During reset it always + // returns 0. 0 Normal mode 1 The + // module is reset + +#define CAMERA_CC_SYSCONFIG_AUTO_IDLE \ + 0x00000001 // Internal OCP clock gating + // strategy 0 OCP clock is + // free-running 1 Automatic OCP + // clock gating strategy is applied + // based on the OCP interface + // activity + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_SYSSTATUS register. +// +//****************************************************************************** +#define CAMERA_CC_SYSSTATUS_RESET_DONE2 \ + 0x00000001 // Internal Reset Monitoring 0 + // Internal module reset is on-going + // 1 Reset completed + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_IRQSTATUS register. +// +//****************************************************************************** +#define CAMERA_CC_IRQSTATUS_FS_IRQ \ + 0x00080000 // Frame Start has occurred 0 Event + // false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_LE_IRQ \ + 0x00040000 // Line End has occurred 0 Event + // false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_LS_IRQ \ + 0x00020000 // Line Start has occurred 0 Event + // false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_FE_IRQ \ + 0x00010000 // Frame End has occurred 0 Event + // false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_FSP_ERR_IRQ \ + 0x00000800 // FSP code error 0 Event false "1 + // Event is true (""pending"")" 0 + // Event status bit unchanged 1 + // Event status bit is reset + +#define CAMERA_CC_IRQSTATUS_FW_ERR_IRQ \ + 0x00000400 // Frame Height Error 0 Event false + // "1 Event is true (""pending"")" 0 + // Event status bit unchanged 1 + // Event status bit is reset + +#define CAMERA_CC_IRQSTATUS_FSC_ERR_IRQ \ + 0x00000200 // False Synchronization Code 0 + // Event false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_SSC_ERR_IRQ \ + 0x00000100 // Shifted Synchronization Code 0 + // Event false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_FIFO_NONEMPTY_IRQ \ + 0x00000010 // FIFO is not empty 0 Event false + // "1 Event is true (""pending"")" 0 + // Event status bit unchanged 1 + // Event status bit is reset + +#define CAMERA_CC_IRQSTATUS_FIFO_FULL_IRQ \ + 0x00000008 // FIFO is full 0 Event false "1 + // Event is true (""pending"")" 0 + // Event status bit unchanged 1 + // Event status bit is reset + +#define CAMERA_CC_IRQSTATUS_FIFO_THR_IRQ \ + 0x00000004 // FIFO threshold has been reached + // 0 Event false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_FIFO_OF_IRQ \ + 0x00000002 // FIFO overflow has occurred 0 + // Event false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +#define CAMERA_CC_IRQSTATUS_FIFO_UF_IRQ \ + 0x00000001 // FIFO underflow has occurred 0 + // Event false "1 Event is true + // (""pending"")" 0 Event status bit + // unchanged 1 Event status bit is + // reset + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_IRQENABLE register. +// +//****************************************************************************** +#define CAMERA_CC_IRQENABLE_FS_IRQ_EN \ + 0x00080000 // Frame Start Interrupt Enable 0 + // Event is masked 1 Event generates + // an interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_LE_IRQ_EN \ + 0x00040000 // Line End Interrupt Enable 0 + // Event is masked 1 Event generates + // an interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_LS_IRQ_EN \ + 0x00020000 // Line Start Interrupt Enable 0 + // Event is masked 1 Event generates + // an interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_FE_IRQ_EN \ + 0x00010000 // Frame End Interrupt Enable 0 + // Event is masked 1 Event generates + // an interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_FSP_IRQ_EN \ + 0x00000800 // FSP code Interrupt Enable 0 + // Event is masked 1 Event generates + // an interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_FW_ERR_IRQ_EN \ + 0x00000400 // Frame Height Error Interrupt + // Enable 0 Event is masked 1 Event + // generates an interrupt when it + // occurs + +#define CAMERA_CC_IRQENABLE_FSC_ERR_IRQ_EN \ + 0x00000200 // False Synchronization Code + // Interrupt Enable 0 Event is + // masked 1 Event generates an + // interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_SSC_ERR_IRQ_EN \ + 0x00000100 // False Synchronization Code + // Interrupt Enable 0 Event is + // masked 1 Event generates an + // interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_FIFO_NONEMPTY_IRQ_EN \ + 0x00000010 // FIFO Threshold Interrupt Enable + // 0 Event is masked 1 Event + // generates an interrupt when it + // occurs + +#define CAMERA_CC_IRQENABLE_FIFO_FULL_IRQ_EN \ + 0x00000008 // FIFO Threshold Interrupt Enable + // 0 Event is masked 1 Event + // generates an interrupt when it + // occurs + +#define CAMERA_CC_IRQENABLE_FIFO_THR_IRQ_EN \ + 0x00000004 // FIFO Threshold Interrupt Enable + // 0 Event is masked 1 Event + // generates an interrupt when it + // occurs + +#define CAMERA_CC_IRQENABLE_FIFO_OF_IRQ_EN \ + 0x00000002 // FIFO Overflow Interrupt Enable 0 + // Event is masked 1 Event generates + // an interrupt when it occurs + +#define CAMERA_CC_IRQENABLE_FIFO_UF_IRQ_EN \ + 0x00000001 // FIFO Underflow Interrupt Enable + // 0 Event is masked 1 Event + // generates an interrupt when it + // occurs + +//****************************************************************************** +// +// The following are defines for the bit fields in the CAMERA_O_CC_CTRL register. +// +//****************************************************************************** +#define CAMERA_CC_CTRL_CC_IF_SYNCHRO \ + 0x00080000 // Synchronize all camera sensor + // inputs This must be set during + // the configuration phase before + // CC_EN set to '1'. This can be + // used in very high frequency to + // avoid dependancy to the IO + // timings. 0 No synchro (most of + // applications) 1 Synchro enabled + // (should never be required) + +#define CAMERA_CC_CTRL_CC_RST 0x00040000 // Resets all the internal finite + // states machines of the camera + // core module - by writing a 1 to + // this bit. must be applied when + // CC_EN = 0 Reads returns 0 +#define CAMERA_CC_CTRL_CC_FRAME_TRIG \ + 0x00020000 // Set the modality in which CC_EN + // works when a disabling of the + // sensor camera core is wanted "If + // CC_FRAME_TRIG = 1 by writing + // ""0"" to CC_EN" the module is + // disabled at the end of the frame + // "If CC_FRAME_TRIG = 0 by writing + // ""0"" to CC_EN" the module is + // disabled immediately + +#define CAMERA_CC_CTRL_CC_EN 0x00010000 // Enables the sensor interface of + // the camera core module "By + // writing ""1"" to this field the + // module is enabled." "By writing + // ""0"" to this field the module is + // disabled at" the end of the frame + // if CC_FRAM_TRIG =1 and is + // disabled immediately if + // CC_FRAM_TRIG = 0 +#define CAMERA_CC_CTRL_NOBT_SYNCHRO \ + 0x00002000 // Enables to start at the + // beginning of the frame or not in + // NoBT 0 Acquisition starts when + // Vertical synchro is high 1 + // Acquisition starts when Vertical + // synchro goes from low to high + // (beginning of the frame) - + // Recommended. + +#define CAMERA_CC_CTRL_BT_CORRECT \ + 0x00001000 // Enables the correction within + // the sync codes in BT mode 0 + // correction is not enabled 1 + // correction is enabled + +#define CAMERA_CC_CTRL_PAR_ORDERCAM \ + 0x00000800 // Enables swap between image-data + // in parallel mode 0 swap is not + // enabled 1 swap is enabled + +#define CAMERA_CC_CTRL_PAR_CLK_POL \ + 0x00000400 // Inverts the clock coming from + // the sensor in parallel mode 0 + // clock not inverted - data sampled + // on rising edge 1 clock inverted - + // data sampled on falling edge + +#define CAMERA_CC_CTRL_NOBT_HS_POL \ + 0x00000200 // Sets the polarity of the + // synchronization signals in NOBT + // parallel mode 0 CAM_P_HS is + // active high 1 CAM_P_HS is active + // low + +#define CAMERA_CC_CTRL_NOBT_VS_POL \ + 0x00000100 // Sets the polarity of the + // synchronization signals in NOBT + // parallel mode 0 CAM_P_VS is + // active high 1 CAM_P_VS is active + // low + +#define CAMERA_CC_CTRL_PAR_MODE_M \ + 0x0000000E // Sets the Protocol Mode of the + // Camera Core module in parallel + // mode (when CCP_MODE = 0) """000"" + // Parallel NOBT 8-bit" """001"" + // Parallel NOBT 10-bit" """010"" + // Parallel NOBT 12-bit" """011"" + // reserved" """100"" Parallet BT + // 8-bit" """101"" Parallel BT + // 10-bit" """110"" reserved" + // """111"" FIFO test mode. Refer to + // Table 12 - FIFO Write and Read + // access" + +#define CAMERA_CC_CTRL_PAR_MODE_S 1 +#define CAMERA_CC_CTRL_CCP_MODE 0x00000001 // Set the Camera Core in CCP mode + // 0 CCP mode disabled 1 CCP mode + // enabled +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_CTRL_DMA register. +// +//****************************************************************************** +#define CAMERA_CC_CTRL_DMA_DMA_EN \ + 0x00000100 // Sets the number of dma request + // lines 0 DMA interface disabled + // The DMA request line stays + // inactive 1 DMA interface enabled + // The DMA request line is + // operational + +#define CAMERA_CC_CTRL_DMA_FIFO_THRESHOLD_M \ + 0x0000007F // Sets the threshold of the FIFO + // the assertion of the dmarequest + // line takes place when the + // threshold is reached. + // """0000000"" threshold set to 1" + // """0000001"" threshold set to 2" + // … """1111111"" threshold set to + // 128" + +#define CAMERA_CC_CTRL_DMA_FIFO_THRESHOLD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_CTRL_XCLK register. +// +//****************************************************************************** +#define CAMERA_CC_CTRL_XCLK_XCLK_DIV_M \ + 0x0000001F // Sets the clock divisor value for + // CAM_XCLK generation. based on + // CAM_MCK (value of CAM_MCLK is + // 96MHz) """00000"" CAM_XCLK Stable + // Low Level" Divider not enabled + // """00001"" CAM_XCLK Stable High + // Level" Divider not enabled from 2 + // to 30 CAM_XCLK = CAM_MCLK / + // XCLK_DIV """11111"" Bypass - + // CAM_XCLK = CAM_MCLK" + +#define CAMERA_CC_CTRL_XCLK_XCLK_DIV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_FIFO_DATA register. +// +//****************************************************************************** +#define CAMERA_CC_FIFO_DATA_FIFO_DATA_M \ + 0xFFFFFFFF // Writes the 32-bit word into the + // FIFO Reads the 32-bit word from + // the FIFO + +#define CAMERA_CC_FIFO_DATA_FIFO_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the CAMERA_O_CC_TEST register. +// +//****************************************************************************** +#define CAMERA_CC_TEST_FIFO_RD_POINTER_M \ + 0xFF000000 // FIFO READ Pointer This field + // shows the value of the FIFO read + // pointer Expected value ranges + // from 0 to 127 + +#define CAMERA_CC_TEST_FIFO_RD_POINTER_S 24 +#define CAMERA_CC_TEST_FIFO_WR_POINTER_M \ + 0x00FF0000 // FIFO WRITE pointer This field + // shows the value of the FIFO write + // pointer Expected value ranges + // from 0 to 127 + +#define CAMERA_CC_TEST_FIFO_WR_POINTER_S 16 +#define CAMERA_CC_TEST_FIFO_LEVEL_M \ + 0x0000FF00 // FIFO level (how many 32-bit + // words the FIFO contains) This + // field shows the value of the FIFO + // level and can assume values from + // 0 to 128 + +#define CAMERA_CC_TEST_FIFO_LEVEL_S 8 +#define CAMERA_CC_TEST_FIFO_LEVEL_PEAK_M \ + 0x000000FF // FIFO level peak This field shows + // the max value of the FIFO level + // and can assume values from 0 to + // 128 + +#define CAMERA_CC_TEST_FIFO_LEVEL_PEAK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// CAMERA_O_CC_GEN_PAR register. +// +//****************************************************************************** +#define CAMERA_CC_GEN_PAR_CC_FIFO_DEPTH_M \ + 0x00000007 // Camera Core FIFO DEPTH generic + // parameter + +#define CAMERA_CC_GEN_PAR_CC_FIFO_DEPTH_S 0 + + + +#endif // __HW_CAMERA_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_common_reg.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_common_reg.h new file mode 100644 index 00000000..417544ad --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_common_reg.h @@ -0,0 +1,1117 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_COMMON_REG_H__ +#define __HW_COMMON_REG_H__ + +//***************************************************************************** +// +// The following are defines for the COMMON_REG register offsets. +// +//***************************************************************************** +#define COMMON_REG_O_I2C_Properties_Register \ + 0x00000000 + +#define COMMON_REG_O_SPI_Properties_Register \ + 0x00000004 + +#define COMMON_REG_O_APPS_sh_resource_Interrupt_enable \ + 0x0000000C + +#define COMMON_REG_O_APPS_sh_resource_Interrupt_status \ + 0x00000010 + +#define COMMON_REG_O_NWP_sh_resource_Interrupt_enable \ + 0x00000014 + +#define COMMON_REG_O_NWP_sh_resource_Interrupt_status \ + 0x00000018 + +#define COMMON_REG_O_Flash_ctrl_reg \ + 0x0000001C + +#define COMMON_REG_O_Bus_matrix_M0_segment_access_config \ + 0x00000024 + +#define COMMON_REG_O_Bus_matrix_M1_segment_access_config \ + 0x00000028 + +#define COMMON_REG_O_Bus_matrix_M2_segment_access_config \ + 0x0000002C + +#define COMMON_REG_O_Bus_matrix_M3_segment_access_config \ + 0x00000030 + +#define COMMON_REG_O_Bus_matrix_M4_segment_access_config \ + 0x00000034 + +#define COMMON_REG_O_Bus_matrix_M5_segment_access_config \ + 0x00000038 + +#define COMMON_REG_O_GPIO_properties_register \ + 0x0000003C + +#define COMMON_REG_O_APPS_NW_SEMAPHORE1 \ + 0x00000040 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE2 \ + 0x00000044 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE3 \ + 0x00000048 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE4 \ + 0x0000004C + +#define COMMON_REG_O_APPS_NW_SEMAPHORE5 \ + 0x00000050 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE6 \ + 0x00000054 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE7 \ + 0x00000058 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE8 \ + 0x0000005C + +#define COMMON_REG_O_APPS_NW_SEMAPHORE9 \ + 0x00000060 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE10 \ + 0x00000064 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE11 \ + 0x00000068 + +#define COMMON_REG_O_APPS_NW_SEMAPHORE12 \ + 0x0000006C + +#define COMMON_REG_O_APPS_SEMAPPHORE_PEND \ + 0x00000070 + +#define COMMON_REG_O_NW_SEMAPPHORE_PEND \ + 0x00000074 + +#define COMMON_REG_O_SEMAPHORE_STATUS \ + 0x00000078 + +#define COMMON_REG_O_IDMEM_TIM_Update \ + 0x0000007C + +#define COMMON_REG_O_FPGA_ROM_WR_EN \ + 0x00000080 + +#define COMMON_REG_O_NW_INT_MASK \ + 0x00000084 + +#define COMMON_REG_O_NW_INT_MASK_SET \ + 0x00000088 + +#define COMMON_REG_O_NW_INT_MASK_CLR \ + 0x0000008C + +#define COMMON_REG_O_NW_INT_STS_CLR \ + 0x00000090 + +#define COMMON_REG_O_NW_INT_ACK 0x00000094 +#define COMMON_REG_O_NW_INT_TRIG \ + 0x00000098 + +#define COMMON_REG_O_NW_INT_STS_MASKED \ + 0x0000009C + +#define COMMON_REG_O_NW_INT_STS_RAW \ + 0x000000A0 + +#define COMMON_REG_O_APPS_INT_MASK \ + 0x000000A4 + +#define COMMON_REG_O_APPS_INT_MASK_SET \ + 0x000000A8 + +#define COMMON_REG_O_APPS_INT_MASK_CLR \ + 0x000000AC + +#define COMMON_REG_O_APPS_INT_STS_CLR \ + 0x000000B0 + +#define COMMON_REG_O_APPS_INT_ACK \ + 0x000000B4 + +#define COMMON_REG_O_APPS_INT_TRIG \ + 0x000000B8 + +#define COMMON_REG_O_APPS_INT_STS_MASKED \ + 0x000000BC + +#define COMMON_REG_O_APPS_INT_STS_RAW \ + 0x000000C0 + +#define COMMON_REG_O_IDMEM_TIM_Updated \ + 0x000000C4 + +#define COMMON_REG_O_APPS_GPIO_TRIG_EN \ + 0x000000C8 + +#define COMMON_REG_O_EMU_DEBUG_REG \ + 0x000000CC + +#define COMMON_REG_O_SEMAPHORE_STATUS2 \ + 0x000000D0 + +#define COMMON_REG_O_SEMAPHORE_PREV_OWNER1 \ + 0x000000D4 + +#define COMMON_REG_O_SEMAPHORE_PREV_OWNER2 \ + 0x000000D8 + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_I2C_Properties_Register register. +// +//****************************************************************************** +#define COMMON_REG_I2C_Properties_Register_I2C_Properties_Register_M \ + 0x00000003 // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_I2C_Properties_Register_I2C_Properties_Register_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_SPI_Properties_Register register. +// +//****************************************************************************** +#define COMMON_REG_SPI_Properties_Register_SPI_Properties_Register_M \ + 0x00000003 // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_SPI_Properties_Register_SPI_Properties_Register_S 0 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_sh_resource_Interrupt_enable register. +// +//****************************************************************************** +#define COMMON_REG_APPS_sh_resource_Interrupt_enable_APPS_sh_resource_Interrupt_enable_M \ + 0x0000000F // Interrupt enable APPS bit 0 -> + // when '1' enable I2C interrupt bit + // 1 -> when '1' enable SPI + // interrupt bit 3 -> + // when '1' enable GPIO interrupt + +#define COMMON_REG_APPS_sh_resource_Interrupt_enable_APPS_sh_resource_Interrupt_enable_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_sh_resource_Interrupt_status register. +// +//****************************************************************************** +#define COMMON_REG_APPS_sh_resource_Interrupt_status_APPS_sh_resource_Interrupt_status_M \ + 0x0000000F // Interrupt enable APPS bit 0 -> + // when '1' enable I2C interrupt bit + // 1 -> when '1' enable SPI + // interrupt bit 3 -> + // when '1' enable GPIO interrupt + +#define COMMON_REG_APPS_sh_resource_Interrupt_status_APPS_sh_resource_Interrupt_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NWP_sh_resource_Interrupt_enable register. +// +//****************************************************************************** +#define COMMON_REG_NWP_sh_resource_Interrupt_enable_NWP_sh_resource_Interrupt_enable_M \ + 0x0000000F // Interrupt enable NWP bit 0 -> + // when '1' enable I2C interrupt bit + // 1 -> when '1' enable SPI + // interrupt bit 3 -> + // when '1' enable GPIO interrupt + +#define COMMON_REG_NWP_sh_resource_Interrupt_enable_NWP_sh_resource_Interrupt_enable_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NWP_sh_resource_Interrupt_status register. +// +//****************************************************************************** +#define COMMON_REG_NWP_sh_resource_Interrupt_status_NWP_sh_resource_Interrupt_status_M \ + 0x0000000F // Interrupt enable NWP bit 0 -> + // when '1' enable I2C interrupt bit + // 1 -> when '1' enable SPI + // interrupt bit 3 -> + // when '1' enable GPIO interrupt + +#define COMMON_REG_NWP_sh_resource_Interrupt_status_NWP_sh_resource_Interrupt_status_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_Flash_ctrl_reg register. +// +//****************************************************************************** +#define COMMON_REG_Flash_ctrl_reg_Flash_ctrl_reg_M \ + 0x00000003 // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_Flash_ctrl_reg_Flash_ctrl_reg_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_Bus_matrix_M0_segment_access_config register. +// +//****************************************************************************** +#define COMMON_REG_Bus_matrix_M0_segment_access_config_Bus_matrix_M0_segment_access_config_M \ + 0x0003FFFF // Master 0 control word matrix to + // each segment. Tieoff. Bit value 1 + // indicates segment is accesable. + +#define COMMON_REG_Bus_matrix_M0_segment_access_config_Bus_matrix_M0_segment_access_config_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_Bus_matrix_M1_segment_access_config register. +// +//****************************************************************************** +#define COMMON_REG_Bus_matrix_M1_segment_access_config_Bus_matrix_M1_segment_access_config_M \ + 0x0003FFFF // Master 1 control word matrix to + // each segment. Tieoff. Bit value 1 + // indicates segment is accesable. + +#define COMMON_REG_Bus_matrix_M1_segment_access_config_Bus_matrix_M1_segment_access_config_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_Bus_matrix_M2_segment_access_config register. +// +//****************************************************************************** +#define COMMON_REG_Bus_matrix_M2_segment_access_config_Bus_matrix_M2_segment_access_config_M \ + 0x0003FFFF // Master 2 control word matrix to + // each segment. Tieoff. Bit value 1 + // indicates segment is accesable. + +#define COMMON_REG_Bus_matrix_M2_segment_access_config_Bus_matrix_M2_segment_access_config_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_Bus_matrix_M3_segment_access_config register. +// +//****************************************************************************** +#define COMMON_REG_Bus_matrix_M3_segment_access_config_Bus_matrix_M3_segment_access_config_M \ + 0x0003FFFF // Master 3 control word matrix to + // each segment. Tieoff. Bit value 1 + // indicates segment is accesable. + +#define COMMON_REG_Bus_matrix_M3_segment_access_config_Bus_matrix_M3_segment_access_config_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_Bus_matrix_M4_segment_access_config register. +// +//****************************************************************************** +#define COMMON_REG_Bus_matrix_M4_segment_access_config_Bus_matrix_M4_segment_access_config_M \ + 0x0003FFFF // Master 4 control word matrix to + // each segment. Tieoff. Bit value 1 + // indicates segment is accesable. + +#define COMMON_REG_Bus_matrix_M4_segment_access_config_Bus_matrix_M4_segment_access_config_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_Bus_matrix_M5_segment_access_config register. +// +//****************************************************************************** +#define COMMON_REG_Bus_matrix_M5_segment_access_config_Bus_matrix_M5_segment_access_config_M \ + 0x0003FFFF // Master 5 control word matrix to + // each segment. Tieoff. Bit value 1 + // indicates segment is accesable. + +#define COMMON_REG_Bus_matrix_M5_segment_access_config_Bus_matrix_M5_segment_access_config_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_GPIO_properties_register register. +// +//****************************************************************************** +#define COMMON_REG_GPIO_properties_register_GPIO_properties_register_M \ + 0x000003FF // Shared GPIO configuration + // register. Bit [1:0] to configure + // GPIO0 Bit [3:2] to configure + // GPIO1 Bit [5:4] to configure + // GPIO2 Bit [7:6] to configure + // GPIO3 Bit [9:8] to configure + // GPIO4 each GPIO can be + // individully selected. When “00” + // GPIO is free resource. When “01” + // GPIO is APPS resource. When “10” + // GPIO is NWP resource. Writing 11 + // doesnt have any affect, i.e. If + // one write only relevant gpio + // semaphore and other bits are 1s, + // it'll not disturb the other + // semaphore bits. For example : Say + // If NW wants to take control of + // gpio-1, one should write + // 10'b11_1111_1011 and if one wants + // to release it write + // 10'b11_1111_0011. + +#define COMMON_REG_GPIO_properties_register_GPIO_properties_register_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE1 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE1_APPS_NW_SEMAPHORE1_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE1_APPS_NW_SEMAPHORE1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE2 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE2_APPS_NW_SEMAPHORE2_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE2_APPS_NW_SEMAPHORE2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE3 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE3_APPS_NW_SEMAPHORE3_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE3_APPS_NW_SEMAPHORE3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE4 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE4_APPS_NW_SEMAPHORE4_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE4_APPS_NW_SEMAPHORE4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE5 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE5_APPS_NW_SEMAPHORE5_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE5_APPS_NW_SEMAPHORE5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE6 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE6_APPS_NW_SEMAPHORE6_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE6_APPS_NW_SEMAPHORE6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE7 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE7_APPS_NW_SEMAPHORE7_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE7_APPS_NW_SEMAPHORE7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE8 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE8_APPS_NW_SEMAPHORE8_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE8_APPS_NW_SEMAPHORE8_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE9 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE9_APPS_NW_SEMAPHORE9_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE9_APPS_NW_SEMAPHORE9_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE10 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE10_APPS_NW_SEMAPHORE10_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE10_APPS_NW_SEMAPHORE10_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE11 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE11_APPS_NW_SEMAPHORE11_M \ + 0xFFFFFFFF // • Each semaphore register is of + // 2 bit. • When this register is + // set to 2’b01 – Apps have access + // and when set to 2’b10 – NW have + // access. • Ideally both the master + // can modify any of this 2 bit, but + // assumption apps will write only + // 2’b01 or 2’b00 to this register + // and nw will write only 2’b10 or + // 2’b00. • Implementation is when + // any of the bit of this register + // is set, only next write + // allowedvis 2’b00 – Again + // assumption is one master will not + // write 2’b00 if other is already + // holding the semaphore. + +#define COMMON_REG_APPS_NW_SEMAPHORE11_APPS_NW_SEMAPHORE11_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_NW_SEMAPHORE12 register. +// +//****************************************************************************** +#define COMMON_REG_APPS_NW_SEMAPHORE12_APPS_NW_SEMAPHORE12_M \ + 0xFFFFFFFF // APPS NW semaphore register - not + // reflected in status. + +#define COMMON_REG_APPS_NW_SEMAPHORE12_APPS_NW_SEMAPHORE12_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_SEMAPPHORE_PEND register. +// +//****************************************************************************** +#define COMMON_REG_APPS_SEMAPPHORE_PEND_APPS_SEMAPPHORE_PEND_M \ + 0xFFFFFFFF // APPS SEMAPOHORE STATUS + +#define COMMON_REG_APPS_SEMAPPHORE_PEND_APPS_SEMAPPHORE_PEND_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_SEMAPPHORE_PEND register. +// +//****************************************************************************** +#define COMMON_REG_NW_SEMAPPHORE_PEND_NW_SEMAPPHORE_PEND_M \ + 0xFFFFFFFF // NW SEMAPHORE STATUS + +#define COMMON_REG_NW_SEMAPPHORE_PEND_NW_SEMAPPHORE_PEND_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_SEMAPHORE_STATUS register. +// +//****************************************************************************** +#define COMMON_REG_SEMAPHORE_STATUS_SEMAPHORE_STATUS_M \ + 0xFFFFFFFF // SEMAPHORE STATUS 9:8 :semaphore + // status of flash_control 7:6 + // :semaphore status of + // gpio_properties 5:4 + // :semaphore status of + // spi_propertie 1:0 :semaphore + // status of i2c_propertie + +#define COMMON_REG_SEMAPHORE_STATUS_SEMAPHORE_STATUS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_IDMEM_TIM_Update register. +// +//****************************************************************************** +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_FPGA_ROM_WR_EN register. +// +//****************************************************************************** +#define COMMON_REG_FPGA_ROM_WR_EN_FPGA_ROM_WR_EN \ + 0x00000001 // when '1' enables Write into + // IDMEM CORE ROM, APPS ROM, NWP ROM + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_MASK register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_MASK_NW_INT_MASK_M \ + 0xFFFFFFFF // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define COMMON_REG_NW_INT_MASK_NW_INT_MASK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_MASK_SET register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_MASK_SET_NW_INT_MASK_SET_M \ + 0xFFFFFFFF // write 1 to set corresponding bit + // in NW_INT_MASK;0 = no effect + +#define COMMON_REG_NW_INT_MASK_SET_NW_INT_MASK_SET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_MASK_CLR register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_MASK_CLR_NW_INT_MASK_CLR_M \ + 0xFFFFFFFF // write 1 to clear corresponding + // bit in NW_INT_MASK;0 = no effect + +#define COMMON_REG_NW_INT_MASK_CLR_NW_INT_MASK_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_STS_CLR register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_STS_CLR_NW_INT_STS_CLR_M \ + 0xFFFFFFFF // write 1 to clear corresponding + // interrupt; 0 = no effect; + // interrupt is not lost if coincide + // with write operation + +#define COMMON_REG_NW_INT_STS_CLR_NW_INT_STS_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_ACK register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_ACK_NW_INT_ACK_M \ + 0xFFFFFFFF // write 1 to clear corresponding + // interrupt;0 = no effect + +#define COMMON_REG_NW_INT_ACK_NW_INT_ACK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_TRIG register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_TRIG_NW_INT_TRIG_M \ + 0xFFFFFFFF // Writing a 1 to a bit in this + // register causes the the Host CPU + // if enabled (not masked). This + // register is self-clearing. + // Writing 0 has no effect + +#define COMMON_REG_NW_INT_TRIG_NW_INT_TRIG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_STS_MASKED register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_STS_MASKED_NW_INT_STS_MASKED_M \ + 0xFFFFFFFF // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by NW_INT mask + +#define COMMON_REG_NW_INT_STS_MASKED_NW_INT_STS_MASKED_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_NW_INT_STS_RAW register. +// +//****************************************************************************** +#define COMMON_REG_NW_INT_STS_RAW_NW_INT_STS_RAW_M \ + 0xFFFFFFFF // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define COMMON_REG_NW_INT_STS_RAW_NW_INT_STS_RAW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_MASK register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_MASK_APPS_INT_MASK_M \ + 0xFFFFFFFF // 1= disable corresponding + // interrupt;0 = interrupt enabled + +#define COMMON_REG_APPS_INT_MASK_APPS_INT_MASK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_MASK_SET register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_MASK_SET_APPS_INT_MASK_SET_M \ + 0xFFFFFFFF // write 1 to set corresponding bit + // in APPS_INT_MASK;0 = no effect + +#define COMMON_REG_APPS_INT_MASK_SET_APPS_INT_MASK_SET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_MASK_CLR register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_MASK_CLR_APPS_INT_MASK_CLR_M \ + 0xFFFFFFFF // write 1 to clear corresponding + // bit in APPS_INT_MASK;0 = no + // effect + +#define COMMON_REG_APPS_INT_MASK_CLR_APPS_INT_MASK_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_STS_CLR register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_STS_CLR_APPS_INT_STS_CLR_M \ + 0xFFFFFFFF // write 1 to clear corresponding + // interrupt; 0 = no effect; + // interrupt is not lost if coincide + // with write operation + +#define COMMON_REG_APPS_INT_STS_CLR_APPS_INT_STS_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_ACK register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_ACK_APPS_INT_ACK_M \ + 0xFFFFFFFF // write 1 to clear corresponding + // interrupt;0 = no effect + +#define COMMON_REG_APPS_INT_ACK_APPS_INT_ACK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_TRIG register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_TRIG_APPS_INT_TRIG_M \ + 0xFFFFFFFF // Writing a 1 to a bit in this + // register causes the the Host CPU + // if enabled (not masked). This + // register is self-clearing. + // Writing 0 has no effect + +#define COMMON_REG_APPS_INT_TRIG_APPS_INT_TRIG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_STS_MASKED register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_STS_MASKED_APPS_INT_STS_MASKED_M \ + 0xFFFFFFFF // 1= corresponding interrupt is + // active and not masked. read is + // non-destructive;0 = corresponding + // interrupt is inactive or masked + // by APPS_INT mask + +#define COMMON_REG_APPS_INT_STS_MASKED_APPS_INT_STS_MASKED_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_INT_STS_RAW register. +// +//****************************************************************************** +#define COMMON_REG_APPS_INT_STS_RAW_APPS_INT_STS_RAW_M \ + 0xFFFFFFFF // 1= corresponding interrupt is + // active. read is non-destructive;0 + // = corresponding interrupt is + // inactive + +#define COMMON_REG_APPS_INT_STS_RAW_APPS_INT_STS_RAW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_IDMEM_TIM_Updated register. +// +//****************************************************************************** +#define COMMON_REG_IDMEM_TIM_Updated_TIM_UPDATED \ + 0x00000001 // toggle in this signal + // indicatesIDMEM_TIM_UPDATE + // register mentioned above is + // updated. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_APPS_GPIO_TRIG_EN register. +// +//****************************************************************************** +#define COMMON_REG_APPS_GPIO_TRIG_EN_APPS_GPIO_TRIG_EN_M \ + 0x0000001F // APPS GPIO Trigger EN control. + // Bit 0: when '1' enable GPIO 0 + // trigger. This bit enables trigger + // for all GPIO 0 pins (GPIO 0 to + // GPIO7). Bit 1: when '1' enable + // GPIO 1 trigger. This bit enables + // trigger for all GPIO 1 pins ( + // GPIO8 to GPIO15). Bit 2: when '1' + // enable GPIO 2 trigger. This bit + // enables trigger for all GPIO 2 + // pins (GPIO16 to GPIO23). Bit 3: + // when '1' enable GPIO 3 trigger. + // This bit enables trigger for all + // GPIO 3 pins (GPIO24 to GPIO31). + // Bit 4: when '1' enable GPIO 4 + // trigger. This bit enables trigger + // for all GPIO 4 pins.(GPIO32 to + // GPIO39) + +#define COMMON_REG_APPS_GPIO_TRIG_EN_APPS_GPIO_TRIG_EN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_EMU_DEBUG_REG register. +// +//****************************************************************************** +#define COMMON_REG_EMU_DEBUG_REG_EMU_DEBUG_REG_M \ + 0xFFFFFFFF // 0 th bit used for stalling APPS + // DMA and 1st bit is used for + // stalling NWP DMA for debug + // purpose. Other bits are unused. + +#define COMMON_REG_EMU_DEBUG_REG_EMU_DEBUG_REG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_SEMAPHORE_STATUS2 register. +// +//****************************************************************************** +#define COMMON_REG_SEMAPHORE_STATUS2_SEMPAPHORE_STATUS2_M \ + 0x00FFFFFF // SEMAPHORE STATUS 23:22 + // :semaphore status of + // apps_nw_semaphore11 21:20 + // :semaphore status of + // apps_nw_semaphore11 19:18 + // :semaphore status of + // apps_nw_semaphore10 17:16 + // :semaphore status of + // apps_nw_semaphore9 15:14 + // :semaphore status of + // apps_nw_semaphore8 13:12 + // :semaphore status of + // apps_nw_semaphore7 11:10 + // :semaphore status of + // apps_nw_semaphore6 9:8 :semaphore + // status of apps_nw_semaphore5 7:6 + // :semaphore status of + // apps_nw_semaphore4 5:4 :semaphore + // status of apps_nw_semaphore3 3:2 + // :semaphore status of + // apps_nw_semaphore2 1:0 :semaphore + // status of apps_nw_semaphore1 + +#define COMMON_REG_SEMAPHORE_STATUS2_SEMPAPHORE_STATUS2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_SEMAPHORE_PREV_OWNER1 register. +// +//****************************************************************************** +#define COMMON_REG_SEMAPHORE_PREV_OWNER1_SEMAPHORE_PREV_OWNER1_M \ + 0x0003FFFF // 1:0 : prvious owner of + // i2c_properties_reg[1:0] 3:2 : + // prvious owner of + // spi_properties_reg[1:0] 5:4 : + // prvious owner of + // gpio_properties_reg[1:0] 9:8 : + // prvious owner of + // gpio_properties_reg[3:2] 11:10 : + // prvious owner of + // gpio_properties_reg[5:4] 13:12 : + // prvious owner of + // gpio_properties_reg[7:6] 15:14 : + // prvious owner of + // gpio_properties_reg[9:8] 17:16 : + // prvious owner of + // flash_control_reg[1:0] + +#define COMMON_REG_SEMAPHORE_PREV_OWNER1_SEMAPHORE_PREV_OWNER1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// COMMON_REG_O_SEMAPHORE_PREV_OWNER2 register. +// +//****************************************************************************** +#define COMMON_REG_SEMAPHORE_PREV_OWNER2_SEMAPHORE_PREV_OWNER2_M \ + 0x00FFFFFF // 1:0 : previous owner of + // apps_nw_semaphore1_reg[1:0] 3:2 : + // previous owner of + // apps_nw_semaphore2_reg[1:0] 5:4 : + // previous owner of + // apps_nw_semaphore3_reg[1:0] 7:6 : + // previous owner of + // apps_nw_semaphore4_reg[1:0] 9:8 : + // previous owner of + // apps_nw_semaphore5_reg[1:0] 11:10 + // : previous owner of + // apps_nw_semaphore6_reg[1:0] 13:12 + // : previous owner of + // apps_nw_semaphore7_reg[1:0] 15:14 + // : previous owner of + // apps_nw_semaphore8_reg[1:0] 17:16 + // : previous owner of + // apps_nw_semaphore9_reg[1:0] 19:18 + // : previous owner of + // apps_nw_semaphore10_reg[1:0] + // 21:20 : previous owner of + // apps_nw_semaphore11_reg[1:0] + // 23:22 : previous owner of + // apps_nw_semaphore12_reg[1:0] + +#define COMMON_REG_SEMAPHORE_PREV_OWNER2_SEMAPHORE_PREV_OWNER2_S 0 + + + +#endif // __HW_COMMON_REG_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_des.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_des.h new file mode 100644 index 00000000..c3aed656 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_des.h @@ -0,0 +1,339 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_DES_H__ +#define __HW_DES_H__ + +//***************************************************************************** +// +// The following are defines for the DES_P register offsets. +// +//***************************************************************************** +#define DES_O_KEY3_L 0x00000000 // KEY3 (LSW) for 192-bit key +#define DES_O_KEY3_H 0x00000004 // KEY3 (MSW) for 192-bit key +#define DES_O_KEY2_L 0x00000008 // KEY2 (LSW) for 192-bit key +#define DES_O_KEY2_H 0x0000000C // KEY2 (MSW) for 192-bit key +#define DES_O_KEY1_L 0x00000010 // KEY1 (LSW) for 128-bit + // key/192-bit key +#define DES_O_KEY1_H 0x00000014 // KEY1 (LSW) for 128-bit + // key/192-bit key +#define DES_O_IV_L 0x00000018 // Initialization vector LSW +#define DES_O_IV_H 0x0000001C // Initialization vector MSW +#define DES_O_CTRL 0x00000020 +#define DES_O_LENGTH 0x00000024 // Indicates the cryptographic data + // length in bytes for all modes. + // Once processing is started with + // this context this length + // decrements to zero. Data lengths + // up to (2^32 – 1) bytes are + // allowed. A write to this register + // triggers the engine to start + // using this context. For a Host + // read operation these registers + // return all-zeroes. +#define DES_O_DATA_L 0x00000028 // Data register(LSW) to read/write + // encrypted/decrypted data. +#define DES_O_DATA_H 0x0000002C // Data register(MSW) to read/write + // encrypted/decrypted data. +#define DES_O_REVISION 0x00000030 +#define DES_O_SYSCONFIG 0x00000034 +#define DES_O_SYSSTATUS 0x00000038 +#define DES_O_IRQSTATUS 0x0000003C // This register indicates the + // interrupt status. If one of the + // interrupt bits is set the + // interrupt output will be asserted +#define DES_O_IRQENABLE 0x00000040 // This register contains an enable + // bit for each unique interrupt + // generated by the module. It + // matches the layout of + // DES_IRQSTATUS register. An + // interrupt is enabled when the bit + // in this register is set to 1 + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_KEY3_L register. +// +//****************************************************************************** +#define DES_KEY3_L_KEY3_L_M 0xFFFFFFFF // data for key3 +#define DES_KEY3_L_KEY3_L_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_KEY3_H register. +// +//****************************************************************************** +#define DES_KEY3_H_KEY3_H_M 0xFFFFFFFF // data for key3 +#define DES_KEY3_H_KEY3_H_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_KEY2_L register. +// +//****************************************************************************** +#define DES_KEY2_L_KEY2_L_M 0xFFFFFFFF // data for key2 +#define DES_KEY2_L_KEY2_L_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_KEY2_H register. +// +//****************************************************************************** +#define DES_KEY2_H_KEY2_H_M 0xFFFFFFFF // data for key2 +#define DES_KEY2_H_KEY2_H_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_KEY1_L register. +// +//****************************************************************************** +#define DES_KEY1_L_KEY1_L_M 0xFFFFFFFF // data for key1 +#define DES_KEY1_L_KEY1_L_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_KEY1_H register. +// +//****************************************************************************** +#define DES_KEY1_H_KEY1_H_M 0xFFFFFFFF // data for key1 +#define DES_KEY1_H_KEY1_H_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_IV_L register. +// +//****************************************************************************** +#define DES_IV_L_IV_L_M 0xFFFFFFFF // initialization vector for CBC + // CFB modes +#define DES_IV_L_IV_L_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_IV_H register. +// +//****************************************************************************** +#define DES_IV_H_IV_H_M 0xFFFFFFFF // initialization vector for CBC + // CFB modes +#define DES_IV_H_IV_H_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_CTRL register. +// +//****************************************************************************** +#define DES_CTRL_CONTEXT 0x80000000 // If ‘1’ this read-only status bit + // indicates that the context data + // registers can be overwritten and + // the host is permitted to write + // the next context. +#define DES_CTRL_MODE_M 0x00000030 // Select CBC ECB or CFB mode 0x0 + // ecb mode 0x1 cbc mode 0x2 cfb + // mode 0x3 reserved +#define DES_CTRL_MODE_S 4 +#define DES_CTRL_TDES 0x00000008 // Select DES or triple DES + // encryption/decryption. 0 des mode + // 1 tdes mode +#define DES_CTRL_DIRECTION 0x00000004 // select encryption/decryption 0 + // decryption is selected 1 + // Encryption is selected +#define DES_CTRL_INPUT_READY 0x00000002 // When '1' ready to + // encrypt/decrypt data +#define DES_CTRL_OUTPUT_READY 0x00000001 // When '1' Data + // decrypted/encrypted ready +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_LENGTH register. +// +//****************************************************************************** +#define DES_LENGTH_LENGTH_M 0xFFFFFFFF +#define DES_LENGTH_LENGTH_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_DATA_L register. +// +//****************************************************************************** +#define DES_DATA_L_DATA_L_M 0xFFFFFFFF // data for encryption/decryption +#define DES_DATA_L_DATA_L_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_DATA_H register. +// +//****************************************************************************** +#define DES_DATA_H_DATA_H_M 0xFFFFFFFF // data for encryption/decryption +#define DES_DATA_H_DATA_H_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_REVISION register. +// +//****************************************************************************** +#define DES_REVISION_SCHEME_M 0xC0000000 +#define DES_REVISION_SCHEME_S 30 +#define DES_REVISION_FUNC_M 0x0FFF0000 // Function indicates a software + // compatible module family. If + // there is no level of software + // compatibility a new Func number + // (and hence REVISION) should be + // assigned. +#define DES_REVISION_FUNC_S 16 +#define DES_REVISION_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP + // design owner. RTL follows a + // numbering such as X.Y.R.Z which + // are explained in this table. R + // changes ONLY when: (1) PDS + // uploads occur which may have been + // due to spec changes (2) Bug fixes + // occur (3) Resets to '0' when X or + // Y changes. Design team has an + // internal 'Z' (customer invisible) + // number which increments on every + // drop that happens due to DV and + // RTL updates. Z resets to 0 when R + // increments. +#define DES_REVISION_R_RTL_S 11 +#define DES_REVISION_X_MAJOR_M \ + 0x00000700 // Major Revision (X) maintained by + // IP specification owner. X changes + // ONLY when: (1) There is a major + // feature addition. An example + // would be adding Master Mode to + // Utopia Level2. The Func field (or + // Class/Type in old PID format) + // will remain the same. X does NOT + // change due to: (1) Bug fixes (2) + // Change in feature parameters. + +#define DES_REVISION_X_MAJOR_S 8 +#define DES_REVISION_CUSTOM_M 0x000000C0 +#define DES_REVISION_CUSTOM_S 6 +#define DES_REVISION_Y_MINOR_M \ + 0x0000003F // Minor Revision (Y) maintained by + // IP specification owner. Y changes + // ONLY when: (1) Features are + // scaled (up or down). Flexibility + // exists in that this feature + // scalability may either be + // represented in the Y change or a + // specific register in the IP that + // indicates which features are + // exactly available. (2) When + // feature creeps from Is-Not list + // to Is list. But this may not be + // the case once it sees silicon; in + // which case X will change. Y does + // NOT change due to: (1) Bug fixes + // (2) Typos or clarifications (3) + // major functional/feature + // change/addition/deletion. Instead + // these changes may be reflected + // via R S X as applicable. Spec + // owner maintains a + // customer-invisible number 'S' + // which changes due to: (1) + // Typos/clarifications (2) Bug + // documentation. Note that this bug + // is not due to a spec change but + // due to implementation. + // Nevertheless the spec tracks the + // IP bugs. An RTL release (say for + // silicon PG1.1) that occurs due to + // bug fix should document the + // corresponding spec number (X.Y.S) + // in its release notes. + +#define DES_REVISION_Y_MINOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_SYSCONFIG register. +// +//****************************************************************************** +#define DES_SYSCONFIG_DMA_REQ_CONTEXT_IN_EN \ + 0x00000080 // If set to ‘1’ the DMA context + // request is enabled. 0 Dma + // disabled 1 Dma enabled + +#define DES_SYSCONFIG_DMA_REQ_DATA_OUT_EN \ + 0x00000040 // If set to ‘1’ the DMA output + // request is enabled. 0 Dma + // disabled 1 Dma enabled + +#define DES_SYSCONFIG_DMA_REQ_DATA_IN_EN \ + 0x00000020 // If set to ‘1’ the DMA input + // request is enabled. 0 Dma + // disabled 1 Dma enabled + +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_SYSSTATUS register. +// +//****************************************************************************** +#define DES_SYSSTATUS_RESETDONE \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_IRQSTATUS register. +// +//****************************************************************************** +#define DES_IRQSTATUS_DATA_OUT \ + 0x00000004 // This bit indicates data output + // interrupt is active and triggers + // the interrupt output. + +#define DES_IRQSTATUS_DATA_IN 0x00000002 // This bit indicates data input + // interrupt is active and triggers + // the interrupt output. +#define DES_IRQSTATUS_CONTEX_IN \ + 0x00000001 // This bit indicates context + // interrupt is active and triggers + // the interrupt output. + +//****************************************************************************** +// +// The following are defines for the bit fields in the DES_O_IRQENABLE register. +// +//****************************************************************************** +#define DES_IRQENABLE_M_DATA_OUT \ + 0x00000004 // If this bit is set to ‘1’ the + // secure data output interrupt is + // enabled. + +#define DES_IRQENABLE_M_DATA_IN \ + 0x00000002 // If this bit is set to ‘1’ the + // secure data input interrupt is + // enabled. + +#define DES_IRQENABLE_M_CONTEX_IN \ + 0x00000001 // If this bit is set to ‘1’ the + // secure context interrupt is + // enabled. + + + + +#endif // __HW_DES_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_dthe.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_dthe.h new file mode 100644 index 00000000..1d302f42 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_dthe.h @@ -0,0 +1,392 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** +//***************************************************************************** + +#ifndef __HW_DTHE_H__ +#define __HW_DTHE_H__ + +//***************************************************************************** +// +// The following are defines for the DTHE register offsets. +// +//***************************************************************************** +#define DTHE_O_SHA_IM 0x00000810 +#define DTHE_O_SHA_RIS 0x00000814 +#define DTHE_O_SHA_MIS 0x00000818 +#define DTHE_O_SHA_IC 0x0000081C +#define DTHE_O_AES_IM 0x00000820 +#define DTHE_O_AES_RIS 0x00000824 +#define DTHE_O_AES_MIS 0x00000828 +#define DTHE_O_AES_IC 0x0000082C +#define DTHE_O_DES_IM 0x00000830 +#define DTHE_O_DES_RIS 0x00000834 +#define DTHE_O_DES_MIS 0x00000838 +#define DTHE_O_DES_IC 0x0000083C +#define DTHE_O_EIP_CGCFG 0x00000A00 +#define DTHE_O_EIP_CGREQ 0x00000A04 +#define DTHE_O_CRC_CTRL 0x00000C00 +#define DTHE_O_CRC_SEED 0x00000C10 +#define DTHE_O_CRC_DIN 0x00000C14 +#define DTHE_O_CRC_RSLT_PP 0x00000C18 +#define DTHE_O_RAND_KEY0 0x00000F00 +#define DTHE_O_RAND_KEY1 0x00000F04 +#define DTHE_O_RAND_KEY2 0x00000F08 +#define DTHE_O_RAND_KEY3 0x00000F0C + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_SHAMD5_IMST register. +// +//****************************************************************************** +#define DTHE_SHAMD5_IMST_DIN 0x00000004 // Data in: this interrupt is + // raised when DMA writes last word + // of input data to internal FIFO of + // the engine +#define DTHE_SHAMD5_IMST_COUT 0x00000002 // Context out: this interrupt is + // raised when DMA complets the + // output context movement from + // internal register +#define DTHE_SHAMD5_IMST_CIN 0x00000001 // context in: this interrupt is + // raised when DMA complets Context + // write to internal register +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_SHAMD5_IRIS register. +// +//****************************************************************************** +#define DTHE_SHAMD5_IRIS_DIN 0x00000004 // input Data movement is done +#define DTHE_SHAMD5_IRIS_COUT 0x00000002 // Context output is done +#define DTHE_SHAMD5_IRIS_CIN 0x00000001 // context input is done +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_SHAMD5_IMIS register. +// +//****************************************************************************** +#define DTHE_SHAMD5_IMIS_DIN 0x00000004 // input Data movement is done +#define DTHE_SHAMD5_IMIS_COUT 0x00000002 // Context output is done +#define DTHE_SHAMD5_IMIS_CIN 0x00000001 // context input is done +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_SHAMD5_ICIS register. +// +//****************************************************************************** +#define DTHE_SHAMD5_ICIS_DIN 0x00000004 // Clear “input Data movement done” + // flag +#define DTHE_SHAMD5_ICIS_COUT 0x00000002 // Clear “Context output done” flag +#define DTHE_SHAMD5_ICIS_CIN 0x00000001 // Clear “context input done” flag +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_AES_IMST register. +// +//****************************************************************************** +#define DTHE_AES_IMST_DOUT 0x00000008 // Data out: this interrupt is + // raised when DMA finishes writing + // last word of the process result +#define DTHE_AES_IMST_DIN 0x00000004 // Data in: this interrupt is + // raised when DMA writes last word + // of input data to internal FIFO of + // the engine +#define DTHE_AES_IMST_COUT 0x00000002 // Context out: this interrupt is + // raised when DMA complets the + // output context movement from + // internal register +#define DTHE_AES_IMST_CIN 0x00000001 // context in: this interrupt is + // raised when DMA complets Context + // write to internal register +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_AES_IRIS register. +// +//****************************************************************************** +#define DTHE_AES_IRIS_DOUT 0x00000008 // Output Data movement is done +#define DTHE_AES_IRIS_DIN 0x00000004 // input Data movement is done +#define DTHE_AES_IRIS_COUT 0x00000002 // Context output is done +#define DTHE_AES_IRIS_CIN 0x00000001 // context input is done +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_AES_IMIS register. +// +//****************************************************************************** +#define DTHE_AES_IMIS_DOUT 0x00000008 // Output Data movement is done +#define DTHE_AES_IMIS_DIN 0x00000004 // input Data movement is done +#define DTHE_AES_IMIS_COUT 0x00000002 // Context output is done +#define DTHE_AES_IMIS_CIN 0x00000001 // context input is done +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_AES_ICIS register. +// +//****************************************************************************** +#define DTHE_AES_ICIS_DOUT 0x00000008 // Clear “output Data movement + // done” flag +#define DTHE_AES_ICIS_DIN 0x00000004 // Clear “input Data movement done” + // flag +#define DTHE_AES_ICIS_COUT 0x00000002 // Clear “Context output done” flag +#define DTHE_AES_ICIS_CIN 0x00000001 // Clear “context input done” flag +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_DES_IMST register. +// +//****************************************************************************** +#define DTHE_DES_IMST_DOUT 0x00000008 // Data out: this interrupt is + // raised when DMA finishes writing + // last word of the process result +#define DTHE_DES_IMST_DIN 0x00000004 // Data in: this interrupt is + // raised when DMA writes last word + // of input data to internal FIFO of + // the engine +#define DTHE_DES_IMST_CIN 0x00000001 // context in: this interrupt is + // raised when DMA complets Context + // write to internal register +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_DES_IRIS register. +// +//****************************************************************************** +#define DTHE_DES_IRIS_DOUT 0x00000008 // Output Data movement is done +#define DTHE_DES_IRIS_DIN 0x00000004 // input Data movement is done +#define DTHE_DES_IRIS_CIN 0x00000001 // context input is done +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_DES_IMIS register. +// +//****************************************************************************** +#define DTHE_DES_IMIS_DOUT 0x00000008 // Output Data movement is done +#define DTHE_DES_IMIS_DIN 0x00000004 // input Data movement is done +#define DTHE_DES_IMIS_CIN 0x00000001 // context input is done +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_DES_ICIS register. +// +//****************************************************************************** +#define DTHE_DES_ICIS_DOUT 0x00000008 // Clear “output Data movement + // done” flag +#define DTHE_DES_ICIS_DIN 0x00000004 // Clear “input Data movement done” + // flag +#define DTHE_DES_ICIS_CIN 0x00000001 // Clear "context input done” flag +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_EIP_CGCFG register. +// +//****************************************************************************** +#define DTHE_EIP_CGCFG_EIP29_CFG \ + 0x00000010 // Clock gating protocol setting + // for EIP29T. 0 – Follow direct + // protocol 1 – Follow idle_req/ack + // protocol. + +#define DTHE_EIP_CGCFG_EIP75_CFG \ + 0x00000008 // Clock gating protocol setting + // for EIP75T. 0 – Follow direct + // protocol 1 – Follow idle_req/ack + // protocol. + +#define DTHE_EIP_CGCFG_EIP16_CFG \ + 0x00000004 // Clock gating protocol setting + // for DES. 0 – Follow direct + // protocol 1 – Follow idle_req/ack + // protocol. + +#define DTHE_EIP_CGCFG_EIP36_CFG \ + 0x00000002 // Clock gating protocol setting + // for AES. 0 – Follow direct + // protocol 1 – Follow idle_req/ack + // protocol. + +#define DTHE_EIP_CGCFG_EIP57_CFG \ + 0x00000001 // Clock gating protocol setting + // for SHAMD5. 0 – Follow direct + // protocol 1 – Follow idle_req/ack + // protocol. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_EIP_CGREQ register. +// +//****************************************************************************** +#define DTHE_EIP_CGREQ_Key_M 0xF0000000 // When “0x5” write “1” to lower + // bits [4:0] will set the bit. + // Write “0” will be ignored When + // “0x2” write “1” to lower bit + // [4:0] will clear the bit. Write + // “0” will be ignored for other key + // value, regular read write + // operation +#define DTHE_EIP_CGREQ_Key_S 28 +#define DTHE_EIP_CGREQ_EIP29_REQ \ + 0x00000010 // 0 – request clock gating 1 – + // request to un-gate the clock. + +#define DTHE_EIP_CGREQ_EIP75_REQ \ + 0x00000008 // 0 – request clock gating 1 – + // request to un-gate the clock. + +#define DTHE_EIP_CGREQ_EIP16_REQ \ + 0x00000004 // 0 – request clock gating 1 – + // request to un-gate the clock. + +#define DTHE_EIP_CGREQ_EIP36_REQ \ + 0x00000002 // 0 – request clock gating 1 – + // request to un-gate the clock. + +#define DTHE_EIP_CGREQ_EIP57_REQ \ + 0x00000001 // 0 – request clock gating 1 – + // request to un-gate the clock. + +//****************************************************************************** +// +// The following are defines for the bit fields in the DTHE_O_CRC_CTRL register. +// +//****************************************************************************** +#define DTHE_CRC_CTRL_INIT_M 0x00006000 // Initialize the CRC 00 – use SEED + // register context as starting + // value 10 – all “zero” 11 – all + // “one” This is self clearing. With + // first write to data register this + // value clears to zero and remain + // zero for rest of the operation + // unless written again +#define DTHE_CRC_CTRL_INIT_S 13 +#define DTHE_CRC_CTRL_SIZE 0x00001000 // Input data size 0 – 32 bit 1 – 8 + // bit +#define DTHE_CRC_CTRL_OINV 0x00000200 // Inverse the bits of result + // before storing to CRC_RSLT_PP0 +#define DTHE_CRC_CTRL_OBR 0x00000100 // Bit reverse the output result + // byte before storing to + // CRC_RSLT_PP0. applicable for all + // bytes in word +#define DTHE_CRC_CTRL_IBR 0x00000080 // Bit reverse the input byte. For + // all bytes in word +#define DTHE_CRC_CTRL_ENDIAN_M \ + 0x00000030 // Endian control [0] – swap byte + // in half-word [1] – swap half word + +#define DTHE_CRC_CTRL_ENDIAN_S 4 +#define DTHE_CRC_CTRL_TYPE_M 0x0000000F // Type of operation 0000 – + // polynomial 0x8005 0001 – + // polynomial 0x1021 0010 – + // polynomial 0x4C11DB7 0011 – + // polynomial 0x1EDC6F41 1000 – TCP + // checksum TYPE in DTHE_S_CRC_CTRL + // & DTHE_S_CRC_CTRL should be + // exclusive +#define DTHE_CRC_CTRL_TYPE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DTHE_O_CRC_SEED register. +// +//****************************************************************************** +#define DTHE_CRC_SEED_SEED_M 0xFFFFFFFF // Starting seed of CRC and + // checksum operation. Please see + // CTRL register for more detail. + // This resister also holds the + // latest result of CRC or checksum + // operation +#define DTHE_CRC_SEED_SEED_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the DTHE_O_CRC_DIN register. +// +//****************************************************************************** +#define DTHE_CRC_DIN_DATA_IN_M \ + 0xFFFFFFFF // Input data for CRC or checksum + // operation + +#define DTHE_CRC_DIN_DATA_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_CRC_RSLT_PP register. +// +//****************************************************************************** +#define DTHE_CRC_RSLT_PP_RSLT_PP_M \ + 0xFFFFFFFF // Input data for CRC or checksum + // operation + +#define DTHE_CRC_RSLT_PP_RSLT_PP_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_RAND_KEY0 register. +// +//****************************************************************************** +#define DTHE_RAND_KEY0_KEY_M 0xFFFFFFFF // Device Specific Randon key + // [31:0] +#define DTHE_RAND_KEY0_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_RAND_KEY1 register. +// +//****************************************************************************** +#define DTHE_RAND_KEY1_KEY_M 0xFFFFFFFF // Device Specific Randon key + // [63:32] +#define DTHE_RAND_KEY1_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_RAND_KEY2 register. +// +//****************************************************************************** +#define DTHE_RAND_KEY2_KEY_M 0xFFFFFFFF // Device Specific Randon key + // [95:34] +#define DTHE_RAND_KEY2_KEY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// DTHE_O_RAND_KEY3 register. +// +//****************************************************************************** +#define DTHE_RAND_KEY3_KEY_M 0xFFFFFFFF // Device Specific Randon key + // [127:96] +#define DTHE_RAND_KEY3_KEY_S 0 + + + +#endif // __HW_DTHE_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_flash_ctrl.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_flash_ctrl.h new file mode 100644 index 00000000..b57044aa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_flash_ctrl.h @@ -0,0 +1,1862 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_FLASH_CTRL_H__ +#define __HW_FLASH_CTRL_H__ + +//***************************************************************************** +// +// The following are defines for the FLASH_CTRL register offsets. +// +//***************************************************************************** +#define FLASH_CTRL_O_FMA 0x00000000 // Flash Memory Address (FMA) + // offset 0x000 During a write + // operation this register contains + // a 4-byte-aligned address and + // specifies where the data is + // written. During erase operations + // this register contains a 1 + // KB-aligned CPU byte address and + // specifies which block is erased. + // Note that the alignment + // requirements must be met by + // software or the results of the + // operation are unpredictable. +#define FLASH_CTRL_O_FMD 0x00000004 // Flash Memory Data (FMD) offset + // 0x004 This register contains the + // data to be written during the + // programming cycle or read during + // the read cycle. Note that the + // contents of this register are + // undefined for a read access of an + // execute-only block. This register + // is not used during erase cycles. +#define FLASH_CTRL_O_FMC 0x00000008 // Flash Memory Control (FMC) + // offset 0x008 When this register + // is written the Flash memory + // controller initiates the + // appropriate access cycle for the + // location specified by the Flash + // Memory Address (FMA) register . + // If the access is a write access + // the data contained in the Flash + // Memory Data (FMD) register is + // written to the specified address. + // This register must be the final + // register written and initiates + // the memory operation. The four + // control bits in the lower byte of + // this register are used to + // initiate memory operations. +#define FLASH_CTRL_O_FCRIS 0x0000000C // Flash Controller Raw Interrupt + // Status (FCRIS) offset 0x00C This + // register indicates that the Flash + // memory controller has an + // interrupt condition. An interrupt + // is sent to the interrupt + // controller only if the + // corresponding FCIM register bit + // is set. +#define FLASH_CTRL_O_FCIM 0x00000010 // Flash Controller Interrupt Mask + // (FCIM) offset 0x010 This register + // controls whether the Flash memory + // controller generates interrupts + // to the controller. +#define FLASH_CTRL_O_FCMISC 0x00000014 // Flash Controller Masked + // Interrupt Status and Clear + // (FCMISC) offset 0x014 This + // register provides two functions. + // First it reports the cause of an + // interrupt by indicating which + // interrupt source or sources are + // signalling the interrupt. Second + // it serves as the method to clear + // the interrupt reporting. +#define FLASH_CTRL_O_FMC2 0x00000020 // Flash Memory Control 2 (FMC2) + // offset 0x020 When this register + // is written the Flash memory + // controller initiates the + // appropriate access cycle for the + // location specified by the Flash + // Memory Address (FMA) register . + // If the access is a write access + // the data contained in the Flash + // Write Buffer (FWB) registers is + // written. This register must be + // the final register written as it + // initiates the memory operation. +#define FLASH_CTRL_O_FWBVAL 0x00000030 // Flash Write Buffer Valid + // (FWBVAL) offset 0x030 This + // register provides a bitwise + // status of which FWBn registers + // have been written by the + // processor since the last write of + // the Flash memory write buffer. + // The entries with a 1 are written + // on the next write of the Flash + // memory write buffer. This + // register is cleared after the + // write operation by hardware. A + // protection violation on the write + // operation also clears this + // status. Software can program the + // same 32 words to various Flash + // memory locations by setting the + // FWB[n] bits after they are + // cleared by the write operation. + // The next write operation then + // uses the same data as the + // previous one. In addition if a + // FWBn register change should not + // be written to Flash memory + // software can clear the + // corresponding FWB[n] bit to + // preserve the existing data when + // the next write operation occurs. +#define FLASH_CTRL_O_FWB1 0x00000100 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB2 0x00000104 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB3 0x00000108 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB4 0x0000010C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB5 0x00000110 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB6 0x00000114 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB7 0x00000118 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB8 0x0000011C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB9 0x00000120 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB10 0x00000124 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB11 0x00000128 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB12 0x0000012C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB13 0x00000130 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB14 0x00000134 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB15 0x00000138 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB16 0x0000013C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB17 0x00000140 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB18 0x00000144 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB19 0x00000148 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB20 0x0000014C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB21 0x00000150 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB22 0x00000154 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB23 0x00000158 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB24 0x0000015C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB25 0x00000160 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB26 0x00000164 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB27 0x00000168 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB28 0x0000016C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB29 0x00000170 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB30 0x00000174 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB31 0x00000178 // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FWB32 0x0000017C // Flash Write Buffer n (FWBn) + // offset 0x100 - 0x17C These 32 + // registers hold the contents of + // the data to be written into the + // Flash memory on a buffered Flash + // memory write operation. The + // offset selects one of the 32-bit + // registers. Only FWBn registers + // that have been updated since the + // preceding buffered Flash memory + // write operation are written into + // the Flash memory so it is not + // necessary to write the entire + // bank of registers in order to + // write 1 or 2 words. The FWBn + // registers are written into the + // Flash memory with the FWB0 + // register corresponding to the + // address contained in FMA. FWB1 is + // written to the address FMA+0x4 + // etc. Note that only data bits + // that are 0 result in the Flash + // memory being modified. A data bit + // that is 1 leaves the content of + // the Flash memory bit at its + // previous value. +#define FLASH_CTRL_O_FSIZE 0x00000FC0 // Flash Size (FSIZE) offset 0xFC0 + // This register indicates the size + // of the on-chip Flash memory. + // Important: This register should + // be used to determine the size of + // the Flash memory that is + // implemented on this + // microcontroller. However to + // support legacy software the DC0 + // register is available. A read of + // the DC0 register correctly + // identifies legacy memory sizes. + // Software must use the FSIZE + // register for memory sizes that + // are not listed in the DC0 + // register description. +#define FLASH_CTRL_O_SSIZE 0x00000FC4 // SRAM Size (SSIZE) offset 0xFC4 + // This register indicates the size + // of the on-chip SRAM. Important: + // This register should be used to + // determine the size of the SRAM + // that is implemented on this + // microcontroller. However to + // support legacy software the DC0 + // register is available. A read of + // the DC0 register correctly + // identifies legacy memory sizes. + // Software must use the SSIZE + // register for memory sizes that + // are not listed in the DC0 + // register description. + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FMA register. +// +//****************************************************************************** +#define FLASH_CTRL_FMA_OFFSET_M 0x0003FFFF // Address Offset Address offset in + // Flash memory where operation is + // performed except for nonvolatile + // registers +#define FLASH_CTRL_FMA_OFFSET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FMD register. +// +//****************************************************************************** +#define FLASH_CTRL_FMD_DATA_M 0xFFFFFFFF // Data Value Data value for write + // operation. +#define FLASH_CTRL_FMD_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FMC register. +// +//****************************************************************************** +#define FLASH_CTRL_FMC_WRKEY_M 0xFFFF0000 // Flash Memory Write Key This + // field contains a write key which + // is used to minimize the incidence + // of accidental Flash memory + // writes. The value 0xA442 must be + // written into this field for a + // Flash memory write to occur. + // Writes to the FMC register + // without this WRKEY value are + // ignored. A read of this field + // returns the value 0. +#define FLASH_CTRL_FMC_WRKEY_S 16 +#define FLASH_CTRL_FMC_COMT 0x00000008 // Commit Register Value This bit + // is used to commit writes to + // Flash-memory-resident registers + // and to monitor the progress of + // that process. Value Description 1 + // Set this bit to commit (write) + // the register value to a + // Flash-memory-resident register. + // When read a 1 indicates that the + // previous commit access is not + // complete. 0 A write of 0 has no + // effect on the state of this bit. + // When read a 0 indicates that the + // previous commit access is + // complete. +#define FLASH_CTRL_FMC_MERASE1 0x00000004 // Mass Erase Flash Memory This bit + // is used to mass erase the Flash + // main memory and to monitor the + // progress of that process. Value + // Description 1 Set this bit to + // erase the Flash main memory. When + // read a 1 indicates that the + // previous mass erase access is not + // complete. 0 A write of 0 has no + // effect on the state of this bit. + // When read a 0 indicates that the + // previous mass erase access is + // complete. +#define FLASH_CTRL_FMC_ERASE 0x00000002 // Erase a Page of Flash Memory + // This bit is used to erase a page + // of Flash memory and to monitor + // the progress of that process. + // Value Description 1 Set this bit + // to erase the Flash memory page + // specified by the contents of the + // FMA register. When read a 1 + // indicates that the previous page + // erase access is not complete. 0 A + // write of 0 has no effect on the + // state of this bit. When read a 0 + // indicates that the previous page + // erase access is complete. +#define FLASH_CTRL_FMC_WRITE 0x00000001 // Write a Word into Flash Memory + // This bit is used to write a word + // into Flash memory and to monitor + // the progress of that process. + // Value Description 1 Set this bit + // to write the data stored in the + // FMD register into the Flash + // memory location specified by the + // contents of the FMA register. + // When read a 1 indicates that the + // write update access is not + // complete. 0 A write of 0 has no + // effect on the state of this bit. + // When read a 0 indicates that the + // previous write update access is + // complete. +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FCRIS register. +// +//****************************************************************************** +#define FLASH_CTRL_FCRIS_PROGRIS \ + 0x00002000 // Program Verify Error Raw + // Interrupt Status Value + // Description 1 An interrupt is + // pending because the verify of a + // PROGRAM operation failed. 0 An + // interrupt has not occurred. This + // bit is cleared by writing a 1 to + // the PROGMISC bit in the FCMISC + // register. + +#define FLASH_CTRL_FCRIS_ERRIS 0x00000800 // Erase Verify Error Raw Interrupt + // Status Value Description 1 An + // interrupt is pending because the + // verify of an ERASE operation + // failed. 0 An interrupt has not + // occurred. This bit is cleared by + // writing a 1 to the ERMISC bit in + // the FCMISC register. +#define FLASH_CTRL_FCRIS_INVDRIS \ + 0x00000400 // Invalid Data Raw Interrupt + // Status Value Description 1 An + // interrupt is pending because a + // bit that was previously + // programmed as a 0 is now being + // requested to be programmed as a + // 1. 0 An interrupt has not + // occurred. This bit is cleared by + // writing a 1 to the INVMISC bit in + // the FCMISC register. + +#define FLASH_CTRL_FCRIS_VOLTRIS \ + 0x00000200 // Pump Voltage Raw Interrupt + // Status Value Description 1 An + // interrupt is pending because the + // regulated voltage of the pump + // went out of spec during the Flash + // operation and the operation was + // terminated. 0 An interrupt has + // not occurred. This bit is cleared + // by writing a 1 to the VOLTMISC + // bit in the FCMISC register. + +#define FLASH_CTRL_FCRIS_ERIS 0x00000004 // EEPROM Raw Interrupt Status This + // bit provides status EEPROM + // operation. Value Description 1 An + // EEPROM interrupt has occurred. 0 + // An EEPROM interrupt has not + // occurred. This bit is cleared by + // writing a 1 to the EMISC bit in + // the FCMISC register. +#define FLASH_CTRL_FCRIS_PRIS 0x00000002 // Programming Raw Interrupt Status + // This bit provides status on + // programming cycles which are + // write or erase actions generated + // through the FMC or FMC2 register + // bits (see page 537 and page 549). + // Value Description 1 The + // programming or erase cycle has + // completed. 0 The programming or + // erase cycle has not completed. + // This status is sent to the + // interrupt controller when the + // PMASK bit in the FCIM register is + // set. This bit is cleared by + // writing a 1 to the PMISC bit in + // the FCMISC register. +#define FLASH_CTRL_FCRIS_ARIS 0x00000001 // Access Raw Interrupt Status + // Value Description 1 A program or + // erase action was attempted on a + // block of Flash memory that + // contradicts the protection policy + // for that block as set in the + // FMPPEn registers. 0 No access has + // tried to improperly program or + // erase the Flash memory. This + // status is sent to the interrupt + // controller when the AMASK bit in + // the FCIM register is set. This + // bit is cleared by writing a 1 to + // the AMISC bit in the FCMISC + // register. +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FCIM register. +// +//****************************************************************************** +#define FLASH_CTRL_FCIM_ILLMASK 0x00004000 // Illegal Address Interrupt Mask + // Value Description 1 An interrupt + // is sent to the interrupt + // controller when the ILLARIS bit + // is set. 0 The ILLARIS interrupt + // is suppressed and not sent to the + // interrupt controller. +#define FLASH_CTRL_FCIM_PROGMASK \ + 0x00002000 // PROGVER Interrupt Mask Value + // Description 1 An interrupt is + // sent to the interrupt controller + // when the PROGRIS bit is set. 0 + // The PROGRIS interrupt is + // suppressed and not sent to the + // interrupt controller. + +#define FLASH_CTRL_FCIM_PREMASK 0x00001000 // PREVER Interrupt Mask Value + // Description 1 An interrupt is + // sent to the interrupt controller + // when the PRERIS bit is set. 0 The + // PRERIS interrupt is suppressed + // and not sent to the interrupt + // controller. +#define FLASH_CTRL_FCIM_ERMASK 0x00000800 // ERVER Interrupt Mask Value + // Description 1 An interrupt is + // sent to the interrupt controller + // when the ERRIS bit is set. 0 The + // ERRIS interrupt is suppressed and + // not sent to the interrupt + // controller. +#define FLASH_CTRL_FCIM_INVDMASK \ + 0x00000400 // Invalid Data Interrupt Mask + // Value Description 1 An interrupt + // is sent to the interrupt + // controller when the INVDRIS bit + // is set. 0 The INVDRIS interrupt + // is suppressed and not sent to the + // interrupt controller. + +#define FLASH_CTRL_FCIM_VOLTMASK \ + 0x00000200 // VOLT Interrupt Mask Value + // Description 1 An interrupt is + // sent to the interrupt controller + // when the VOLTRIS bit is set. 0 + // The VOLTRIS interrupt is + // suppressed and not sent to the + // interrupt controller. + +#define FLASH_CTRL_FCIM_LOCKMASK \ + 0x00000100 // LOCK Interrupt Mask Value + // Description 1 An interrupt is + // sent to the interrupt controller + // when the LOCKRIS bit is set. 0 + // The LOCKRIS interrupt is + // suppressed and not sent to the + // interrupt controller. + +#define FLASH_CTRL_FCIM_EMASK 0x00000004 // EEPROM Interrupt Mask Value + // Description 1 An interrupt is + // sent to the interrupt controller + // when the ERIS bit is set. 0 The + // ERIS interrupt is suppressed and + // not sent to the interrupt + // controller. +#define FLASH_CTRL_FCIM_PMASK 0x00000002 // Programming Interrupt Mask This + // bit controls the reporting of the + // programming raw interrupt status + // to the interrupt controller. + // Value Description 1 An interrupt + // is sent to the interrupt + // controller when the PRIS bit is + // set. 0 The PRIS interrupt is + // suppressed and not sent to the + // interrupt controller. +#define FLASH_CTRL_FCIM_AMASK 0x00000001 // Access Interrupt Mask This bit + // controls the reporting of the + // access raw interrupt status to + // the interrupt controller. Value + // Description 1 An interrupt is + // sent to the interrupt controller + // when the ARIS bit is set. 0 The + // ARIS interrupt is suppressed and + // not sent to the interrupt + // controller. +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FCMISC register. +// +//****************************************************************************** +#define FLASH_CTRL_FCMISC_ILLMISC \ + 0x00004000 // Illegal Address Masked Interrupt + // Status and Clear Value + // Description 1 When read a 1 + // indicates that an unmasked + // interrupt was signaled. Writing a + // 1 to this bit clears ILLAMISC and + // also the ILLARIS bit in the FCRIS + // register (see page 540). 0 When + // read a 0 indicates that an + // interrupt has not occurred. A + // write of 0 has no effect on the + // state of this bit. + +#define FLASH_CTRL_FCMISC_PROGMISC \ + 0x00002000 // PROGVER Masked Interrupt Status + // and Clear Value Description 1 + // When read a 1 indicates that an + // unmasked interrupt was signaled. + // Writing a 1 to this bit clears + // PROGMISC and also the PROGRIS bit + // in the FCRIS register (see page + // 540). 0 When read a 0 indicates + // that an interrupt has not + // occurred. A write of 0 has no + // effect on the state of this bit. + +#define FLASH_CTRL_FCMISC_PREMISC \ + 0x00001000 // PREVER Masked Interrupt Status + // and Clear Value Description 1 + // When read a 1 indicates that an + // unmasked interrupt was signaled. + // Writing a 1 to this bit clears + // PREMISC and also the PRERIS bit + // in the FCRIS register . 0 When + // read a 0 indicates that an + // interrupt has not occurred. A + // write of 0 has no effect on the + // state of this bit. + +#define FLASH_CTRL_FCMISC_ERMISC \ + 0x00000800 // ERVER Masked Interrupt Status + // and Clear Value Description 1 + // When read a 1 indicates that an + // unmasked interrupt was signaled. + // Writing a 1 to this bit clears + // ERMISC and also the ERRIS bit in + // the FCRIS register 0 When read a + // 0 indicates that an interrupt has + // not occurred. A write of 0 has no + // effect on the state of this bit. + +#define FLASH_CTRL_FCMISC_INVDMISC \ + 0x00000400 // Invalid Data Masked Interrupt + // Status and Clear Value + // Description 1 When read a 1 + // indicates that an unmasked + // interrupt was signaled. Writing a + // 1 to this bit clears INVDMISC and + // also the INVDRIS bit in the FCRIS + // register (see page 540). 0 When + // read a 0 indicates that an + // interrupt has not occurred. A + // write of 0 has no effect on the + // state of this bit. + +#define FLASH_CTRL_FCMISC_VOLTMISC \ + 0x00000200 // VOLT Masked Interrupt Status and + // Clear Value Description 1 When + // read a 1 indicates that an + // unmasked interrupt was signaled. + // Writing a 1 to this bit clears + // VOLTMISC and also the VOLTRIS bit + // in the FCRIS register (see page + // 540). 0 When read a 0 indicates + // that an interrupt has not + // occurred. A write of 0 has no + // effect on the state of this bit. + +#define FLASH_CTRL_FCMISC_LOCKMISC \ + 0x00000100 // LOCK Masked Interrupt Status and + // Clear Value Description 1 When + // read a 1 indicates that an + // unmasked interrupt was signaled. + // Writing a 1 to this bit clears + // LOCKMISC and also the LOCKRIS bit + // in the FCRIS register (see page + // 540). 0 When read a 0 indicates + // that an interrupt has not + // occurred. A write of 0 has no + // effect on the state of this bit. + +#define FLASH_CTRL_FCMISC_EMISC 0x00000004 // EEPROM Masked Interrupt Status + // and Clear Value Description 1 + // When read a 1 indicates that an + // unmasked interrupt was signaled. + // Writing a 1 to this bit clears + // EMISC and also the ERIS bit in + // the FCRIS register 0 When read a + // 0 indicates that an interrupt has + // not occurred. A write of 0 has no + // effect on the state of this bit. +#define FLASH_CTRL_FCMISC_PMISC 0x00000002 // Programming Masked Interrupt + // Status and Clear Value + // Description 1 When read a 1 + // indicates that an unmasked + // interrupt was signaled because a + // programming cycle completed. + // Writing a 1 to this bit clears + // PMISC and also the PRIS bit in + // the FCRIS register 0 When read a + // 0 indicates that a programming + // cycle complete interrupt has not + // occurred. A write of 0 has no + // effect on the state of this bit. +#define FLASH_CTRL_FCMISC_AMISC 0x00000001 // Access Masked Interrupt Status + // and Clear Value Description 1 + // When read a 1 indicates that an + // unmasked interrupt was signaled + // because a program or erase action + // was attempted on a block of Flash + // memory that contradicts the + // protection policy for that block + // as set in the FMPPEn registers. + // Writing a 1 to this bit clears + // AMISC and also the ARIS bit in + // the FCRIS register 0 When read a + // 0 indicates that no improper + // accesses have occurred. A write + // of 0 has no effect on the state + // of this bit. +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FMC2 register. +// +//****************************************************************************** +#define FLASH_CTRL_FMC2_WRKEY_M 0xFFFF0000 // Flash Memory Write Key This + // field contains a write key which + // is used to minimize the incidence + // of accidental Flash memory + // writes. The value 0xA442 must be + // written into this field for a + // write to occur. Writes to the + // FMC2 register without this WRKEY + // value are ignored. A read of this + // field returns the value 0. +#define FLASH_CTRL_FMC2_WRKEY_S 16 +#define FLASH_CTRL_FMC2_WRBUF 0x00000001 // Buffered Flash Memory Write This + // bit is used to start a buffered + // write to Flash memory. Value + // Description 1 Set this bit to + // write the data stored in the FWBn + // registers to the location + // specified by the contents of the + // FMA register. When read a 1 + // indicates that the previous + // buffered Flash memory write + // access is not complete. 0 A write + // of 0 has no effect on the state + // of this bit. When read a 0 + // indicates that the previous + // buffered Flash memory write + // access is complete. +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWBVAL register. +// +//****************************************************************************** +#define FLASH_CTRL_FWBVAL_FWBN_M \ + 0xFFFFFFFF // Flash Memory Write Buffer Value + // Description 1 The corresponding + // FWBn register has been updated + // since the last buffer write + // operation and is ready to be + // written to Flash memory. 0 The + // corresponding FWBn register has + // no new data to be written. Bit 0 + // corresponds to FWB0 offset 0x100 + // and bit 31 corresponds to FWB31 + // offset 0x13C. + +#define FLASH_CTRL_FWBVAL_FWBN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB1 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB1_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB1_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB2 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB2_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB2_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB3 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB3_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB3_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB4 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB4_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB4_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB5 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB5_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB5_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB6 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB6_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB6_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB7 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB7_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB7_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB8 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB8_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB8_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the FLASH_CTRL_O_FWB9 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB9_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB9_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB10 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB10_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB10_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB11 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB11_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB11_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB12 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB12_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB12_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB13 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB13_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB13_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB14 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB14_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB14_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB15 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB15_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB15_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB16 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB16_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB16_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB17 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB17_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB17_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB18 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB18_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB18_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB19 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB19_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB19_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB20 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB20_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB20_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB21 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB21_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB21_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB22 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB22_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB22_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB23 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB23_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB23_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB24 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB24_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB24_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB25 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB25_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB25_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB26 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB26_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB26_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB27 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB27_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB27_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB28 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB28_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB28_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB29 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB29_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB29_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB30 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB30_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB30_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB31 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB31_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB31_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FWB32 register. +// +//****************************************************************************** +#define FLASH_CTRL_FWB32_DATA_M 0xFFFFFFFF // Data Data to be written into the + // Flash memory. +#define FLASH_CTRL_FWB32_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_FSIZE register. +// +//****************************************************************************** +#define FLASH_CTRL_FSIZE_SIZE_M 0x0000FFFF // Flash Size Indicates the size of + // the on-chip Flash memory. Value + // Description 0x0003 8 KB of Flash + // 0x0007 16 KB of Flash 0x000F 32 + // KB of Flash 0x001F 64 KB of Flash + // 0x002F 96 KB of Flash 0x003F 128 + // KB of Flash 0x005F 192 KB of + // Flash 0x007F 256 KB of Flash +#define FLASH_CTRL_FSIZE_SIZE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// FLASH_CTRL_O_SSIZE register. +// +//****************************************************************************** +#define FLASH_CTRL_SSIZE_SRAM_SIZE_M \ + 0x0000FFFF // SRAM Size Indicates the size of + // the on-chip SRAM. Value + // Description 0x0007 2 KB of SRAM + // 0x000F 4 KB of SRAM 0x0017 6 KB + // of SRAM 0x001F 8 KB of SRAM + // 0x002F 12 KB of SRAM 0x003F 16 KB + // of SRAM 0x004F 20 KB of SRAM + // 0x005F 24 KB of SRAM 0x007F 32 KB + // of SRAM + +#define FLASH_CTRL_SSIZE_SRAM_SIZE_S 0 +#define FLASH_CTRL_FMC_WRKEY 0xA4420000 // FLASH write key +#define FLASH_CTRL_FMC2_WRKEY 0xA4420000 // FLASH write key +#define FLASH_CTRL_O_FWBN FLASH_CTRL_O_FWB1 +#define FLASH_ERASE_SIZE 0x00000400 +#define FLASH_PROTECT_SIZE 0x00000800 +#define FLASH_FMP_BLOCK_0 0x00000001 // Enable for block 0 + +#define FLASH_FMPRE0 0x400FE200 // Flash Memory Protection Read + // Enable 0 +#define FLASH_FMPRE1 0x400FE204 // Flash Memory Protection Read + // Enable 1 +#define FLASH_FMPRE2 0x400FE208 // Flash Memory Protection Read + // Enable 2 +#define FLASH_FMPRE3 0x400FE20C // Flash Memory Protection Read + // Enable 3 +#define FLASH_FMPRE4 0x400FE210 // Flash Memory Protection Read + // Enable 4 +#define FLASH_FMPRE5 0x400FE214 // Flash Memory Protection Read + // Enable 5 +#define FLASH_FMPRE6 0x400FE218 // Flash Memory Protection Read + // Enable 6 +#define FLASH_FMPRE7 0x400FE21C // Flash Memory Protection Read + // Enable 7 +#define FLASH_FMPRE8 0x400FE220 // Flash Memory Protection Read + // Enable 8 +#define FLASH_FMPRE9 0x400FE224 // Flash Memory Protection Read + // Enable 9 +#define FLASH_FMPRE10 0x400FE228 // Flash Memory Protection Read + // Enable 10 +#define FLASH_FMPRE11 0x400FE22C // Flash Memory Protection Read + // Enable 11 +#define FLASH_FMPRE12 0x400FE230 // Flash Memory Protection Read + // Enable 12 +#define FLASH_FMPRE13 0x400FE234 // Flash Memory Protection Read + // Enable 13 +#define FLASH_FMPRE14 0x400FE238 // Flash Memory Protection Read + // Enable 14 +#define FLASH_FMPRE15 0x400FE23C // Flash Memory Protection Read + // Enable 15 + +#define FLASH_FMPPE0 0x400FE400 // Flash Memory Protection Program + // Enable 0 +#define FLASH_FMPPE1 0x400FE404 // Flash Memory Protection Program + // Enable 1 +#define FLASH_FMPPE2 0x400FE408 // Flash Memory Protection Program + // Enable 2 +#define FLASH_FMPPE3 0x400FE40C // Flash Memory Protection Program + // Enable 3 +#define FLASH_FMPPE4 0x400FE410 // Flash Memory Protection Program + // Enable 4 +#define FLASH_FMPPE5 0x400FE414 // Flash Memory Protection Program + // Enable 5 +#define FLASH_FMPPE6 0x400FE418 // Flash Memory Protection Program + // Enable 6 +#define FLASH_FMPPE7 0x400FE41C // Flash Memory Protection Program + // Enable 7 +#define FLASH_FMPPE8 0x400FE420 // Flash Memory Protection Program + // Enable 8 +#define FLASH_FMPPE9 0x400FE424 // Flash Memory Protection Program + // Enable 9 +#define FLASH_FMPPE10 0x400FE428 // Flash Memory Protection Program + // Enable 10 +#define FLASH_FMPPE11 0x400FE42C // Flash Memory Protection Program + // Enable 11 +#define FLASH_FMPPE12 0x400FE430 // Flash Memory Protection Program + // Enable 12 +#define FLASH_FMPPE13 0x400FE434 // Flash Memory Protection Program + // Enable 13 +#define FLASH_FMPPE14 0x400FE438 // Flash Memory Protection Program + // Enable 14 +#define FLASH_FMPPE15 0x400FE43C // Flash Memory Protection Program + // Enable 15 + +#define FLASH_USECRL 0x400FE140 // USec Reload +#define FLASH_CTRL_ERASE_SIZE 0x00000400 + + +#endif // __HW_FLASH_CTRL_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gpio.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gpio.h new file mode 100644 index 00000000..2bd6e0f3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gpio.h @@ -0,0 +1,1349 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_GPIO_H__ +#define __HW_GPIO_H__ + +//***************************************************************************** +// +// The following are defines for the GPIO register offsets. +// +//***************************************************************************** +#define GPIO_O_GPIO_DATA 0x00000000 // 0x4000 5000 0x4000 6000 0x4000 + // 7000 0x4002 4000 GPIO Data + // (GPIODATA)@@ offset 0x000 The + // GPIODATA register is the data + // register. In software control + // mode@@ values written in the + // GPIODATA register are transferred + // onto the GPIO port pins if the + // respective pins have been + // configured as outputs through the + // GPIO Direction (GPIODIR) register + // (see page 653). In order to write + // to GPIODATA@@ the corresponding + // bits in the mask@@ resulting from + // the address bus bits [9:2]@@ must + // be set. Otherwise@@ the bit + // values remain unchanged by the + // write. Similarly@@ the values + // read from this register are + // determined for each bit by the + // mask bit derived from the address + // used to access the data + // register@@ bits [9:2]. Bits that + // are set in the address mask cause + // the corresponding bits in + // GPIODATA to be read@@ and bits + // that are clear in the address + // mask cause the corresponding bits + // in GPIODATA to be read as 0@@ + // regardless of their value. A read + // from GPIODATA returns the last + // bit value written if the + // respective pins are configured as + // outputs@@ or it returns the value + // on the corresponding input pin + // when these are configured as + // inputs. All bits are cleared by a + // reset. +#define GPIO_O_GPIO_DIR 0x00000400 // 0x4000 5400 0x4000 6400 0x4000 + // 7400 0x4002 4400 GPIO Direction + // (GPIODIR)@@ offset 0x400 The + // GPIODIR register is the data + // direction register. Setting a bit + // in the GPIODIR register + // configures the corresponding pin + // to be an output@@ while clearing + // a bit configures the + // corresponding pin to be an input. + // All bits are cleared by a reset@@ + // meaning all GPIO pins are inputs + // by default. +#define GPIO_O_GPIO_IS 0x00000404 // 0x4000 5404 0x4000 6404 0x4000 + // 7404 0x4002 4404 GPIO Interrupt + // Sense (GPIOIS)@@ offset 0x404 The + // GPIOIS register is the interrupt + // sense register. Setting a bit in + // the GPIOIS register configures + // the corresponding pin to detect + // levels@@ while clearing a bit + // configures the corresponding pin + // to detect edges. All bits are + // cleared by a reset. +#define GPIO_O_GPIO_IBE 0x00000408 // 0x4000 5408 0x4000 6408 0x4000 + // 7408 0x4002 4408 GPIO Interrupt + // Both Edges (GPIOIBE)@@ offset + // 0x408 The GPIOIBE register allows + // both edges to cause interrupts. + // When the corresponding bit in the + // GPIO Interrupt Sense (GPIOIS) + // register is set to detect edges@@ + // setting a bit in the GPIOIBE + // register configures the + // corresponding pin to detect both + // rising and falling edges@@ + // regardless of the corresponding + // bit in the GPIO Interrupt Event + // (GPIOIEV) register . Clearing a + // bit configures the pin to be + // controlled by the GPIOIEV + // register. All bits are cleared by + // a reset. +#define GPIO_O_GPIO_IEV 0x0000040C // 0x4000 540C 0x4000 640C 0x4000 + // 740C 0x4002 440C GPIO Interrupt + // Event (GPIOIEV)@@ offset 0x40C + // The GPIOIEV register is the + // interrupt event register. Setting + // a bit in the GPIOIEV register + // configures the corresponding pin + // to detect rising edges or high + // levels@@ depending on the + // corresponding bit value in the + // GPIO Interrupt Sense (GPIOIS) + // register . Clearing a bit + // configures the pin to detect + // falling edges or low levels@@ + // depending on the corresponding + // bit value in the GPIOIS register. + // All bits are cleared by a reset. +#define GPIO_O_GPIO_IM 0x00000410 // 0x4000 5410 0x4000 6410 0x4000 + // 7410 0x4002 4410 GPIO Interrupt + // Mask (GPIOIM)@@ offset 0x410 The + // GPIOIM register is the interrupt + // mask register. Setting a bit in + // the GPIOIM register allows + // interrupts that are generated by + // the corresponding pin to be sent + // to the interrupt controller on + // the combined interrupt signal. + // Clearing a bit prevents an + // interrupt on the corresponding + // pin from being sent to the + // interrupt controller. All bits + // are cleared by a reset. +#define GPIO_O_GPIO_RIS 0x00000414 // 0x4000 5414 0x4000 6414 0x4000 + // 7414 0x4002 4414 GPIO Raw + // Interrupt Status (GPIORIS)@@ + // offset 0x414 The GPIORIS register + // is the raw interrupt status + // register. A bit in this register + // is set when an interrupt + // condition occurs on the + // corresponding GPIO pin. If the + // corresponding bit in the GPIO + // Interrupt Mask (GPIOIM) register + // is set@@ the interrupt is sent to + // the interrupt controller. Bits + // read as zero indicate that + // corresponding input pins have not + // initiated an interrupt. A bit in + // this register can be cleared by + // writing a 1 to the corresponding + // bit in the GPIO Interrupt Clear + // (GPIOICR) register. +#define GPIO_O_GPIO_MIS 0x00000418 // 0x4000 5418 0x4000 6418 0x4000 + // 7418 0x4002 4418 GPIO Masked + // Interrupt Status (GPIOMIS)@@ + // offset 0x418 The GPIOMIS register + // is the masked interrupt status + // register. If a bit is set in this + // register@@ the corresponding + // interrupt has triggered an + // interrupt to the interrupt + // controller. If a bit is clear@@ + // either no interrupt has been + // generated@@ or the interrupt is + // masked. If no port pin@@ other + // than the one that is being used + // as an ADC trigger@@ is being used + // to generate interrupts@@ the + // appropriate Interrupt Set Enable + // (ENn) register can disable the + // interrupts for the port@@ and the + // ADC interrupt can be used to read + // back the converted data. + // Otherwise@@ the port interrupt + // handler must ignore and clear + // interrupts on the port pin and + // wait for the ADC interrupt@@ or + // the ADC interrupt must be + // disabled in the EN0 register and + // the port interrupt handler must + // poll the ADC registers until the + // conversion is completed. If no + // port pin@@ other than the one + // that is being used as an ADC + // trigger@@ is being used to + // generate interrupts@@ the + // appropriate Interrupt Set Enable + // (ENn) register can disable the + // interrupts for the port@@ and the + // ADC interrupt can be used to read + // back the converted data. + // Otherwise@@ the port interrupt + // handler must ignore and clear + // interrupts on the port pin and + // wait for the ADC interrupt@@ or + // the ADC interrupt must be + // disabled in the EN0 register and + // the port interrupt handler must + // poll the ADC registers until the + // conversion is completed. Note + // that if the Port B GPIOADCCTL + // register is cleared@@ PB4 can + // still be used as an external + // trigger for the ADC. This is a + // legacy mode which allows code + // written for previous Stellaris + // devices to operate on this + // microcontroller. GPIOMIS is the + // state of the interrupt after + // masking. +#define GPIO_O_GPIO_ICR 0x0000041C // 0x4000 541C 0x4000 641C 0x4000 + // 741C 0x4002 441C GPIO Interrupt + // Clear (GPIOICR)@@ offset 0x41C + // The GPIOICR register is the + // interrupt clear register. Writing + // a 1 to a bit in this register + // clears the corresponding + // interrupt bit in the GPIORIS and + // GPIOMIS registers. Writing a 0 + // has no effect. +#define GPIO_O_GPIO_AFSEL 0x00000420 // 0x4000 5420 0x4000 6420 0x4000 + // 7420 0x4002 4420 GPIO Alternate + // Function Select (GPIOAFSEL)@@ + // offset 0x420 The GPIOAFSEL + // register is the mode control + // select register. If a bit is + // clear@@ the pin is used as a GPIO + // and is controlled by the GPIO + // registers. Setting a bit in this + // register configures the + // corresponding GPIO line to be + // controlled by an associated + // peripheral. Several possible + // peripheral functions are + // multiplexed on each GPIO. The + // GPIO Port Control (GPIOPCTL) + // register is used to select one of + // the possible functions. +#define GPIO_O_GPIO_DR2R 0x00000500 // 0x4000 5500 0x4000 6500 0x4000 + // 7500 0x4002 4500 GPIO 2-mA Drive + // Select (GPIODR2R)@@ offset 0x500 + // The GPIODR2R register is the 2-mA + // drive control register. Each GPIO + // signal in the port can be + // individually configured without + // affecting the other pads. When + // setting the DRV2 bit for a GPIO + // signal@@ the corresponding DRV4 + // bit in the GPIODR4R register and + // DRV8 bit in the GPIODR8R register + // are automatically cleared by + // hardware. By default@@ all GPIO + // pins have 2-mA drive. +#define GPIO_O_GPIO_DR4R 0x00000504 // 0x4000 5504 0x4000 6504 0x4000 + // 7504 0x4002 4504 GPIO 4-mA Drive + // Select (GPIODR4R)@@ offset 0x504 + // The GPIODR4R register is the 4-mA + // drive control register. Each GPIO + // signal in the port can be + // individually configured without + // affecting the other pads. When + // setting the DRV4 bit for a GPIO + // signal@@ the corresponding DRV2 + // bit in the GPIODR2R register and + // DRV8 bit in the GPIODR8R register + // are automatically cleared by + // hardware. +#define GPIO_O_GPIO_DR8R 0x00000508 // 0x4000 5508 0x4000 6508 0x4000 + // 7508 0x4002 4508 GPIO 8-mA Drive + // Select (GPIODR8R)@@ offset 0x508 + // The GPIODR8R register is the 8-mA + // drive control register. Each GPIO + // signal in the port can be + // individually configured without + // affecting the other pads. When + // setting the DRV8 bit for a GPIO + // signal@@ the corresponding DRV2 + // bit in the GPIODR2R register and + // DRV4 bit in the GPIODR4R register + // are automatically cleared by + // hardware. The 8-mA setting is + // also used for high-current + // operation. Note: There is no + // configuration difference between + // 8-mA and high-current operation. + // The additional current capacity + // results from a shift in the + // VOH/VOL levels. +#define GPIO_O_GPIO_ODR 0x0000050C // 0x4000 550C 0x4000 650C 0x4000 + // 750C 0x4002 450C GPIO Open Drain + // Select (GPIOODR)@@ offset 0x50C + // The GPIOODR register is the open + // drain control register. Setting a + // bit in this register enables the + // open-drain configuration of the + // corresponding GPIO pad. When + // open-drain mode is enabled@@ the + // corresponding bit should also be + // set in the GPIO Digital Input + // Enable (GPIODEN) register . + // Corresponding bits in the drive + // strength and slew rate control + // registers (GPIODR2R@@ GPIODR4R@@ + // GPIODR8R@@ and GPIOSLR) can be + // set to achieve the desired rise + // and fall times. The GPIO acts as + // an open-drain input if the + // corresponding bit in the GPIODIR + // register is cleared. If open + // drain is selected while the GPIO + // is configured as an input@@ the + // GPIO will remain an input and the + // open-drain selection has no + // effect until the GPIO is changed + // to an output. When using the I2C + // module@@ in addition to + // configuring the pin to open + // drain@@ the GPIO Alternate + // Function Select (GPIOAFSEL) + // register bits for the I2C clock + // and data pins should be set +#define GPIO_O_GPIO_PUR 0x00000510 // 0x4000 5510 0x4000 6510 0x4000 + // 7510 0x4002 4510 GPIO Pull-Up + // Select (GPIOPUR)@@ offset 0x510 + // The GPIOPUR register is the + // pull-up control register. When a + // bit is set@@ a weak pull-up + // resistor on the corresponding + // GPIO signal is enabled. Setting a + // bit in GPIOPUR automatically + // clears the corresponding bit in + // the GPIO Pull-Down Select + // (GPIOPDR) register . Write access + // to this register is protected + // with the GPIOCR register. Bits in + // GPIOCR that are cleared prevent + // writes to the equivalent bit in + // this register. +#define GPIO_O_GPIO_PDR 0x00000514 // 0x4000 5514 0x4000 6514 0x4000 + // 7514 0x4002 4514 GPIO Pull-Down + // Select (GPIOPDR)@@ offset 0x514 + // The GPIOPDR register is the + // pull-down control register. When + // a bit is set@@ a weak pull-down + // resistor on the corresponding + // GPIO signal is enabled. Setting a + // bit in GPIOPDR automatically + // clears the corresponding bit in + // the GPIO Pull-Up Select (GPIOPUR) + // register +#define GPIO_O_GPIO_SLR 0x00000518 // 0x4000 5518 0x4000 6518 0x4000 + // 7518 0x4002 4518 The GPIOSLR + // register is the slew rate control + // register. Slew rate control is + // only available when using the + // 8-mA drive strength option via + // the GPIO 8-mA Drive Select + // (GPIODR8R) register +#define GPIO_O_GPIO_DEN 0x0000051C // 0x4000 551C 0x4000 651C 0x4000 + // 751C 0x4002 451C GPIO Digital + // Enable (GPIODEN)@@ offset 0x51C + // Note: Pins configured as digital + // inputs are Schmitt-triggered. The + // GPIODEN register is the digital + // enable register. By default@@ all + // GPIO signals except those listed + // below are configured out of reset + // to be undriven (tristate). Their + // digital function is disabled; + // they do not drive a logic value + // on the pin and they do not allow + // the pin voltage into the GPIO + // receiver. To use the pin as a + // digital input or output (either + // GPIO or alternate function)@@ the + // corresponding GPIODEN bit must be + // set. +#define GPIO_O_GPIO_LOCK 0x00000520 // 0x4000 5520 0x4000 6520 0x4000 + // 7520 0x4002 4520 GPIO Lock + // (GPIOLOCK)@@ offset 0x520 The + // GPIOLOCK register enables write + // access to the GPIOCR register . + // Writing 0x4C4F.434B to the + // GPIOLOCK register unlocks the + // GPIOCR register. Writing any + // other value to the GPIOLOCK + // register re-enables the locked + // state. Reading the GPIOLOCK + // register returns the lock status + // rather than the 32-bit value that + // was previously written. + // Therefore@@ when write accesses + // are disabled@@ or locked@@ + // reading the GPIOLOCK register + // returns 0x0000.0001. When write + // accesses are enabled@@ or + // unlocked@@ reading the GPIOLOCK + // register returns 0x0000.0000. +#define GPIO_O_GPIO_CR 0x00000524 // 0x4000 5524 0x4000 6524 0x4000 + // 7524 0x4002 4524 GPIO Commit + // (GPIOCR)@@ offset 0x524 The + // GPIOCR register is the commit + // register. The value of the GPIOCR + // register determines which bits of + // the GPIOAFSEL@@ GPIOPUR@@ + // GPIOPDR@@ and GPIODEN registers + // are committed when a write to + // these registers is performed. If + // a bit in the GPIOCR register is + // cleared@@ the data being written + // to the corresponding bit in the + // GPIOAFSEL@@ GPIOPUR@@ GPIOPDR@@ + // or GPIODEN registers cannot be + // committed and retains its + // previous value. If a bit in the + // GPIOCR register is set@@ the data + // being written to the + // corresponding bit of the + // GPIOAFSEL@@ GPIOPUR@@ GPIOPDR@@ + // or GPIODEN registers is committed + // to the register and reflects the + // new value. The contents of the + // GPIOCR register can only be + // modified if the status in the + // GPIOLOCK register is unlocked. + // Writes to the GPIOCR register are + // ignored if the status in the + // GPIOLOCK register is locked. +#define GPIO_O_GPIO_AMSEL 0x00000528 // 0x4000 5528 0x4000 6528 0x4000 + // 7528 0x4002 4528 The GPIOAMSEL + // register controls isolation + // circuits to the analog side of a + // unified I/O pad. Because the + // GPIOs may be driven by a 5-V + // source and affect analog + // operation@@ analog circuitry + // requires isolation from the pins + // when they are not used in their + // analog function. Each bit of this + // register controls the isolation + // circuitry for the corresponding + // GPIO signal. +#define GPIO_O_GPIO_PCTL 0x0000052C // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) 0x4000 552C + // 0x4000 652C 0x4000 752C 0x4002 + // 452C GPIO Port Control + // (GPIOPCTL)@@ offset 0x52C The + // GPIOPCTL register is used in + // conjunction with the GPIOAFSEL + // register and selects the specific + // peripheral signal for each GPIO + // pin when using the alternate + // function mode. Most bits in the + // GPIOAFSEL register are cleared on + // reset@@ therefore most GPIO pins + // are configured as GPIOs by + // default. When a bit is set in the + // GPIOAFSEL register@@ the + // corresponding GPIO signal is + // controlled by an associated + // peripheral. The GPIOPCTL register + // selects one out of a set of + // peripheral functions for each + // GPIO@@ providing additional + // flexibility in signal definition. +#define GPIO_O_GPIO_ADCCTL 0x00000530 // This register is not used in + // cc3xx. ADC trigger via GPIO is + // not supported. 0x4000 5530 0x4000 + // 6530 0x4000 7530 0x4002 4530 GPIO + // ADC Control (GPIOADCCTL)@@ offset + // 0x530 This register is used to + // configure a GPIO pin as a source + // for the ADC trigger. Note that if + // the Port B GPIOADCCTL register is + // cleared@@ PB4 can still be used + // as an external trigger for the + // ADC. This is a legacy mode which + // allows code written for previous + // Stellaris devices to operate on + // this microcontroller. +#define GPIO_O_GPIO_DMACTL 0x00000534 // 0x4000 5534 0x4000 6534 0x4000 + // 7534 0x4002 4534 GPIO DMA Control + // (GPIODMACTL)@@ offset 0x534 This + // register is used to configure a + // GPIO pin as a source for the ?DMA + // trigger. +#define GPIO_O_GPIO_SI 0x00000538 // 0x4000 5538 0x4000 6538 0x4000 + // 7538 0x4002 4538 GPIO Select + // Interrupt (GPIOSI)@@ offset 0x538 + // This register is used to enable + // individual interrupts for each + // pin. Note: This register is only + // available on Port P and Port Q. +#define GPIO_O_GPIO_PERIPHID4 0x00000FD0 // 0x4000 5FD0 0x4000 6FD0 0x4000 + // 7FD0 0x4002 4FD0 GPIO Peripheral + // Identification 4 + // (GPIOPeriphID4)@@ offset 0xFD0 + // The GPIOPeriphID4@@ + // GPIOPeriphID5@@ GPIOPeriphID6@@ + // and GPIOPeriphID7 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PERIPHID5 0x00000FD4 // 0x4000 5FD4 0x4000 6FD4 0x4000 + // 7FD4 0x4002 4FD4 GPIO Peripheral + // Identification 5 + // (GPIOPeriphID5)@@ offset 0xFD4 + // The GPIOPeriphID4@@ + // GPIOPeriphID5@@ GPIOPeriphID6@@ + // and GPIOPeriphID7 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PERIPHID6 0x00000FD8 // 0x4000 5FD8 0x4000 6FD8 0x4000 + // 7FD8 0x4002 4FD8 GPIO Peripheral + // Identification 6 + // (GPIOPeriphID6)@@ offset 0xFD8 + // The GPIOPeriphID4@@ + // GPIOPeriphID5@@ GPIOPeriphID6@@ + // and GPIOPeriphID7 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PERIPHID7 0x00000FDC // 0x4000 5FDC 0x4000 6FDC 0x4000 + // 7FDC 0x4002 4FDC GPIO Peripheral + // Identification 7 + // (GPIOPeriphID7)@@ offset 0xFDC + // The GPIOPeriphID4@@ + // GPIOPeriphID5@@ GPIOPeriphID6@@ + // and GPIOPeriphID7 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PERIPHID0 0x00000FE0 // 0x4000 5FE0 0x4000 6FE0 0x4000 + // 7FE0 0x4002 4FE0 GPIO Peripheral + // Identification 0 + // (GPIOPeriphID0)@@ offset 0xFE0 + // The GPIOPeriphID0@@ + // GPIOPeriphID1@@ GPIOPeriphID2@@ + // and GPIOPeriphID3 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PERIPHID1 0x00000FE4 // 0x4000 5FE4 0x4000 6FE4 0x4000 + // 7FE4 0x4002 4FE4 GPIO Peripheral + // Identification 1 + // (GPIOPeriphID1)@@ offset 0xFE4 + // The GPIOPeriphID0@@ + // GPIOPeriphID1@@ GPIOPeriphID2@@ + // and GPIOPeriphID3 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PERIPHID2 0x00000FE8 // 0x4000 5FE8 0x4000 6FE8 0x4000 + // 7FE8 0x4002 4FE8 GPIO Peripheral + // Identification 2 + // (GPIOPeriphID2)@@ offset 0xFE8 + // The GPIOPeriphID0@@ + // GPIOPeriphID1@@ GPIOPeriphID2@@ + // and GPIOPeriphID3 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PERIPHID3 0x00000FEC // 0x4000 5FEC 0x4000 6FEC 0x4000 + // 7FEC 0x4002 4FEC GPIO Peripheral + // Identification 3 + // (GPIOPeriphID3)@@ offset 0xFEC + // The GPIOPeriphID0@@ + // GPIOPeriphID1@@ GPIOPeriphID2@@ + // and GPIOPeriphID3 registers can + // conceptually be treated as one + // 32-bit register; each register + // contains eight bits of the 32-bit + // register@@ used by software to + // identify the peripheral. +#define GPIO_O_GPIO_PCELLID0 0x00000FF0 // 0x4000 5FF0 0x4000 6FF0 0x4000 + // 7FF0 0x4002 4FF0 GPIO PrimeCell + // Identification 0 (GPIOPCellID0)@@ + // offset 0xFF0 The GPIOPCellID0@@ + // GPIOPCellID1@@ GPIOPCellID2@@ and + // GPIOPCellID3 registers are four + // 8-bit wide registers@@ that can + // conceptually be treated as one + // 32-bit register. The register is + // used as a standard + // cross-peripheral identification + // system. +#define GPIO_O_GPIO_PCELLID1 0x00000FF4 // 0x4000 5FF4 0x4000 6FF4 0x4000 + // 7FF4 0x4002 4FF4 GPIO PrimeCell + // Identification 1 (GPIOPCellID1)@@ + // offset 0xFF4 The GPIOPCellID0@@ + // GPIOPCellID1@@ GPIOPCellID2@@ and + // GPIOPCellID3 registers are four + // 8-bit wide registers@@ that can + // conceptually be treated as one + // 32-bit register. The register is + // used as a standard + // cross-peripheral identification + // system. +#define GPIO_O_GPIO_PCELLID2 0x00000FF8 // 0x4000 5FF8 0x4000 6FF8 0x4000 + // 7FF8 0x4002 4FF8 GPIO PrimeCell + // Identification 2 (GPIOPCellID2)@@ + // offset 0xFF8 The GPIOPCellID0@@ + // GPIOPCellID1@@ GPIOPCellID2@@ and + // GPIOPCellID3 registers are four + // 8-bit wide registers@@ that can + // conceptually be treated as one + // 32-bit register. The register is + // used as a standard + // cross-peripheral identification + // system. +#define GPIO_O_GPIO_PCELLID3 0x00000FFC // 0x4000 5FFC 0x4000 6FFC 0x4000 + // 7FFC 0x4002 4FFC GPIO PrimeCell + // Identification 3 (GPIOPCellID3)@@ + // offset 0xFFC The GPIOPCellID0@@ + // GPIOPCellID1@@ GPIOPCellID2@@ and + // GPIOPCellID3 registers are four + // 8-bit wide registers@@ that can + // conceptually be treated as one + // 32-bit register. The register is + // used as a standard + // cross-peripheral identification + // system.0xb1 + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_DATA register. +// +//****************************************************************************** +#define GPIO_GPIO_DATA_DATA_M 0x000000FF // GPIO Data This register is + // virtually mapped to 256 locations + // in the address space. To + // facilitate the reading and + // writing of data to these + // registers by independent + // drivers@@ the data read from and + // written to the registers are + // masked by the eight address lines + // [9:2]. Reads from this register + // return its current state. Writes + // to this register only affect bits + // that are not masked by ADDR[9:2] + // and are configured as outputs. +#define GPIO_GPIO_DATA_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_DIR register. +// +//****************************************************************************** +#define GPIO_GPIO_DIR_DIR_M 0x000000FF // GPIO Data Direction Value + // Description 0 Corresponding pin + // is an input. 1 Corresponding pins + // is an output. +#define GPIO_GPIO_DIR_DIR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_IS register. +// +//****************************************************************************** +#define GPIO_GPIO_IS_IS_M 0x000000FF // GPIO Interrupt Sense Value + // Description 0 The edge on the + // corresponding pin is detected + // (edge-sensitive). 1 The level on + // the corresponding pin is detected + // (level-sensitive). +#define GPIO_GPIO_IS_IS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_IBE register. +// +//****************************************************************************** +#define GPIO_GPIO_IBE_IBE_M 0x000000FF // GPIO Interrupt Both Edges Value + // Description 0 Interrupt + // generation is controlled by the + // GPIO Interrupt Event (GPIOIEV) + // register. 1 Both edges on the + // corresponding pin trigger an + // interrupt. +#define GPIO_GPIO_IBE_IBE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_IEV register. +// +//****************************************************************************** +#define GPIO_GPIO_IEV_IEV_M 0x000000FF // GPIO Interrupt Event Value + // Description 1 A falling edge or a + // Low level on the corresponding + // pin triggers an interrupt. 0 A + // rising edge or a High level on + // the corresponding pin triggers an + // interrupt. +#define GPIO_GPIO_IEV_IEV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_IM register. +// +//****************************************************************************** +#define GPIO_GPIO_IM_IME_M 0x000000FF // GPIO Interrupt Mask Enable Value + // Description 0 The interrupt from + // the corresponding pin is masked. + // 1 The interrupt from the + // corresponding pin is sent to the + // interrupt controller. +#define GPIO_GPIO_IM_IME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_RIS register. +// +//****************************************************************************** +#define GPIO_GPIO_RIS_RIS_M 0x000000FF // GPIO Interrupt Raw Status Value + // Description 1 An interrupt + // condition has occurred on the + // corresponding pin. 0 interrupt + // condition has not occurred on the + // corresponding pin. A bit is + // cleared by writing a 1 to the + // corresponding bit in the GPIOICR + // register. +#define GPIO_GPIO_RIS_RIS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_MIS register. +// +//****************************************************************************** +#define GPIO_GPIO_MIS_MIS_M 0x000000FF // GPIO Masked Interrupt Status + // Value Description 1 An interrupt + // condition on the corresponding + // pin has triggered an interrupt to + // the interrupt controller. 0 An + // interrupt condition on the + // corresponding pin is masked or + // has not occurred. A bit is + // cleared by writing a 1 to the + // corresponding bit in the GPIOICR + // register. +#define GPIO_GPIO_MIS_MIS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_ICR register. +// +//****************************************************************************** +#define GPIO_GPIO_ICR_IC_M 0x000000FF // GPIO Interrupt Clear Value + // Description 1 The corresponding + // interrupt is cleared. 0 The + // corresponding interrupt is + // unaffected. +#define GPIO_GPIO_ICR_IC_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_AFSEL register. +// +//****************************************************************************** +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_DR2R register. +// +//****************************************************************************** +#define GPIO_GPIO_DR2R_DRV2_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Output Pad + // 2-mA Drive Enable Value + // Description 1 The corresponding + // GPIO pin has 2-mA drive. The + // drive for the corresponding GPIO + // pin is controlled by the GPIODR4R + // or GPIODR8R register. 0 Setting a + // bit in either the GPIODR4 + // register or the GPIODR8 register + // clears the corresponding 2-mA + // enable bit. The change is + // effective on the second clock + // cycle after the write if + // accessing GPIO via the APB memory + // aperture. If using AHB access@@ + // the change is effective on the + // next clock cycle. +#define GPIO_GPIO_DR2R_DRV2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_DR4R register. +// +//****************************************************************************** +#define GPIO_GPIO_DR4R_DRV4_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Output Pad + // 4-mA Drive Enable Value + // Description 1 The corresponding + // GPIO pin has 4-mA drive. The + // drive for the corresponding GPIO + // pin is controlled by the GPIODR2R + // or GPIODR8R register. 0 Setting a + // bit in either the GPIODR2 + // register or the GPIODR8 register + // clears the corresponding 4-mA + // enable bit. The change is + // effective on the second clock + // cycle after the write if + // accessing GPIO via the APB memory + // aperture. If using AHB access@@ + // the change is effective on the + // next clock cycle. +#define GPIO_GPIO_DR4R_DRV4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_DR8R register. +// +//****************************************************************************** +#define GPIO_GPIO_DR8R_DRV8_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Output Pad + // 8-mA Drive Enable Value + // Description 1 The corresponding + // GPIO pin has 8-mA drive. The + // drive for the corresponding GPIO + // pin is controlled by the GPIODR2R + // or GPIODR4R register. 0 Setting a + // bit in either the GPIODR2 + // register or the GPIODR4 register + // clears the corresponding 8-mA + // enable bit. The change is + // effective on the second clock + // cycle after the write if + // accessing GPIO via the APB memory + // aperture. If using AHB access@@ + // the change is effective on the + // next clock cycle. +#define GPIO_GPIO_DR8R_DRV8_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_ODR register. +// +//****************************************************************************** +#define GPIO_GPIO_ODR_ODE_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Output Pad + // Open Drain Enable Value + // Description 1 The corresponding + // pin is configured as open drain. + // 0 The corresponding pin is not + // configured as open drain. +#define GPIO_GPIO_ODR_ODE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_PUR register. +// +//****************************************************************************** +#define GPIO_GPIO_PUR_PUE_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Pad Weak + // Pull-Up Enable Value Description + // 1 The corresponding pin has a + // weak pull-up resistor. 0 The + // corresponding pin is not + // affected. Setting a bit in the + // GPIOPDR register clears the + // corresponding bit in the GPIOPUR + // register. The change is effective + // on the second clock cycle after + // the write if accessing GPIO via + // the APB memory aperture. If using + // AHB access@@ the change is + // effective on the next clock + // cycle. +#define GPIO_GPIO_PUR_PUE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_PDR register. +// +//****************************************************************************** +#define GPIO_GPIO_PDR_PDE_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Pad Weak + // Pull-Down Enable Value + // Description 1 The corresponding + // pin has a weak pull-down + // resistor. 0 The corresponding pin + // is not affected. Setting a bit in + // the GPIOPUR register clears the + // corresponding bit in the GPIOPDR + // register. The change is effective + // on the second clock cycle after + // the write if accessing GPIO via + // the APB memory aperture. If using + // AHB access@@ the change is + // effective on the next clock + // cycle. +#define GPIO_GPIO_PDR_PDE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_SLR register. +// +//****************************************************************************** +#define GPIO_GPIO_SLR_SRL_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Slew Rate + // Limit Enable (8-mA drive only) + // Value Description 1 Slew rate + // control is enabled for the + // corresponding pin. 0 Slew rate + // control is disabled for the + // corresponding pin. +#define GPIO_GPIO_SLR_SRL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_DEN register. +// +//****************************************************************************** +#define GPIO_GPIO_DEN_DEN_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Digital Enable + // Value Description 0 The digital + // functions for the corresponding + // pin are disabled. 1 The digital + // functions for the corresponding + // pin are enabled. +#define GPIO_GPIO_DEN_DEN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_LOCK register. +// +//****************************************************************************** +#define GPIO_GPIO_LOCK_LOCK_M 0xFFFFFFFF // This register is not used in + // cc3xx. GPIO Lock A write of the + // value 0x4C4F.434B unlocks the + // GPIO Commit (GPIOCR) register for + // write access.A write of any other + // value or a write to the GPIOCR + // register reapplies the lock@@ + // preventing any register updates. + // A read of this register returns + // the following values: Value + // Description 0x1 The GPIOCR + // register is locked and may not be + // modified. 0x0 The GPIOCR register + // is unlocked and may be modified. +#define GPIO_GPIO_LOCK_LOCK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_CR register. +// +//****************************************************************************** +#define GPIO_GPIO_CR_CR_M 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) GPIO Commit + // Value Description The + // corresponding GPIOAFSEL@@ + // GPIOPUR@@ GPIOPDR@@ or GPIODEN + // bits can be written. 1 The + // corresponding GPIOAFSEL@@ + // GPIOPUR@@ GPIOPDR@@ or GPIODEN + // bits cannot be written. 0 Note: + // The default register type for the + // GPIOCR register is RO for all + // GPIO pins with the exception of + // the NMI pin and the four JTAG/SWD + // pins (PD7@@ PF0@@ and PC[3:0]). + // These six pins are the only GPIOs + // that are protected by the GPIOCR + // register. Because of this@@ the + // register type for GPIO Port D7@@ + // GPIO Port F0@@ and GPIO Port + // C[3:0] is R/W. The default reset + // value for the GPIOCR register is + // 0x0000.00FF for all GPIO pins@@ + // with the exception of the NMI pin + // and the four JTAG/SWD pins (PD7@@ + // PF0@@ and PC[3:0]). To ensure + // that the JTAG port is not + // accidentally programmed as GPIO + // pins@@ the PC[3:0] pins default + // to non-committable. Similarly@@ + // to ensure that the NMI pin is not + // accidentally programmed as a GPIO + // pin@@ the PD7 and PF0 pins + // default to non-committable. + // Because of this@@ the default + // reset value of GPIOCR for GPIO + // Port C is 0x0000.00F0@@ for GPIO + // Port D is 0x0000.007F@@ and for + // GPIO Port F is 0x0000.00FE. +#define GPIO_GPIO_CR_CR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_AMSEL register. +// +//****************************************************************************** +#define GPIO_GPIO_AMSEL_GPIO_AMSEL_M \ + 0x000000FF // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) GPIO Analog + // Mode Select Value Description 1 + // The analog function of the pin is + // enabled@@ the isolation is + // disabled@@ and the pin is capable + // of analog functions. 0 The analog + // function of the pin is disabled@@ + // the isolation is enabled@@ and + // the pin is capable of digital + // functions as specified by the + // other GPIO configuration + // registers. Note: This register + // and bits are only valid for GPIO + // signals that share analog + // function through a unified I/O + // pad. The reset state of this + // register is 0 for all signals. + +#define GPIO_GPIO_AMSEL_GPIO_AMSEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_PCTL register. +// +//****************************************************************************** +#define GPIO_GPIO_PCTL_PMC7_M 0xF0000000 // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 7 This field controls the + // configuration for GPIO pin 7. +#define GPIO_GPIO_PCTL_PMC7_S 28 +#define GPIO_GPIO_PCTL_PMC6_M 0x0F000000 // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 6 This field controls the + // configuration for GPIO pin 6. +#define GPIO_GPIO_PCTL_PMC6_S 24 +#define GPIO_GPIO_PCTL_PMC5_M 0x00F00000 // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 5 This field controls the + // configuration for GPIO pin 5. +#define GPIO_GPIO_PCTL_PMC5_S 20 +#define GPIO_GPIO_PCTL_PMC4_M 0x000F0000 // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 4 This field controls the + // configuration for GPIO pin 4. +#define GPIO_GPIO_PCTL_PMC4_S 16 +#define GPIO_GPIO_PCTL_PMC3_M 0x0000F000 // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 43 This field controls + // the configuration for GPIO pin 3. +#define GPIO_GPIO_PCTL_PMC3_S 12 +#define GPIO_GPIO_PCTL_PMC1_M 0x00000F00 // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 1 This field controls the + // configuration for GPIO pin 1. +#define GPIO_GPIO_PCTL_PMC1_S 8 +#define GPIO_GPIO_PCTL_PMC2_M 0x000000F0 // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 2 This field controls the + // configuration for GPIO pin 2. +#define GPIO_GPIO_PCTL_PMC2_S 4 +#define GPIO_GPIO_PCTL_PMC0_M 0x0000000F // This register is not used in + // cc3xx. equivalant register exsist + // outside GPIO IP (refer + // PAD*_config register in the + // shared comn space) Port Mux + // Control 0 This field controls the + // configuration for GPIO pin 0. +#define GPIO_GPIO_PCTL_PMC0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_ADCCTL register. +// +//****************************************************************************** +#define GPIO_GPIO_ADCCTL_ADCEN_M \ + 0x000000FF // This register is not used in + // cc3xx. ADC trigger via GPIO is + // not supported. ADC Trigger Enable + // Value Description 1 The + // corresponding pin is used to + // trigger the ADC. 0 The + // corresponding pin is not used to + // trigger the ADC. + +#define GPIO_GPIO_ADCCTL_ADCEN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_DMACTL register. +// +//****************************************************************************** +#define GPIO_GPIO_DMACTL_DMAEN_M \ + 0x000000FF // This register is not used in the + // cc3xx. Alternate register to + // support this feature is coded in + // the APPS_NWP_CMN space. refer + // register as offset 0x400F70D8 + // ?DMA Trigger Enable Value + // Description 1 The corresponding + // pin is used to trigger the ?DMA. + // 0 The corresponding pin is not + // used to trigger the ?DMA. + +#define GPIO_GPIO_DMACTL_DMAEN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPIO_O_GPIO_SI register. +// +//****************************************************************************** +#define GPIO_GPIO_SI_SUM 0x00000001 // Summary Interrupt Value + // Description 1 Each pin has its + // own interrupt vector. 0 All port + // pin interrupts are OR'ed together + // to produce a summary interrupt. +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID4 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID4_PID4_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO Peripheral ID + // Register [7:0] + +#define GPIO_GPIO_PERIPHID4_PID4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID5 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID5_PID5_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO Peripheral ID + // Register [15:8] + +#define GPIO_GPIO_PERIPHID5_PID5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID6 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID6_PID6_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO Peripheral ID + // Register [23:16] + +#define GPIO_GPIO_PERIPHID6_PID6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID7 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID7_PID7_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO Peripheral ID + // Register [31:24] + +#define GPIO_GPIO_PERIPHID7_PID7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID0 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID0_PID0_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO Peripheral ID + // Register [7:0] Can be used by + // software to identify the presence + // of this peripheral. + +#define GPIO_GPIO_PERIPHID0_PID0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID1 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID1_PID1_M \ + 0x000000FF // GPIO Peripheral ID Register + // [15:8] Can be used by software to + // identify the presence of this + // peripheral. + +#define GPIO_GPIO_PERIPHID1_PID1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID2 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID2_PID2_M \ + 0x000000FF // This register is not used in + // CC3XX.v GPIO Peripheral ID + // Register [23:16] Can be used by + // software to identify the presence + // of this peripheral. + +#define GPIO_GPIO_PERIPHID2_PID2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PERIPHID3 register. +// +//****************************************************************************** +#define GPIO_GPIO_PERIPHID3_PID3_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO Peripheral ID + // Register [31:24] Can be used by + // software to identify the presence + // of this peripheral. + +#define GPIO_GPIO_PERIPHID3_PID3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PCELLID0 register. +// +//****************************************************************************** +#define GPIO_GPIO_PCELLID0_CID0_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO PrimeCell ID Register + // [7:0] Provides software a + // standard cross-peripheral + // identification system. + +#define GPIO_GPIO_PCELLID0_CID0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PCELLID1 register. +// +//****************************************************************************** +#define GPIO_GPIO_PCELLID1_CID1_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO PrimeCell ID Register + // [15:8] Provides software a + // standard cross-peripheral + // identification system. + +#define GPIO_GPIO_PCELLID1_CID1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PCELLID2 register. +// +//****************************************************************************** +#define GPIO_GPIO_PCELLID2_CID2_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO PrimeCell ID Register + // [23:16] Provides software a + // standard cross-peripheral + // identification system. + +#define GPIO_GPIO_PCELLID2_CID2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPIO_O_GPIO_PCELLID3 register. +// +//****************************************************************************** +#define GPIO_GPIO_PCELLID3_CID3_M \ + 0x000000FF // This register is not used in + // CC3XX. GPIO PrimeCell ID Register + // [31:24] Provides software a + // standard cross-peripheral + // identification system. + +#define GPIO_GPIO_PCELLID3_CID3_S 0 + + + +#endif // __HW_GPIO_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gprcm.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gprcm.h new file mode 100644 index 00000000..43628f4a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_gprcm.h @@ -0,0 +1,3322 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_GPRCM_H__ +#define __HW_GPRCM_H__ + +//***************************************************************************** +// +// The following are defines for the GPRCM register offsets. +// +//***************************************************************************** +#define GPRCM_O_APPS_SOFT_RESET 0x00000000 +#define GPRCM_O_APPS_LPDS_WAKEUP_CFG \ + 0x00000004 + +#define GPRCM_O_APPS_LPDS_WAKEUP_SRC \ + 0x00000008 + +#define GPRCM_O_APPS_RESET_CAUSE \ + 0x0000000C + +#define GPRCM_O_APPS_LPDS_WAKETIME_OPP_CFG \ + 0x00000010 + +#define GPRCM_O_APPS_SRAM_DSLP_CFG \ + 0x00000018 + +#define GPRCM_O_APPS_SRAM_LPDS_CFG \ + 0x0000001C + +#define GPRCM_O_APPS_LPDS_WAKETIME_WAKE_CFG \ + 0x00000020 + +#define GPRCM_O_TOP_DIE_ENABLE 0x00000100 +#define GPRCM_O_TOP_DIE_ENABLE_PARAMETERS \ + 0x00000104 + +#define GPRCM_O_MCU_GLOBAL_SOFT_RESET \ + 0x00000108 + +#define GPRCM_O_ADC_CLK_CONFIG 0x0000010C +#define GPRCM_O_APPS_GPIO_WAKE_CONF \ + 0x00000110 + +#define GPRCM_O_EN_NWP_BOOT_WO_DEVINIT \ + 0x00000114 + +#define GPRCM_O_MEM_HCLK_DIV_CFG \ + 0x00000118 + +#define GPRCM_O_MEM_SYSCLK_DIV_CFG \ + 0x0000011C + +#define GPRCM_O_APLLMCS_LOCK_TIME_CONF \ + 0x00000120 + +#define GPRCM_O_NWP_SOFT_RESET 0x00000400 +#define GPRCM_O_NWP_LPDS_WAKEUP_CFG \ + 0x00000404 + +#define GPRCM_O_NWP_LPDS_WAKEUP_SRC \ + 0x00000408 + +#define GPRCM_O_NWP_RESET_CAUSE 0x0000040C +#define GPRCM_O_NWP_LPDS_WAKETIME_OPP_CFG \ + 0x00000410 + +#define GPRCM_O_NWP_SRAM_DSLP_CFG \ + 0x00000418 + +#define GPRCM_O_NWP_SRAM_LPDS_CFG \ + 0x0000041C + +#define GPRCM_O_NWP_LPDS_WAKETIME_WAKE_CFG \ + 0x00000420 + +#define GPRCM_O_NWP_AUTONMS_SPI_MASTER_SEL \ + 0x00000424 + +#define GPRCM_O_NWP_AUTONMS_SPI_IDLE_REQ \ + 0x00000428 + +#define GPRCM_O_WLAN_TO_NWP_WAKE_REQUEST \ + 0x0000042C + +#define GPRCM_O_NWP_TO_WLAN_WAKE_REQUEST \ + 0x00000430 + +#define GPRCM_O_NWP_GPIO_WAKE_CONF \ + 0x00000434 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG12 \ + 0x00000438 + +#define GPRCM_O_GPRCM_DIEID_READ_REG5 \ + 0x00000448 + +#define GPRCM_O_GPRCM_DIEID_READ_REG6 \ + 0x0000044C + +#define GPRCM_O_REF_FSM_CFG0 0x00000800 +#define GPRCM_O_REF_FSM_CFG1 0x00000804 +#define GPRCM_O_APLLMCS_WLAN_CONFIG0_40 \ + 0x00000808 + +#define GPRCM_O_APLLMCS_WLAN_CONFIG1_40 \ + 0x0000080C + +#define GPRCM_O_APLLMCS_WLAN_CONFIG0_26 \ + 0x00000810 + +#define GPRCM_O_APLLMCS_WLAN_CONFIG1_26 \ + 0x00000814 + +#define GPRCM_O_APLLMCS_WLAN_OVERRIDES \ + 0x00000818 + +#define GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_38P4 \ + 0x0000081C + +#define GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_38P4 \ + 0x00000820 + +#define GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_26 \ + 0x00000824 + +#define GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_26 \ + 0x00000828 + +#define GPRCM_O_SPARE_RW0 0x0000082C +#define GPRCM_O_SPARE_RW1 0x00000830 +#define GPRCM_O_APLLMCS_MCU_OVERRIDES \ + 0x00000834 + +#define GPRCM_O_SYSCLK_SWITCH_STATUS \ + 0x00000838 + +#define GPRCM_O_REF_LDO_CONTROLS \ + 0x0000083C + +#define GPRCM_O_REF_RTRIM_CONTROL \ + 0x00000840 + +#define GPRCM_O_REF_SLICER_CONTROLS0 \ + 0x00000844 + +#define GPRCM_O_REF_SLICER_CONTROLS1 \ + 0x00000848 + +#define GPRCM_O_REF_ANA_BGAP_CONTROLS0 \ + 0x0000084C + +#define GPRCM_O_REF_ANA_BGAP_CONTROLS1 \ + 0x00000850 + +#define GPRCM_O_REF_ANA_SPARE_CONTROLS0 \ + 0x00000854 + +#define GPRCM_O_REF_ANA_SPARE_CONTROLS1 \ + 0x00000858 + +#define GPRCM_O_MEMSS_PSCON_OVERRIDES0 \ + 0x0000085C + +#define GPRCM_O_MEMSS_PSCON_OVERRIDES1 \ + 0x00000860 + +#define GPRCM_O_PLL_REF_LOCK_OVERRIDES \ + 0x00000864 + +#define GPRCM_O_MCU_PSCON_DEBUG 0x00000868 +#define GPRCM_O_MEMSS_PWR_PS 0x0000086C +#define GPRCM_O_REF_FSM_DEBUG 0x00000870 +#define GPRCM_O_MEM_SYS_OPP_REQ_OVERRIDE \ + 0x00000874 + +#define GPRCM_O_MEM_TESTCTRL_PD_OPP_CONFIG \ + 0x00000878 + +#define GPRCM_O_MEM_WL_FAST_CLK_REQ_OVERRIDES \ + 0x0000087C + +#define GPRCM_O_MEM_MCU_PD_MODE_REQ_OVERRIDES \ + 0x00000880 + +#define GPRCM_O_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES \ + 0x00000884 + +#define GPRCM_O_MEM_WLAN_APLLMCS_OVERRIDES \ + 0x00000888 + +#define GPRCM_O_MEM_REF_FSM_CFG2 \ + 0x0000088C + +#define GPRCM_O_TESTCTRL_POWER_CTRL \ + 0x00000C10 + +#define GPRCM_O_SSDIO_POWER_CTRL \ + 0x00000C14 + +#define GPRCM_O_MCSPI_N1_POWER_CTRL \ + 0x00000C18 + +#define GPRCM_O_WELP_POWER_CTRL 0x00000C1C +#define GPRCM_O_WL_SDIO_POWER_CTRL \ + 0x00000C20 + +#define GPRCM_O_WLAN_SRAM_ACTIVE_PWR_CFG \ + 0x00000C24 + +#define GPRCM_O_WLAN_SRAM_SLEEP_PWR_CFG \ + 0x00000C28 + +#define GPRCM_O_APPS_SECURE_INIT_DONE \ + 0x00000C30 + +#define GPRCM_O_APPS_DEV_MODE_INIT_DONE \ + 0x00000C34 + +#define GPRCM_O_EN_APPS_REBOOT 0x00000C38 +#define GPRCM_O_MEM_APPS_PERIPH_PRESENT \ + 0x00000C3C + +#define GPRCM_O_MEM_NWP_PERIPH_PRESENT \ + 0x00000C40 + +#define GPRCM_O_MEM_SHARED_PERIPH_PRESENT \ + 0x00000C44 + +#define GPRCM_O_NWP_PWR_STATE 0x00000C48 +#define GPRCM_O_APPS_PWR_STATE 0x00000C4C +#define GPRCM_O_MCU_PWR_STATE 0x00000C50 +#define GPRCM_O_WTOP_PM_PS 0x00000C54 +#define GPRCM_O_WTOP_PD_RESETZ_OVERRIDE_REG \ + 0x00000C58 + +#define GPRCM_O_WELP_PD_RESETZ_OVERRIDE_REG \ + 0x00000C5C + +#define GPRCM_O_WL_SDIO_PD_RESETZ_OVERRIDE_REG \ + 0x00000C60 + +#define GPRCM_O_SSDIO_PD_RESETZ_OVERRIDE_REG \ + 0x00000C64 + +#define GPRCM_O_MCSPI_N1_PD_RESETZ_OVERRIDE_REG \ + 0x00000C68 + +#define GPRCM_O_TESTCTRL_PD_RESETZ_OVERRIDE_REG \ + 0x00000C6C + +#define GPRCM_O_MCU_PD_RESETZ_OVERRIDE_REG \ + 0x00000C70 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG0 \ + 0x00000C78 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG1 \ + 0x00000C7C + +#define GPRCM_O_GPRCM_EFUSE_READ_REG2 \ + 0x00000C80 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG3 \ + 0x00000C84 + +#define GPRCM_O_WTOP_MEM_RET_CFG \ + 0x00000C88 + +#define GPRCM_O_COEX_CLK_SWALLOW_CFG0 \ + 0x00000C8C + +#define GPRCM_O_COEX_CLK_SWALLOW_CFG1 \ + 0x00000C90 + +#define GPRCM_O_COEX_CLK_SWALLOW_CFG2 \ + 0x00000C94 + +#define GPRCM_O_COEX_CLK_SWALLOW_ENABLE \ + 0x00000C98 + +#define GPRCM_O_DCDC_CLK_GEN_CONFIG \ + 0x00000C9C + +#define GPRCM_O_GPRCM_EFUSE_READ_REG4 \ + 0x00000CA0 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG5 \ + 0x00000CA4 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG6 \ + 0x00000CA8 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG7 \ + 0x00000CAC + +#define GPRCM_O_GPRCM_EFUSE_READ_REG8 \ + 0x00000CB0 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG9 \ + 0x00000CB4 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG10 \ + 0x00000CB8 + +#define GPRCM_O_GPRCM_EFUSE_READ_REG11 \ + 0x00000CBC + +#define GPRCM_O_GPRCM_DIEID_READ_REG0 \ + 0x00000CC0 + +#define GPRCM_O_GPRCM_DIEID_READ_REG1 \ + 0x00000CC4 + +#define GPRCM_O_GPRCM_DIEID_READ_REG2 \ + 0x00000CC8 + +#define GPRCM_O_GPRCM_DIEID_READ_REG3 \ + 0x00000CCC + +#define GPRCM_O_GPRCM_DIEID_READ_REG4 \ + 0x00000CD0 + +#define GPRCM_O_APPS_SS_OVERRIDES \ + 0x00000CD4 + +#define GPRCM_O_NWP_SS_OVERRIDES \ + 0x00000CD8 + +#define GPRCM_O_SHARED_SS_OVERRIDES \ + 0x00000CDC + +#define GPRCM_O_IDMEM_CORE_RST_OVERRIDES \ + 0x00000CE0 + +#define GPRCM_O_TOP_DIE_FSM_OVERRIDES \ + 0x00000CE4 + +#define GPRCM_O_MCU_PSCON_OVERRIDES \ + 0x00000CE8 + +#define GPRCM_O_WTOP_PSCON_OVERRIDES \ + 0x00000CEC + +#define GPRCM_O_WELP_PSCON_OVERRIDES \ + 0x00000CF0 + +#define GPRCM_O_WL_SDIO_PSCON_OVERRIDES \ + 0x00000CF4 + +#define GPRCM_O_MCSPI_PSCON_OVERRIDES \ + 0x00000CF8 + +#define GPRCM_O_SSDIO_PSCON_OVERRIDES \ + 0x00000CFC + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_SOFT_RESET register. +// +//****************************************************************************** +#define GPRCM_APPS_SOFT_RESET_APPS_SOFT_RESET1 \ + 0x00000002 // Soft-reset1 for APPS : Cortex + // sysrstn is asserted and in + // addition to that the associated + // APPS Peripherals are also reset. + // This is an auto-clear bit. + +#define GPRCM_APPS_SOFT_RESET_APPS_SOFT_RESET0 \ + 0x00000001 // Soft-reset0 for APPS : Only + // sys-resetn for Cortex will be + // asserted. This is an auto-clear + // bit. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_LPDS_WAKEUP_CFG register. +// +//****************************************************************************** +#define GPRCM_APPS_LPDS_WAKEUP_CFG_APPS_LPDS_WAKEUP_CFG_M \ + 0x000000FF // Mask for LPDS Wakeup interrupt : + // [7] - Host IRQ from NWP [6] - + // NWP_LPDS_Wake_irq (TRUE_LPDS) [5] + // - NWP Wake-request to APPS [4] - + // GPIO [3:1] - Reserved [0] - LPDS + // Wakeup-timer + +#define GPRCM_APPS_LPDS_WAKEUP_CFG_APPS_LPDS_WAKEUP_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_LPDS_WAKEUP_SRC register. +// +//****************************************************************************** +#define GPRCM_APPS_LPDS_WAKEUP_SRC_APPS_LPDS_WAKEUP_SRC_M \ + 0x000000FF // Indicates the cause for wakeup + // from LPDS : [7] - Host IRQ from + // NWP [6] - NWP_LPDS_Wake_irq + // (TRUE_LPDS) [5] - NWP + // Wake-request to APPS [4] - GPIO + // [3:1] - Reserved [0] - LPDS + // Wakeup-timer + +#define GPRCM_APPS_LPDS_WAKEUP_SRC_APPS_LPDS_WAKEUP_SRC_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_RESET_CAUSE register. +// +//****************************************************************************** +#define GPRCM_APPS_RESET_CAUSE_APPS_RESET_CAUSE_M \ + 0x000000FF // Indicates the reset cause for + // APPS : "0000" - Wake from HIB/OFF + // mode; "0001" - Wake from LPDS ; + // "0010" - Reserved ; "0011" - + // Soft-reset0 (Only APPS + // Cortex-sysrstn is asserted); + // "0100" - Soft-reset1 (APPS + // Cortex-sysrstn and APPS + // peripherals are reset); "0101" - + // WDOG0 (APPS Cortex-sysrstn and + // APPS peripherals are reset); + // "0110" - MCU Soft-reset (APPS + + // NWP Cortex-sysrstn + Peripherals + // are reset); "0111" - Secure Init + // done (Indication that reset has + // happened after DevInit); "1000" - + // Dev Mode Patch Init done (During + // development mode, patch + // downloading and Cortex + // re-vectoring is completed) + +#define GPRCM_APPS_RESET_CAUSE_APPS_RESET_CAUSE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_LPDS_WAKETIME_OPP_CFG register. +// +//****************************************************************************** +#define GPRCM_APPS_LPDS_WAKETIME_OPP_CFG_APPS_LPDS_WAKETIME_OPP_CFG_M \ + 0xFFFFFFFF // OPP Request Configuration + // (Number of slow-clk cycles) for + // LPDS Wake-timer : This + // configuration implies the RTC + // time-stamp, which must be few + // slow-clks prior to + // APPS_LPDS_WAKETIME_WAKE_CFG, such + // that by the time actual wakeup is + // given, OPP is already switched to + // ACTIVE (RUN). + +#define GPRCM_APPS_LPDS_WAKETIME_OPP_CFG_APPS_LPDS_WAKETIME_OPP_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_SRAM_DSLP_CFG register. +// +//****************************************************************************** +#define GPRCM_APPS_SRAM_DSLP_CFG_APPS_SRAM_DSLP_CFG_M \ + 0x000FFFFF // Configuration of APPS Memories + // during Deep-sleep : 0 - SRAMs are + // OFF ; 1 - SRAMs are Retained. + // APPS SRAM Cluster information : + // [0] - 1st column in MEMSS + // (Applicable only when owned by + // APPS); [1] - 2nd column in MEMSS + // (Applicable only when owned by + // APPS); [2] - 3rd column in MEMSS + // (Applicable only when owned by + // APPS) ; [3] - 4th column in MEMSS + // (Applicable only when owned by + // APPS) ; [16] - MCU-PD - Apps + // cluster 0 (TBD); [19:18] - + // Reserved. + +#define GPRCM_APPS_SRAM_DSLP_CFG_APPS_SRAM_DSLP_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_SRAM_LPDS_CFG register. +// +//****************************************************************************** +#define GPRCM_APPS_SRAM_LPDS_CFG_APPS_SRAM_LPDS_CFG_M \ + 0x000FFFFF // Configuration of APPS Memories + // during LPDS : 0 - SRAMs are OFF ; + // 1 - SRAMs are Retained. APPS SRAM + // Cluster information : [0] - 1st + // column in MEMSS (Applicable only + // when owned by APPS); [1] - 2nd + // column in MEMSS (Applicable only + // when owned by APPS); [2] - 3rd + // column in MEMSS (Applicable only + // when owned by APPS) ; [3] - 4th + // column in MEMSS (Applicable only + // when owned by APPS) ; [16] - + // MCU-PD - Apps cluster 0 (TBD); + // [19:18] - Reserved. + +#define GPRCM_APPS_SRAM_LPDS_CFG_APPS_SRAM_LPDS_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_LPDS_WAKETIME_WAKE_CFG register. +// +//****************************************************************************** +#define GPRCM_APPS_LPDS_WAKETIME_WAKE_CFG_APPS_LPDS_WAKETIME_WAKE_CFG_M \ + 0xFFFFFFFF // Configuration (in no of + // slow_clks) which says when the + // actual wakeup request for + // removing the PD-reset be given. + +#define GPRCM_APPS_LPDS_WAKETIME_WAKE_CFG_APPS_LPDS_WAKETIME_WAKE_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_TOP_DIE_ENABLE register. +// +//****************************************************************************** +#define GPRCM_TOP_DIE_ENABLE_FLASH_BUSY \ + 0x00001000 + +#define GPRCM_TOP_DIE_ENABLE_TOP_DIE_PWR_PS_M \ + 0x00000F00 + +#define GPRCM_TOP_DIE_ENABLE_TOP_DIE_PWR_PS_S 8 +#define GPRCM_TOP_DIE_ENABLE_TOP_DIE_ENABLE_STATUS \ + 0x00000002 // 1 - Top-die is enabled ; + +#define GPRCM_TOP_DIE_ENABLE_TOP_DIE_ENABLE \ + 0x00000001 // 1 - Enable the top-die ; 0 - + // Disable the top-die + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_TOP_DIE_ENABLE_PARAMETERS register. +// +//****************************************************************************** +#define GPRCM_TOP_DIE_ENABLE_PARAMETERS_FLASH_3P3_RSTN2D2D_POR_RSTN_M \ + 0xF0000000 // Configuration (in slow_clks) for + // number of clks between + // Flash-3p3-rstn to D2D POR Resetn. + +#define GPRCM_TOP_DIE_ENABLE_PARAMETERS_FLASH_3P3_RSTN2D2D_POR_RSTN_S 28 +#define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_SW_EN2TOP_DIE_FLASH_3P3_RSTN_M \ + 0x00FF0000 // Configuration (in slow_clks) for + // number of clks between Top-die + // Switch-Enable and Top-die Flash + // 3p3 Reset removal + +#define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_SW_EN2TOP_DIE_FLASH_3P3_RSTN_S 16 +#define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_POR_RSTN2BOTT_DIE_FMC_RSTN_M \ + 0x000000FF // Configuration (in slow_clks) for + // number of clks between D2D POR + // Reset removal and bottom die FMC + // reset removal + +#define GPRCM_TOP_DIE_ENABLE_PARAMETERS_TOP_DIE_POR_RSTN2BOTT_DIE_FMC_RSTN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCU_GLOBAL_SOFT_RESET register. +// +//****************************************************************************** +#define GPRCM_MCU_GLOBAL_SOFT_RESET_MCU_GLOBAL_SOFT_RESET \ + 0x00000001 // 1 - Assert the global reset for + // MCU (APPS + NWP) ; Asserts both + // Cortex sysrstn and its + // peripherals 0 - Deassert the + // global reset for MCU (APPS + NWP) + // ; Asserts both Cortex sysrstn and + // its peripherals Note : Reset for + // shared peripherals is not + // affected here. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_ADC_CLK_CONFIG register. +// +//****************************************************************************** +#define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_OFF_TIME_M \ + 0x000007C0 // Configuration (in number of 38.4 + // MHz clks) for the OFF-Time in + // generation of ADC_CLK + +#define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_OFF_TIME_S 6 +#define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_ON_TIME_M \ + 0x0000003E // Configuration (in number of 38.4 + // MHz clks) for the ON-Time in + // generation of ADC_CLK + +#define GPRCM_ADC_CLK_CONFIG_ADC_CLKGEN_ON_TIME_S 1 +#define GPRCM_ADC_CLK_CONFIG_ADC_CLK_ENABLE \ + 0x00000001 // 1 - Enable the ADC_CLK ; 0 - + // Disable the ADC_CLK + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_GPIO_WAKE_CONF register. +// +//****************************************************************************** +#define GPRCM_APPS_GPIO_WAKE_CONF_APPS_GPIO_WAKE_CONF_M \ + 0x00000003 // "00" - Wake on Level0 on + // selected GPIO pin (GPIO is + // selected inside the HIB3p3 + // module); "01" - Wakeup on + // fall-edge of GPIO pin. + +#define GPRCM_APPS_GPIO_WAKE_CONF_APPS_GPIO_WAKE_CONF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_EN_NWP_BOOT_WO_DEVINIT register. +// +//****************************************************************************** +#define GPRCM_EN_NWP_BOOT_WO_DEVINIT_reserved_M \ + 0xFFFFFFFE + +#define GPRCM_EN_NWP_BOOT_WO_DEVINIT_reserved_S 1 +#define GPRCM_EN_NWP_BOOT_WO_DEVINIT_mem_en_nwp_boot_wo_devinit \ + 0x00000001 // 1 - Override the secure-mode + // done for booting up NWP (Wakeup + // NWP on its event independent of + // CM4 state) ; 0 - Donot override + // the secure-mode done for NWP boot + // (NWP must be enabled by CM4 only) + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_HCLK_DIV_CFG register. +// +//****************************************************************************** +#define GPRCM_MEM_HCLK_DIV_CFG_mem_hclk_div_cfg_M \ + 0x00000007 // Division configuration for + // HCLKDIVOUT : "000" - Divide by 1 + // ; "001" - Divide by 2 ; "010" - + // Divide by 3 ; "011" - Divide by 4 + // ; "100" - Divide by 5 ; "101" - + // Divide by 6 ; "110" - Divide by 7 + // ; "111" - Divide by 8 + +#define GPRCM_MEM_HCLK_DIV_CFG_mem_hclk_div_cfg_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_SYSCLK_DIV_CFG register. +// +//****************************************************************************** +#define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_off_time_M \ + 0x00000038 + +#define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_off_time_S 3 +#define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_on_time_M \ + 0x00000007 + +#define GPRCM_MEM_SYSCLK_DIV_CFG_mem_sysclk_div_on_time_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_LOCK_TIME_CONF register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_wlan_lock_time_M \ + 0x0000FF00 + +#define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_wlan_lock_time_S 8 +#define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_mcu_lock_time_M \ + 0x000000FF + +#define GPRCM_APLLMCS_LOCK_TIME_CONF_mem_apllmcs_mcu_lock_time_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_SOFT_RESET register. +// +//****************************************************************************** +#define GPRCM_NWP_SOFT_RESET_NWP_SOFT_RESET1 \ + 0x00000002 // Soft-reset1 for NWP - Cortex + // sysrstn and NWP associated + // peripherals are - This is an + // auto-clr bit. + +#define GPRCM_NWP_SOFT_RESET_NWP_SOFT_RESET0 \ + 0x00000001 // Soft-reset0 for NWP - Only + // Cortex-sysrstn is asserted - This + // is an auto-clear bit. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_LPDS_WAKEUP_CFG register. +// +//****************************************************************************** +#define GPRCM_NWP_LPDS_WAKEUP_CFG_NWP_LPDS_WAKEUP_CFG_M \ + 0x000000FF // Mask for LPDS Wakeup interrupt : + // 7 - WLAN Host Interrupt ; 6 - + // WLAN to NWP Wake request ; 5 - + // APPS to NWP Wake request; 4 - + // GPIO Wakeup ; 3 - Autonomous UART + // Wakeup ; 2 - SSDIO Wakeup ; 1 - + // Autonomous SPI Wakeup ; 0 - LPDS + // Wakeup-timer + +#define GPRCM_NWP_LPDS_WAKEUP_CFG_NWP_LPDS_WAKEUP_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_LPDS_WAKEUP_SRC register. +// +//****************************************************************************** +#define GPRCM_NWP_LPDS_WAKEUP_SRC_NWP_LPDS_WAKEUP_SRC_M \ + 0x000000FF // Indicates the cause for NWP + // LPDS-Wakeup : 7 - WLAN Host + // Interrupt ; 6 - WLAN to NWP Wake + // request ; 5 - APPS to NWP Wake + // request; 4 - GPIO Wakeup ; 3 - + // Autonomous UART Wakeup ; 2 - + // SSDIO Wakeup ; 1 - Autonomous SPI + // Wakeup ; 0 - LPDS Wakeup-timer + +#define GPRCM_NWP_LPDS_WAKEUP_SRC_NWP_LPDS_WAKEUP_SRC_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_RESET_CAUSE register. +// +//****************************************************************************** +#define GPRCM_NWP_RESET_CAUSE_NWP_RESET_CAUSE_M \ + 0x000000FF // Indicates the reset cause for + // NWP : "0000" - Wake from HIB/OFF + // mode; "0001" - Wake from LPDS ; + // "0010" - Reserved ; "0011" - + // Soft-reset0 (Only NWP + // Cortex-sysrstn is asserted); + // "0100" - Soft-reset1 (NWP + // Cortex-sysrstn and NWP + // peripherals are reset); "0101" - + // WDOG0 (NWP Cortex-sysrstn and NWP + // peripherals are reset); "0110" - + // MCU Soft-reset (APPS + NWP + // Cortex-sysrstn + Peripherals are + // reset); "0111" - SSDIO Function2 + // reset (Only Cortex-sysrstn is + // asserted) ; "1000" - Reset due to + // WDOG of APPS (NWP Cortex-sysrstn + // and NWP peripherals are reset); + +#define GPRCM_NWP_RESET_CAUSE_NWP_RESET_CAUSE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_LPDS_WAKETIME_OPP_CFG register. +// +//****************************************************************************** +#define GPRCM_NWP_LPDS_WAKETIME_OPP_CFG_NWP_LPDS_WAKETIME_OPP_CFG_M \ + 0xFFFFFFFF // OPP Request Configuration + // (Number of slow-clk cycles) for + // LPDS Wake-timer + +#define GPRCM_NWP_LPDS_WAKETIME_OPP_CFG_NWP_LPDS_WAKETIME_OPP_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_SRAM_DSLP_CFG register. +// +//****************************************************************************** +#define GPRCM_NWP_SRAM_DSLP_CFG_NWP_SRAM_DSLP_CFG_M \ + 0x000FFFFF // Configuration of NWP Memories + // during DSLP : 0 - SRAMs are OFF ; + // 1 - SRAMs are Retained. NWP SRAM + // Cluster information : [2] - 3rd + // column in MEMSS (Applicable only + // when owned by NWP) ; [3] - 4th + // column in MEMSS (Applicable only + // when owned by NWP) ; [4] - 5th + // column in MEMSS (Applicable only + // when owned by NWP) ; [5] - 6th + // column in MEMSS (Applicable only + // when owned by NWP) ; [6] - 7th + // column in MEMSS (Applicable only + // when owned by NWP) ; [7] - 8th + // column in MEMSS (Applicable only + // when owned by NWP) ; [8] - 9th + // column in MEMSS (Applicable only + // when owned by NWP) ; [9] - 10th + // column in MEMSS (Applicable only + // when owned by NWP) ; [10] - 11th + // column in MEMSS (Applicable only + // when owned by NWP) ; [11] - 12th + // column in MEMSS (Applicable only + // when owned by NWP) ; [12] - 13th + // column in MEMSS (Applicable only + // when owned by NWP) ; [13] - 14th + // column in MEMSS (Applicable only + // when owned by NWP) ; [14] - 15th + // column in MEMSS (Applicable only + // when owned by NWP) ; [19:18] - + // Reserved. + +#define GPRCM_NWP_SRAM_DSLP_CFG_NWP_SRAM_DSLP_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_SRAM_LPDS_CFG register. +// +//****************************************************************************** +#define GPRCM_NWP_SRAM_LPDS_CFG_NWP_SRAM_LPDS_CFG_M \ + 0x000FFFFF // Configuration of NWP Memories + // during LPDS : 0 - SRAMs are OFF ; + // 1 - SRAMs are Retained. NWP SRAM + // Cluster information : [2] - 3rd + // column in MEMSS (Applicable only + // when owned by NWP) ; [3] - 4th + // column in MEMSS (Applicable only + // when owned by NWP) ; [4] - 5th + // column in MEMSS (Applicable only + // when owned by NWP) ; [5] - 6th + // column in MEMSS (Applicable only + // when owned by NWP) ; [6] - 7th + // column in MEMSS (Applicable only + // when owned by NWP) ; [7] - 8th + // column in MEMSS (Applicable only + // when owned by NWP) ; [8] - 9th + // column in MEMSS (Applicable only + // when owned by NWP) ; [9] - 10th + // column in MEMSS (Applicable only + // when owned by NWP) ; [10] - 11th + // column in MEMSS (Applicable only + // when owned by NWP) ; [11] - 12th + // column in MEMSS (Applicable only + // when owned by NWP) ; [12] - 13th + // column in MEMSS (Applicable only + // when owned by NWP) ; [13] - 14th + // column in MEMSS (Applicable only + // when owned by NWP) ; [14] - 15th + // column in MEMSS (Applicable only + // when owned by NWP) ; [19:18] - + // Reserved. + +#define GPRCM_NWP_SRAM_LPDS_CFG_NWP_SRAM_LPDS_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_LPDS_WAKETIME_WAKE_CFG register. +// +//****************************************************************************** +#define GPRCM_NWP_LPDS_WAKETIME_WAKE_CFG_NWP_LPDS_WAKETIME_WAKE_CFG_M \ + 0xFFFFFFFF // Wake time configuration (no of + // slow clks) for NWP wake from + // LPDS. + +#define GPRCM_NWP_LPDS_WAKETIME_WAKE_CFG_NWP_LPDS_WAKETIME_WAKE_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_AUTONMS_SPI_MASTER_SEL register. +// +//****************************************************************************** +#define GPRCM_NWP_AUTONMS_SPI_MASTER_SEL_F_M \ + 0xFFFE0000 + +#define GPRCM_NWP_AUTONMS_SPI_MASTER_SEL_F_S 17 +#define GPRCM_NWP_AUTONMS_SPI_MASTER_SEL_MEM_AUTONMS_SPI_MASTER_SEL \ + 0x00010000 // 0 - APPS is selected as host for + // Autonms SPI ; 1 - External host + // is selected as host for Autonms + // SPI + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_AUTONMS_SPI_IDLE_REQ register. +// +//****************************************************************************** +#define GPRCM_NWP_AUTONMS_SPI_IDLE_REQ_NWP_AUTONMS_SPI_IDLE_WAKEUP \ + 0x00010000 + +#define GPRCM_NWP_AUTONMS_SPI_IDLE_REQ_NWP_AUTONMS_SPI_IDLE_ACK \ + 0x00000002 // When 1 => IDLE-mode is + // acknowledged by the SPI-IP. (This + // is for MCSPI_N1) + +#define GPRCM_NWP_AUTONMS_SPI_IDLE_REQ_NWP_AUTONMS_SPI_IDLE_REQ \ + 0x00000001 // When 1 => Request for IDLE-mode + // for autonomous SPI. (This is for + // MCSPI_N1) + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WLAN_TO_NWP_WAKE_REQUEST register. +// +//****************************************************************************** +#define GPRCM_WLAN_TO_NWP_WAKE_REQUEST_WLAN_TO_NWP_WAKE_REQUEST \ + 0x00000001 // 1 - Request for waking up NWP + // from any of its low-power modes + // (SLP/DSLP/LPDS) + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_TO_WLAN_WAKE_REQUEST register. +// +//****************************************************************************** +#define GPRCM_NWP_TO_WLAN_WAKE_REQUEST_NWP_TO_WLAN_WAKE_REQUEST \ + 0x00000001 // 1 - Request for wakinp up WLAN + // from its ELP Mode (This gets + // triggered to ELP-logic of WLAN) + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_GPIO_WAKE_CONF register. +// +//****************************************************************************** +#define GPRCM_NWP_GPIO_WAKE_CONF_NWP_GPIO_WAKE_CONF_M \ + 0x00000003 // "00" - Wakeup on level0 of the + // selected GPIO (GPIO gets selected + // inside HIB3P3-module); "01" - + // Wakeup on fall-edge of selected + // GPIO. + +#define GPRCM_NWP_GPIO_WAKE_CONF_NWP_GPIO_WAKE_CONF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG12 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG12_FUSEFARM_ROW_32_MSW_M \ + 0x0000FFFF // This corrsponds to ROW_32 + // [31:16] of the FUSEFARM. SPARE + +#define GPRCM_GPRCM_EFUSE_READ_REG12_FUSEFARM_ROW_32_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_DIEID_READ_REG5 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_DIEID_READ_REG5_FUSEFARM_ROW_10_M \ + 0xFFFFFFFF // Corresponds to ROW10 of FUSEFARM + // : [5:0] - ADC OFFSET ; [13:6] - + // TEMP_SENSE ; [14:14] - DFT_GSG ; + // [15:15] - FMC_DISABLE ; [31:16] - + // WLAN_MAC ID + +#define GPRCM_GPRCM_DIEID_READ_REG5_FUSEFARM_ROW_10_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_DIEID_READ_REG6 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_DIEID_READ_REG6_FUSEFARM_ROW_11_M \ + 0xFFFFFFFF // Corresponds to ROW11 of FUSEFARM + // : [31:0] : WLAN MAC ID + +#define GPRCM_GPRCM_DIEID_READ_REG6_FUSEFARM_ROW_11_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_FSM_CFG0 register. +// +//****************************************************************************** +#define GPRCM_REF_FSM_CFG0_BGAP_SETTLING_TIME_M \ + 0x00FF0000 // ANA-BGAP Settling time (In + // number of slow_clks) + +#define GPRCM_REF_FSM_CFG0_BGAP_SETTLING_TIME_S 16 +#define GPRCM_REF_FSM_CFG0_FREF_LDO_SETTLING_TIME_M \ + 0x0000FF00 // Slicer LDO settling time (In + // number of slow clks) + +#define GPRCM_REF_FSM_CFG0_FREF_LDO_SETTLING_TIME_S 8 +#define GPRCM_REF_FSM_CFG0_DIG_BUF_SETTLING_TIME_M \ + 0x000000FF // Dig-buffer settling time (In + // number of slow clks) + +#define GPRCM_REF_FSM_CFG0_DIG_BUF_SETTLING_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_FSM_CFG1 register. +// +//****************************************************************************** +#define GPRCM_REF_FSM_CFG1_XTAL_SETTLING_TIME_M \ + 0xFF000000 // XTAL settling time (In number of + // slow clks) + +#define GPRCM_REF_FSM_CFG1_XTAL_SETTLING_TIME_S 24 +#define GPRCM_REF_FSM_CFG1_SLICER_LV_SETTLING_TIME_M \ + 0x00FF0000 // LV Slicer settling time + +#define GPRCM_REF_FSM_CFG1_SLICER_LV_SETTLING_TIME_S 16 +#define GPRCM_REF_FSM_CFG1_SLICER_HV_PD_SETTLING_TIME_M \ + 0x0000FF00 // HV Slicer Pull-down settling + // time + +#define GPRCM_REF_FSM_CFG1_SLICER_HV_PD_SETTLING_TIME_S 8 +#define GPRCM_REF_FSM_CFG1_SLICER_HV_SETTLING_TIME_M \ + 0x000000FF // HV Slicer settling time + +#define GPRCM_REF_FSM_CFG1_SLICER_HV_SETTLING_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_WLAN_CONFIG0_40 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_N_40_M \ + 0x00007F00 // Configuration for WLAN APLLMCS - + // N[6:0], if the XTAL frequency is + // 40 MHz (Selected by efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_N_40_S 8 +#define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_M_40_M \ + 0x000000FF // Configuration for WLAN APLLMCS - + // M[7:0], if the XTAL frequency is + // 40 MHz (Selected by efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG0_40_APLLMCS_WLAN_M_40_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_WLAN_CONFIG1_40 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_HISPEED_40 \ + 0x00000010 // Configuration for WLAN APLLMCS - + // if the XTAL frequency if 40 MHz + // (Selected by Efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_SEL96_40 \ + 0x00000008 // Configuration for WLAN APLLMCS - + // Sel96, if the XTAL frequency is + // 40 MHz (Selected by Efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_SELINPFREQ_40_M \ + 0x00000007 // Configuration for WLAN APLLMCS - + // Selinpfreq, if the XTAL frequency + // is 40 MHz (Selected by Efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG1_40_APLLMCS_SELINPFREQ_40_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_WLAN_CONFIG0_26 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_N_26_M \ + 0x00007F00 // Configuration for WLAN APLLMCS - + // N[6:0], if the XTAL frequency is + // 26 MHz (Selected by efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_N_26_S 8 +#define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_M_26_M \ + 0x000000FF // Configuration for WLAN APLLMCS - + // M[7:0], if the XTAL frequency is + // 26 MHz (Selected by efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG0_26_APLLMCS_WLAN_M_26_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_WLAN_CONFIG1_26 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_HISPEED_26 \ + 0x00000010 // Configuration for WLAN APLLMCS - + // if the XTAL frequency if 26 MHz + // (Selected by Efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_SEL96_26 \ + 0x00000008 // Configuration for WLAN APLLMCS - + // Sel96, if the XTAL frequency is + // 26 MHz (Selected by Efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_SELINPFREQ_26_M \ + 0x00000007 // Configuration for WLAN APLLMCS - + // Selinpfreq, if the XTAL frequency + // is 26 MHz (Selected by Efuse) + +#define GPRCM_APLLMCS_WLAN_CONFIG1_26_APLLMCS_SELINPFREQ_26_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_WLAN_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_POSTDIV_OVERRIDE_CTRL \ + 0x00080000 + +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_POSTDIV_OVERRIDE_M \ + 0x00070000 + +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_POSTDIV_OVERRIDE_S 16 +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_SPARE_M \ + 0x00000700 + +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_SPARE_S 8 +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_M_8_OVERRIDE_CTRL \ + 0x00000020 // Override control for + // WLAN_APLLMCS_M[8]. When set to1, + // M[8] will be selected by bit [3]. + // (Else controlled from WTOP) + +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_M_8_OVERRIDE \ + 0x00000010 // Override for WLAN_APLLMCS_M[8]. + // Applicable only when bit [4] is + // set to 1. (Else controlled from + // WTOP) + +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_N_7_8_OVERRIDE_CTRL \ + 0x00000004 // Override control for + // WLAN_APLLMCS_N[8:7]. When set + // to1, N[8:7] will be selected by + // bits [2:1]. (Else controlled from + // WTOP) + +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_N_7_8_OVERRIDE_M \ + 0x00000003 // Override value for + // WLAN_APLLMCS_N[8:7] bits. + // Applicable only when bit [1] is + // set to 1. (Else controlled from + // WTOP) + +#define GPRCM_APLLMCS_WLAN_OVERRIDES_APLLMCS_WLAN_N_7_8_OVERRIDE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_38P4 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_POSTDIV_M \ + 0x38000000 + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_POSTDIV_S 27 +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_SPARE_M \ + 0x07000000 + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_SPARE_S 24 +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_38P4_M \ + 0x007F0000 // Configuration for MCU-APLLMCS : + // N during RUN mode. Selected if + // the XTAL frequency is 38.4 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_38P4_S 16 +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_M_38P4_M \ + 0x0000FF00 // Configuration for MCU-APLLMCS : + // M during RUN mode. Selected if + // the XTAL frequency is 38.4 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_M_38P4_S 8 +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_M_8_38P4 \ + 0x00000010 // Configuration for MCU-APLLMCS : + // M[8] during RUN mode. Selected if + // the XTAL frequency is 38.4 MHz + // (From Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_7_8_38P4_M \ + 0x00000003 // Configuration for MCU-APLLMCS : + // N[8:7] during RUN mode. Selected + // if the XTAL frequency is 38.4 MHz + // (From Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_38P4_APLLMCS_MCU_RUN_N_7_8_38P4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_38P4 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_HISPEED_38P4 \ + 0x00000010 // Configuration for MCU-APLLMCS : + // HISPEED during RUN mode. Selected + // if the XTAL frequency is 38.4 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_SEL96_38P4 \ + 0x00000008 // Configuration for MCU-APLLMCS : + // SEL96 during RUN mode. Selected + // if the XTAL frequency is 38.4 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_SELINPFREQ_38P4_M \ + 0x00000007 // Configuration for MCU-APLLMCS : + // SELINPFREQ during RUN mode. + // Selected if the XTAL frequency is + // 38.4 MHz (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_38P4_APLLMCS_MCU_RUN_SELINPFREQ_38P4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_MCU_RUN_CONFIG0_26 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_26_M \ + 0x007F0000 // Configuration for MCU-APLLMCS : + // N during RUN mode. Selected if + // the XTAL frequency is 26 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_26_S 16 +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_M_26_M \ + 0x0000FF00 // Configuration for MCU-APLLMCS : + // M during RUN mode. Selected if + // the XTAL frequency is 26 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_M_26_S 8 +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_M_8_26 \ + 0x00000010 // Configuration for MCU-APLLMCS : + // M[8] during RUN mode. Selected if + // the XTAL frequency is 26 MHz + // (From Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_7_8_26_M \ + 0x00000003 // Configuration for MCU-APLLMCS : + // N[8:7] during RUN mode. Selected + // if the XTAL frequency is 26 MHz + // (From Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG0_26_APLLMCS_MCU_RUN_N_7_8_26_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_MCU_RUN_CONFIG1_26 register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_HISPEED_26 \ + 0x00000010 // Configuration for MCU-APLLMCS : + // HISPEED during RUN mode. Selected + // if the XTAL frequency is 26 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_SEL96_26 \ + 0x00000008 // Configuration for MCU-APLLMCS : + // SEL96 during RUN mode. Selected + // if the XTAL frequency is 26 MHz + // (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_SELINPFREQ_26_M \ + 0x00000007 // Configuration for MCU-APLLMCS : + // SELINPFREQ during RUN mode. + // Selected if the XTAL frequency is + // 26 MHz (from Efuse) + +#define GPRCM_APLLMCS_MCU_RUN_CONFIG1_26_APLLMCS_MCU_RUN_SELINPFREQ_26_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the GPRCM_O_SPARE_RW0 register. +// +//****************************************************************************** +//****************************************************************************** +// +// The following are defines for the bit fields in the GPRCM_O_SPARE_RW1 register. +// +//****************************************************************************** +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APLLMCS_MCU_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_APLLMCS_MCU_OVERRIDES_APLLMCS_MCU_LOCK \ + 0x00000400 // 1 - APLLMCS_MCU is locked ; 0 - + // APLLMCS_MCU is not locked + +#define GPRCM_APLLMCS_MCU_OVERRIDES_APLLMCS_MCU_ENABLE_OVERRIDE \ + 0x00000200 // Override for APLLMCS_MCU Enable. + // Applicable if bit [8] is set + +#define GPRCM_APLLMCS_MCU_OVERRIDES_APLLMCS_MCU_ENABLE_OVERRIDE_CTRL \ + 0x00000100 // 1 - Enable for APLLMCS_MCU comes + // from bit [9]. 0 - Enable for + // APLLMCS_MCU comes from FSM. + +#define GPRCM_APLLMCS_MCU_OVERRIDES_SYSCLK_SRC_OVERRIDE_M \ + 0x00000006 // Override for sysclk src + // (applicable only if bit [0] is + // set to 1. "00"- SLOW_CLK "01"- + // XTAL_CLK "10"- PLL_CLK + +#define GPRCM_APLLMCS_MCU_OVERRIDES_SYSCLK_SRC_OVERRIDE_S 1 +#define GPRCM_APLLMCS_MCU_OVERRIDES_SYSCLK_SRC_OVERRIDE_CTRL \ + 0x00000001 // 1 - Sysclk src is selected from + // bits [2:1] of this register. 0 - + // Sysclk src is selected from FSM + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_SYSCLK_SWITCH_STATUS register. +// +//****************************************************************************** +#define GPRCM_SYSCLK_SWITCH_STATUS_SYSCLK_SWITCH_STATUS \ + 0x00000001 // 1 - Sysclk switching is + // complete. 0 - Sysclk switching is + // in progress. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_LDO_CONTROLS register. +// +//****************************************************************************** +#define GPRCM_REF_LDO_CONTROLS_REF_LDO_ENABLE_OVERRIDE_CTRL \ + 0x00010000 // 1 - Enable for REF_LDO comes + // from bit [0] of this register ; 0 + // - Enable for REF_LDO comes from + // the FSM. Note : Final REF_LDO_EN + // reaches on the port + // TOP_PM_REG2[0] of gprcm. + +#define GPRCM_REF_LDO_CONTROLS_REF_SPARE_CONTROL_M \ + 0x0000C000 // Spare bits for REF_CTRL_FSM. + // Reaches directly on port + // TOP_PM_REG2[15:14] of gprcm. + +#define GPRCM_REF_LDO_CONTROLS_REF_SPARE_CONTROL_S 14 +#define GPRCM_REF_LDO_CONTROLS_REF_TLOAD_ENABLE_M \ + 0x00003800 // REF TLOAD Enable. Reaches + // directly on port + // TOP_PM_REG2[13:11] of gprcm. + +#define GPRCM_REF_LDO_CONTROLS_REF_TLOAD_ENABLE_S 11 +#define GPRCM_REF_LDO_CONTROLS_REF_LDO_TMUX_CONTROL_M \ + 0x00000700 // REF_LDO Test-mux control. + // Reaches directly on port + // TOP_PM_REG2[10:8] of gprcm. + +#define GPRCM_REF_LDO_CONTROLS_REF_LDO_TMUX_CONTROL_S 8 +#define GPRCM_REF_LDO_CONTROLS_REF_BW_CONTROL_M \ + 0x000000C0 // REF BW Control. Reaches directly + // on port TOP_PM_REG2[7:6] of + // gprcm. + +#define GPRCM_REF_LDO_CONTROLS_REF_BW_CONTROL_S 6 +#define GPRCM_REF_LDO_CONTROLS_REF_VTRIM_CONTROL_M \ + 0x0000003C // REF VTRIM Control. Reaches + // directly on port TOP_PM_REG2[5:2] + // of gprcm. + +#define GPRCM_REF_LDO_CONTROLS_REF_VTRIM_CONTROL_S 2 +#define GPRCM_REF_LDO_CONTROLS_REF_LDO_BYPASS_ENABLE \ + 0x00000002 // REF LDO Bypass Enable. Reaches + // directly on port TOP_PM_REG2[1] + // of gprcm. + +#define GPRCM_REF_LDO_CONTROLS_REF_LDO_ENABLE \ + 0x00000001 // Override for REF_LDO Enable. + // Applicable only if bit [16] of + // this register is set. Note : + // Final REF_LDO_EN reaches on the + // port TOP_PM_REG2[0] of gprcm. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_RTRIM_CONTROL register. +// +//****************************************************************************** +#define GPRCM_REF_RTRIM_CONTROL_TOP_PM_REG0_5_4_M \ + 0x18000000 // This is [5:4] bits of + // TOP_PM_REG0 + +#define GPRCM_REF_RTRIM_CONTROL_TOP_PM_REG0_5_4_S 27 +#define GPRCM_REF_RTRIM_CONTROL_TOP_CLKM_REG0_15_5_M \ + 0x07FF0000 // This is [15:5] bits of + // TOP_CLKM_REG0 + +#define GPRCM_REF_RTRIM_CONTROL_TOP_CLKM_REG0_15_5_S 16 +#define GPRCM_REF_RTRIM_CONTROL_REF_CLKM_RTRIM_OVERRIDE_CTRL \ + 0x00000100 // 1 - CLKM_RTRIM comes for + // bits[4:0] of this register. 0 - + // CLKM_RTRIM comes from Efuse + // (after efuse_done = 1). + +#define GPRCM_REF_RTRIM_CONTROL_REF_CLKM_RTRIM_M \ + 0x0000001F // CLKM_TRIM Override. Applicable + // when efuse_done = 0 or bit[8] is + // set to 1. + +#define GPRCM_REF_RTRIM_CONTROL_REF_CLKM_RTRIM_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_SLICER_CONTROLS0 register. +// +//****************************************************************************** +#define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_WLAN_LOWV_OVERRIDE_CTRL \ + 0x00200000 // 1 - EN_DIG_BUF_TOP comes from + // bit [14] of this register. 0 - + // EN_DIG_BUF_TOP comes from the + // FSM. Note : Final EN_DIG_BUF_WLAN + // reaches on TOP_CLKM_REG1_IN[14] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_TOP_LOWV_OVERRIDE_CTRL \ + 0x00100000 // 1 - EN_DIG_BUF_TOP comes from + // bit [15] of this register. 0 - + // EN_DIG_BUF_TOP comes from the + // FSM. Note : Final EN_DIG_BUF_TOP + // reaches on TOP_CLKM_REG1_IN[15] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_EN_XTAL_OVERRIDE_CTRL \ + 0x00080000 // 1 - EN_XTAL comes from bit [3] + // of this register. 0 - EN_XTAL + // comes from FSM. Note : Final + // XTAL_EN reaches on + // TOP_CLKM_REG1_IN[3] of gprcm. + +#define GPRCM_REF_SLICER_CONTROLS0_EN_SLI_HV_OVERRIDE_CTRL \ + 0x00040000 // 1 - Enable HV Slicer comes from + // bit [2] of this register. 0 - + // Enable HV Slicer comes from FSM. + // Note : Final HV_SLICER_EN reaches + // on port TOP_CLKM_REG1_IN[1] of + // gprcm. + +#define GPRCM_REF_SLICER_CONTROLS0_EN_SLI_LV_OVERRIDE_CTRL \ + 0x00020000 // 1 - Enable LV Slicer comes from + // bit[1] of this register. 0 - + // Enable LV Slicer comes from FSM. + // Note : final LV_SLICER_EN reaches + // on port TOP_CLKM_REG1_IN[2] of + // gprcm. + +#define GPRCM_REF_SLICER_CONTROLS0_EN_SLI_HV_PDN_OVERRIDE_CTRL \ + 0x00010000 // 1 - Enable HV Pull-down comes + // from bit[0] of this register. 0 - + // Enable HV Pull-down comes from + // FSM. Note : Final HV_PULL_DOWN + // reaches on port + // TOP_CLKM_REG1_IN[0] of gprcm. + +#define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_TOP_LOWV \ + 0x00008000 // Override for EN_DIG_BUF_TOP. + // Applicable if bit[20] is set to + // 1. Note : Final EN_DIG_BUF_TOP + // reaches on TOP_CLKM_REG1_IN[15] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_CLK_EN_WLAN_LOWV \ + 0x00004000 // Override for EN_DIG_BUF_WLAN. + // Applicable if bit[19] is set to + // 1. Note : Final EN_DIG_BUF_WLAN + // reaches on TOP_CLKM_REG1_IN[14] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_CLKOUT_FLIP_EN \ + 0x00002000 // CLKOUT Flip Enable. Reaches on + // bit[13] of TOP_CLKM_REG1_IN[13] + // port of gprcm. + +#define GPRCM_REF_SLICER_CONTROLS0_EN_DIV2_WLAN_CLK \ + 0x00001000 // Enable divide2 in WLAN Clk-path. + // Reaches on TOP_CLKM_REG1_IN[12] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_EN_DIV3_WLAN_CLK \ + 0x00000800 // Enable divide3 in WLAN Clk-path. + // Reaches on TOP_CLKM_REG1_IN[11] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_EN_DIV4_WLAN_CLK \ + 0x00000400 // Enable divide4 in WLAN Clk-path. + // Reaches on TOP_CLKM_REG1_IN[10] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_CM_TMUX_SEL_LOWV_M \ + 0x000003C0 // CM Test-mux select. Reaches on + // TOP_CLMM_REG1_IN[9:6] port of + // gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_CM_TMUX_SEL_LOWV_S 6 +#define GPRCM_REF_SLICER_CONTROLS0_SLICER_SPARE0_M \ + 0x00000030 // Slicer spare0 control. Reaches + // on TOP_CLKM_REG1_IN[5:4] port of + // gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_SLICER_SPARE0_S 4 +#define GPRCM_REF_SLICER_CONTROLS0_EN_XTAL \ + 0x00000008 // Enable XTAL override. Reaches on + // TOP_CLKM_REG1_IN[3] port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_EN_SLICER_HV \ + 0x00000004 // Enable HV Slicer override. + // Reaches on TOP_CLKM_REG1_IN[1] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_EN_SLICER_LV \ + 0x00000002 // Enable LV Slicer override. + // Reaches on TOP_CLKM_REG1_IN[2] + // port of gprcm + +#define GPRCM_REF_SLICER_CONTROLS0_EN_SLICER_HV_PDN \ + 0x00000001 // Enable HV Pull-down override. + // Reaches on TOP_CLKM_REG1_IN[0] + // port of gprcm + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_SLICER_CONTROLS1 register. +// +//****************************************************************************** +#define GPRCM_REF_SLICER_CONTROLS1_SLICER_SPARE1_M \ + 0x0000FC00 // Slicer spare1. Reaches on port + // TOP_CLKM_REG2_IN[15:10] of gprcm. + +#define GPRCM_REF_SLICER_CONTROLS1_SLICER_SPARE1_S 10 +#define GPRCM_REF_SLICER_CONTROLS1_XOSC_TRIM_M \ + 0x000003F0 // XOSC Trim. Reaches on port + // TOP_CLKM_REG2_IN[9:4] of gprcm + +#define GPRCM_REF_SLICER_CONTROLS1_XOSC_TRIM_S 4 +#define GPRCM_REF_SLICER_CONTROLS1_SLICER_ITRIM_CHANGE_TOGGLE \ + 0x00000008 // Slicer ITRIM Toggle. Reaches on + // port TOP_CLKM_REG2_IN[3] of + // gprcm. + +#define GPRCM_REF_SLICER_CONTROLS1_SLICER_LV_TRIM_M \ + 0x00000007 // LV Slicer trim. Reaches on port + // TOP_CLKM_REG2_IN[2:0] of gprcm. + +#define GPRCM_REF_SLICER_CONTROLS1_SLICER_LV_TRIM_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_ANA_BGAP_CONTROLS0 register. +// +//****************************************************************************** +#define GPRCM_REF_ANA_BGAP_CONTROLS0_reserved_M \ + 0xFF800000 + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_reserved_S 23 +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_mag_trim_override_ctrl \ + 0x00400000 // 1 - REF_MAG_TRIM comes from + // bit[4:0] of register + // REF_ANA_BGAP_CONTROLS1 [Addr : + // 0x0850]; 0 - REF_MAG_TRIM comes + // from efuse (After efc_done = 1). + // Note : Final REF_MAG_TRIM reaches + // on port TOP_PM_REG1[4:0] of gprcm + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_trim_override_ctrl \ + 0x00200000 // 1 - REF_V2I_TRIM comes from + // bit[9:6] of this register ; 0 - + // REF_V2I_TRIM comes from efuse + // (After efc_done = 1). Note : + // Final REF_V2I_TRIM reaches on + // port TOP_PM_REG0[9:6] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_temp_trim_override_ctrl \ + 0x00100000 // 1 - REF_TEMP_TRIM comes from + // bit[15:10] of this register ; 0 - + // REF_TEMP_TRIM comes from efuse + // (After efc_done = 1). Note : + // Final REF_TEMP_TRIM reaches on + // port TOP_PM_REG0[15:10] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_startup_en_override_ctrl \ + 0x00080000 // 1 - REF_STARTUP_EN comes from + // bit [3] of this register ; 0 - + // REF_STARTUP_EN comes from FSM. + // Note : Final REF_STARTUP_EN + // reaches on port TOP_PM_REG0[3] of + // gprcm + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_en_override_ctrl \ + 0x00040000 // 1 - REF_V2I_EN comes from bit + // [2] of this register ; 0 - + // REF_V2I_EN comes from FSM. Note : + // Final REF_V2I_EN reaches on port + // TOP_PM_REG0[2] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_fc_en_override_ctrl \ + 0x00020000 // 1 - REF_FC_EN comes from bit [1] + // of this register ; 0 - REF_FC_EN + // comes from FSM. Note : Final + // REF_FC_EN reaches on port + // TOP_PM_REG0[1] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_bgap_en_override_ctrl \ + 0x00010000 // 1 - REF_BGAP_EN comes from bit + // [0] of this register ; 0 - + // REF_BGAP_EN comes from FSM. Note + // : Final REF_BGAP_EN reaches on + // port TOP_PM_REG0[0] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_temp_trim_M \ + 0x0000FC00 // REF_TEMP_TRIM override. + // Applicable when bit [20] of this + // register set to 1. (or efc_done = + // 0) Note : Final REF_TEMP_TRIM + // reaches on port + // TOP_PM_REG0[15:10] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_temp_trim_S 10 +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_trim_M \ + 0x000003C0 // REF_V2I_TRIM Override. + // Applicable when bit [21] of this + // register set to 1 . (of efc_done + // = 0) Note : Final REF_V2I_TRIM + // reaches on port TOP_PM_REG0[9:6] + // of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_trim_S 6 +#define GPRCM_REF_ANA_BGAP_CONTROLS0_NU1_M \ + 0x00000030 + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_NU1_S 4 +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_startup_en \ + 0x00000008 // REF_STARTUP_EN override. + // Applicable when bit [19] of this + // register is set to 1. Note : + // Final REF_STARTUP_EN reaches on + // port TOP_PM_REG0[3] of gprcm + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_v2i_en \ + 0x00000004 // REF_V2I_EN override. Applicable + // when bit [21] of this register is + // set to 1. Note : Final REF_V2I_EN + // reaches on port TOP_PM_REG0[2] of + // gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_fc_en \ + 0x00000002 // REF_FC_EN override. Applicable + // when bit [17] of this register is + // set to 1. Note : Final REF_FC_EN + // reaches on port TOP_PM_REG0[1] of + // gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS0_mem_ref_bgap_en \ + 0x00000001 // REF_BGAP_EN override. Applicable + // when bit [16] of this register + // set to 1. Note : Final + // REF_BGAP_EN reaches on port + // TOP_PM_REG0[0] of gprcm. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_ANA_BGAP_CONTROLS1 register. +// +//****************************************************************************** +#define GPRCM_REF_ANA_BGAP_CONTROLS1_reserved_M \ + 0xFFFF0000 + +#define GPRCM_REF_ANA_BGAP_CONTROLS1_reserved_S 16 +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bg_spare_M \ + 0x0000C000 // REF_BGAP_SPARE. Reaches on port + // TOP_PM_REG1[15:14] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bg_spare_S 14 +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bgap_tmux_ctrl_M \ + 0x00003E00 // REF_BGAP_TMUX_CTRL. Reaches on + // port TOP_PM_REG1[13:9] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_bgap_tmux_ctrl_S 9 +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_filt_trim_M \ + 0x000001E0 // REF_FILT_TRIM. Reaches on port + // TOP_PM_REG1[8:5] of gprcm. + +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_filt_trim_S 5 +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_mag_trim_M \ + 0x0000001F // REF_MAG_TRIM Override. + // Applicable when bit[22] of + // REF_ANA_BGAP_CONTROLS0 [0x084C] + // set to 1 (of efc_done = 0). Note + // : Final REF_MAG_TRIM reaches on + // port TOP_PM_REG1[4:0] of gprcm + +#define GPRCM_REF_ANA_BGAP_CONTROLS1_mem_ref_mag_trim_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_ANA_SPARE_CONTROLS0 register. +// +//****************************************************************************** +#define GPRCM_REF_ANA_SPARE_CONTROLS0_reserved_M \ + 0xFFFF0000 + +#define GPRCM_REF_ANA_SPARE_CONTROLS0_reserved_S 16 +#define GPRCM_REF_ANA_SPARE_CONTROLS0_mem_top_pm_reg3_M \ + 0x0000FFFF // Spare control. Reaches on + // TOP_PM_REG3 [15:0] of gprcm. + +#define GPRCM_REF_ANA_SPARE_CONTROLS0_mem_top_pm_reg3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_ANA_SPARE_CONTROLS1 register. +// +//****************************************************************************** +#define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg3_M \ + 0xFFFF0000 // Spare control. Reaches on + // TOP_CLKM_REG3 [15:0] of gprcm. + +#define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg3_S 16 +#define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg4_M \ + 0x0000FFFF // Spare control. Reaches on + // TOP_CLKM_REG4 [15:0] of gprcm. + +#define GPRCM_REF_ANA_SPARE_CONTROLS1_mem_top_clkm_reg4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEMSS_PSCON_OVERRIDES0 register. +// +//****************************************************************************** +#define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_off_override_M \ + 0xFFFF0000 + +#define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_off_override_S 16 +#define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_retain_override_M \ + 0x0000FFFF + +#define GPRCM_MEMSS_PSCON_OVERRIDES0_mem_memss_pscon_mem_retain_override_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEMSS_PSCON_OVERRIDES1 register. +// +//****************************************************************************** +#define GPRCM_MEMSS_PSCON_OVERRIDES1_reserved_M \ + 0xFFFFFFC0 + +#define GPRCM_MEMSS_PSCON_OVERRIDES1_reserved_S 6 +#define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_mem_update_override_ctrl \ + 0x00000020 + +#define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_mem_update_override \ + 0x00000010 + +#define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_sleep_override_ctrl \ + 0x00000008 + +#define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_sleep_override \ + 0x00000004 + +#define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memss_pscon_mem_off_override_ctrl \ + 0x00000002 + +#define GPRCM_MEMSS_PSCON_OVERRIDES1_mem_memms_pscon_mem_retain_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_PLL_REF_LOCK_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_PLL_REF_LOCK_OVERRIDES_reserved_M \ + 0xFFFFFFF8 + +#define GPRCM_PLL_REF_LOCK_OVERRIDES_reserved_S 3 +#define GPRCM_PLL_REF_LOCK_OVERRIDES_mem_mcu_apllmcs_lock_override \ + 0x00000004 + +#define GPRCM_PLL_REF_LOCK_OVERRIDES_mem_wlan_apllmcs_lock_override \ + 0x00000002 + +#define GPRCM_PLL_REF_LOCK_OVERRIDES_mem_ref_clk_valid_override \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCU_PSCON_DEBUG register. +// +//****************************************************************************** +#define GPRCM_MCU_PSCON_DEBUG_reserved_M \ + 0xFFFFFFC0 + +#define GPRCM_MCU_PSCON_DEBUG_reserved_S 6 +#define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_rtc_ps_M \ + 0x00000038 // MCU_PSCON_RTC_ON = "0000"; + // MCU_PSCON_RTC_OFF = "0001"; + // MCU_PSCON_RTC_RET = "0010"; + // MCU_PSCON_RTC_OFF_TO_ON = "0011"; + // MCU_PSCON_RTC_RET_TO_ON = "0100"; + // MCU_PSCON_RTC_ON_TO_RET = "0101"; + // MCU_PSCON_RTC_ON_TO_OFF = "0110"; + // MCU_PSCON_RTC_RET_TO_ON_WAIT_OPP + // = "0111"; + // MCU_PSCON_RTC_OFF_TO_ON_WAIT_OPP + // = "1000"; + +#define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_rtc_ps_S 3 +#define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_sys_ps_M \ + 0x00000007 + +#define GPRCM_MCU_PSCON_DEBUG_mcu_pscon_sys_ps_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEMSS_PWR_PS register. +// +//****************************************************************************** +#define GPRCM_MEMSS_PWR_PS_reserved_M \ + 0xFFFFFFF8 + +#define GPRCM_MEMSS_PWR_PS_reserved_S 3 +#define GPRCM_MEMSS_PWR_PS_pwr_ps_memss_M \ + 0x00000007 // MEMSS_PM_SLEEP = "000"; + // MEMSS_PM_WAIT_OPP = "010"; + // MEMSS_PM_ACTIVE = "011"; + // MEMSS_PM_SLEEP_TO_ACTIVE = "100"; + // MEMSS_PM_ACTIVE_TO_SLEEP = "101"; + +#define GPRCM_MEMSS_PWR_PS_pwr_ps_memss_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_REF_FSM_DEBUG register. +// +//****************************************************************************** +#define GPRCM_REF_FSM_DEBUG_reserved_M \ + 0xFFFFFFC0 + +#define GPRCM_REF_FSM_DEBUG_reserved_S 6 +#define GPRCM_REF_FSM_DEBUG_fref_mode_M \ + 0x00000030 // 01 - HV Mode ; 10 - LV Mode ; 11 + // - XTAL Mode + +#define GPRCM_REF_FSM_DEBUG_fref_mode_S 4 +#define GPRCM_REF_FSM_DEBUG_ref_fsm_ps_M \ + 0x0000000F // constant FREF_CLK_OFF = "00000"; + // constant FREF_EN_BGAP = "00001"; + // constant FREF_EN_LDO = "00010"; + // constant FREF_EN_SLI_HV = + // "00011"; constant + // FREF_EN_SLI_HV_PD = "00100"; + // constant FREF_EN_DIG_BUF = + // "00101"; constant FREF_EN_OSC = + // "00110"; constant FREF_EN_SLI_LV + // = "00111"; constant + // FREF_EN_CLK_REQ = "01000"; + // constant FREF_CLK_VALID = + // "01001"; constant FREF_MODE_DET0 + // = "01010"; constant + // FREF_MODE_DET1 = "01011"; + // constant FREF_MODE_DET2 = + // "10010"; constant FREF_MODE_DET3 + // = "10011"; constant FREF_VALID = + // "01100"; constant FREF_VALID0 = + // "01101"; constant FREF_VALID1 = + // "01110"; constant FREF_VALID2 = + // "01111"; constant + // FREF_WAIT_EXT_TCXO0 = "10000"; + // constant FREF_WAIT_EXT_TCXO1 = + // "10001"; + +#define GPRCM_REF_FSM_DEBUG_ref_fsm_ps_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_SYS_OPP_REQ_OVERRIDE register. +// +//****************************************************************************** +#define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_reserved_M \ + 0xFFFFFFE0 + +#define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_reserved_S 5 +#define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_mem_sys_opp_req_override_ctrl \ + 0x00000010 // 1 - Override the sytem-opp + // request to ANATOP using bit0 of + // this register + +#define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_mem_sys_opp_req_override_M \ + 0x0000000F // "0001" - RUN ; "0010" - DSLP ; + // "0100" - LPDS ; Others - NA + +#define GPRCM_MEM_SYS_OPP_REQ_OVERRIDE_mem_sys_opp_req_override_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_TESTCTRL_PD_OPP_CONFIG register. +// +//****************************************************************************** +#define GPRCM_MEM_TESTCTRL_PD_OPP_CONFIG_reserved_M \ + 0xFFFFFFFE + +#define GPRCM_MEM_TESTCTRL_PD_OPP_CONFIG_reserved_S 1 +#define GPRCM_MEM_TESTCTRL_PD_OPP_CONFIG_mem_sleep_opp_enter_with_testpd_on \ + 0x00000001 // 1 - Enable sleep-opp (DSLP/LPDS) + // entry even if Test-Pd is kept ON + // ; 0 - Donot enable sleep-opp + // (DSLP/LPDS) entry with Test-Pd + // ON. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_WL_FAST_CLK_REQ_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_reserved_M \ + 0xFFFFFFF8 + +#define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_reserved_S 3 +#define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_mem_wl_fast_clk_req_override_ctrl \ + 0x00000004 // NA + +#define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_mem_wl_fast_clk_req_override \ + 0x00000002 // NA + +#define GPRCM_MEM_WL_FAST_CLK_REQ_OVERRIDES_mem_wl_sleep_with_clk_req_override \ + 0x00000001 // NA + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_MCU_PD_MODE_REQ_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_MEM_MCU_PD_MODE_REQ_OVERRIDES_mem_mcu_pd_mode_req_override_ctrl \ + 0x00000004 // 1 - Override the MCU-PD power + // modes using bits [1] & [0] ; + +#define GPRCM_MEM_MCU_PD_MODE_REQ_OVERRIDES_mem_mcu_pd_pwrdn_req_override \ + 0x00000002 // 1 - Request for power-down of + // MCU-PD ; + +#define GPRCM_MEM_MCU_PD_MODE_REQ_OVERRIDES_mem_mcu_pd_ret_req_override \ + 0x00000001 // 1 - Request for retention mode + // of MCU-PD. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES_mem_mcspi_sram_off_req_override_ctrl \ + 0x00000002 // 1- Override the MCSPI + // (Autonomous SPI) memory state + // using bit [0] + +#define GPRCM_MEM_MCSPI_SRAM_OFF_REQ_OVERRIDES_mem_mcspi_sram_off_req_override \ + 0x00000001 // 1 - Request for power-down of + // Autonomous SPI 8k memory ; 0 - + // Donot request power-down of + // Autonomous SPI 8k Memory + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_WLAN_APLLMCS_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_MEM_WLAN_APLLMCS_OVERRIDES_wlan_apllmcs_lock \ + 0x00000100 + +#define GPRCM_MEM_WLAN_APLLMCS_OVERRIDES_mem_wlan_apllmcs_enable_override \ + 0x00000002 + +#define GPRCM_MEM_WLAN_APLLMCS_OVERRIDES_mem_wlan_apllmcs_enable_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_REF_FSM_CFG2 register. +// +//****************************************************************************** +#define GPRCM_MEM_REF_FSM_CFG2_MEM_FC_DEASSERT_DELAY_M \ + 0x00380000 // Number of RTC clocks for keeping + // the FC_EN asserted high + +#define GPRCM_MEM_REF_FSM_CFG2_MEM_FC_DEASSERT_DELAY_S 19 +#define GPRCM_MEM_REF_FSM_CFG2_MEM_STARTUP_DEASSERT_DELAY_M \ + 0x00070000 // Number of RTC clocks for keeping + // the STARTUP_EN asserted high + +#define GPRCM_MEM_REF_FSM_CFG2_MEM_STARTUP_DEASSERT_DELAY_S 16 +#define GPRCM_MEM_REF_FSM_CFG2_MEM_EXT_TCXO_SETTLING_TIME_M \ + 0x0000FFFF // Number of RTC clocks for waiting + // for clock to settle. + +#define GPRCM_MEM_REF_FSM_CFG2_MEM_EXT_TCXO_SETTLING_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_TESTCTRL_POWER_CTRL register. +// +//****************************************************************************** +#define GPRCM_TESTCTRL_POWER_CTRL_TESTCTRL_PD_STATUS_M \ + 0x00000006 + +#define GPRCM_TESTCTRL_POWER_CTRL_TESTCTRL_PD_STATUS_S 1 +#define GPRCM_TESTCTRL_POWER_CTRL_TESTCTRL_PD_ENABLE \ + 0x00000001 // 0 - Disable the TestCtrl-pd ; 1 + // - Enable the TestCtrl-pd. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_SSDIO_POWER_CTRL register. +// +//****************************************************************************** +#define GPRCM_SSDIO_POWER_CTRL_SSDIO_PD_STATUS_M \ + 0x00000006 // 1 - SSDIO-PD is ON ; 0 - + // SSDIO-PD is OFF + +#define GPRCM_SSDIO_POWER_CTRL_SSDIO_PD_STATUS_S 1 +#define GPRCM_SSDIO_POWER_CTRL_SSDIO_PD_ENABLE \ + 0x00000001 // 0 - Disable the SSDIO-pd ; 1 - + // Enable the SSDIO-pd. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCSPI_N1_POWER_CTRL register. +// +//****************************************************************************** +#define GPRCM_MCSPI_N1_POWER_CTRL_MCSPI_N1_PD_STATUS_M \ + 0x00000006 // 1 - MCSPI_N1-PD is ON ; 0 - + // MCSPI_N1-PD if OFF + +#define GPRCM_MCSPI_N1_POWER_CTRL_MCSPI_N1_PD_STATUS_S 1 +#define GPRCM_MCSPI_N1_POWER_CTRL_MCSPI_N1_PD_ENABLE \ + 0x00000001 // 0 - Disable the MCSPI_N1-pd ; 1 + // - Enable the MCSPI_N1-pd. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WELP_POWER_CTRL register. +// +//****************************************************************************** +#define GPRCM_WELP_POWER_CTRL_WTOP_PD_STATUS_M \ + 0x00001C00 + +#define GPRCM_WELP_POWER_CTRL_WTOP_PD_STATUS_S 10 +#define GPRCM_WELP_POWER_CTRL_WTOP_PD_REQ_OVERRIDE \ + 0x00000200 + +#define GPRCM_WELP_POWER_CTRL_WTOP_PD_REQ_OVERRIDE_CTRL \ + 0x00000100 + +#define GPRCM_WELP_POWER_CTRL_WELP_PD_STATUS_M \ + 0x00000006 + +#define GPRCM_WELP_POWER_CTRL_WELP_PD_STATUS_S 1 +#define GPRCM_WELP_POWER_CTRL_WELP_PD_ENABLE \ + 0x00000001 // 0 - Disable the WELP-pd ; 1 - + // Enable the WELP-pd. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WL_SDIO_POWER_CTRL register. +// +//****************************************************************************** +#define GPRCM_WL_SDIO_POWER_CTRL_WL_SDIO_PD_STATUS_M \ + 0x00000006 + +#define GPRCM_WL_SDIO_POWER_CTRL_WL_SDIO_PD_STATUS_S 1 +#define GPRCM_WL_SDIO_POWER_CTRL_WL_SDIO_PD_ENABLE \ + 0x00000001 // 0 - Disable the WL_SDIO-pd ; 1 - + // Enable the WL_SDIO-pd. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WLAN_SRAM_ACTIVE_PWR_CFG register. +// +//****************************************************************************** +#define GPRCM_WLAN_SRAM_ACTIVE_PWR_CFG_WLAN_SRAM_ACTIVE_PWR_CFG_M \ + 0x00FFFFFF // SRAM (WTOP+DRP) state during + // Active-mode : 1 - SRAMs are ON ; + // 0 - SRAMs are OFF. Cluster + // information : [0] - 1st column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) [1] - 2nd column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) ; [2] - 3rd column + // of MEMSS (Applicable only when + // owned by WTOP/PHY) ; [3] - 4th + // column of MEMSS (Applicable only + // when owned by WTOP/PHY) ; [4] - + // 5th column of MEMSS (Applicable + // only when owned by WTOP/PHY) ; + // [5] - 6th column of MEMSS + // (Applicable only when owned by + // WTOP/PHY) ; [6] - 7th column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) ; [7] - 8th column + // of MEMSS (Applicable only when + // owned by WTOP/PHY) ; [8] - 9th + // column of MEMSS (Applicable only + // when owned by WTOP/PHY) ; [9] - + // 10th column of MEMSS (Applicable + // only when owned by WTOP/PHY) ; + // [10] - 11th column of MEMSS + // (Applicable only when owned by + // WTOP/PHY) ; [11] - 12th column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) ; [12] - 13th column + // of MEMSS (Applicable only when + // owned by WTOP/PHY) ; [13] - 14th + // column of MEMSS (Applicable only + // when owned by WTOP/PHY) ; [14] - + // 15th column of MEMSS (Applicable + // only when owned by WTOP/PHY) ; + // [15] - 16th column of MEMSS + // (Applicable only when owned by + // WTOP/PHY) ; [23:16] - Internal to + // WTOP Cluster + +#define GPRCM_WLAN_SRAM_ACTIVE_PWR_CFG_WLAN_SRAM_ACTIVE_PWR_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WLAN_SRAM_SLEEP_PWR_CFG register. +// +//****************************************************************************** +#define GPRCM_WLAN_SRAM_SLEEP_PWR_CFG_WLAN_SRAM_SLEEP_PWR_CFG_M \ + 0x00FFFFFF // SRAM (WTOP+DRP) state during + // Sleep-mode : 1 - SRAMs are RET ; + // 0 - SRAMs are OFF. Cluster + // information : [0] - 1st column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) [1] - 2nd column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) ; [2] - 3rd column + // of MEMSS (Applicable only when + // owned by WTOP/PHY) ; [3] - 4th + // column of MEMSS (Applicable only + // when owned by WTOP/PHY) ; [4] - + // 5th column of MEMSS (Applicable + // only when owned by WTOP/PHY) ; + // [5] - 6th column of MEMSS + // (Applicable only when owned by + // WTOP/PHY) ; [6] - 7th column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) ; [7] - 8th column + // of MEMSS (Applicable only when + // owned by WTOP/PHY) ; [8] - 9th + // column of MEMSS (Applicable only + // when owned by WTOP/PHY) ; [9] - + // 10th column of MEMSS (Applicable + // only when owned by WTOP/PHY) ; + // [10] - 11th column of MEMSS + // (Applicable only when owned by + // WTOP/PHY) ; [11] - 12th column of + // MEMSS (Applicable only when owned + // by WTOP/PHY) ; [12] - 13th column + // of MEMSS (Applicable only when + // owned by WTOP/PHY) ; [13] - 14th + // column of MEMSS (Applicable only + // when owned by WTOP/PHY) ; [14] - + // 15th column of MEMSS (Applicable + // only when owned by WTOP/PHY) ; + // [15] - 16th column of MEMSS + // (Applicable only when owned by + // WTOP/PHY) ; [23:16] - Internal to + // WTOP Cluster + +#define GPRCM_WLAN_SRAM_SLEEP_PWR_CFG_WLAN_SRAM_SLEEP_PWR_CFG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_SECURE_INIT_DONE register. +// +//****************************************************************************** +#define GPRCM_APPS_SECURE_INIT_DONE_SECURE_INIT_DONE_STATUS \ + 0x00000002 // 1-Secure mode init is done ; + // 0-Secure mode init is not done + +#define GPRCM_APPS_SECURE_INIT_DONE_APPS_SECURE_INIT_DONE \ + 0x00000001 // Must be programmed 1 in order to + // say that secure-mode device init + // is done + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_DEV_MODE_INIT_DONE register. +// +//****************************************************************************** +#define GPRCM_APPS_DEV_MODE_INIT_DONE_APPS_DEV_MODE_INIT_DONE \ + 0x00000001 // 1 - Patch download and other + // initializations are done (before + // removing APPS resetn) for + // development mode (#3) . 0 - + // Development mode (#3) init is not + // done yet + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_EN_APPS_REBOOT register. +// +//****************************************************************************** +#define GPRCM_EN_APPS_REBOOT_EN_APPS_REBOOT \ + 0x00000001 // 1 - When 1, disable the reboot + // of APPS after DevInit is + // completed. In this case, APPS + // will permanantly help in reset. 0 + // - When 0, enable the reboot of + // APPS after DevInit is completed. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_APPS_PERIPH_PRESENT register. +// +//****************************************************************************** +#define GPRCM_MEM_APPS_PERIPH_PRESENT_WLAN_GEM_PP \ + 0x00010000 // 1 - Enable ; 0 - Disable + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_AES_PP \ + 0x00008000 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_DES_PP \ + 0x00004000 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_SHA_PP \ + 0x00002000 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_CAMERA_PP \ + 0x00001000 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MMCHS_PP \ + 0x00000800 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MCASP_PP \ + 0x00000400 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MCSPI_A1_PP \ + 0x00000200 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_MCSPI_A2_PP \ + 0x00000100 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_UDMA_PP \ + 0x00000080 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_WDOG_PP \ + 0x00000040 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_UART_A0_PP \ + 0x00000020 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_UART_A1_PP \ + 0x00000010 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A0_PP \ + 0x00000008 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A1_PP \ + 0x00000004 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A2_PP \ + 0x00000002 + +#define GPRCM_MEM_APPS_PERIPH_PRESENT_APPS_GPT_A3_PP \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_NWP_PERIPH_PRESENT register. +// +//****************************************************************************** +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_ASYNC_BRIDGE_PP \ + 0x00000200 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_MCSPI_N2_PP \ + 0x00000100 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_GPT_N0_PP \ + 0x00000080 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_GPT_N1_PP \ + 0x00000040 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_WDOG_PP \ + 0x00000020 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_UDMA_PP \ + 0x00000010 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_UART_N0_PP \ + 0x00000008 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_UART_N1_PP \ + 0x00000004 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_SSDIO_PP \ + 0x00000002 + +#define GPRCM_MEM_NWP_PERIPH_PRESENT_NWP_MCSPI_N1_PP \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MEM_SHARED_PERIPH_PRESENT register. +// +//****************************************************************************** + +#define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_MCSPI_PP \ + 0x00000040 + +#define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_I2C_PP \ + 0x00000020 + +#define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_A_PP \ + 0x00000010 + +#define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_B_PP \ + 0x00000008 + +#define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_C_PP \ + 0x00000004 + +#define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_D_PP \ + 0x00000002 + +#define GPRCM_MEM_SHARED_PERIPH_PRESENT_SHARED_GPIO_E_PP \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_PWR_STATE register. +// +//****************************************************************************** +#define GPRCM_NWP_PWR_STATE_NWP_PWR_STATE_PS_M \ + 0x00000F00 // "0000"- PORZ :- NWP is yet to be + // enabled by APPS during powerup + // (from HIB/OFF) ; "0011"- ACTIVE + // :- NWP is enabled, clocks and + // resets to NWP-SubSystem are + // enabled ; "0010"- LPDS :- NWP is + // in LPDS-mode ; Clocks and reset + // to NWP-SubSystem are gated ; + // "0101"- WAIT_FOR_OPP :- NWP is in + // transition from LPDS to ACTIVE, + // where it is waiting for OPP to be + // stable ; "1000"- + // WAKE_TIMER_OPP_REQ :- NWP is in + // transition from LPDS, where the + // wakeup cause is LPDS_Wake timer + // OTHERS : NA + +#define GPRCM_NWP_PWR_STATE_NWP_PWR_STATE_PS_S 8 +#define GPRCM_NWP_PWR_STATE_NWP_RCM_PS_M \ + 0x00000007 // "000" - NWP_RUN : NWP is in RUN + // state (default) - Applicable only + // when NWP_PWR_STATE_PS = ACTIVE ; + // "001" - NWP_SLP : NWP is in SLEEP + // state (default) - Applicable only + // when NWP_PWR_STATE_PS = ACTIVE ; + // "010" - NWP_DSLP : NWP is in + // Deep-Sleep state (default) - + // Applicable only when + // NWP_PWR_STATE_PS = ACTIVE ; "011" + // - WAIT_FOR_ACTIVE : NWP is in + // transition from Deep-sleep to + // Run, where it is waiting for OPP + // to be stable ; "100" - + // WAIT_FOR_DSLP_TIMER_WAKE_REQ : + // NWP is in transition from + // Deep-sleep to Run, where the + // wakeup cause is deep-sleep + // wake-timer + +#define GPRCM_NWP_PWR_STATE_NWP_RCM_PS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_PWR_STATE register. +// +//****************************************************************************** +#define GPRCM_APPS_PWR_STATE_APPS_PWR_STATE_PS_M \ + 0x00000F00 // "0000"- PORZ :- APPS is waiting + // for PLL_clock during powerup + // (from HIB/OFF) ; "0011"- ACTIVE + // :- APPS is enabled, clocks and + // resets to APPS-SubSystem are + // enabled ; APPS might be either in + // Secure or Un-secure mode during + // this state. "1001" - + // SECURE_MODE_LPDS :- While in + // ACTIVE (Secure-mode), APPS had to + // program the DevInit_done bit at + // the end, after which it enters + // into this state, where the reset + // to APPS will be asserted. From + // this state APPS might either + // re-boot itself or enter into LPDS + // depending upon whether the device + // is 3200 or 3100. "0010"- LPDS :- + // APPS is in LPDS-mode ; Clocks and + // reset to APPS-SubSystem are gated + // ; "0101"- WAIT_FOR_OPP :- APPS is + // in transition from LPDS to + // ACTIVE, where it is waiting for + // OPP to be stable ; "1000" - + // WAKE_TIMER_OPP_REQ : APPS is in + // transition from LPDS, where the + // wakeup cause is LPDS_Wake timer ; + // "1010" - WAIT_FOR_PATCH_INIT : + // APPS enters into this state + // during development-mode #3 (SOP = + // 3), where it is waiting for patch + // download to complete and 0x4 hack + // is programmed. OTHERS : NA + +#define GPRCM_APPS_PWR_STATE_APPS_PWR_STATE_PS_S 8 +#define GPRCM_APPS_PWR_STATE_APPS_RCM_PS_M \ + 0x00000007 // "000" - APPS_RUN : APPS is in + // RUN state (default) - Applicable + // only when APPS_PWR_STATE_PS = + // ACTIVE ; "001" - APPS_SLP : APPS + // is in SLEEP state (default) - + // Applicable only when + // APPS_PWR_STATE_PS = ACTIVE ; + // "010" - APPS_DSLP : APPS is in + // Deep-Sleep state (default) - + // Applicable only when + // APPS_PWR_STATE_PS = ACTIVE ; + // "011" - WAIT_FOR_ACTIVE : APPS is + // in transition from Deep-sleep to + // Run, where it is waiting for OPP + // to be stable ; "100" - + // WAIT_FOR_DSLP_TIMER_WAKE_REQ : + // APPS is in transition from + // Deep-sleep to Run, where the + // wakeup cause is deep-sleep + // wake-timer + +#define GPRCM_APPS_PWR_STATE_APPS_RCM_PS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCU_PWR_STATE register. +// +//****************************************************************************** +#define GPRCM_MCU_PWR_STATE_MCU_OPP_PS_M \ + 0x0000001F // TBD + +#define GPRCM_MCU_PWR_STATE_MCU_OPP_PS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WTOP_PM_PS register. +// +//****************************************************************************** +#define GPRCM_WTOP_PM_PS_WTOP_PM_PS_M \ + 0x00000007 // "011" - WTOP_PM_ACTIVE (Default) + // :- WTOP_Pd is in ACTIVE mode; + // "100" - WTOP_PM_ACTIVE_TO_SLEEP + // :- WTOP_Pd is in transition from + // ACTIVE to SLEEP ; "000" - + // WTOP_PM_SLEEP : WTOP-Pd is in + // Sleep-state ; "100" - + // WTOP_PM_SLEEP_TO_ACTIVE : WTOP_Pd + // is in transition from SLEEP to + // ACTIVE ; "000" - + // WTOP_PM_WAIT_FOR_OPP : Wait for + // OPP to be stable ; + +#define GPRCM_WTOP_PM_PS_WTOP_PM_PS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WTOP_PD_RESETZ_OVERRIDE_REG register. +// +//****************************************************************************** +#define GPRCM_WTOP_PD_RESETZ_OVERRIDE_REG_WTOP_PD_RESETZ_OVERRIDE_CTRL \ + 0x00000100 // Override control for WTOP PD + // Resetz. When set to 1, + // WTOP_Resetz will be controlled by + // bit [0] + +#define GPRCM_WTOP_PD_RESETZ_OVERRIDE_REG_WTOP_PD_RESETZ_OVERRIDE \ + 0x00000001 // Override for WTOP PD Resetz. + // Applicable only when bit[8] is + // set to 1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WELP_PD_RESETZ_OVERRIDE_REG register. +// +//****************************************************************************** +#define GPRCM_WELP_PD_RESETZ_OVERRIDE_REG_WELP_PD_RESETZ_OVERRIDE_CTRL \ + 0x00000100 // Override control for WELP PD + // Resetz. When set to 1, + // WELP_Resetz will be controlled by + // bit [0] + +#define GPRCM_WELP_PD_RESETZ_OVERRIDE_REG_WELP_PD_RESETZ_OVERRIDE \ + 0x00000001 // Override for WELP PD Resetz. + // Applicable only when bit[8] is + // set to 1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WL_SDIO_PD_RESETZ_OVERRIDE_REG register. +// +//****************************************************************************** +#define GPRCM_WL_SDIO_PD_RESETZ_OVERRIDE_REG_WL_SDIO_PD_RESETZ_OVERRIDE_CTRL \ + 0x00000100 // Override control for WL_SDIO + // Resetz. When set to 1, + // WL_SDIO_Resetz will be controlled + // by bit [0] + +#define GPRCM_WL_SDIO_PD_RESETZ_OVERRIDE_REG_WL_SDIO_PD_RESETZ_OVERRIDE \ + 0x00000001 // Override for WL_SDIO Resetz. + // Applicable only when bit[8] is + // set to 1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_SSDIO_PD_RESETZ_OVERRIDE_REG register. +// +//****************************************************************************** +#define GPRCM_SSDIO_PD_RESETZ_OVERRIDE_REG_SSDIO_PD_RESETZ_OVERRIDE_CTRL \ + 0x00000100 // Override control for SSDIO + // Resetz. When set to 1, + // SSDIO_Resetz will be controlled + // by bit [0] + +#define GPRCM_SSDIO_PD_RESETZ_OVERRIDE_REG_SSDIO_PD_RESETZ_OVERRIDE \ + 0x00000001 // Override for SSDIO Resetz. + // Applicable only when bit[8] is + // set to 1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCSPI_N1_PD_RESETZ_OVERRIDE_REG register. +// +//****************************************************************************** +#define GPRCM_MCSPI_N1_PD_RESETZ_OVERRIDE_REG_MCSPI_N1_PD_RESETZ_OVERRIDE_CTRL \ + 0x00000100 // Override control for MCSPI_N1 + // Resetz. When set to 1, + // MCSPI_N1_Resetz will be + // controlled by bit [0] + +#define GPRCM_MCSPI_N1_PD_RESETZ_OVERRIDE_REG_MCSPI_N1_PD_RESETZ_OVERRIDE \ + 0x00000001 // Override for MCSPI_N1 Resetz. + // Applicable only when bit[8] is + // set to 1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_TESTCTRL_PD_RESETZ_OVERRIDE_REG register. +// +//****************************************************************************** +#define GPRCM_TESTCTRL_PD_RESETZ_OVERRIDE_REG_TESTCTRL_PD_RESETZ_OVERRIDE_CTRL \ + 0x00000100 // Override control for TESTCTRL-PD + // Resetz. When set to 1, + // TESTCTRL_Resetz will be + // controlled by bit [0] + +#define GPRCM_TESTCTRL_PD_RESETZ_OVERRIDE_REG_TESTCTRL_PD_RESETZ_OVERRIDE \ + 0x00000001 // Override for TESTCTRL Resetz. + // Applicable only when bit[8] is + // set to 1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCU_PD_RESETZ_OVERRIDE_REG register. +// +//****************************************************************************** +#define GPRCM_MCU_PD_RESETZ_OVERRIDE_REG_MCU_PD_RESETZ_OVERRIDE_CTRL \ + 0x00000100 // Override control for MCU-PD + // Resetz. When set to 1, MCU_Resetz + // will be controlled by bit [0] + +#define GPRCM_MCU_PD_RESETZ_OVERRIDE_REG_MCU_PD_RESETZ_OVERRIDE \ + 0x00000001 // Override for MCU Resetz. + // Applicable only when bit[8] is + // set to 1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG0 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG0_FUSEFARM_ROW_14_M \ + 0xFFFFFFFF // This is ROW_14 [31:0] of + // FUSEFARM. [0:0] : XTAL_IS_26MHZ + // [5:1] : TOP_CLKM_RTRIM[4:0] + // [10:6] : ANA_BGAP_MAG_TRIM[4:0] + // [16:11] : ANA_BGAP_TEMP_TRIM[5:0] + // [20:17] : ANA_BGAP_V2I_TRIM[3:0] + // [25:22] : PROCESS INDICATOR + // [26:26] : Reserved [31:27] : + // FUSEROM Version + +#define GPRCM_GPRCM_EFUSE_READ_REG0_FUSEFARM_ROW_14_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG1 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG1_FUSEFARM_ROW_15_LSW_M \ + 0x0000FFFF // This is ROW_15[15:0] of FUSEFARM + // 1. NWP Peripheral Present bits + // [15:8] NWP_GPT_N0_PP [15:15] + // NWP_GPT_N1_PP [14:14] NWP_WDOG_PP + // [13:13] NWP_UDMA_PP [12:12] + // NWP_UART_N0_PP [11:11] + // NWP_UART_N1_PP [10:10] + // NWP_SSDIO_PP [9:9] + // NWP_MCSPI_N1_PP [8:8] 2. Shared + // Peripheral Present bits [7:0] + // SHARED SPI PP [6:6] + // SHARED I2C PP [5:5] SHARED + // GPIO-A PP [4:4] SHARED GPIO-B PP + // [3:3] SHARED GPIO-C PP [2:2] + // SHARED GPIO-D PP [1:1] SHARED + // GPIO-E PP [0:0] + +#define GPRCM_GPRCM_EFUSE_READ_REG1_FUSEFARM_ROW_15_LSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG2 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG2_FUSEFARM_ROW_16_LSW_ROW_15_MSW_M \ + 0xFFFFFFFF // This is ROW_16[15:0] & + // ROW_15[31:16] of FUSEFARM. + // [31:21] - Reserved [20:16] - + // CHIP_ID [15:15] - SSBD SOP + // Control [14:14] - SSBD TAP + // Control [13:2] - APPS Peripheral + // Present bits : APPS_CAMERA_PP + // [13:13] APPS_MMCHS_PP [12:12] + // APPS_MCASP_PP [11:11] + // APPS_MCSPI_A1_PP [10:10] + // APPS_MCSPI_A2_PP [9:9] + // APPS_UDMA_PP [8:8] APPS_WDOG_PP + // [7:7] APPS_UART_A0_PP [6:6] + // APPS_UART_A1_PP [5:5] + // APPS_GPT_A0_PP [4:4] + // APPS_GPT_A1_PP [3:3] + // APPS_GPT_A2_PP [2:2] + // APPS_GPT_A3_PP [1:1] [0:0] - NWP + // Peripheral present bits + // NWP_ACSPI_PP [0:0] + +#define GPRCM_GPRCM_EFUSE_READ_REG2_FUSEFARM_ROW_16_LSW_ROW_15_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG3 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG3_FUSEFARM_ROW_17_LSW_ROW_16_MSW_M \ + 0xFFFFFFFF // This is ROW_17[15:0] & + // ROW_16[31:16] of FUSEFARM : + // [31:16] - TEST_TAP_KEY(15:0) + // [15:0] - Reserved + +#define GPRCM_GPRCM_EFUSE_READ_REG3_FUSEFARM_ROW_17_LSW_ROW_16_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WTOP_MEM_RET_CFG register. +// +//****************************************************************************** +#define GPRCM_WTOP_MEM_RET_CFG_WTOP_MEM_RET_CFG \ + 0x00000001 // 1 - Soft-compile memories in + // WTOP can be turned-off during + // WTOP-sleep mode ; 0 - + // Soft-compile memories in WTOP + // must be kept on during WTOP-sleep + // mode. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_COEX_CLK_SWALLOW_CFG0 register. +// +//****************************************************************************** +#define GPRCM_COEX_CLK_SWALLOW_CFG0_Q_FACTOR_M \ + 0x007FFFFF // TBD + +#define GPRCM_COEX_CLK_SWALLOW_CFG0_Q_FACTOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_COEX_CLK_SWALLOW_CFG1 register. +// +//****************************************************************************** +#define GPRCM_COEX_CLK_SWALLOW_CFG1_P_FACTOR_M \ + 0x000FFFFF // TBD + +#define GPRCM_COEX_CLK_SWALLOW_CFG1_P_FACTOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_COEX_CLK_SWALLOW_CFG2 register. +// +//****************************************************************************** +#define GPRCM_COEX_CLK_SWALLOW_CFG2_CONSECUTIVE_SWALLOW_M \ + 0x00000018 + +#define GPRCM_COEX_CLK_SWALLOW_CFG2_CONSECUTIVE_SWALLOW_S 3 +#define GPRCM_COEX_CLK_SWALLOW_CFG2_PRBS_GAIN \ + 0x00000004 + +#define GPRCM_COEX_CLK_SWALLOW_CFG2_PRBS_ENABLE \ + 0x00000002 + +#define GPRCM_COEX_CLK_SWALLOW_CFG2_SWALLOW_ENABLE \ + 0x00000001 // TBD + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_COEX_CLK_SWALLOW_ENABLE register. +// +//****************************************************************************** +#define GPRCM_COEX_CLK_SWALLOW_ENABLE_COEX_CLK_SWALLOW_ENABLE \ + 0x00000001 // 1 - Enable switching of sysclk + // to Coex-clk path ; 0 - Disable + // switching of sysclk to Coex-clk + // path. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_DCDC_CLK_GEN_CONFIG register. +// +//****************************************************************************** +#define GPRCM_DCDC_CLK_GEN_CONFIG_DCDC_CLK_ENABLE \ + 0x00000001 // 1 - Enable the clock for DCDC + // (PWM-mode) ; 0 - Disable the + // clock for DCDC (PWM-mode) + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG4 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG4_FUSEFARM_ROW_17_MSW_M \ + 0x0000FFFF // This corresponds to + // ROW_17[31:16] of the FUSEFARM : + // [15:0] : TEST_TAP_KEY(31:16) + +#define GPRCM_GPRCM_EFUSE_READ_REG4_FUSEFARM_ROW_17_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG5 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG5_FUSEFARM_ROW_18_M \ + 0xFFFFFFFF // Corresponds to ROW_18 of + // FUSEFARM. [29:0] - + // MEMSS_COLUMN_SEL_LSW ; [30:30] - + // WLAN GEM DISABLE ; [31:31] - + // SERIAL WIRE JTAG SELECT + +#define GPRCM_GPRCM_EFUSE_READ_REG5_FUSEFARM_ROW_18_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG6 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG6_FUSEFARM_ROW_19_LSW_M \ + 0x0000FFFF // Corresponds to ROW_19[15:0] of + // FUSEFARM. [15:0] : + // MEMSS_COLUMN_SEL_MSW + +#define GPRCM_GPRCM_EFUSE_READ_REG6_FUSEFARM_ROW_19_LSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG7 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG7_FUSEFARM_ROW_20_LSW_ROW_19_MSW_M \ + 0xFFFFFFFF // Corresponds to ROW_20[15:0] & + // ROW_19[31:16] of FUSEFARM. + // FLASH_REGION0 + +#define GPRCM_GPRCM_EFUSE_READ_REG7_FUSEFARM_ROW_20_LSW_ROW_19_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG8 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG8_FUSEFARM_ROW_21_LSW_ROW_20_MSW_M \ + 0xFFFFFFFF // Corresponds to ROW_21[15:0] & + // ROW_20[31:16] of FUSEFARM. + // FLASH_REGION1 + +#define GPRCM_GPRCM_EFUSE_READ_REG8_FUSEFARM_ROW_21_LSW_ROW_20_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG9 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG9_FUSEFARM_ROW_22_LSW_ROW_21_MSW_M \ + 0xFFFFFFFF // Corresponds to ROW_22[15:0] & + // ROW_21[31:16] of FUSEFARM. + // FLASH_REGION2 + +#define GPRCM_GPRCM_EFUSE_READ_REG9_FUSEFARM_ROW_22_LSW_ROW_21_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG10 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG10_FUSEFARM_ROW_23_LSW_ROW_22_MSW_M \ + 0xFFFFFFFF // Corresponds to ROW_23[15:0] & + // ROW_22[31:16] of FUSEFARM. + // FLASH_REGION3 + +#define GPRCM_GPRCM_EFUSE_READ_REG10_FUSEFARM_ROW_23_LSW_ROW_22_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_EFUSE_READ_REG11 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_EFUSE_READ_REG11_FUSEFARM_ROW_24_LSW_ROW_23_MSW_M \ + 0xFFFFFFFF // Corresponds to ROW_24[15:0] & + // ROW_23[31:16] of FUSEFARM. + // FLASH_DESCRIPTOR + +#define GPRCM_GPRCM_EFUSE_READ_REG11_FUSEFARM_ROW_24_LSW_ROW_23_MSW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_DIEID_READ_REG0 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_DIEID_READ_REG0_FUSEFARM_191_160_M \ + 0xFFFFFFFF // Corresponds to bits [191:160] of + // the FUSEFARM. This is ROW_5 of + // FUSEFARM [191:160] : [31:0] : + // DIE_ID0 [31:0] : DEVX [11:0] DEVY + // [23:12] DEVWAF [29:24] DEV_SPARE + // [31:30] + +#define GPRCM_GPRCM_DIEID_READ_REG0_FUSEFARM_191_160_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_DIEID_READ_REG1 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_DIEID_READ_REG1_FUSEFARM_223_192_M \ + 0xFFFFFFFF // Corresponds to bits [223:192] of + // the FUSEFARM. This is ROW_6 of + // FUSEFARM :- DEVLOT [23:0] DEVFAB + // [28:24] DEVFABBE [31:29] + +#define GPRCM_GPRCM_DIEID_READ_REG1_FUSEFARM_223_192_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_DIEID_READ_REG2 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_DIEID_READ_REG2_FUSEFARM_255_224_M \ + 0xFFFFFFFF // Corresponds to bits [255:224] of + // the FUSEFARM. This is ROW_7 of + // FUSEFARM:- DEVDESREV[4:0] + // Memrepair[5:5] MakeDefined[16:6] + // CHECKSUM[30:17] Reserved : + // [31:31] + +#define GPRCM_GPRCM_DIEID_READ_REG2_FUSEFARM_255_224_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_DIEID_READ_REG3 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_DIEID_READ_REG3_FUSEFARM_287_256_M \ + 0xFFFFFFFF // Corresponds to bits [287:256] of + // the FUSEFARM. This is ROW_8 of + // FUSEFARM :- DIEID0 - DEVREG + // [31:0] + +#define GPRCM_GPRCM_DIEID_READ_REG3_FUSEFARM_287_256_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_GPRCM_DIEID_READ_REG4 register. +// +//****************************************************************************** +#define GPRCM_GPRCM_DIEID_READ_REG4_FUSEFARM_319_288_M \ + 0xFFFFFFFF // Corresponds to bits [319:288] of + // the FUSEFARM. This is ROW_9 of + // FUSEFARM :- [7:0] - VBATMON ; + // [13:8] - BUFF_OFFSET ; [15:15] - + // DFT_GXG ; [14:14] - DFT_GLX ; + // [19:16] - PHY ROM Version ; + // [23:20] - MAC ROM Version ; + // [27:24] - NWP ROM Version ; + // [31:28] - APPS ROM Version + +#define GPRCM_GPRCM_DIEID_READ_REG4_FUSEFARM_319_288_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_APPS_SS_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_APPS_SS_OVERRIDES_reserved_M \ + 0xFFFFFC00 + +#define GPRCM_APPS_SS_OVERRIDES_reserved_S 10 +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_refclk_gating_override \ + 0x00000200 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_refclk_gating_override_ctrl \ + 0x00000100 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_pllclk_gating_override \ + 0x00000080 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_pllclk_gating_override_ctrl \ + 0x00000040 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_por_rstn_override \ + 0x00000020 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysrstn_override \ + 0x00000010 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysclk_gating_override \ + 0x00000008 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_por_rstn_override_ctrl \ + 0x00000004 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysrstn_override_ctrl \ + 0x00000002 + +#define GPRCM_APPS_SS_OVERRIDES_mem_apps_sysclk_gating_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_NWP_SS_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_NWP_SS_OVERRIDES_reserved_M \ + 0xFFFFFC00 + +#define GPRCM_NWP_SS_OVERRIDES_reserved_S 10 +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_refclk_gating_override \ + 0x00000200 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_refclk_gating_override_ctrl \ + 0x00000100 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_pllclk_gating_override \ + 0x00000080 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_pllclk_gating_override_ctrl \ + 0x00000040 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_por_rstn_override \ + 0x00000020 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysrstn_override \ + 0x00000010 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysclk_gating_override \ + 0x00000008 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_por_rstn_override_ctrl \ + 0x00000004 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysrstn_override_ctrl \ + 0x00000002 + +#define GPRCM_NWP_SS_OVERRIDES_mem_nwp_sysclk_gating_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_SHARED_SS_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_SHARED_SS_OVERRIDES_reserved_M \ + 0xFFFFFF00 + +#define GPRCM_SHARED_SS_OVERRIDES_reserved_S 8 +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_pllclk_gating_override_ctrl \ + 0x00000080 + +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_pllclk_gating_override \ + 0x00000040 + +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_refclk_gating_override_ctrl \ + 0x00000020 + +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_refclk_gating_override \ + 0x00000010 + +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_rstn_override \ + 0x00000008 + +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_sysclk_gating_override \ + 0x00000004 + +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_rstn_override_ctrl \ + 0x00000002 + +#define GPRCM_SHARED_SS_OVERRIDES_mem_shared_sysclk_gating_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_IDMEM_CORE_RST_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_reserved_M \ + 0xFFFFFF00 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_reserved_S 8 +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_sysrstn_override \ + 0x00000080 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_fmc_rstn_override \ + 0x00000040 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_SPARE_RW1 \ + 0x00000020 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_piosc_gating_override \ + 0x00000010 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_sysrstn_override_ctrl \ + 0x00000008 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_fmc_rstn_override_ctrl \ + 0x00000004 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_SPARE_RW0 \ + 0x00000002 + +#define GPRCM_IDMEM_CORE_RST_OVERRIDES_mem_idmem_core_piosc_gating_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_TOP_DIE_FSM_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_TOP_DIE_FSM_OVERRIDES_reserved_M \ + 0xFFFFF000 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_reserved_S 12 +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_pgoodin_override_ctrl \ + 0x00000800 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_pgoodin_override \ + 0x00000400 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_hclk_gating_override \ + 0x00000200 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_piosc_gating_override \ + 0x00000100 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_rstn_override \ + 0x00000080 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_ponin_override \ + 0x00000040 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_flash_ready_override \ + 0x00000020 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_hclk_gating_override_ctrl \ + 0x00000010 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_piosc_gating_override_ctrl \ + 0x00000008 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_rstn_override_ctrl \ + 0x00000004 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_d2d_pwr_switch_ponin_override_ctrl \ + 0x00000002 + +#define GPRCM_TOP_DIE_FSM_OVERRIDES_mem_flash_ready_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCU_PSCON_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_MCU_PSCON_OVERRIDES_reserved_M \ + 0xFFF00000 + +#define GPRCM_MCU_PSCON_OVERRIDES_reserved_S 20 +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_sleep_override_ctrl \ + 0x00080000 + +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_update_override_ctrl \ + 0x00040000 + +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_off_override_ctrl \ + 0x00020000 + +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_retain_override_ctrl \ + 0x00010000 + +#define GPRCM_MCU_PSCON_OVERRIDES_NU1_M \ + 0x0000FC00 + +#define GPRCM_MCU_PSCON_OVERRIDES_NU1_S 10 +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_sleep_override \ + 0x00000200 + +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_update_override \ + 0x00000100 + +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_off_override_M \ + 0x000000F0 + +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_off_override_S 4 +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_retain_override_M \ + 0x0000000F + +#define GPRCM_MCU_PSCON_OVERRIDES_mem_mcu_pscon_mem_retain_override_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WTOP_PSCON_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_WTOP_PSCON_OVERRIDES_reserved_M \ + 0xFFC00000 + +#define GPRCM_WTOP_PSCON_OVERRIDES_reserved_S 22 +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_sleep_override_ctrl \ + 0x00200000 + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_update_override_ctrl \ + 0x00100000 + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_off_override_ctrl \ + 0x00080000 + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_retain_override_ctrl \ + 0x00040000 + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_sleep_override \ + 0x00020000 + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_update_override \ + 0x00010000 + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_off_override_M \ + 0x0000FF00 + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_off_override_S 8 +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_retain_override_M \ + 0x000000FF + +#define GPRCM_WTOP_PSCON_OVERRIDES_mem_wtop_pscon_mem_retain_override_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WELP_PSCON_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_WELP_PSCON_OVERRIDES_reserved_M \ + 0xFFFFFFFC + +#define GPRCM_WELP_PSCON_OVERRIDES_reserved_S 2 +#define GPRCM_WELP_PSCON_OVERRIDES_mem_welp_pscon_sleep_override_ctrl \ + 0x00000002 + +#define GPRCM_WELP_PSCON_OVERRIDES_mem_welp_pscon_sleep_override \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_WL_SDIO_PSCON_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_WL_SDIO_PSCON_OVERRIDES_reserved_M \ + 0xFFFFFFFC + +#define GPRCM_WL_SDIO_PSCON_OVERRIDES_reserved_S 2 +#define GPRCM_WL_SDIO_PSCON_OVERRIDES_mem_wl_sdio_pscon_sleep_override_ctrl \ + 0x00000002 + +#define GPRCM_WL_SDIO_PSCON_OVERRIDES_mem_wl_sdio_pscon_sleep_override \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_MCSPI_PSCON_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_MCSPI_PSCON_OVERRIDES_reserved_M \ + 0xFFFFFF00 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_reserved_S 8 +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_retain_override_ctrl \ + 0x00000080 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_off_override_ctrl \ + 0x00000040 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_retain_override \ + 0x00000020 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_off_override \ + 0x00000010 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_update_override_ctrl \ + 0x00000008 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_mem_update_override \ + 0x00000004 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_sleep_override_ctrl \ + 0x00000002 + +#define GPRCM_MCSPI_PSCON_OVERRIDES_mem_mcspi_pscon_sleep_override \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// GPRCM_O_SSDIO_PSCON_OVERRIDES register. +// +//****************************************************************************** +#define GPRCM_SSDIO_PSCON_OVERRIDES_reserved_M \ + 0xFFFFFFFC + +#define GPRCM_SSDIO_PSCON_OVERRIDES_reserved_S 2 +#define GPRCM_SSDIO_PSCON_OVERRIDES_mem_ssdio_pscon_sleep_override_ctrl \ + 0x00000002 + +#define GPRCM_SSDIO_PSCON_OVERRIDES_mem_ssdio_pscon_sleep_override \ + 0x00000001 + + + + +#endif // __HW_GPRCM_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib1p2.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib1p2.h new file mode 100644 index 00000000..95e25ff7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib1p2.h @@ -0,0 +1,1750 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_HIB1P2_H__ +#define __HW_HIB1P2_H__ + +//***************************************************************************** +// +// The following are defines for the HIB1P2 register offsets. +// +//***************************************************************************** +#define HIB1P2_O_SRAM_SKA_LDO_PARAMETERS0 \ + 0x00000000 + +#define HIB1P2_O_SRAM_SKA_LDO_PARAMETERS1 \ + 0x00000004 + +#define HIB1P2_O_DIG_DCDC_PARAMETERS0 \ + 0x00000008 + +#define HIB1P2_O_DIG_DCDC_PARAMETERS1 \ + 0x0000000C + +#define HIB1P2_O_DIG_DCDC_PARAMETERS2 \ + 0x00000010 + +#define HIB1P2_O_DIG_DCDC_PARAMETERS3 \ + 0x00000014 + +#define HIB1P2_O_DIG_DCDC_PARAMETERS4 \ + 0x00000018 + +#define HIB1P2_O_DIG_DCDC_PARAMETERS5 \ + 0x0000001C + +#define HIB1P2_O_DIG_DCDC_PARAMETERS6 \ + 0x00000020 + +#define HIB1P2_O_ANA_DCDC_PARAMETERS0 \ + 0x00000024 + +#define HIB1P2_O_ANA_DCDC_PARAMETERS1 \ + 0x00000028 + +#define HIB1P2_O_ANA_DCDC_PARAMETERS16 \ + 0x00000064 + +#define HIB1P2_O_ANA_DCDC_PARAMETERS17 \ + 0x00000068 + +#define HIB1P2_O_ANA_DCDC_PARAMETERS18 \ + 0x0000006C + +#define HIB1P2_O_ANA_DCDC_PARAMETERS19 \ + 0x00000070 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS0 \ + 0x00000074 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS1 \ + 0x00000078 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS2 \ + 0x0000007C + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS3 \ + 0x00000080 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS4 \ + 0x00000084 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS5 \ + 0x00000088 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS6 \ + 0x0000008C + +#define HIB1P2_O_PMBIST_PARAMETERS0 \ + 0x00000094 + +#define HIB1P2_O_PMBIST_PARAMETERS1 \ + 0x00000098 + +#define HIB1P2_O_PMBIST_PARAMETERS2 \ + 0x0000009C + +#define HIB1P2_O_PMBIST_PARAMETERS3 \ + 0x000000A0 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS8 \ + 0x000000A4 + +#define HIB1P2_O_ANA_DCDC_PARAMETERS_OVERRIDE \ + 0x000000A8 + +#define HIB1P2_O_FLASH_DCDC_PARAMETERS_OVERRIDE \ + 0x000000AC + +#define HIB1P2_O_DIG_DCDC_VTRIM_CFG \ + 0x000000B0 + +#define HIB1P2_O_DIG_DCDC_FSM_PARAMETERS \ + 0x000000B4 + +#define HIB1P2_O_ANA_DCDC_FSM_PARAMETERS \ + 0x000000B8 + +#define HIB1P2_O_SRAM_SKA_LDO_FSM_PARAMETERS \ + 0x000000BC + +#define HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG \ + 0x000000C0 + +#define HIB1P2_O_CM_OSC_16M_CONFIG \ + 0x000000C4 + +#define HIB1P2_O_SOP_SENSE_VALUE \ + 0x000000C8 + +#define HIB1P2_O_HIB_RTC_TIMER_LSW_1P2 \ + 0x000000CC + +#define HIB1P2_O_HIB_RTC_TIMER_MSW_1P2 \ + 0x000000D0 + +#define HIB1P2_O_HIB1P2_BGAP_TRIM_OVERRIDES \ + 0x000000D4 + +#define HIB1P2_O_HIB1P2_EFUSE_READ_REG0 \ + 0x000000D8 + +#define HIB1P2_O_HIB1P2_EFUSE_READ_REG1 \ + 0x000000DC + +#define HIB1P2_O_HIB1P2_POR_TEST_CTRL \ + 0x000000E0 + +#define HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG0 \ + 0x000000E4 + +#define HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG1 \ + 0x000000E8 + +#define HIB1P2_O_HIB_TIMER_SYNC_CFG2 \ + 0x000000EC + +#define HIB1P2_O_HIB_TIMER_SYNC_TSF_ADJ_VAL \ + 0x000000F0 + +#define HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW \ + 0x000000F4 + +#define HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW \ + 0x000000F8 + +#define HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW \ + 0x000000FC + +#define HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW \ + 0x00000100 + +#define HIB1P2_O_HIB_TIMER_SYNC_WAKE_OFFSET_ERR \ + 0x00000104 + +#define HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW \ + 0x00000108 + +#define HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW \ + 0x0000010C + +#define HIB1P2_O_CM_SPARE 0x00000110 +#define HIB1P2_O_PORPOL_SPARE 0x00000114 +#define HIB1P2_O_MEM_DIG_DCDC_CLK_CONFIG \ + 0x00000118 + +#define HIB1P2_O_MEM_ANA_DCDC_CLK_CONFIG \ + 0x0000011C + +#define HIB1P2_O_MEM_FLASH_DCDC_CLK_CONFIG \ + 0x00000120 + +#define HIB1P2_O_MEM_PA_DCDC_CLK_CONFIG \ + 0x00000124 + +#define HIB1P2_O_MEM_SLDO_VNWA_OVERRIDE \ + 0x00000128 + +#define HIB1P2_O_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE \ + 0x0000012C + +#define HIB1P2_O_MEM_HIB_FSM_DEBUG \ + 0x00000130 + +#define HIB1P2_O_MEM_SLDO_VNWA_SW_CTRL \ + 0x00000134 + +#define HIB1P2_O_MEM_SLDO_WEAK_PROCESS \ + 0x00000138 + +#define HIB1P2_O_MEM_PA_DCDC_OV_UV_STATUS \ + 0x0000013C + +#define HIB1P2_O_MEM_CM_TEST_MODE \ + 0x00000140 + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_SRAM_SKA_LDO_PARAMETERS0 register. +// +//****************************************************************************** +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_sc_itrim_lowv_M \ + 0xC0000000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_sc_itrim_lowv_S 30 +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_iq_trim_lowv_M \ + 0x30000000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_iq_trim_lowv_S 28 +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_sc_prot_lowv \ + 0x08000000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_lowv_override \ + 0x04000000 // FSM Override value for SLDO_EN : + // Applicable only when bit [4] of + // this register is set to 1. + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_low_pwr_lowv \ + 0x02000000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_int_cap_sel_lowv \ + 0x01000000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_vtrim_lowv_M \ + 0x00FC0000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_vtrim_lowv_S 18 +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_spare_lowv_M \ + 0x0003FF00 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_spare_lowv_S 8 +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_lowv_override \ + 0x00000080 // FSM Override value for + // SKA_LDO_EN : Applicable only when + // bit [3] of this register is set + // to 1. + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_cap_ref_lowv \ + 0x00000040 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_resdiv_ref_lowv \ + 0x00000020 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_sldo_en_lowv_fsm_override_ctrl \ + 0x00000010 // When 1, bit[26] of this register + // will be used as SLDO_EN + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_mem_skaldo_en_lowv_fsm_override_ctrl \ + 0x00000008 // When 1, bit[26] of this register + // will be used as SKA_LDO_EN + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_NA1_M \ + 0x00000007 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS0_NA1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_SRAM_SKA_LDO_PARAMETERS1 register. +// +//****************************************************************************** +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_ctrl_lowv_M \ + 0xFFC00000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_ctrl_lowv_S 22 +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_vtrim_lowv_M \ + 0x003F0000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_vtrim_lowv_S 16 +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_sldo_en_tload_lowv \ + 0x00008000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_en_tload_lowv \ + 0x00004000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_cap_sw_en_lowv \ + 0x00002000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_en_hib_lowv \ + 0x00001000 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_mem_skaldo_en_vref_buf_lowv \ + 0x00000800 + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_NA2_M \ + 0x000007FF + +#define HIB1P2_SRAM_SKA_LDO_PARAMETERS1_NA2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_PARAMETERS0 register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_lowv_override \ + 0x80000000 // Override value for DCDC_DIG_EN : + // Applicable only when bit [31] of + // DIG_DCDC_PARAMETERS1 [0x000C] is + // set to 1. Else from FSM + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_delayed_en_lowv \ + 0x40000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_subreg_1p8v_lowv_override \ + 0x20000000 // Override value for + // DCDC_DIG_EN_SUBREG_1P8V : + // Applicable only when bit [30] of + // DIG_DCDC_PARAMETERS1 [0x000C] is + // set to 1. Else from FSM + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_subreg_1p2v_lowv_override \ + 0x10000000 // Override value for + // DCDC_DIG_EN_SUBREG_1P2V : + // Applicable only when bit [29] of + // DIG_DCDC_PARAMETERS1 [0x000C] is + // set to 1. Else from FSM + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_slp_mode_lowv_override \ + 0x08000000 // Override value for + // DCDC_DIG_SLP_EN : Applicable only + // when bit [28] of + // DIG_DCDC_PARAMETERS1 [0x000C] is + // set to 1. Else from FSM + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_ldo_mode_lowv \ + 0x04000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_nfet_rds_mode_lowv \ + 0x02000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_pfet_rds_mode_lowv \ + 0x01000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_ext_smps_override_mode_lowv \ + 0x00800000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_clk_in_lowv_enable \ + 0x00400000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_vtrim_lowv_override_M \ + 0x003F0000 // Override value for + // DCDC_DIG_VTRIM : Applicable only + // when bit [27] of + // DIG_DCDC_PARAMETERS1 [0x000C] is + // set to 1. + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_vtrim_lowv_override_S 16 +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_pfm_ripple_trim_lowv_M \ + 0x0000C000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_pfm_ripple_trim_lowv_S 14 +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_iq_ctrl_lowv_M \ + 0x00003000 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_iq_ctrl_lowv_S 12 +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_en_cl_non_ov_lowv \ + 0x00000800 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_non_ov_ctrl_lowv_M \ + 0x00000780 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_non_ov_ctrl_lowv_S 7 +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_slp_drv_dly_sel_lowv_M \ + 0x00000078 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_mem_dcdc_dig_slp_drv_dly_sel_lowv_S 3 +#define HIB1P2_DIG_DCDC_PARAMETERS0_NA3_M \ + 0x00000007 + +#define HIB1P2_DIG_DCDC_PARAMETERS0_NA3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_PARAMETERS1 register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_lowv_fsm_override_ctrl \ + 0x80000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_subreg_1p8v_fsm_override_ctrl \ + 0x40000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_subreg_1p2v_fsm_override_ctrl \ + 0x20000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_en_slp_mode_lowv_fsm_override_ctrl \ + 0x10000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_vtrim_fsm_override_ctrl \ + 0x08000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_cot_mode_en_lowv_fsm_override_ctrl \ + 0x04000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS1_mem_dcdc_dig_ilim_trim_lowv_efc_override_ctrl \ + 0x02000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS1_NA4_M \ + 0x01FFFFFF + +#define HIB1P2_DIG_DCDC_PARAMETERS1_NA4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_PARAMETERS2 register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pfet_sel_lowv_M \ + 0xF0000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pfet_sel_lowv_S 28 +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_nfet_sel_lowv_M \ + 0x0F000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_nfet_sel_lowv_S 24 +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_stagger_ctrl_lowv_M \ + 0x00C00000 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_stagger_ctrl_lowv_S 22 +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_stagger_ctrl_lowv_M \ + 0x00300000 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_stagger_ctrl_lowv_S 20 +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_str_sel_lowv_M \ + 0x000F0000 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_pdrv_str_sel_lowv_S 16 +#define HIB1P2_DIG_DCDC_PARAMETERS2_NA5 \ + 0x00008000 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_str_sel_lowv_M \ + 0x00007800 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ndrv_str_sel_lowv_S 11 +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_en_shootthru_ctrl_lowv \ + 0x00000400 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ton_trim_lowv_M \ + 0x000003FC + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_ton_trim_lowv_S 2 +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_swcap_res_hf_clk_lowv \ + 0x00000002 + +#define HIB1P2_DIG_DCDC_PARAMETERS2_mem_dcdc_dig_cot_mode_en_lowv_override \ + 0x00000001 // Override value for + // DCDC_DIG_COT_EN : Applicable only + // when bit[26] of + // DIG_DCDC_PARAMETERS1 [0x000C] is + // set to 1. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_PARAMETERS3 register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_PARAMETERS3_NA6 \ + 0x80000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_cot_ctrl_lowv_M \ + 0x7F800000 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_cot_ctrl_lowv_S 23 +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ilim_lowv \ + 0x00400000 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ilim_hib_lowv \ + 0x00200000 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_trim_lowv_override_M \ + 0x001FE000 // Override value for + // DCDC_DIG_ILIM_TRIM : Applicable + // only when bit [25] of + // DIG_DCDC_PARAMETERS1 [0x000C] is + // set to 1 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_trim_lowv_override_S 13 +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_mask_dly_sel_lowv_M \ + 0x00001800 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ilim_mask_dly_sel_lowv_S 11 +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ncomp_lowv \ + 0x00000400 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ncomp_hib_lowv \ + 0x00000200 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_trim_lowv_M \ + 0x000001F0 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_trim_lowv_S 4 +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_mask_dly_sel_lowv_M \ + 0x0000000C + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_ncomp_mask_dly_sel_lowv_S 2 +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_uv_prot_lowv \ + 0x00000002 + +#define HIB1P2_DIG_DCDC_PARAMETERS3_mem_dcdc_dig_en_ov_prot_lowv \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_PARAMETERS4 register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_PARAMETERS4_dcdc_dig_uv_prot_out_lowv \ + 0x80000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS4_dcdc_dig_ov_prot_out_lowv \ + 0x40000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS4_mem_dcdc_dig_en_tmux_lowv \ + 0x20000000 + +#define HIB1P2_DIG_DCDC_PARAMETERS4_NA7_M \ + 0x1FFFFFFF + +#define HIB1P2_DIG_DCDC_PARAMETERS4_NA7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_PARAMETERS5 register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_PARAMETERS5_mem_dcdc_dig_tmux_ctrl_lowv_M \ + 0xFFFFFFFF + +#define HIB1P2_DIG_DCDC_PARAMETERS5_mem_dcdc_dig_tmux_ctrl_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_PARAMETERS6 register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_PARAMETERS6_mem_dcdc_dig_spare_lowv_M \ + 0xFFFFFFFF + +#define HIB1P2_DIG_DCDC_PARAMETERS6_mem_dcdc_dig_spare_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_PARAMETERS0 register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_lowv_override \ + 0x80000000 // Override for ANA DCDC EN + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_delayed_en_lowv \ + 0x40000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_subreg_1p8v_lowv \ + 0x20000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_subreg_1p2v_lowv \ + 0x10000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_pwm_mode_lowv_override \ + 0x08000000 // Override for ANA DCDC PWM + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_slp_mode_lowv_override \ + 0x04000000 // Override for ANA DCDC SLP + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_ldo_mode_lowv \ + 0x02000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_pfet_rds_mode_lowv \ + 0x01000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_nfet_rds_mode_lowv \ + 0x00800000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_ext_smps_override_mode_lowv \ + 0x00400000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_clk_in_lowv_enable \ + 0x00200000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_vtrim_lowv_M \ + 0x001E0000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_vtrim_lowv_S 17 +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfm_ripple_trim_lowv_M \ + 0x00018000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfm_ripple_trim_lowv_S 15 +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_iq_ctrl_lowv_M \ + 0x00006000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_iq_ctrl_lowv_S 13 +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_en_cl_non_ov_lowv \ + 0x00001000 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_non_ov_ctrl_lowv_M \ + 0x00000F00 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_non_ov_ctrl_lowv_S 8 +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_slp_drv_dly_sel_lowv_M \ + 0x000000F0 + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_slp_drv_dly_sel_lowv_S 4 +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfet_sel_lowv_M \ + 0x0000000F + +#define HIB1P2_ANA_DCDC_PARAMETERS0_mem_dcdc_ana_pfet_sel_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_PARAMETERS1 register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_nfet_sel_lowv_M \ + 0xF0000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_nfet_sel_lowv_S 28 +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_stagger_ctrl_lowv_M \ + 0x0C000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_stagger_ctrl_lowv_S 26 +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_stagger_ctrl_lowv_M \ + 0x03000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_stagger_ctrl_lowv_S 24 +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_str_sel_lowv_M \ + 0x00F00000 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_pdrv_str_sel_lowv_S 20 +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_str_sel_lowv_M \ + 0x000F0000 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ndrv_str_sel_lowv_S 16 +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_rtrim_lowv \ + 0x00008000 // (Earlier SHOOTTHRU CTRL) + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_apwm_en_lowv \ + 0x00004000 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ramp_hgt_lowv_M \ + 0x00003E00 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_ramp_hgt_lowv_S 9 +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_anti_glitch_lowv \ + 0x00000100 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_hi_clamp_lowv \ + 0x00000080 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_hi_clamp_trim_lowv_M \ + 0x00000060 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_hi_clamp_trim_lowv_S 5 +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_en_lo_clamp_lowv \ + 0x00000010 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_lo_clamp_trim_lowv_M \ + 0x0000000C + +#define HIB1P2_ANA_DCDC_PARAMETERS1_mem_dcdc_ana_lo_clamp_trim_lowv_S 2 +#define HIB1P2_ANA_DCDC_PARAMETERS1_NA8_M \ + 0x00000003 + +#define HIB1P2_ANA_DCDC_PARAMETERS1_NA8_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_PARAMETERS16 register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ilim_lowv \ + 0x00200000 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ilim_hib_lowv \ + 0x00100000 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_trim_lowv_override_M \ + 0x000FF000 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_trim_lowv_override_S 12 +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_mask_dly_sel_lowv_M \ + 0x00000C00 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ilim_mask_dly_sel_lowv_S 10 +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ncomp_lowv \ + 0x00000200 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ncomp_hib_lowv \ + 0x00000100 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_trim_lowv_M \ + 0x000000F8 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_trim_lowv_S 3 +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_mask_dly_sel_lowv_M \ + 0x00000006 + +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_ncomp_mask_dly_sel_lowv_S 1 +#define HIB1P2_ANA_DCDC_PARAMETERS16_mem_dcdc_ana_en_ov_prot_lowv \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_PARAMETERS17 register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_PARAMETERS17_dcdc_ana_ov_prot_out_lowv \ + 0x80000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS17_mem_dcdc_ana_en_tmux_lowv \ + 0x40000000 + +#define HIB1P2_ANA_DCDC_PARAMETERS17_NA17_M \ + 0x3FFFFFFF + +#define HIB1P2_ANA_DCDC_PARAMETERS17_NA17_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_PARAMETERS18 register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_PARAMETERS18_mem_dcdc_ana_tmux_ctrl_lowv_M \ + 0xFFFFFFFF + +#define HIB1P2_ANA_DCDC_PARAMETERS18_mem_dcdc_ana_tmux_ctrl_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_PARAMETERS19 register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_PARAMETERS19_mem_dcdc_ana_spare_lowv_M \ + 0xFFFFFFFF + +#define HIB1P2_ANA_DCDC_PARAMETERS19_mem_dcdc_ana_spare_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS0 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_lowv \ + 0x80000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_delayed_en_lowv \ + 0x40000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_clk_in_lowv_enable \ + 0x20000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_iq_ctrl_lowv_M \ + 0x18000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_iq_ctrl_lowv_S 27 +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_buck_mode_lowv \ + 0x04000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_boost_mode_lowv \ + 0x02000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_buck_boost_mode_lowv \ + 0x01000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_bb_alt_cycles_lowv \ + 0x00800000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_cl_non_ov_lowv \ + 0x00400000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_non_ov_ctrl_lowv_M \ + 0x003C0000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_non_ov_ctrl_lowv_S 18 +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_drv_lowv \ + 0x00020000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_pwm_mode_lowv \ + 0x00010000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_pfm_comp_lowv \ + 0x00008000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_slp_mode_lowv \ + 0x00004000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_n1fet_rds_mode_lowv \ + 0x00002000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_n2fet_rds_mode_lowv \ + 0x00001000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_p1fet_rds_mode_lowv \ + 0x00000800 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_en_p2fet_rds_mode_lowv \ + 0x00000400 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_ext_smps_mode_override_lowv \ + 0x00000200 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_p1fet_sel_lowv_M \ + 0x000001E0 + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_p1fet_sel_lowv_S 5 +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_n1fet_sel_lowv_M \ + 0x0000001E + +#define HIB1P2_FLASH_DCDC_PARAMETERS0_mem_dcdc_flash_n1fet_sel_lowv_S 1 +#define HIB1P2_FLASH_DCDC_PARAMETERS0_NA18 \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS1 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_sel_lowv_M \ + 0xF0000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_sel_lowv_S 28 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_sel_lowv_M \ + 0x0F000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_sel_lowv_S 24 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1drv_str_sel_lowv_M \ + 0x00F00000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1drv_str_sel_lowv_S 20 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1drv_str_sel_lowv_M \ + 0x000F0000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1drv_str_sel_lowv_S 16 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2drv_str_sel_lowv_M \ + 0x0000F000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2drv_str_sel_lowv_S 12 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2drv_str_sel_lowv_M \ + 0x00000F00 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2drv_str_sel_lowv_S 8 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1fet_non_ov_lowv_M \ + 0x000000C0 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p1fet_non_ov_lowv_S 6 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1fet_non_ov_lowv_M \ + 0x00000030 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n1fet_non_ov_lowv_S 4 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_non_ov_lowv_M \ + 0x0000000C + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_p2fet_non_ov_lowv_S 2 +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_non_ov_lowv_M \ + 0x00000003 + +#define HIB1P2_FLASH_DCDC_PARAMETERS1_mem_dcdc_flash_n2fet_non_ov_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS2 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p1fet_stagger_lowv_M \ + 0xC0000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p1fet_stagger_lowv_S 30 +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n1fet_stagger_lowv_M \ + 0x30000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n1fet_stagger_lowv_S 28 +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p2fet_stagger_lowv_M \ + 0x0C000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_p2fet_stagger_lowv_S 26 +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n2fet_stagger_lowv_M \ + 0x03000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_n2fet_stagger_lowv_S 24 +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_shoot_thru_ctrl_lowv \ + 0x00800000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ncomp_lowv \ + 0x00400000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ncomp_hib_lowv \ + 0x00200000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_trim_lowv_M \ + 0x001F0000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_trim_lowv_S 16 +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_mask_dly_trim_lowv_M \ + 0x0000F000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ncomp_mask_dly_trim_lowv_S 12 +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ilim_lowv \ + 0x00000800 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_en_ilim_hib_lowv \ + 0x00000400 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_trim_lowv_override_M \ + 0x000003FC + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_trim_lowv_override_S 2 +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_mask_dly_sel_lowv_M \ + 0x00000003 + +#define HIB1P2_FLASH_DCDC_PARAMETERS2_mem_dcdc_flash_ilim_mask_dly_sel_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS3 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_anti_glitch_lowv \ + 0x80000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_hi_clamp_lowv \ + 0x40000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_lo_clamp_lowv \ + 0x20000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_ramp_hgt_lowv_M \ + 0x1F000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_ramp_hgt_lowv_S 24 +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclamph_trim_lowv_M \ + 0x00E00000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclamph_trim_lowv_S 21 +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclampl_trim_lowv_M \ + 0x001C0000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vclampl_trim_lowv_S 18 +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vtrim_lowv_M \ + 0x0003C000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_vtrim_lowv_S 14 +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_pfm_ripple_trim_lowv_M \ + 0x00003C00 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_pfm_ripple_trim_lowv_S 10 +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_slp_drv_dly_sel_lowv_M \ + 0x00000300 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_slp_drv_dly_sel_lowv_S 8 +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_ov_prot_lowv \ + 0x00000080 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_uv_prot_lowv \ + 0x00000040 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_mem_dcdc_flash_en_tmux_lowv \ + 0x00000020 + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_NA19_M \ + 0x0000001F + +#define HIB1P2_FLASH_DCDC_PARAMETERS3_NA19_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS4 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS4_mem_dcdc_flash_tmux_ctrl_lowv_M \ + 0xFFFFFFFF + +#define HIB1P2_FLASH_DCDC_PARAMETERS4_mem_dcdc_flash_tmux_ctrl_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS5 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS5_mem_dcdc_flash_spare_lowv_M \ + 0xFFFFFFFF + +#define HIB1P2_FLASH_DCDC_PARAMETERS5_mem_dcdc_flash_spare_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS6 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS6_dcdc_flash_ov_prot_out_lowv \ + 0x80000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS6_dcdc_flash_uv_prot_out_lowv \ + 0x40000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS6_NA20_M \ + 0x3FFFFFFF + +#define HIB1P2_FLASH_DCDC_PARAMETERS6_NA20_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_PMBIST_PARAMETERS0 register. +// +//****************************************************************************** +#define HIB1P2_PMBIST_PARAMETERS0_mem_pm_bist_en_lowv \ + 0x80000000 + +#define HIB1P2_PMBIST_PARAMETERS0_mem_pm_bist_ctrl_lowv_M \ + 0x7FFFF800 + +#define HIB1P2_PMBIST_PARAMETERS0_mem_pm_bist_ctrl_lowv_S 11 +#define HIB1P2_PMBIST_PARAMETERS0_NA21_M \ + 0x000007FF + +#define HIB1P2_PMBIST_PARAMETERS0_NA21_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_PMBIST_PARAMETERS1 register. +// +//****************************************************************************** +#define HIB1P2_PMBIST_PARAMETERS1_mem_pm_bist_spare_lowv_M \ + 0xFFFF0000 + +#define HIB1P2_PMBIST_PARAMETERS1_mem_pm_bist_spare_lowv_S 16 +#define HIB1P2_PMBIST_PARAMETERS1_mem_pmtest_en_lowv \ + 0x00008000 + +#define HIB1P2_PMBIST_PARAMETERS1_NA22_M \ + 0x00007FFF + +#define HIB1P2_PMBIST_PARAMETERS1_NA22_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_PMBIST_PARAMETERS2 register. +// +//****************************************************************************** +#define HIB1P2_PMBIST_PARAMETERS2_mem_pmtest_tmux_ctrl_lowv_M \ + 0xFFFFFFFF + +#define HIB1P2_PMBIST_PARAMETERS2_mem_pmtest_tmux_ctrl_lowv_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_PMBIST_PARAMETERS3 register. +// +//****************************************************************************** +#define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_spare_lowv_M \ + 0xFFFF0000 + +#define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_spare_lowv_S 16 +#define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_load_trim_lowv_M \ + 0x0000E000 + +#define HIB1P2_PMBIST_PARAMETERS3_mem_pmtest_load_trim_lowv_S 13 +#define HIB1P2_PMBIST_PARAMETERS3_mem_rnwell_calib_en_lowv \ + 0x00001000 + +#define HIB1P2_PMBIST_PARAMETERS3_NA23_M \ + 0x00000FFF + +#define HIB1P2_PMBIST_PARAMETERS3_NA23_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS8 register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_en_flash_sup_comp_lowv \ + 0x80000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_high_sup_trim_lowv_M \ + 0x7C000000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_high_sup_trim_lowv_S 26 +#define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_low_sup_trim_lowv_M \ + 0x03E00000 + +#define HIB1P2_FLASH_DCDC_PARAMETERS8_mem_flash_low_sup_trim_lowv_S 21 +#define HIB1P2_FLASH_DCDC_PARAMETERS8_NA24_M \ + 0x001FFFFF + +#define HIB1P2_FLASH_DCDC_PARAMETERS8_NA24_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_PARAMETERS_OVERRIDE register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_reserved_M \ + 0xFFFFFFC0 + +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_reserved_S 6 +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_subreg_1p2v_lowv_override_ctrl \ + 0x00000020 + +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_subreg_1p8v_lowv_override_ctrl \ + 0x00000010 + +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_ilim_trim_lowv_efc_override_ctrl \ + 0x00000008 + +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_slp_mode_lowv_fsm_override_ctrl \ + 0x00000004 + +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_pwm_mode_lowv_fsm_override_ctrl \ + 0x00000002 + +#define HIB1P2_ANA_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_ana_en_lowv_fsm_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_FLASH_DCDC_PARAMETERS_OVERRIDE register. +// +//****************************************************************************** +#define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_reserved_M \ + 0xFFFFFFFC + +#define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_reserved_S 2 +#define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_flash_en_lowv_override_ctrl \ + 0x00000002 + +#define HIB1P2_FLASH_DCDC_PARAMETERS_OVERRIDE_mem_dcdc_flash_ilim_trim_lowv_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_VTRIM_CFG register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_VTRIM_CFG_reserved_M \ + 0xFF000000 + +#define HIB1P2_DIG_DCDC_VTRIM_CFG_reserved_S 24 +#define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_run_vtrim_M \ + 0x00FC0000 + +#define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_run_vtrim_S 18 +#define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_dslp_vtrim_M \ + 0x0003F000 + +#define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_dslp_vtrim_S 12 +#define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_lpds_vtrim_M \ + 0x00000FC0 + +#define HIB1P2_DIG_DCDC_VTRIM_CFG_mem_dcdc_dig_lpds_vtrim_S 6 +#define HIB1P2_DIG_DCDC_VTRIM_CFG_Spare_RW_M \ + 0x0000003F + +#define HIB1P2_DIG_DCDC_VTRIM_CFG_Spare_RW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_DIG_DCDC_FSM_PARAMETERS register. +// +//****************************************************************************** +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_reserved_M \ + 0xFFFF8000 + +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_reserved_S 15 +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_cot_to_vtrim_M \ + 0x00007000 + +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_cot_to_vtrim_S 12 +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_vtrim_to_sleep_M \ + 0x00000E00 + +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_enter_vtrim_to_sleep_S 9 +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_sleep_to_vtrim_M \ + 0x000001C0 + +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_sleep_to_vtrim_S 6 +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_vtrim_to_cot_M \ + 0x00000038 + +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_vtrim_to_cot_S 3 +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_cot_to_run_M \ + 0x00000007 + +#define HIB1P2_DIG_DCDC_FSM_PARAMETERS_mem_dcdc_dig_dslp_exit_cot_to_run_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_ANA_DCDC_FSM_PARAMETERS register. +// +//****************************************************************************** +#define HIB1P2_ANA_DCDC_FSM_PARAMETERS_reserved_M \ + 0xFFFFFFF8 + +#define HIB1P2_ANA_DCDC_FSM_PARAMETERS_reserved_S 3 +#define HIB1P2_ANA_DCDC_FSM_PARAMETERS_mem_dcdc_ana_dslp_exit_sleep_to_run_M \ + 0x00000007 + +#define HIB1P2_ANA_DCDC_FSM_PARAMETERS_mem_dcdc_ana_dslp_exit_sleep_to_run_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_SRAM_SKA_LDO_FSM_PARAMETERS register. +// +//****************************************************************************** +#define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_reserved_M \ + 0xFFFFFFC0 + +#define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_reserved_S 6 +#define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_ska_ldo_en_to_sram_ldo_dis_M \ + 0x00000038 + +#define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_ska_ldo_en_to_sram_ldo_dis_S 3 +#define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_sram_ldo_en_to_ska_ldo_dis_M \ + 0x00000007 + +#define HIB1P2_SRAM_SKA_LDO_FSM_PARAMETERS_mem_sram_ldo_en_to_ska_ldo_dis_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_BGAP_DUTY_CYCLING_EXIT_CFG register. +// +//****************************************************************************** +#define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_reserved_M \ + 0xFFFFFFF8 + +#define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_reserved_S 3 +#define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_mem_bgap_duty_cycling_exit_time_M \ + 0x00000007 + +#define HIB1P2_BGAP_DUTY_CYCLING_EXIT_CFG_mem_bgap_duty_cycling_exit_time_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_CM_OSC_16M_CONFIG register. +// +//****************************************************************************** +#define HIB1P2_CM_OSC_16M_CONFIG_reserved_M \ + 0xFFFC0000 + +#define HIB1P2_CM_OSC_16M_CONFIG_reserved_S 18 +#define HIB1P2_CM_OSC_16M_CONFIG_cm_clk_good_16m \ + 0x00020000 + +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_en_osc_16m \ + 0x00010000 + +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_trim_M \ + 0x0000FC00 + +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_trim_S 10 +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_spare_M \ + 0x000003F0 + +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_16m_spare_S 4 +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_osc_en_sli_16m \ + 0x00000008 + +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_sli_16m_trim_M \ + 0x00000007 + +#define HIB1P2_CM_OSC_16M_CONFIG_mem_cm_sli_16m_trim_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_SOP_SENSE_VALUE register. +// +//****************************************************************************** +#define HIB1P2_SOP_SENSE_VALUE_reserved_M \ + 0xFFFFFF00 + +#define HIB1P2_SOP_SENSE_VALUE_reserved_S 8 +#define HIB1P2_SOP_SENSE_VALUE_sop_sense_value_M \ + 0x000000FF + +#define HIB1P2_SOP_SENSE_VALUE_sop_sense_value_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_RTC_TIMER_LSW_1P2 register. +// +//****************************************************************************** +#define HIB1P2_HIB_RTC_TIMER_LSW_1P2_hib_rtc_timer_lsw_M \ + 0xFFFFFFFF + +#define HIB1P2_HIB_RTC_TIMER_LSW_1P2_hib_rtc_timer_lsw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_RTC_TIMER_MSW_1P2 register. +// +//****************************************************************************** +#define HIB1P2_HIB_RTC_TIMER_MSW_1P2_hib_rtc_timer_msw_M \ + 0x0000FFFF + +#define HIB1P2_HIB_RTC_TIMER_MSW_1P2_hib_rtc_timer_msw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB1P2_BGAP_TRIM_OVERRIDES register. +// +//****************************************************************************** +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_reserved_M \ + 0xFF800000 + +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_reserved_S 23 +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_mag_trim_override_ctrl \ + 0x00400000 + +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_mag_trim_override_M \ + 0x003FC000 + +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_mag_trim_override_S 14 +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_temp_trim_override_ctrl \ + 0x00002000 + +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_temp_trim_override_M \ + 0x00001FC0 + +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_temp_trim_override_S 6 +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_rtrim_override_ctrl \ + 0x00000020 + +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_rtrim_override_M \ + 0x0000001F + +#define HIB1P2_HIB1P2_BGAP_TRIM_OVERRIDES_mem_bgap_rtrim_override_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB1P2_EFUSE_READ_REG0 register. +// +//****************************************************************************** +#define HIB1P2_HIB1P2_EFUSE_READ_REG0_FUSEFARM_ROW_12_M \ + 0xFFFFFFFF // Corresponds to ROW_12 of + // FUSEFARM. [7:0] : + // DCDC_DIG_ILIM_TRIM_LOWV(7:0) + // [15:8] : + // DCDC_ANA_ILIM_TRIM_LOWV(7:0) + // [23:16] : + // DCDC_FLASH_ILIM_TRIM_LOWV(7:0) + // [24:24] : DTHE SHA DISABLE + // [25:25] : DTHE DES DISABLE + // [26:26] : DTHE AES DISABLE + // [31:27] : HD_BG_RTRIM (4:0) + +#define HIB1P2_HIB1P2_EFUSE_READ_REG0_FUSEFARM_ROW_12_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB1P2_EFUSE_READ_REG1 register. +// +//****************************************************************************** +#define HIB1P2_HIB1P2_EFUSE_READ_REG1_FUSEFARM_ROW_13_M \ + 0xFFFFFFFF // Corresponds to ROW_13 of the + // FUSEFARM. [7:0] : HD_BG_MAG_TRIM + // (7:0) [14:8] : HD_BG_TEMP_TRIM + // (6:0) [15:15] : GREYOUT ENABLE + // DUTY CYCLING [31:16] : + // Reserved/Checksum + +#define HIB1P2_HIB1P2_EFUSE_READ_REG1_FUSEFARM_ROW_13_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB1P2_POR_TEST_CTRL register. +// +//****************************************************************************** +#define HIB1P2_HIB1P2_POR_TEST_CTRL_reserved_M \ + 0xFFFFFF00 + +#define HIB1P2_HIB1P2_POR_TEST_CTRL_reserved_S 8 +#define HIB1P2_HIB1P2_POR_TEST_CTRL_mem_prcm_por_test_ctrl_M \ + 0x000000FF + +#define HIB1P2_HIB1P2_POR_TEST_CTRL_mem_prcm_por_test_ctrl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG0 register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_reserved_M \ + 0xFFFF0000 + +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_reserved_S 16 +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_mem_cfg_calib_time_M \ + 0x0000FF00 + +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_mem_cfg_calib_time_S 8 +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_NU1_M \ + 0x000000FE + +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_NU1_S 1 +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG0_mem_cfg_calib_start \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_SYNC_CALIB_CFG1 register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_reserved_M \ + 0xFFF00000 + +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_reserved_S 20 +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_fast_calib_count_M \ + 0x000FFFFF + +#define HIB1P2_HIB_TIMER_SYNC_CALIB_CFG1_fast_calib_count_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_SYNC_CFG2 register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_SYNC_CFG2_reserved_M \ + 0xFFFFFE00 + +#define HIB1P2_HIB_TIMER_SYNC_CFG2_reserved_S 9 +#define HIB1P2_HIB_TIMER_SYNC_CFG2_mem_cfg_hib_unload \ + 0x00000100 + +#define HIB1P2_HIB_TIMER_SYNC_CFG2_NU1_M \ + 0x000000FC + +#define HIB1P2_HIB_TIMER_SYNC_CFG2_NU1_S 2 +#define HIB1P2_HIB_TIMER_SYNC_CFG2_mem_cfg_tsf_adj \ + 0x00000002 + +#define HIB1P2_HIB_TIMER_SYNC_CFG2_mem_cfg_update_tsf \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_SYNC_TSF_ADJ_VAL register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_SYNC_TSF_ADJ_VAL_mem_tsf_adj_val_M \ + 0xFFFFFFFF + +#define HIB1P2_HIB_TIMER_SYNC_TSF_ADJ_VAL_mem_tsf_adj_val_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW_rtc_gts_timestamp_lsw_M \ + 0xFFFFFFFF + +#define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_LSW_rtc_gts_timestamp_lsw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_reserved_M \ + 0xFFFF0000 + +#define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_reserved_S 16 +#define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_rtc_gts_timestamp_msw_M \ + 0x0000FFFF + +#define HIB1P2_HIB_TIMER_RTC_GTS_TIMESTAMP_MSW_rtc_gts_timestamp_msw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW_rtc_wup_timestamp_lsw_M \ + 0xFFFFFFFF + +#define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_LSW_rtc_wup_timestamp_lsw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_reserved_M \ + 0xFFFF0000 + +#define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_reserved_S 16 +#define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_rtc_wup_timestamp_msw_M \ + 0x0000FFFF + +#define HIB1P2_HIB_TIMER_RTC_WUP_TIMESTAMP_MSW_rtc_wup_timestamp_msw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_SYNC_WAKE_OFFSET_ERR register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_reserved_M \ + 0xFFFFF000 + +#define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_reserved_S 12 +#define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_wup_offset_error_M \ + 0x00000FFF + +#define HIB1P2_HIB_TIMER_SYNC_WAKE_OFFSET_ERR_wup_offset_error_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW_tsf_curr_val_lsw_M \ + 0xFFFFFFFF + +#define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_LSW_tsf_curr_val_lsw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW register. +// +//****************************************************************************** +#define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW_tsf_curr_val_msw_M \ + 0xFFFFFFFF + +#define HIB1P2_HIB_TIMER_SYNC_TSF_CURR_VAL_MSW_tsf_curr_val_msw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the HIB1P2_O_CM_SPARE register. +// +//****************************************************************************** +#define HIB1P2_CM_SPARE_CM_SPARE_OUT_M \ + 0xFF000000 + +#define HIB1P2_CM_SPARE_CM_SPARE_OUT_S 24 +#define HIB1P2_CM_SPARE_MEM_CM_TEST_CTRL_M \ + 0x00FF0000 + +#define HIB1P2_CM_SPARE_MEM_CM_TEST_CTRL_S 16 +#define HIB1P2_CM_SPARE_MEM_CM_SPARE_M \ + 0x0000FFFF + +#define HIB1P2_CM_SPARE_MEM_CM_SPARE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_PORPOL_SPARE register. +// +//****************************************************************************** +#define HIB1P2_PORPOL_SPARE_MEM_PORPOL_SPARE_M \ + 0xFFFFFFFF + +#define HIB1P2_PORPOL_SPARE_MEM_PORPOL_SPARE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_DIG_DCDC_CLK_CONFIG register. +// +//****************************************************************************** +#define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_ENABLE \ + 0x00000100 + +#define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_OFF_TIME_M \ + 0x000000F0 + +#define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_OFF_TIME_S 4 +#define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_ON_TIME_M \ + 0x0000000F + +#define HIB1P2_MEM_DIG_DCDC_CLK_CONFIG_MEM_DIG_DCDC_CLK_PLLGEN_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_ANA_DCDC_CLK_CONFIG register. +// +//****************************************************************************** +#define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_ENABLE \ + 0x00000100 + +#define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_OFF_TIME_M \ + 0x000000F0 + +#define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_OFF_TIME_S 4 +#define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_ON_TIME_M \ + 0x0000000F + +#define HIB1P2_MEM_ANA_DCDC_CLK_CONFIG_MEM_ANA_DCDC_CLK_PLLGEN_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_FLASH_DCDC_CLK_CONFIG register. +// +//****************************************************************************** +#define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_ENABLE \ + 0x00000100 + +#define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_OFF_TIME_M \ + 0x000000F0 + +#define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_OFF_TIME_S 4 +#define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_ON_TIME_M \ + 0x0000000F + +#define HIB1P2_MEM_FLASH_DCDC_CLK_CONFIG_MEM_FLASH_DCDC_CLK_PLLGEN_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_PA_DCDC_CLK_CONFIG register. +// +//****************************************************************************** +#define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_ENABLE \ + 0x00000100 + +#define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_OFF_TIME_M \ + 0x000000F0 + +#define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_OFF_TIME_S 4 +#define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_ON_TIME_M \ + 0x0000000F + +#define HIB1P2_MEM_PA_DCDC_CLK_CONFIG_MEM_PA_DCDC_CLK_PLLGEN_ON_TIME_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_SLDO_VNWA_OVERRIDE register. +// +//****************************************************************************** +#define HIB1P2_MEM_SLDO_VNWA_OVERRIDE_MEM_SLDO_EN_TOP_VNWA_OVERRIDE_CTRL \ + 0x00000002 + +#define HIB1P2_MEM_SLDO_VNWA_OVERRIDE_MEM_SLDO_EN_TOP_VNWA_OVERRIDE \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE register. +// +//****************************************************************************** +#define HIB1P2_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE_MEM_BGAP_DUTY_CYCLING_OVERRIDE_CTRL \ + 0x00000002 + +#define HIB1P2_MEM_BGAP_DUTY_CYCLING_ENABLE_OVERRIDE_MEM_BGAP_DUTY_CYCLING_OVERRIDE \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_HIB_FSM_DEBUG register. +// +//****************************************************************************** +#define HIB1P2_MEM_HIB_FSM_DEBUG_SRAM_PS_M \ + 0x00000700 + +#define HIB1P2_MEM_HIB_FSM_DEBUG_SRAM_PS_S 8 +#define HIB1P2_MEM_HIB_FSM_DEBUG_ANA_DCDC_PS_M \ + 0x000000F0 + +#define HIB1P2_MEM_HIB_FSM_DEBUG_ANA_DCDC_PS_S 4 +#define HIB1P2_MEM_HIB_FSM_DEBUG_DIG_DCDC_PS_M \ + 0x0000000F + +#define HIB1P2_MEM_HIB_FSM_DEBUG_DIG_DCDC_PS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_SLDO_VNWA_SW_CTRL register. +// +//****************************************************************************** +#define HIB1P2_MEM_SLDO_VNWA_SW_CTRL_MEM_SLDO_VNWA_SW_CTRL_M \ + 0x000FFFFF + +#define HIB1P2_MEM_SLDO_VNWA_SW_CTRL_MEM_SLDO_VNWA_SW_CTRL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_SLDO_WEAK_PROCESS register. +// +//****************************************************************************** +#define HIB1P2_MEM_SLDO_WEAK_PROCESS_MEM_SLDO_WEAK_PROCESS \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_PA_DCDC_OV_UV_STATUS register. +// +//****************************************************************************** +#define HIB1P2_MEM_PA_DCDC_OV_UV_STATUS_dcdc_pa_ov_prot_out_lowv \ + 0x00000002 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB1P2_O_MEM_CM_TEST_MODE register. +// +//****************************************************************************** +#define HIB1P2_MEM_CM_TEST_MODE_mem_cm_test_mode \ + 0x00000001 + + + + +#endif // __HW_HIB1P2_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib3p3.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib3p3.h new file mode 100644 index 00000000..97016891 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_hib3p3.h @@ -0,0 +1,1138 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_HIB3P3_H__ +#define __HW_HIB3P3_H__ + +//***************************************************************************** +// +// The following are defines for the HIB3P3 register offsets. +// +//***************************************************************************** +#define HIB3P3_O_MEM_HIB_REQ 0x00000000 +#define HIB3P3_O_MEM_HIB_RTC_TIMER_ENABLE \ + 0x00000004 + +#define HIB3P3_O_MEM_HIB_RTC_TIMER_RESET \ + 0x00000008 + +#define HIB3P3_O_MEM_HIB_RTC_TIMER_READ \ + 0x0000000C + +#define HIB3P3_O_MEM_HIB_RTC_TIMER_LSW \ + 0x00000010 + +#define HIB3P3_O_MEM_HIB_RTC_TIMER_MSW \ + 0x00000014 + +#define HIB3P3_O_MEM_HIB_RTC_WAKE_EN \ + 0x00000018 + +#define HIB3P3_O_MEM_HIB_RTC_WAKE_LSW_CONF \ + 0x0000001C + +#define HIB3P3_O_MEM_HIB_RTC_WAKE_MSW_CONF \ + 0x00000020 + +#define HIB3P3_O_MEM_INT_OSC_CONF \ + 0x0000002C + +#define HIB3P3_O_MEM_XTAL_OSC_CONF \ + 0x00000034 + +#define HIB3P3_O_MEM_BGAP_PARAMETERS0 \ + 0x00000038 + +#define HIB3P3_O_MEM_BGAP_PARAMETERS1 \ + 0x0000003C + +#define HIB3P3_O_MEM_HIB_DETECTION_STATUS \ + 0x00000040 + +#define HIB3P3_O_MEM_HIB_MISC_CONTROLS \ + 0x00000044 + +#define HIB3P3_O_MEM_HIB_CONFIG 0x00000050 +#define HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE \ + 0x00000054 + +#define HIB3P3_O_MEM_HIB_RTC_IRQ_LSW_CONF \ + 0x00000058 + +#define HIB3P3_O_MEM_HIB_RTC_IRQ_MSW_CONF \ + 0x0000005C + +#define HIB3P3_O_MEM_HIB_UART_CONF \ + 0x00000400 + +#define HIB3P3_O_MEM_GPIO_WAKE_EN \ + 0x00000404 + +#define HIB3P3_O_MEM_GPIO_WAKE_CONF \ + 0x00000408 + +#define HIB3P3_O_MEM_PAD_OEN_RET33_CONF \ + 0x0000040C + +#define HIB3P3_O_MEM_UART_RTS_OEN_RET33_CONF \ + 0x00000410 + +#define HIB3P3_O_MEM_JTAG_CONF 0x00000414 +#define HIB3P3_O_MEM_HIB_REG0 0x00000418 +#define HIB3P3_O_MEM_HIB_REG1 0x0000041C +#define HIB3P3_O_MEM_HIB_REG2 0x00000420 +#define HIB3P3_O_MEM_HIB_REG3 0x00000424 +#define HIB3P3_O_MEM_HIB_SEQUENCER_CFG0 \ + 0x0000045C + +#define HIB3P3_O_MEM_HIB_SEQUENCER_CFG1 \ + 0x00000460 + +#define HIB3P3_O_MEM_HIB_MISC_CONFIG \ + 0x00000464 + +#define HIB3P3_O_MEM_HIB_WAKE_STATUS \ + 0x00000468 + +#define HIB3P3_O_MEM_HIB_LPDS_GPIO_SEL \ + 0x0000046C + +#define HIB3P3_O_MEM_HIB_SEQUENCER_CFG2 \ + 0x00000470 + +#define HIB3P3_O_HIBANA_SPARE_LOWV \ + 0x00000474 + +#define HIB3P3_O_HIB_TMUX_CTRL 0x00000478 +#define HIB3P3_O_HIB_1P2_1P8_LDO_TRIM \ + 0x0000047C + +#define HIB3P3_O_HIB_COMP_TRIM 0x00000480 +#define HIB3P3_O_HIB_EN_TS 0x00000484 +#define HIB3P3_O_HIB_1P8V_DET_EN \ + 0x00000488 + +#define HIB3P3_O_HIB_VBAT_MON_EN \ + 0x0000048C + +#define HIB3P3_O_HIB_NHIB_ENABLE \ + 0x00000490 + +#define HIB3P3_O_HIB_UART_RTS_SW_ENABLE \ + 0x00000494 + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_REQ register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_REQ_reserved_M \ + 0xFFFFFE00 + +#define HIB3P3_MEM_HIB_REQ_reserved_S 9 +#define HIB3P3_MEM_HIB_REQ_NU1_M \ + 0x000001FC + +#define HIB3P3_MEM_HIB_REQ_NU1_S 2 +#define HIB3P3_MEM_HIB_REQ_mem_hib_clk_disable \ + 0x00000002 // 1 - Specifies that the Hiberante + // mode is without clocks ; 0 - + // Specified that the Hibernate mode + // is with clocks This register will + // be reset during Hibernate + // -WO-Clks mode (but not during + // Hibernate-W-Clks mode). + +#define HIB3P3_MEM_HIB_REQ_mem_hib_req \ + 0x00000001 // 1 - Request for hibernate mode + // (This is an auto-clear bit) ; 0 - + // Donot request for hibernate mode + // This register will be reset + // during Hibernate -WO-Clks mode + // (but not during Hibernate-W-Clks + // mode). + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_TIMER_ENABLE register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_TIMER_ENABLE_reserved_M \ + 0xFFFFFFFE + +#define HIB3P3_MEM_HIB_RTC_TIMER_ENABLE_reserved_S 1 +#define HIB3P3_MEM_HIB_RTC_TIMER_ENABLE_mem_hib_rtc_timer_enable \ + 0x00000001 // 1 - Enable the RTC timer to + // start running ; 0 - Keep the RTC + // timer disabled This register will + // be reset during Hibernate + // -WO-Clks mode (but not during + // Hibernate-W-Clks mode). + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_TIMER_RESET register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_TIMER_RESET_reserved_M \ + 0xFFFFFFFE + +#define HIB3P3_MEM_HIB_RTC_TIMER_RESET_reserved_S 1 +#define HIB3P3_MEM_HIB_RTC_TIMER_RESET_mem_hib_rtc_timer_reset \ + 0x00000001 // 1 - Reset the RTC timer ; 0 - + // Donot reset the RTC timer. This + // is an auto-clear bit. This + // register will be reset during + // Hibernate -WO-Clks mode (but not + // during Hibernate-W-Clks mode). + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_TIMER_READ register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_TIMER_READ_reserved_M \ + 0xFFFFFFFE + +#define HIB3P3_MEM_HIB_RTC_TIMER_READ_reserved_S 1 +#define HIB3P3_MEM_HIB_RTC_TIMER_READ_mem_hib_rtc_timer_read \ + 0x00000001 // 1 - Latch the running RTC timer + // into local registers. After + // programming this bit to 1, the + // F/w can read the latched RTC + // timer values from + // MEM_HIB_RTC_TIMER_LSW and + // MEM_HIB_RTC_TIMER_MSW. Before the + // F/w (APPS or NWP) wants to read + // the RTC-Timer, it has to program + // this bit to 1, then only read the + // MSW and LSW values. This is an + // auto-clear bit. This register + // will be reset during Hibernate + // -WO-Clks mode (but not during + // Hibernate-W-Clks mode). + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_TIMER_LSW register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_TIMER_LSW_hib_rtc_timer_lsw_M \ + 0xFFFFFFFF // Lower 32b value of the latched + // RTC-Timer. + +#define HIB3P3_MEM_HIB_RTC_TIMER_LSW_hib_rtc_timer_lsw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_TIMER_MSW register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_TIMER_MSW_reserved_M \ + 0xFFFF0000 + +#define HIB3P3_MEM_HIB_RTC_TIMER_MSW_reserved_S 16 +#define HIB3P3_MEM_HIB_RTC_TIMER_MSW_hib_rtc_timer_msw_M \ + 0x0000FFFF // Upper 32b value of the latched + // RTC-Timer. + +#define HIB3P3_MEM_HIB_RTC_TIMER_MSW_hib_rtc_timer_msw_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_WAKE_EN register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_WAKE_EN_reserved_M \ + 0xFFFFFFFE + +#define HIB3P3_MEM_HIB_RTC_WAKE_EN_reserved_S 1 +#define HIB3P3_MEM_HIB_RTC_WAKE_EN_mem_hib_rtc_wake_en \ + 0x00000001 // 1 - Enable the RTC timer based + // wakeup during Hibernate mode ; 0 + // - Disable the RTC timer based + // wakeup during Hibernate mode This + // register will be reset during + // Hibernate-WO-Clks mode (but not + // during Hibernate-W-Clks mode). + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_WAKE_LSW_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_WAKE_LSW_CONF_mem_hib_rtc_wake_lsw_conf_M \ + 0xFFFFFFFF // Configuration for RTC-Timer + // Wakeup (Lower 32b word) + +#define HIB3P3_MEM_HIB_RTC_WAKE_LSW_CONF_mem_hib_rtc_wake_lsw_conf_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_WAKE_MSW_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_reserved_M \ + 0xFFFF0000 + +#define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_reserved_S 16 +#define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_mem_hib_rtc_wake_msw_conf_M \ + 0x0000FFFF // Configuration for RTC-Timer + // Wakeup (Upper 16b word) + +#define HIB3P3_MEM_HIB_RTC_WAKE_MSW_CONF_mem_hib_rtc_wake_msw_conf_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_INT_OSC_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_INT_OSC_CONF_reserved_M \ + 0xFFFF0000 + +#define HIB3P3_MEM_INT_OSC_CONF_reserved_S 16 +#define HIB3P3_MEM_INT_OSC_CONF_cm_clk_good_32k_int \ + 0x00008000 // 1 - Internal 32kHz Oscillator is + // valid ; 0 - Internal 32k + // oscillator clk is not valid + +#define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_spare_M \ + 0x00007E00 + +#define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_spare_S 9 +#define HIB3P3_MEM_INT_OSC_CONF_mem_cm_en_intosc_32k_override_ctrl \ + 0x00000100 // When 1, the INT_32K_OSC_EN comes + // from bit [0] of this register, + // else comes from the FSM. This + // register will be reset during + // Hibernate-WO-Clks mode (but not + // during Hibernate-W-Clks mode) + +#define HIB3P3_MEM_INT_OSC_CONF_NU1 \ + 0x00000080 + +#define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_trim_M \ + 0x0000007E + +#define HIB3P3_MEM_INT_OSC_CONF_mem_cm_intosc_32k_trim_S 1 +#define HIB3P3_MEM_INT_OSC_CONF_mem_cm_en_intosc_32k \ + 0x00000001 // Override value for INT_OSC_EN. + // Applicable only when bit [3] of + // this register is set to 1. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_XTAL_OSC_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_XTAL_OSC_CONF_reserved_M \ + 0xFFF00000 + +#define HIB3P3_MEM_XTAL_OSC_CONF_reserved_S 20 +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_sli_32k_override_ctrl \ + 0x00080000 // When 1, the SLICER_EN comes from + // bit [10] of this register, else + // comes from the FSM. + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_xtal_32k_override_ctrl \ + 0x00040000 // When 1, the XTAL_EN comes from + // bit [0] of this register, else + // comes from the FSM. + +#define HIB3P3_MEM_XTAL_OSC_CONF_cm_clk_good_xtal \ + 0x00020000 // 1 - XTAL Clk is good ; 0 - XTAL + // Clk is yet to be valid. + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_xtal_trim_M \ + 0x0001F800 + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_xtal_trim_S 11 +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_sli_32k \ + 0x00000400 // SLICER_EN Override value : + // Applicable only when bit [19] of + // this register is set to 1. + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_sli_32k_trim_M \ + 0x00000380 + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_sli_32k_trim_S 7 +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_fref_32k_slicer_itrim_M \ + 0x00000070 + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_fref_32k_slicer_itrim_S 4 +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_fref_32k_slicer \ + 0x00000008 + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_input_sense_M \ + 0x00000006 + +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_input_sense_S 1 +#define HIB3P3_MEM_XTAL_OSC_CONF_mem_cm_en_xtal_32k \ + 0x00000001 // XTAL_EN Override value : + // Applicable only when bit [18] of + // this register is set to 1. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_BGAP_PARAMETERS0 register. +// +//****************************************************************************** +#define HIB3P3_MEM_BGAP_PARAMETERS0_reserved_M \ + 0xFFF80000 + +#define HIB3P3_MEM_BGAP_PARAMETERS0_reserved_S 19 +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_en_seq \ + 0x00040000 + +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_vbok4bg_comp_trim_M \ + 0x0001C000 + +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_vbok4bg_comp_trim_S 14 +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_en_vbat_ok_4bg \ + 0x00001000 + +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_en_vbok4bg_comp \ + 0x00000800 + +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_en_vbok4bg_comp_ref \ + 0x00000400 + +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_spare_M \ + 0x000003FF + +#define HIB3P3_MEM_BGAP_PARAMETERS0_mem_bgap_spare_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_BGAP_PARAMETERS1 register. +// +//****************************************************************************** +#define HIB3P3_MEM_BGAP_PARAMETERS1_reserved_M \ + 0xE0000000 + +#define HIB3P3_MEM_BGAP_PARAMETERS1_reserved_S 29 +#define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_act_iref_itrim_M \ + 0x1F000000 + +#define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_act_iref_itrim_S 24 +#define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en_act_iref \ + 0x00000008 + +#define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en_v2i \ + 0x00000004 + +#define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en_cap_sw \ + 0x00000002 + +#define HIB3P3_MEM_BGAP_PARAMETERS1_mem_bgap_en \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_DETECTION_STATUS register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_DETECTION_STATUS_reserved_M \ + 0xFFFFFF80 + +#define HIB3P3_MEM_HIB_DETECTION_STATUS_reserved_S 7 +#define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_forced_ana_status \ + 0x00000040 // 1 - 1.8 V supply forced mode. + +#define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_forced_flash_status \ + 0x00000004 // 1 - 3.3 V supply forced mode for + // Flash supply + +#define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_ext_clk_det_out_status \ + 0x00000002 // 1 - Forced clock mode + +#define HIB3P3_MEM_HIB_DETECTION_STATUS_hib_xtal_det_out_status \ + 0x00000001 // 1 - XTAL clock mode + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_MISC_CONTROLS register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_MISC_CONTROLS_reserved_M \ + 0xFFFFF800 + +#define HIB3P3_MEM_HIB_MISC_CONTROLS_reserved_S 11 +#define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_en_pok_por_comp \ + 0x00000400 + +#define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_en_pok_por_comp_ref \ + 0x00000200 + +#define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_pok_por_comp_trim_M \ + 0x000001C0 + +#define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_pok_por_comp_trim_S 6 +#define HIB3P3_MEM_HIB_MISC_CONTROLS_NU1 \ + 0x00000020 + +#define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_flash_det_en \ + 0x00000010 + +#define HIB3P3_MEM_HIB_MISC_CONTROLS_mem_hib_en_tmux \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_CONFIG register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_CONFIG_TOP_MUX_CTRL_SOP_SPIO_M \ + 0xFF000000 + +#define HIB3P3_MEM_HIB_CONFIG_TOP_MUX_CTRL_SOP_SPIO_S 24 +#define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED3 \ + 0x00080000 // 1 - Enable VDD_FLASH_INDP_PAD + // for digital path (SHARED4) ; 0 - + // Disable VDD_FLASH_INDP_PAD for + // digital path (SHARED4) ; Before + // programming this bit to 1, ensure + // that the device is in FORCED 3.3 + // supply Mode, which can be + // inferred from the register : + // MEM_HIB_DETECTION_STATUS : 0x0040 + +#define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED2 \ + 0x00040000 // 1 - Enable the + // VDD_FB_GPIO_MUX_PAD for digital + // path (SHARED3) ; 0 - Disable the + // VDD_FB_GPIO_MUX_PAD for digital + // path (SHARED3) ; This pin can be + // used only in modes other than + // SOP("111") + +#define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED1 \ + 0x00020000 // 1 - Enable the PM_TEST_PAD for + // digital GPIO path (SHARED2) ; 0 - + // Disable the PM_TEST_PAD for + // digital GPIO path (SHARED2) This + // pin can be used for digital only + // in modes other then SOP-111 + +#define HIB3P3_MEM_HIB_CONFIG_EN_ANA_DIG_SHARED0 \ + 0x00010000 // 1 - Enable the XTAL_N pin + // digital GPIO path (SHARED1); 0 - + // Disable the XTAL_N pin digital + // GPIO path (SHARED1). Before + // programming this bit to 1, ensure + // that the device is in FORCED CLK + // Mode, which can inferred from the + // register : + // MEM_HIB_DETECTION_STATUS : + // 0x0040. + +#define HIB3P3_MEM_HIB_CONFIG_mem_hib_xtal_enable \ + 0x00000100 // 1 - Enable the XTAL Clock ; 0 - + // Donot enable the XTAL Clock. This + // bit has to be programmed to 1 (by + // APPS Devinit F/w), during exit + // from OFF or Hib_wo_clks modes, + // after checking if the slow_clk + // mode is XTAL_CLK mode. Once + // enabled the XTAL will be disabled + // only after entering HIB_WO_CLKS + // mode. This register will be reset + // during Hibernate -WO-Clks mode + // (but not during Hibernate-W-Clks + // mode). + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_IRQ_ENABLE register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_IRQ_ENABLE_HIB_RTC_IRQ_ENABLE \ + 0x00000001 // 1 - Enable the HIB RTC - IRQ ; 0 + // - Disable the HIB RTC - IRQ + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_IRQ_LSW_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_IRQ_LSW_CONF_HIB_RTC_IRQ_LSW_CONF_M \ + 0xFFFFFFFF // Configuration for LSW of the + // RTC-Timestamp at which interrupt + // need to be generated + +#define HIB3P3_MEM_HIB_RTC_IRQ_LSW_CONF_HIB_RTC_IRQ_LSW_CONF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_RTC_IRQ_MSW_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_RTC_IRQ_MSW_CONF_HIB_RTC_IRQ_MSW_CONF_M \ + 0x0000FFFF // Configuration for MSW of thr + // RTC-Timestamp at which the + // interrupt need to be generated + +#define HIB3P3_MEM_HIB_RTC_IRQ_MSW_CONF_HIB_RTC_IRQ_MSW_CONF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_UART_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_UART_CONF_reserved_M \ + 0xFFFFFFFE + +#define HIB3P3_MEM_HIB_UART_CONF_reserved_S 1 +#define HIB3P3_MEM_HIB_UART_CONF_mem_hib_uart_wake_en \ + 0x00000001 // 1 - Enable the UART-Autonomous + // mode wakeup during Hibernate mode + // ; This is an auto-clear bit, once + // programmed to 1, it will latched + // into an internal register which + // remain asserted until the + // Hib-wakeup is initiated. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_GPIO_WAKE_EN register. +// +//****************************************************************************** +#define HIB3P3_MEM_GPIO_WAKE_EN_reserved_M \ + 0xFFFFFF00 + +#define HIB3P3_MEM_GPIO_WAKE_EN_reserved_S 8 +#define HIB3P3_MEM_GPIO_WAKE_EN_mem_gpio_wake_en_M \ + 0x000000FF // 1 - Enable the GPIO-Autonomous + // mode wakeup during Hibernate mode + // ; This is an auto-clear bit, once + // programmed to 1, it will latched + // into an internal register which + // remain asserted until the + // Hib-wakeup is initiated. + +#define HIB3P3_MEM_GPIO_WAKE_EN_mem_gpio_wake_en_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_GPIO_WAKE_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_GPIO_WAKE_CONF_reserved_M \ + 0xFFFF0000 + +#define HIB3P3_MEM_GPIO_WAKE_CONF_reserved_S 16 +#define HIB3P3_MEM_GPIO_WAKE_CONF_mem_gpio_wake_conf_M \ + 0x0000FFFF // Configuration to say whether the + // GPIO wakeup has to happen on + // Level0 or falling-edge for the + // given group. “00” – Level0 “01” – + // Level1 “10”- Fall-edge “11”- + // Rise-edge [1:0] – Conf for GPIO0 + // [3:2] – Conf for GPIO1 [5:4] – + // Conf for GPIO2 [7:6] – Conf for + // GPIO3 [9:8] – Conf for GPIO4 + // [11:10] – Conf for GPIO5 [13:12] + // – Conf for GPIO6 + +#define HIB3P3_MEM_GPIO_WAKE_CONF_mem_gpio_wake_conf_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_PAD_OEN_RET33_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_PAD_OEN_RET33_CONF_mem_pad_oen_ret33_override_ctrl \ + 0x00000004 // 1 - Override the OEN33 and RET33 + // controls of GPIOs during + // SOP-Bootdebug mode ; 0 - Donot + // override the OEN33 and RET33 + // controls of GPIOs during + // SOP-Bootdebug mode + +#define HIB3P3_MEM_PAD_OEN_RET33_CONF_PAD_OEN33_CONF \ + 0x00000002 + +#define HIB3P3_MEM_PAD_OEN_RET33_CONF_PAD_RET33_CONF \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_UART_RTS_OEN_RET33_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_UART_RTS_OEN_RET33_CONF_mem_uart_nrts_oen_ret33_override_ctrl \ + 0x00000004 // 1 - Override the OEN33 and RET33 + // controls of UART NRTS GPIO during + // SOP-Bootdebug mode ; 0 - Donot + // override the OEN33 and RET33 + // controls of UART NRTS GPIO during + // SOP-Bootdebug mode + +#define HIB3P3_MEM_UART_RTS_OEN_RET33_CONF_PAD_UART_RTS_OEN33_CONF \ + 0x00000002 + +#define HIB3P3_MEM_UART_RTS_OEN_RET33_CONF_PAD_UART_RTS_RET33_CONF \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_JTAG_CONF register. +// +//****************************************************************************** +#define HIB3P3_MEM_JTAG_CONF_mem_jtag1_oen_ret33_override_ctrl \ + 0x00000200 + +#define HIB3P3_MEM_JTAG_CONF_mem_jtag0_oen_ret33_override_ctrl \ + 0x00000100 + +#define HIB3P3_MEM_JTAG_CONF_PAD_JTAG1_RTS_OEN33_CONF \ + 0x00000008 + +#define HIB3P3_MEM_JTAG_CONF_PAD_JTAG1_RTS_RET33_CONF \ + 0x00000004 + +#define HIB3P3_MEM_JTAG_CONF_PAD_JTAG0_RTS_OEN33_CONF \ + 0x00000002 + +#define HIB3P3_MEM_JTAG_CONF_PAD_JTAG0_RTS_RET33_CONF \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_REG0 register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_REG0_mem_hib_reg0_M \ + 0xFFFFFFFF + +#define HIB3P3_MEM_HIB_REG0_mem_hib_reg0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_REG1 register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_REG1_mem_hib_reg1_M \ + 0xFFFFFFFF + +#define HIB3P3_MEM_HIB_REG1_mem_hib_reg1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_REG2 register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_REG2_mem_hib_reg2_M \ + 0xFFFFFFFF + +#define HIB3P3_MEM_HIB_REG2_mem_hib_reg2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_REG3 register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_REG3_mem_hib_reg3_M \ + 0xFFFFFFFF + +#define HIB3P3_MEM_HIB_REG3_mem_hib_reg3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_SEQUENCER_CFG0 register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev0_to_ev1_time_M \ + 0xFFFF0000 // Configuration for the number of + // slow-clks between de-assertion of + // EN_BG_3P3V to assertion of + // EN_BG_3P3V + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev0_to_ev1_time_S 16 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_NU1 \ + 0x00008000 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev3_to_ev4_time_M \ + 0x00006000 // Configuration for the number of + // slow-clks between assertion of + // EN_COMP_3P3V and assertion of + // EN_COMP_LATCH_3P3V + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev3_to_ev4_time_S 13 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev2_to_ev3_time_M \ + 0x00001800 // Configuration for the number of + // slow-clks between assertion of + // (EN_CAP_SW_3P3V,EN_COMP_REF) and + // assertion of (EN_COMP_3P3V) + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev2_to_ev3_time_S 11 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev1_to_ev2_time_M \ + 0x00000600 // Configuration for the number of + // slow-clks between assertion of + // (EN_BG_3P3V) and assertion of + // (EN_CAP_SW_3P3V, + // EN_COMP_REF_3P3V) + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bdc_ev1_to_ev2_time_S 9 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_crude_ref_comp \ + 0x00000100 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_vbok4bg_ref_override_ctrl \ + 0x00000080 // 1 - EN_VBOK4BG_REF comes from + // bit[10] of the register + // MEM_BGAP_PARAMETERS0 [0x0038]. 0 + // - EN_VBOK4BG_REF comes directly + // from the Hib-Sequencer. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_vbok4bg_comp_override_ctrl \ + 0x00000040 // 1 - EN_VBOK4BG comes from + // bit[11] of the register + // MEM_BGAP_PARAMETERS0 [0x0038]. 0 + // - EN_VBOK4BG comes directly from + // the Hib-Sequencer. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_v2i_override_ctrl \ + 0x00000020 // 1 - EN_V2I comes from bit[2] of + // the register MEM_BGAP_PARAMETERS1 + // [0x003C]. 0 - EN_V2I comes + // directly from the Hib-Sequencer. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_por_comp_ref_override_ctrl \ + 0x00000010 // 1 - EN_POR_COMP_REF comes from + // bit[9] of the register + // MEM_HIB_MISC_CONTROLS [0x0044]. 0 + // - EN_POR_COMP_REF comes directly + // from the Hib-Sequencer. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_en_por_comp_override_ctrl \ + 0x00000008 // 1 - EN_POR_COMP comes from + // bit[10] of the register + // MEM_HIB_MISC_CONTROLS [0x044]. 0 + // - EN_POR_COMP comes directly from + // the Hib-Sequencer. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_cap_sw_override_ctrl \ + 0x00000004 // 1 - EN_CAP_SW comes from bit[1] + // of the register + // MEM_BGAP_PARAMETERS1 [0x003C]. 0 + // - EN_CAP_SW comes directly from + // Hib-Sequencer. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_bg_override_ctrl \ + 0x00000002 // 1 - EN_BGAP comes from bit[0] of + // the register MEM_BGAP_PARAMETERS1 + // [0x003C]. 0 - EN_BGAP comes + // directly from Hib-Sequencer. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG0_mem_act_iref_override_ctrl \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_SEQUENCER_CFG1 register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_reserved_M \ + 0xFFFF0000 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_reserved_S 16 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_ev5_to_ev6_time_M \ + 0x0000C000 // Configuration for number of + // slow-clks between de-assertion of + // EN_COMP_LATCH and assertion of + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_ev5_to_ev6_time_S 14 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev1_to_ev2_time_M \ + 0x00003000 // Configuration for number of + // slow-clks between assertion of + // EN_COMP_REF to assertion of + // EN_COMP during HIB-Exit + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev1_to_ev2_time_S 12 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_ev1_time_M \ + 0x00000C00 // TBD + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_ev1_time_S 10 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_active_M \ + 0x00000300 // Configuration in number of + // slow-clks between assertion of + // (EN_BGAP_3P3V, EN_CAP_SW_3P3V, + // EN_ACT_IREF_3P3V, EN_COMP_REF) to + // assertion of EN_COMP_3P3V + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_bdc_to_active_ev0_to_active_S 8 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_active_to_bdc_ev1_to_bdc_ev0_time_M \ + 0x000000C0 // Configuration in number of + // slow-clks between de-assertion of + // (EN_COMP_3P3V, EN_COMP_REF_3P3V, + // EN_ACT_IREF_3P3V, EN_CAP_SW_3P3V) + // to deassertion of EN_BGAP_3P3V. + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_mem_active_to_bdc_ev1_to_bdc_ev0_time_S 6 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_NU1_M \ + 0x0000003F + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG1_NU1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_MISC_CONFIG register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_MISC_CONFIG_mem_en_pll_untrim_current \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_WAKE_STATUS register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_WAKE_STATUS_hib_wake_src_M \ + 0x0000001E // "0100" - GPIO ; "0010" - RTC ; + // "0001" - UART Others - Reserved + +#define HIB3P3_MEM_HIB_WAKE_STATUS_hib_wake_src_S 1 +#define HIB3P3_MEM_HIB_WAKE_STATUS_hib_wake_status \ + 0x00000001 // 1 - Wake from Hibernate ; 0 - + // Wake from OFF + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_LPDS_GPIO_SEL register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_LPDS_GPIO_SEL_HIB_LPDS_GPIO_SEL_M \ + 0x00000007 + +#define HIB3P3_MEM_HIB_LPDS_GPIO_SEL_HIB_LPDS_GPIO_SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_MEM_HIB_SEQUENCER_CFG2 register. +// +//****************************************************************************** +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_reserved_M \ + 0xFFFFF800 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_reserved_S 11 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_active_to_bdc_ev0_to_active_to_bdc_ev1_time_M \ + 0x00000600 // Deassertion of EN_COMP_LATCH_3P3 + // to deassertion of (EN_COMP_3P3, + // EN_COMP_REF_3P3, EN_ACT_IREF_3P3, + // EN_CAP_SW_3P3) + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_active_to_bdc_ev0_to_active_to_bdc_ev1_time_S 9 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev4_to_ev5_time_M \ + 0x000001C0 // Assertion of EN_COMP_LATCH_3P3 + // to deassertion of + // EN_COMP_LATCH_3P3 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev4_to_ev5_time_S 6 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev6_to_ev7_time_M \ + 0x00000030 // Deassertion of (EN_CAP_SW_3P3, + // EN_COMP_REF_3P3, EN_COMP_3P3, + // EN_COMP_OUT_LATCH_3P3) to + // deassertion of EN_BGAP_3P3 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_ev6_to_ev7_time_S 4 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_to_active_ev1_to_ev2_time_M \ + 0x0000000C // Assertion of EN_COMP_3P3 to + // assertion of EN_COMPOUT_LATCH_3P3 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_bdc_to_active_ev1_to_ev2_time_S 2 +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_hib_to_active_ev2_to_ev3_time_M \ + 0x00000003 // Assertion of EN_COMP_3P3 to + // assertion of EN_COMPOUT_LATCH_3P3 + +#define HIB3P3_MEM_HIB_SEQUENCER_CFG2_mem_hib_to_active_ev2_to_ev3_time_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIBANA_SPARE_LOWV register. +// +//****************************************************************************** +#define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare1_M \ + 0xFFC00000 + +#define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare1_S 22 +#define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare0_M \ + 0x0001FFFF + +#define HIB3P3_HIBANA_SPARE_LOWV_mem_hibana_spare0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_TMUX_CTRL register. +// +//****************************************************************************** +#define HIB3P3_HIB_TMUX_CTRL_reserved_M \ + 0xFFFFFC00 + +#define HIB3P3_HIB_TMUX_CTRL_reserved_S 10 +#define HIB3P3_HIB_TMUX_CTRL_mem_hd_tmux_cntrl_M \ + 0x000003FF + +#define HIB3P3_HIB_TMUX_CTRL_mem_hd_tmux_cntrl_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_1P2_1P8_LDO_TRIM register. +// +//****************************************************************************** +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_reserved_M \ + 0xFFFFF000 + +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_reserved_S 12 +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_en_override_ctrl \ + 0x00000800 + +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_en_override_ctrl \ + 0x00000400 + +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_en_override \ + 0x00000200 + +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_en_override \ + 0x00000100 + +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_vtrim_M \ + 0x000000F0 + +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p2_ldo_vtrim_S 4 +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_vtrim_M \ + 0x0000000F + +#define HIB3P3_HIB_1P2_1P8_LDO_TRIM_mem_hd_1p8_ldo_vtrim_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_COMP_TRIM register. +// +//****************************************************************************** +#define HIB3P3_HIB_COMP_TRIM_reserved_M \ + 0xFFFFFFF8 + +#define HIB3P3_HIB_COMP_TRIM_reserved_S 3 +#define HIB3P3_HIB_COMP_TRIM_mem_hd_comp_trim_M \ + 0x00000007 + +#define HIB3P3_HIB_COMP_TRIM_mem_hd_comp_trim_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_EN_TS register. +// +//****************************************************************************** +#define HIB3P3_HIB_EN_TS_reserved_M \ + 0xFFFFFFFE + +#define HIB3P3_HIB_EN_TS_reserved_S 1 +#define HIB3P3_HIB_EN_TS_mem_hd_en_ts \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_1P8V_DET_EN register. +// +//****************************************************************************** +#define HIB3P3_HIB_1P8V_DET_EN_reserved_M \ + 0xFFFFFFFE + +#define HIB3P3_HIB_1P8V_DET_EN_reserved_S 1 +#define HIB3P3_HIB_1P8V_DET_EN_mem_hib_1p8v_det_en \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_VBAT_MON_EN register. +// +//****************************************************************************** +#define HIB3P3_HIB_VBAT_MON_EN_reserved_M \ + 0xFFFFFFFC + +#define HIB3P3_HIB_VBAT_MON_EN_reserved_S 2 +#define HIB3P3_HIB_VBAT_MON_EN_mem_hib_vbat_mon_del_en \ + 0x00000002 + +#define HIB3P3_HIB_VBAT_MON_EN_mem_hib_vbat_mon_en \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_NHIB_ENABLE register. +// +//****************************************************************************** +#define HIB3P3_HIB_NHIB_ENABLE_mem_hib_nhib_enable \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// HIB3P3_O_HIB_UART_RTS_SW_ENABLE register. +// +//****************************************************************************** +#define HIB3P3_HIB_UART_RTS_SW_ENABLE_mem_hib_uart_rts_sw_enable \ + 0x00000001 + + + + +#endif // __HW_HIB3P3_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_i2c.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_i2c.h new file mode 100644 index 00000000..17536d3e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_i2c.h @@ -0,0 +1,503 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_I2C_H__ +#define __HW_I2C_H__ + +//***************************************************************************** +// +// The following are defines for the I2C register offsets. +// +//***************************************************************************** +#define I2C_O_MSA 0x00000000 +#define I2C_O_MCS 0x00000004 +#define I2C_O_MDR 0x00000008 +#define I2C_O_MTPR 0x0000000C +#define I2C_O_MIMR 0x00000010 +#define I2C_O_MRIS 0x00000014 +#define I2C_O_MMIS 0x00000018 +#define I2C_O_MICR 0x0000001C +#define I2C_O_MCR 0x00000020 +#define I2C_O_MCLKOCNT 0x00000024 +#define I2C_O_MBMON 0x0000002C +#define I2C_O_MBLEN 0x00000030 +#define I2C_O_MBCNT 0x00000034 +#define I2C_O_SOAR 0x00000800 +#define I2C_O_SCSR 0x00000804 +#define I2C_O_SDR 0x00000808 +#define I2C_O_SIMR 0x0000080C +#define I2C_O_SRIS 0x00000810 +#define I2C_O_SMIS 0x00000814 +#define I2C_O_SICR 0x00000818 +#define I2C_O_SOAR2 0x0000081C +#define I2C_O_SACKCTL 0x00000820 +#define I2C_O_FIFODATA 0x00000F00 +#define I2C_O_FIFOCTL 0x00000F04 +#define I2C_O_FIFOSTATUS 0x00000F08 +#define I2C_O_OBSMUXSEL0 0x00000F80 +#define I2C_O_OBSMUXSEL1 0x00000F84 +#define I2C_O_MUXROUTE 0x00000F88 +#define I2C_O_PV 0x00000FB0 +#define I2C_O_PP 0x00000FC0 +#define I2C_O_PC 0x00000FC4 +#define I2C_O_CC 0x00000FC8 + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MSA register. +// +//****************************************************************************** +#define I2C_MSA_SA_M 0x000000FE // I2C Slave Address +#define I2C_MSA_SA_S 1 +#define I2C_MSA_RS 0x00000001 // Receive not send +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MCS register. +// +//****************************************************************************** +#define I2C_MCS_ACTDMARX 0x80000000 // DMA RX Active Status +#define I2C_MCS_ACTDMATX 0x40000000 // DMA TX Active Status +#define I2C_MCS_CLKTO 0x00000080 // Clock Timeout Error +#define I2C_MCS_BUSBSY 0x00000040 // Bus Busy +#define I2C_MCS_IDLE 0x00000020 // I2C Idle +#define I2C_MCS_ARBLST 0x00000010 // Arbitration Lost +#define I2C_MCS_ACK 0x00000008 // Data Acknowledge Enable +#define I2C_MCS_ADRACK 0x00000004 // Acknowledge Address +#define I2C_MCS_ERROR 0x00000002 // Error +#define I2C_MCS_BUSY 0x00000001 // I2C Busy +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MDR register. +// +//****************************************************************************** +#define I2C_MDR_DATA_M 0x000000FF // Data Transferred +#define I2C_MDR_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MTPR register. +// +//****************************************************************************** +#define I2C_MTPR_HS 0x00000080 // High-Speed Enable +#define I2C_MTPR_TPR_M 0x0000007F // SCL Clock Period +#define I2C_MTPR_TPR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MIMR register. +// +//****************************************************************************** +#define I2C_MIMR_RXFFIM 0x00000800 // Receive FIFO Full Interrupt Mask +#define I2C_MIMR_TXFEIM 0x00000400 // Transmit FIFO Empty Interrupt + // Mask +#define I2C_MIMR_RXIM 0x00000200 // Receive FIFO Request Interrupt + // Mask +#define I2C_MIMR_TXIM 0x00000100 // Transmit FIFO Request Interrupt + // Mask +#define I2C_MIMR_ARBLOSTIM 0x00000080 // Arbitration Lost Interrupt Mask +#define I2C_MIMR_STOPIM 0x00000040 // STOP Detection Interrupt Mask +#define I2C_MIMR_STARTIM 0x00000020 // START Detection Interrupt Mask +#define I2C_MIMR_NACKIM 0x00000010 // Address/Data NACK Interrupt Mask +#define I2C_MIMR_DMATXIM 0x00000008 // Transmit DMA Interrupt Mask +#define I2C_MIMR_DMARXIM 0x00000004 // Receive DMA Interrupt Mask +#define I2C_MIMR_CLKIM 0x00000002 // Clock Timeout Interrupt Mask +#define I2C_MIMR_IM 0x00000001 // Master Interrupt Mask +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MRIS register. +// +//****************************************************************************** +#define I2C_MRIS_RXFFRIS 0x00000800 // Receive FIFO Full Raw Interrupt + // Status +#define I2C_MRIS_TXFERIS 0x00000400 // Transmit FIFO Empty Raw + // Interrupt Status +#define I2C_MRIS_RXRIS 0x00000200 // Receive FIFO Request Raw + // Interrupt Status +#define I2C_MRIS_TXRIS 0x00000100 // Transmit Request Raw Interrupt + // Status +#define I2C_MRIS_ARBLOSTRIS 0x00000080 // Arbitration Lost Raw Interrupt + // Status +#define I2C_MRIS_STOPRIS 0x00000040 // STOP Detection Raw Interrupt + // Status +#define I2C_MRIS_STARTRIS 0x00000020 // START Detection Raw Interrupt + // Status +#define I2C_MRIS_NACKRIS 0x00000010 // Address/Data NACK Raw Interrupt + // Status +#define I2C_MRIS_DMATXRIS 0x00000008 // Transmit DMA Raw Interrupt + // Status +#define I2C_MRIS_DMARXRIS 0x00000004 // Receive DMA Raw Interrupt Status +#define I2C_MRIS_CLKRIS 0x00000002 // Clock Timeout Raw Interrupt + // Status +#define I2C_MRIS_RIS 0x00000001 // Master Raw Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MMIS register. +// +//****************************************************************************** +#define I2C_MMIS_RXFFMIS 0x00000800 // Receive FIFO Full Interrupt Mask +#define I2C_MMIS_TXFEMIS 0x00000400 // Transmit FIFO Empty Interrupt + // Mask +#define I2C_MMIS_RXMIS 0x00000200 // Receive FIFO Request Interrupt + // Mask +#define I2C_MMIS_TXMIS 0x00000100 // Transmit Request Interrupt Mask +#define I2C_MMIS_ARBLOSTMIS 0x00000080 // Arbitration Lost Interrupt Mask +#define I2C_MMIS_STOPMIS 0x00000040 // STOP Detection Interrupt Mask +#define I2C_MMIS_STARTMIS 0x00000020 // START Detection Interrupt Mask +#define I2C_MMIS_NACKMIS 0x00000010 // Address/Data NACK Interrupt Mask +#define I2C_MMIS_DMATXMIS 0x00000008 // Transmit DMA Interrupt Status +#define I2C_MMIS_DMARXMIS 0x00000004 // Receive DMA Interrupt Status +#define I2C_MMIS_CLKMIS 0x00000002 // Clock Timeout Masked Interrupt + // Status +#define I2C_MMIS_MIS 0x00000001 // Masked Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MICR register. +// +//****************************************************************************** +#define I2C_MICR_RXFFIC 0x00000800 // Receive FIFO Full Interrupt + // Clear +#define I2C_MICR_TXFEIC 0x00000400 // Transmit FIFO Empty Interrupt + // Clear +#define I2C_MICR_RXIC 0x00000200 // Receive FIFO Request Interrupt + // Clear +#define I2C_MICR_TXIC 0x00000100 // Transmit FIFO Request Interrupt + // Clear +#define I2C_MICR_ARBLOSTIC 0x00000080 // Arbitration Lost Interrupt Clear +#define I2C_MICR_STOPIC 0x00000040 // STOP Detection Interrupt Clear +#define I2C_MICR_STARTIC 0x00000020 // START Detection Interrupt Clear +#define I2C_MICR_NACKIC 0x00000010 // Address/Data NACK Interrupt + // Clear +#define I2C_MICR_DMATXIC 0x00000008 // Transmit DMA Interrupt Clear +#define I2C_MICR_DMARXIC 0x00000004 // Receive DMA Interrupt Clear +#define I2C_MICR_CLKIC 0x00000002 // Clock Timeout Interrupt Clear +#define I2C_MICR_IC 0x00000001 // Master Interrupt Clear +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MCR register. +// +//****************************************************************************** +#define I2C_MCR_MMD 0x00000040 // Multi-master Disable +#define I2C_MCR_SFE 0x00000020 // I2C Slave Function Enable +#define I2C_MCR_MFE 0x00000010 // I2C Master Function Enable +#define I2C_MCR_LPBK 0x00000001 // I2C Loopback +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MCLKOCNT register. +// +//****************************************************************************** +#define I2C_MCLKOCNT_CNTL_M 0x000000FF // I2C Master Count +#define I2C_MCLKOCNT_CNTL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MBMON register. +// +//****************************************************************************** +#define I2C_MBMON_SDA 0x00000002 // I2C SDA Status +#define I2C_MBMON_SCL 0x00000001 // I2C SCL Status +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MBLEN register. +// +//****************************************************************************** +#define I2C_MBLEN_CNTL_M 0x000000FF // I2C Burst Length +#define I2C_MBLEN_CNTL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MBCNT register. +// +//****************************************************************************** +#define I2C_MBCNT_CNTL_M 0x000000FF // I2C Master Burst Count +#define I2C_MBCNT_CNTL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SOAR register. +// +//****************************************************************************** +#define I2C_SOAR_OAR_M 0x0000007F // I2C Slave Own Address +#define I2C_SOAR_OAR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SCSR register. +// +//****************************************************************************** +#define I2C_SCSR_ACTDMARX 0x80000000 // DMA RX Active Status +#define I2C_SCSR_ACTDMATX 0x40000000 // DMA TX Active Status +#define I2C_SCSR_QCMDRW 0x00000020 // Quick Command Read / Write +#define I2C_SCSR_QCMDST 0x00000010 // Quick Command Status +#define I2C_SCSR_OAR2SEL 0x00000008 // OAR2 Address Matched +#define I2C_SCSR_FBR 0x00000004 // First Byte Received +#define I2C_SCSR_TREQ 0x00000002 // Transmit Request +#define I2C_SCSR_DA 0x00000001 // Device Active +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SDR register. +// +//****************************************************************************** +#define I2C_SDR_DATA_M 0x000000FF // Data for Transfer +#define I2C_SDR_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SIMR register. +// +//****************************************************************************** +#define I2C_SIMR_IM 0x00000100 // Interrupt Mask +#define I2C_SIMR_TXFEIM 0x00000080 // Transmit FIFO Empty Interrupt + // Mask +#define I2C_SIMR_RXIM 0x00000040 // Receive FIFO Request Interrupt + // Mask +#define I2C_SIMR_TXIM 0x00000020 // Transmit FIFO Request Interrupt + // Mask +#define I2C_SIMR_DMATXIM 0x00000010 // Transmit DMA Interrupt Mask +#define I2C_SIMR_DMARXIM 0x00000008 // Receive DMA Interrupt Mask +#define I2C_SIMR_STOPIM 0x00000004 // Stop Condition Interrupt Mask +#define I2C_SIMR_STARTIM 0x00000002 // Start Condition Interrupt Mask +#define I2C_SIMR_DATAIM 0x00000001 // Data Interrupt Mask +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SRIS register. +// +//****************************************************************************** +#define I2C_SRIS_RIS 0x00000100 // Raw Interrupt Status +#define I2C_SRIS_TXFERIS 0x00000080 // Transmit FIFO Empty Raw + // Interrupt Status +#define I2C_SRIS_RXRIS 0x00000040 // Receive FIFO Request Raw + // Interrupt Status +#define I2C_SRIS_TXRIS 0x00000020 // Transmit Request Raw Interrupt + // Status +#define I2C_SRIS_DMATXRIS 0x00000010 // Transmit DMA Raw Interrupt + // Status +#define I2C_SRIS_DMARXRIS 0x00000008 // Receive DMA Raw Interrupt Status +#define I2C_SRIS_STOPRIS 0x00000004 // Stop Condition Raw Interrupt + // Status +#define I2C_SRIS_STARTRIS 0x00000002 // Start Condition Raw Interrupt + // Status +#define I2C_SRIS_DATARIS 0x00000001 // Data Raw Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SMIS register. +// +//****************************************************************************** +#define I2C_SMIS_RXFFMIS 0x00000100 // Receive FIFO Full Interrupt Mask +#define I2C_SMIS_TXFEMIS 0x00000080 // Transmit FIFO Empty Interrupt + // Mask +#define I2C_SMIS_RXMIS 0x00000040 // Receive FIFO Request Interrupt + // Mask +#define I2C_SMIS_TXMIS 0x00000020 // Transmit FIFO Request Interrupt + // Mask +#define I2C_SMIS_DMATXMIS 0x00000010 // Transmit DMA Masked Interrupt + // Status +#define I2C_SMIS_DMARXMIS 0x00000008 // Receive DMA Masked Interrupt + // Status +#define I2C_SMIS_STOPMIS 0x00000004 // Stop Condition Masked Interrupt + // Status +#define I2C_SMIS_STARTMIS 0x00000002 // Start Condition Masked Interrupt + // Status +#define I2C_SMIS_DATAMIS 0x00000001 // Data Masked Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SICR register. +// +//****************************************************************************** +#define I2C_SICR_RXFFIC 0x00000100 // Receive FIFO Full Interrupt Mask +#define I2C_SICR_TXFEIC 0x00000080 // Transmit FIFO Empty Interrupt + // Mask +#define I2C_SICR_RXIC 0x00000040 // Receive Request Interrupt Mask +#define I2C_SICR_TXIC 0x00000020 // Transmit Request Interrupt Mask +#define I2C_SICR_DMATXIC 0x00000010 // Transmit DMA Interrupt Clear +#define I2C_SICR_DMARXIC 0x00000008 // Receive DMA Interrupt Clear +#define I2C_SICR_STOPIC 0x00000004 // Stop Condition Interrupt Clear +#define I2C_SICR_STARTIC 0x00000002 // Start Condition Interrupt Clear +#define I2C_SICR_DATAIC 0x00000001 // Data Interrupt Clear +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SOAR2 register. +// +//****************************************************************************** +#define I2C_SOAR2_OAR2EN 0x00000080 // I2C Slave Own Address 2 Enable +#define I2C_SOAR2_OAR2_M 0x0000007F // I2C Slave Own Address 2 +#define I2C_SOAR2_OAR2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_SACKCTL register. +// +//****************************************************************************** +#define I2C_SACKCTL_ACKOVAL 0x00000002 // I2C Slave ACK Override Value +#define I2C_SACKCTL_ACKOEN 0x00000001 // I2C Slave ACK Override Enable +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_FIFODATA register. +// +//****************************************************************************** +#define I2C_FIFODATA_DATA_M 0x000000FF // I2C FIFO Data Byte +#define I2C_FIFODATA_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_FIFOCTL register. +// +//****************************************************************************** +#define I2C_FIFOCTL_RXASGNMT 0x80000000 // RX Control Assignment +#define I2C_FIFOCTL_RXFLUSH 0x40000000 // RX FIFO Flush +#define I2C_FIFOCTL_DMARXENA 0x20000000 // DMA RX Channel Enable +#define I2C_FIFOCTL_RXTRIG_M 0x00070000 // RX FIFO Trigger +#define I2C_FIFOCTL_RXTRIG_S 16 +#define I2C_FIFOCTL_TXASGNMT 0x00008000 // TX Control Assignment +#define I2C_FIFOCTL_TXFLUSH 0x00004000 // TX FIFO Flush +#define I2C_FIFOCTL_DMATXENA 0x00002000 // DMA TX Channel Enable +#define I2C_FIFOCTL_TXTRIG_M 0x00000007 // TX FIFO Trigger +#define I2C_FIFOCTL_TXTRIG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_FIFOSTATUS register. +// +//****************************************************************************** +#define I2C_FIFOSTATUS_RXABVTRIG \ + 0x00040000 // RX FIFO Above Trigger Level + +#define I2C_FIFOSTATUS_RXFF 0x00020000 // RX FIFO Full +#define I2C_FIFOSTATUS_RXFE 0x00010000 // RX FIFO Empty +#define I2C_FIFOSTATUS_TXBLWTRIG \ + 0x00000004 // TX FIFO Below Trigger Level + +#define I2C_FIFOSTATUS_TXFF 0x00000002 // TX FIFO Full +#define I2C_FIFOSTATUS_TXFE 0x00000001 // TX FIFO Empty +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_OBSMUXSEL0 register. +// +//****************************************************************************** +#define I2C_OBSMUXSEL0_LN3_M 0x07000000 // Observation Mux Lane 3 +#define I2C_OBSMUXSEL0_LN3_S 24 +#define I2C_OBSMUXSEL0_LN2_M 0x00070000 // Observation Mux Lane 2 +#define I2C_OBSMUXSEL0_LN2_S 16 +#define I2C_OBSMUXSEL0_LN1_M 0x00000700 // Observation Mux Lane 1 +#define I2C_OBSMUXSEL0_LN1_S 8 +#define I2C_OBSMUXSEL0_LN0_M 0x00000007 // Observation Mux Lane 0 +#define I2C_OBSMUXSEL0_LN0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_OBSMUXSEL1 register. +// +//****************************************************************************** +#define I2C_OBSMUXSEL1_LN7_M 0x07000000 // Observation Mux Lane 7 +#define I2C_OBSMUXSEL1_LN7_S 24 +#define I2C_OBSMUXSEL1_LN6_M 0x00070000 // Observation Mux Lane 6 +#define I2C_OBSMUXSEL1_LN6_S 16 +#define I2C_OBSMUXSEL1_LN5_M 0x00000700 // Observation Mux Lane 5 +#define I2C_OBSMUXSEL1_LN5_S 8 +#define I2C_OBSMUXSEL1_LN4_M 0x00000007 // Observation Mux Lane 4 +#define I2C_OBSMUXSEL1_LN4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_MUXROUTE register. +// +//****************************************************************************** +#define I2C_MUXROUTE_LN7ROUTE_M \ + 0x70000000 // Lane 7 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN7ROUTE_S 28 +#define I2C_MUXROUTE_LN6ROUTE_M \ + 0x07000000 // Lane 6 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN6ROUTE_S 24 +#define I2C_MUXROUTE_LN5ROUTE_M \ + 0x00700000 // Lane 5 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN5ROUTE_S 20 +#define I2C_MUXROUTE_LN4ROUTE_M \ + 0x00070000 // Lane 4 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN4ROUTE_S 16 +#define I2C_MUXROUTE_LN3ROUTE_M \ + 0x00007000 // Lane 3 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN3ROUTE_S 12 +#define I2C_MUXROUTE_LN2ROUTE_M \ + 0x00000700 // Lane 2 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN2ROUTE_S 8 +#define I2C_MUXROUTE_LN1ROUTE_M \ + 0x00000070 // Lane 1 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN1ROUTE_S 4 +#define I2C_MUXROUTE_LN0ROUTE_M \ + 0x00000007 // Lane 0 output is routed to the + // lane pointed to by the offset in + // this bit field + +#define I2C_MUXROUTE_LN0ROUTE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_PV register. +// +//****************************************************************************** +#define I2C_PV_MAJOR_M 0x0000FF00 // Major Revision +#define I2C_PV_MAJOR_S 8 +#define I2C_PV_MINOR_M 0x000000FF // Minor Revision +#define I2C_PV_MINOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_PP register. +// +//****************************************************************************** +#define I2C_PP_HS 0x00000001 // High-Speed Capable +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_PC register. +// +//****************************************************************************** +#define I2C_PC_HS 0x00000001 // High-Speed Capable +//****************************************************************************** +// +// The following are defines for the bit fields in the I2C_O_CC register. +// +//****************************************************************************** + + + +#endif // __HW_I2C_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ints.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ints.h new file mode 100644 index 00000000..6b401935 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ints.h @@ -0,0 +1,117 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +//***************************************************************************** +// +// hw_ints.h - Macros that define the interrupt assignment on CC3200. +// +//***************************************************************************** + +#ifndef __HW_INTS_H__ +#define __HW_INTS_H__ + +//***************************************************************************** +// +// The following are defines for the fault assignments. +// +//***************************************************************************** +#define FAULT_NMI 2 // NMI fault +#define FAULT_HARD 3 // Hard fault +#define FAULT_MPU 4 // MPU fault +#define FAULT_BUS 5 // Bus fault +#define FAULT_USAGE 6 // Usage fault +#define FAULT_SVCALL 11 // SVCall +#define FAULT_DEBUG 12 // Debug monitor +#define FAULT_PENDSV 14 // PendSV +#define FAULT_SYSTICK 15 // System Tick + +//***************************************************************************** +// +// The following are defines for the interrupt assignments. +// +//***************************************************************************** +#define INT_GPIOA0 16 // GPIO Port S0 +#define INT_GPIOA1 17 // GPIO Port S1 +#define INT_GPIOA2 18 // GPIO Port S2 +#define INT_GPIOA3 19 // GPIO Port S3 +#define INT_UARTA0 21 // UART0 Rx and Tx +#define INT_UARTA1 22 // UART1 Rx and Tx +#define INT_I2CA0 24 // I2C controller +#define INT_ADCCH0 30 // ADC Sequence 0 +#define INT_ADCCH1 31 // ADC Sequence 1 +#define INT_ADCCH2 32 // ADC Sequence 2 +#define INT_ADCCH3 33 // ADC Sequence 3 +#define INT_WDT 34 // Watchdog Timer0 +#define INT_TIMERA0A 35 // Timer 0 subtimer A +#define INT_TIMERA0B 36 // Timer 0 subtimer B +#define INT_TIMERA1A 37 // Timer 1 subtimer A +#define INT_TIMERA1B 38 // Timer 1 subtimer B +#define INT_TIMERA2A 39 // Timer 2 subtimer A +#define INT_TIMERA2B 40 // Timer 2 subtimer B +#define INT_FLASH 45 // FLASH Control +#define INT_TIMERA3A 51 // Timer 3 subtimer A +#define INT_TIMERA3B 52 // Timer 3 subtimer B +#define INT_UDMA 62 // uDMA controller +#define INT_UDMAERR 63 // uDMA Error +#define INT_SHA 164 // SHA +#define INT_AES 167 // AES +#define INT_DES 169 // DES +#define INT_MMCHS 175 // SDIO +#define INT_I2S 177 // McAPS +#define INT_CAMERA 179 // Camera +#define INT_NWPIC 187 // Interprocessor communication +#define INT_PRCM 188 // Power, Reset and Clock Module +#define INT_SSPI 191 // Shared SPI +#define INT_GSPI 192 // Generic SPI +#define INT_LSPI 193 // Link SPI + +//***************************************************************************** +// +// The following are defines for the total number of interrupts. +// +//***************************************************************************** +#define NUM_INTERRUPTS 195 //The above number plus 2? + + +//***************************************************************************** +// +// The following are defines for the total number of priority levels. +// +//***************************************************************************** +#define NUM_PRIORITY 8 +#define NUM_PRIORITY_BITS 3 + + +#endif // __HW_INTS_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcasp.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcasp.h new file mode 100644 index 00000000..c27a0077 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcasp.h @@ -0,0 +1,1706 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_MCASP_H__ +#define __HW_MCASP_H__ + +//***************************************************************************** +// +// The following are defines for the MCASP register offsets. +// +//***************************************************************************** +#define MCASP_O_PID 0x00000000 +#define MCASP_O_ESYSCONFIG 0x00000004 // Power Idle SYSCONFIG register. +#define MCASP_O_PFUNC 0x00000010 +#define MCASP_O_PDIR 0x00000014 +#define MCASP_O_PDOUT 0x00000018 +#define MCASP_O_PDSET 0x0000001C // The pin data set register + // (PDSET) is an alias of the pin + // data output register (PDOUT) for + // writes only. Writing a 1 to the + // PDSET bit sets the corresponding + // bit in PDOUT and if PFUNC = 1 + // (GPIO function) and PDIR = 1 + // (output) drives a logic high on + // the pin. +#define MCASP_O_PDIN 0x0000001C // The pin data input register + // (PDIN) holds the I/O pin state of + // each of the McASP pins. PDIN + // allows the actual value of the + // pin to be read regardless of the + // state of PFUNC and PDIR. +#define MCASP_O_PDCLR 0x00000020 // The pin data clear register + // (PDCLR) is an alias of the pin + // data output register (PDOUT) for + // writes only. Writing a 1 to the + // PDCLR bit clears the + // corresponding bit in PDOUT and if + // PFUNC = 1 (GPIO function) and + // PDIR = 1 (output) drives a logic + // low on the pin. +#define MCASP_O_TLGC 0x00000030 // for IODFT +#define MCASP_O_TLMR 0x00000034 // for IODFT +#define MCASP_O_TLEC 0x00000038 // for IODFT +#define MCASP_O_GBLCTL 0x00000044 +#define MCASP_O_AMUTE 0x00000048 +#define MCASP_O_LBCTL 0x0000004C +#define MCASP_O_TXDITCTL 0x00000050 +#define MCASP_O_GBLCTLR 0x00000060 +#define MCASP_O_RXMASK 0x00000064 +#define MCASP_O_RXFMT 0x00000068 +#define MCASP_O_RXFMCTL 0x0000006C +#define MCASP_O_ACLKRCTL 0x00000070 +#define MCASP_O_AHCLKRCTL 0x00000074 +#define MCASP_O_RXTDM 0x00000078 +#define MCASP_O_EVTCTLR 0x0000007C +#define MCASP_O_RXSTAT 0x00000080 +#define MCASP_O_RXTDMSLOT 0x00000084 +#define MCASP_O_RXCLKCHK 0x00000088 +#define MCASP_O_REVTCTL 0x0000008C +#define MCASP_O_GBLCTLX 0x000000A0 +#define MCASP_O_TXMASK 0x000000A4 +#define MCASP_O_TXFMT 0x000000A8 +#define MCASP_O_TXFMCTL 0x000000AC +#define MCASP_O_ACLKXCTL 0x000000B0 +#define MCASP_O_AHCLKXCTL 0x000000B4 +#define MCASP_O_TXTDM 0x000000B8 +#define MCASP_O_EVTCTLX 0x000000BC +#define MCASP_O_TXSTAT 0x000000C0 +#define MCASP_O_TXTDMSLOT 0x000000C4 +#define MCASP_O_TXCLKCHK 0x000000C8 +#define MCASP_O_XEVTCTL 0x000000CC +#define MCASP_O_CLKADJEN 0x000000D0 +#define MCASP_O_DITCSRA0 0x00000100 +#define MCASP_O_DITCSRA1 0x00000104 +#define MCASP_O_DITCSRA2 0x00000108 +#define MCASP_O_DITCSRA3 0x0000010C +#define MCASP_O_DITCSRA4 0x00000110 +#define MCASP_O_DITCSRA5 0x00000114 +#define MCASP_O_DITCSRB0 0x00000118 +#define MCASP_O_DITCSRB1 0x0000011C +#define MCASP_O_DITCSRB2 0x00000120 +#define MCASP_O_DITCSRB3 0x00000124 +#define MCASP_O_DITCSRB4 0x00000128 +#define MCASP_O_DITCSRB5 0x0000012C +#define MCASP_O_DITUDRA0 0x00000130 +#define MCASP_O_DITUDRA1 0x00000134 +#define MCASP_O_DITUDRA2 0x00000138 +#define MCASP_O_DITUDRA3 0x0000013C +#define MCASP_O_DITUDRA4 0x00000140 +#define MCASP_O_DITUDRA5 0x00000144 +#define MCASP_O_DITUDRB0 0x00000148 +#define MCASP_O_DITUDRB1 0x0000014C +#define MCASP_O_DITUDRB2 0x00000150 +#define MCASP_O_DITUDRB3 0x00000154 +#define MCASP_O_DITUDRB4 0x00000158 +#define MCASP_O_DITUDRB5 0x0000015C +#define MCASP_O_XRSRCTL0 0x00000180 +#define MCASP_O_XRSRCTL1 0x00000184 +#define MCASP_O_XRSRCTL2 0x00000188 +#define MCASP_O_XRSRCTL3 0x0000018C +#define MCASP_O_XRSRCTL4 0x00000190 +#define MCASP_O_XRSRCTL5 0x00000194 +#define MCASP_O_XRSRCTL6 0x00000198 +#define MCASP_O_XRSRCTL7 0x0000019C +#define MCASP_O_XRSRCTL8 0x000001A0 +#define MCASP_O_XRSRCTL9 0x000001A4 +#define MCASP_O_XRSRCTL10 0x000001A8 +#define MCASP_O_XRSRCTL11 0x000001AC +#define MCASP_O_XRSRCTL12 0x000001B0 +#define MCASP_O_XRSRCTL13 0x000001B4 +#define MCASP_O_XRSRCTL14 0x000001B8 +#define MCASP_O_XRSRCTL15 0x000001BC +#define MCASP_O_TXBUF0 0x00000200 +#define MCASP_O_TXBUF1 0x00000204 +#define MCASP_O_TXBUF2 0x00000208 +#define MCASP_O_TXBUF3 0x0000020C +#define MCASP_O_TXBUF4 0x00000210 +#define MCASP_O_TXBUF5 0x00000214 +#define MCASP_O_TXBUF6 0x00000218 +#define MCASP_O_TXBUF7 0x0000021C +#define MCASP_O_TXBUF8 0x00000220 +#define MCASP_O_TXBUF9 0x00000224 +#define MCASP_O_TXBUF10 0x00000228 +#define MCASP_O_TXBUF11 0x0000022C +#define MCASP_O_TXBUF12 0x00000230 +#define MCASP_O_TXBUF13 0x00000234 +#define MCASP_O_TXBUF14 0x00000238 +#define MCASP_O_TXBUF15 0x0000023C +#define MCASP_O_RXBUF0 0x00000280 +#define MCASP_O_RXBUF1 0x00000284 +#define MCASP_O_RXBUF2 0x00000288 +#define MCASP_O_RXBUF3 0x0000028C +#define MCASP_O_RXBUF4 0x00000290 +#define MCASP_O_RXBUF5 0x00000294 +#define MCASP_O_RXBUF6 0x00000298 +#define MCASP_O_RXBUF7 0x0000029C +#define MCASP_O_RXBUF8 0x000002A0 +#define MCASP_O_RXBUF9 0x000002A4 +#define MCASP_O_RXBUF10 0x000002A8 +#define MCASP_O_RXBUF11 0x000002AC +#define MCASP_O_RXBUF12 0x000002B0 +#define MCASP_O_RXBUF13 0x000002B4 +#define MCASP_O_RXBUF14 0x000002B8 +#define MCASP_O_RXBUF15 0x000002BC +#define MCASP_0_WFIFOCTL 0x00001000 +#define MCASP_0_WFIFOSTS 0x00001004 +#define MCASP_0_RFIFOCTL 0x00001008 +#define MCASP_0_RFIFOSTS 0x0000100C + + +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_PID register. +// +//****************************************************************************** +#define MCASP_PID_SCHEME_M 0xC0000000 +#define MCASP_PID_SCHEME_S 30 +#define MCASP_PID_RESV_M 0x30000000 +#define MCASP_PID_RESV_S 28 +#define MCASP_PID_FUNCTION_M 0x0FFF0000 // McASP +#define MCASP_PID_FUNCTION_S 16 +#define MCASP_PID_RTL_M 0x0000F800 +#define MCASP_PID_RTL_S 11 +#define MCASP_PID_REVMAJOR_M 0x00000700 +#define MCASP_PID_REVMAJOR_S 8 +#define MCASP_PID_CUSTOM_M 0x000000C0 // non-custom +#define MCASP_PID_CUSTOM_S 6 +#define MCASP_PID_REVMINOR_M 0x0000003F +#define MCASP_PID_REVMINOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// MCASP_O_ESYSCONFIG register. +// +//****************************************************************************** +#define MCASP_ESYSCONFIG_RSV_M 0xFFFFFFC0 // Reserved as per PDR 3.5 +#define MCASP_ESYSCONFIG_RSV_S 6 +#define MCASP_ESYSCONFIG_OTHER_M \ + 0x0000003C // Reserved for future expansion + +#define MCASP_ESYSCONFIG_OTHER_S 2 +#define MCASP_ESYSCONFIG_IDLE_MODE_M \ + 0x00000003 // Idle Mode + +#define MCASP_ESYSCONFIG_IDLE_MODE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_PFUNC register. +// +//****************************************************************************** +#define MCASP_PFUNC_AFSR 0x80000000 // AFSR PFUNC 31 0 1 +#define MCASP_PFUNC_AHCLKR 0x40000000 // AHCLKR PFUNC 30 0 1 +#define MCASP_PFUNC_ACLKR 0x20000000 // ACLKR PFUNC 29 0 1 +#define MCASP_PFUNC_AFSX 0x10000000 // AFSX PFUNC 28 0 1 +#define MCASP_PFUNC_AHCLKX 0x08000000 // AHCLKX PFUNC 27 0 1 +#define MCASP_PFUNC_ACLKX 0x04000000 // ACLKX PFUNC 26 0 1 +#define MCASP_PFUNC_AMUTE 0x02000000 // AMUTE PFUNC 25 0 1 +#define MCASP_PFUNC_RESV1_M 0x01FF0000 // Reserved +#define MCASP_PFUNC_RESV1_S 16 +#define MCASP_PFUNC_AXR15 0x00008000 // AXR PFUNC BIT 15 0 1 +#define MCASP_PFUNC_AXR14 0x00004000 // AXR PFUNC BIT 14 0 1 +#define MCASP_PFUNC_AXR13 0x00002000 // AXR PFUNC BIT 13 0 1 +#define MCASP_PFUNC_AXR12 0x00001000 // AXR PFUNC BIT 12 0 1 +#define MCASP_PFUNC_AXR11 0x00000800 // AXR PFUNC BIT 11 0 1 +#define MCASP_PFUNC_AXR10 0x00000400 // AXR PFUNC BIT 10 0 1 +#define MCASP_PFUNC_AXR9 0x00000200 // AXR PFUNC BIT 9 0 1 +#define MCASP_PFUNC_AXR8 0x00000100 // AXR PFUNC BIT 8 0 1 +#define MCASP_PFUNC_AXR7 0x00000080 // AXR PFUNC BIT 7 0 1 +#define MCASP_PFUNC_AXR6 0x00000040 // AXR PFUNC BIT 6 0 1 +#define MCASP_PFUNC_AXR5 0x00000020 // AXR PFUNC BIT 5 0 1 +#define MCASP_PFUNC_AXR4 0x00000010 // AXR PFUNC BIT 4 0 1 +#define MCASP_PFUNC_AXR3 0x00000008 // AXR PFUNC BIT 3 0 1 +#define MCASP_PFUNC_AXR2 0x00000004 // AXR PFUNC BIT 2 0 1 +#define MCASP_PFUNC_AXR1 0x00000002 // AXR PFUNC BIT 1 0 1 +#define MCASP_PFUNC_AXR0 0x00000001 // AXR PFUNC BIT 0 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_PDIR register. +// +//****************************************************************************** +#define MCASP_PDIR_AFSR 0x80000000 // AFSR PDIR 31 0 1 +#define MCASP_PDIR_AHCLKR 0x40000000 // AHCLKR PDIR 30 0 1 +#define MCASP_PDIR_ACLKR 0x20000000 // ACLKR PDIR 29 0 1 +#define MCASP_PDIR_AFSX 0x10000000 // AFSX PDIR 28 0 1 +#define MCASP_PDIR_AHCLKX 0x08000000 // AHCLKX PDIR 27 0 1 +#define MCASP_PDIR_ACLKX 0x04000000 // ACLKX PDIR 26 0 1 +#define MCASP_PDIR_AMUTE 0x02000000 // AMUTE PDIR 25 0 1 +#define MCASP_PDIR_RESV_M 0x01FF0000 // Reserved +#define MCASP_PDIR_RESV_S 16 +#define MCASP_PDIR_AXR15 0x00008000 // AXR PDIR BIT 15 0 1 +#define MCASP_PDIR_AXR14 0x00004000 // AXR PDIR BIT 14 0 1 +#define MCASP_PDIR_AXR13 0x00002000 // AXR PDIR BIT 13 0 1 +#define MCASP_PDIR_AXR12 0x00001000 // AXR PDIR BIT 12 0 1 +#define MCASP_PDIR_AXR11 0x00000800 // AXR PDIR BIT 11 0 1 +#define MCASP_PDIR_AXR10 0x00000400 // AXR PDIR BIT 10 0 1 +#define MCASP_PDIR_AXR9 0x00000200 // AXR PDIR BIT 9 0 1 +#define MCASP_PDIR_AXR8 0x00000100 // AXR PDIR BIT 8 0 1 +#define MCASP_PDIR_AXR7 0x00000080 // AXR PDIR BIT 7 0 1 +#define MCASP_PDIR_AXR6 0x00000040 // AXR PDIR BIT 6 0 1 +#define MCASP_PDIR_AXR5 0x00000020 // AXR PDIR BIT 5 0 1 +#define MCASP_PDIR_AXR4 0x00000010 // AXR PDIR BIT 4 0 1 +#define MCASP_PDIR_AXR3 0x00000008 // AXR PDIR BIT 3 0 1 +#define MCASP_PDIR_AXR2 0x00000004 // AXR PDIR BIT 2 0 1 +#define MCASP_PDIR_AXR1 0x00000002 // AXR PDIR BIT 1 0 1 +#define MCASP_PDIR_AXR0 0x00000001 // AXR PDIR BIT 0 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_PDOUT register. +// +//****************************************************************************** +#define MCASP_PDOUT_AFSR 0x80000000 // AFSR PDOUT 31 0 1 +#define MCASP_PDOUT_AHCLKR 0x40000000 // AHCLKR PDOUT 30 0 1 +#define MCASP_PDOUT_ACLKR 0x20000000 // ACLKR PDOUT 29 0 1 +#define MCASP_PDOUT_AFSX 0x10000000 // AFSX PDOUT 28 0 1 +#define MCASP_PDOUT_AHCLKX 0x08000000 // AHCLKX PDOUT 27 0 1 +#define MCASP_PDOUT_ACLKX 0x04000000 // ACLKX PDOUT 26 0 1 +#define MCASP_PDOUT_AMUTE 0x02000000 // AMUTE PDOUT 25 0 1 +#define MCASP_PDOUT_RESV_M 0x01FF0000 // Reserved +#define MCASP_PDOUT_RESV_S 16 +#define MCASP_PDOUT_AXR15 0x00008000 // AXR PDOUT BIT 15 0 1 +#define MCASP_PDOUT_AXR14 0x00004000 // AXR PDOUT BIT 14 0 1 +#define MCASP_PDOUT_AXR13 0x00002000 // AXR PDOUT BIT 13 0 1 +#define MCASP_PDOUT_AXR12 0x00001000 // AXR PDOUT BIT 12 0 1 +#define MCASP_PDOUT_AXR11 0x00000800 // AXR PDOUT BIT 11 0 1 +#define MCASP_PDOUT_AXR10 0x00000400 // AXR PDOUT BIT 10 0 1 +#define MCASP_PDOUT_AXR9 0x00000200 // AXR PDOUT BIT 9 0 1 +#define MCASP_PDOUT_AXR8 0x00000100 // AXR PDOUT BIT 8 0 1 +#define MCASP_PDOUT_AXR7 0x00000080 // AXR PDOUT BIT 7 0 1 +#define MCASP_PDOUT_AXR6 0x00000040 // AXR PDOUT BIT 6 0 1 +#define MCASP_PDOUT_AXR5 0x00000020 // AXR PDOUT BIT 5 0 1 +#define MCASP_PDOUT_AXR4 0x00000010 // AXR PDOUT BIT 4 0 1 +#define MCASP_PDOUT_AXR3 0x00000008 // AXR PDOUT BIT 3 0 1 +#define MCASP_PDOUT_AXR2 0x00000004 // AXR PDOUT BIT 2 0 1 +#define MCASP_PDOUT_AXR1 0x00000002 // AXR PDOUT BIT 1 0 1 +#define MCASP_PDOUT_AXR0 0x00000001 // AXR PDOUT BIT 0 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_PDSET register. +// +//****************************************************************************** +#define MCASP_PDSET_AFSR 0x80000000 +#define MCASP_PDSET_AHCLKR 0x40000000 +#define MCASP_PDSET_ACLKR 0x20000000 +#define MCASP_PDSET_AFSX 0x10000000 +#define MCASP_PDSET_AHCLKX 0x08000000 +#define MCASP_PDSET_ACLKX 0x04000000 +#define MCASP_PDSET_AMUTE 0x02000000 +#define MCASP_PDSET_RESV_M 0x01FF0000 // Reserved +#define MCASP_PDSET_RESV_S 16 +#define MCASP_PDSET_AXR15 0x00008000 +#define MCASP_PDSET_AXR14 0x00004000 +#define MCASP_PDSET_AXR13 0x00002000 +#define MCASP_PDSET_AXR12 0x00001000 +#define MCASP_PDSET_AXR11 0x00000800 +#define MCASP_PDSET_AXR10 0x00000400 +#define MCASP_PDSET_AXR9 0x00000200 +#define MCASP_PDSET_AXR8 0x00000100 +#define MCASP_PDSET_AXR7 0x00000080 +#define MCASP_PDSET_AXR6 0x00000040 +#define MCASP_PDSET_AXR5 0x00000020 +#define MCASP_PDSET_AXR4 0x00000010 +#define MCASP_PDSET_AXR3 0x00000008 +#define MCASP_PDSET_AXR2 0x00000004 +#define MCASP_PDSET_AXR1 0x00000002 +#define MCASP_PDSET_AXR0 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_PDIN register. +// +//****************************************************************************** +#define MCASP_PDIN_AFSR 0x80000000 +#define MCASP_PDIN_AHCLKR 0x40000000 +#define MCASP_PDIN_ACLKR 0x20000000 +#define MCASP_PDIN_AFSX 0x10000000 +#define MCASP_PDIN_AHCLKX 0x08000000 +#define MCASP_PDIN_ACLKX 0x04000000 +#define MCASP_PDIN_AMUTE 0x02000000 +#define MCASP_PDIN_RESV_M 0x01FF0000 // Reserved +#define MCASP_PDIN_RESV_S 16 +#define MCASP_PDIN_AXR15 0x00008000 +#define MCASP_PDIN_AXR14 0x00004000 +#define MCASP_PDIN_AXR13 0x00002000 +#define MCASP_PDIN_AXR12 0x00001000 +#define MCASP_PDIN_AXR11 0x00000800 +#define MCASP_PDIN_AXR10 0x00000400 +#define MCASP_PDIN_AXR9 0x00000200 +#define MCASP_PDIN_AXR8 0x00000100 +#define MCASP_PDIN_AXR7 0x00000080 +#define MCASP_PDIN_AXR6 0x00000040 +#define MCASP_PDIN_AXR5 0x00000020 +#define MCASP_PDIN_AXR4 0x00000010 +#define MCASP_PDIN_AXR3 0x00000008 +#define MCASP_PDIN_AXR2 0x00000004 +#define MCASP_PDIN_AXR1 0x00000002 +#define MCASP_PDIN_AXR0 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_PDCLR register. +// +//****************************************************************************** +#define MCASP_PDCLR_AFSR 0x80000000 // AFSR PDCLR 31 0 1 +#define MCASP_PDCLR_AHCLKR 0x40000000 // AHCLKR PDCLR 30 0 1 +#define MCASP_PDCLR_ACLKR 0x20000000 // ACLKR PDCLR 29 0 1 +#define MCASP_PDCLR_AFSX 0x10000000 // AFSX PDCLR 28 0 1 +#define MCASP_PDCLR_AHCLKX 0x08000000 // AHCLKX PDCLR 27 0 1 +#define MCASP_PDCLR_ACLKX 0x04000000 // ACLKX PDCLR 26 0 1 +#define MCASP_PDCLR_AMUTE 0x02000000 // AMUTE PDCLR 25 0 1 +#define MCASP_PDCLR_RESV_M 0x01FF0000 // Reserved +#define MCASP_PDCLR_RESV_S 16 +#define MCASP_PDCLR_AXR15 0x00008000 // AXR PDCLR BIT 15 0 1 +#define MCASP_PDCLR_AXR14 0x00004000 // AXR PDCLR BIT 14 0 1 +#define MCASP_PDCLR_AXR13 0x00002000 // AXR PDCLR BIT 13 0 1 +#define MCASP_PDCLR_AXR12 0x00001000 // AXR PDCLR BIT 12 0 1 +#define MCASP_PDCLR_AXR11 0x00000800 // AXR PDCLR BIT 11 0 1 +#define MCASP_PDCLR_AXR10 0x00000400 // AXR PDCLR BIT 10 0 1 +#define MCASP_PDCLR_AXR9 0x00000200 // AXR PDCLR BIT 9 0 1 +#define MCASP_PDCLR_AXR8 0x00000100 // AXR PDCLR BIT 8 0 1 +#define MCASP_PDCLR_AXR7 0x00000080 // AXR PDCLR BIT 7 0 1 +#define MCASP_PDCLR_AXR6 0x00000040 // AXR PDCLR BIT 6 0 1 +#define MCASP_PDCLR_AXR5 0x00000020 // AXR PDCLR BIT 5 0 1 +#define MCASP_PDCLR_AXR4 0x00000010 // AXR PDCLR BIT 4 0 1 +#define MCASP_PDCLR_AXR3 0x00000008 // AXR PDCLR BIT 3 0 1 +#define MCASP_PDCLR_AXR2 0x00000004 // AXR PDCLR BIT 2 0 1 +#define MCASP_PDCLR_AXR1 0x00000002 // AXR PDCLR BIT 1 0 1 +#define MCASP_PDCLR_AXR0 0x00000001 // AXR PDCLR BIT 0 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TLGC register. +// +//****************************************************************************** +#define MCASP_TLGC_RESV_M 0xFFFF0000 // Reserved +#define MCASP_TLGC_RESV_S 16 +#define MCASP_TLGC_MT_M 0x0000C000 // MISR on/off trigger command 0x0 + // 0x1 0x2 0x3 +#define MCASP_TLGC_MT_S 14 +#define MCASP_TLGC_RESV1_M 0x00003E00 // Reserved +#define MCASP_TLGC_RESV1_S 9 +#define MCASP_TLGC_MMS 0x00000100 // Source of MISR input 0 1 +#define MCASP_TLGC_ESEL 0x00000080 // Output enable select 0 1 +#define MCASP_TLGC_TOEN 0x00000040 // Test output enable control. 0 1 +#define MCASP_TLGC_MC_M 0x00000030 // States of MISR 0x0 0x1 0x2 0x3 +#define MCASP_TLGC_MC_S 4 +#define MCASP_TLGC_PC_M 0x0000000E // Pattern code 0x0 0x1 0x2 0x3 0x4 + // 0x5 0x6 0x7 +#define MCASP_TLGC_PC_S 1 +#define MCASP_TLGC_TM 0x00000001 // Tie high; do not write to this + // bit 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TLMR register. +// +//****************************************************************************** +#define MCASP_TLMR_TLMR_M 0xFFFFFFFF // Contains test result signature. +#define MCASP_TLMR_TLMR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TLEC register. +// +//****************************************************************************** +#define MCASP_TLEC_TLEC_M 0xFFFFFFFF // Contains number of cycles during + // which MISR sig will be + // accumulated. +#define MCASP_TLEC_TLEC_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_GBLCTL register. +// +//****************************************************************************** +#define MCASP_GBLCTL_XFRST 0x00001000 // Frame sync generator reset 0 1 +#define MCASP_GBLCTL_XSMRST 0x00000800 // XMT state machine reset 0 1 +#define MCASP_GBLCTL_XSRCLR 0x00000400 // XMT serializer clear 0 1 +#define MCASP_GBLCTL_XHCLKRST 0x00000200 // XMT High Freq. clk Divider 0 1 +#define MCASP_GBLCTL_XCLKRST 0x00000100 // XMT clock divder reset 0 1 +#define MCASP_GBLCTL_RFRST 0x00000010 // Frame sync generator reset 0 1 +#define MCASP_GBLCTL_RSMRST 0x00000008 // RCV state machine reset 0 1 +#define MCASP_GBLCTL_RSRCLR 0x00000004 // RCV serializer clear 0 1 +#define MCASP_GBLCTL_RHCLKRST 0x00000002 // RCV High Freq. clk Divider 0 1 +#define MCASP_GBLCTL_RCLKRST 0x00000001 // RCV clock divder reset 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_AMUTE register. +// +//****************************************************************************** +#define MCASP_AMUTE_XDMAERR 0x00001000 // MUTETXDMAERR occur 0 1 +#define MCASP_AMUTE_RDMAERR 0x00000800 // MUTERXDMAERR occur 0 1 +#define MCASP_AMUTE_XCKFAIL 0x00000400 // XMT bad clock 0 1 +#define MCASP_AMUTE_RCKFAIL 0x00000200 // RCV bad clock 0 1 +#define MCASP_AMUTE_XSYNCERR 0x00000100 // XMT unexpected FS 0 1 +#define MCASP_AMUTE_RSYNCERR 0x00000080 // RCV unexpected FS 0 1 +#define MCASP_AMUTE_XUNDRN 0x00000040 // XMT underrun occurs 0 1 +#define MCASP_AMUTE_ROVRN 0x00000020 // RCV overun occurs 0 1 +#define MCASP_AMUTE_INSTAT 0x00000010 +#define MCASP_AMUTE_INEN 0x00000008 // drive AMUTE active on mute in + // active 0 1 +#define MCASP_AMUTE_INPOL 0x00000004 // Mute input polarity 0 1 +#define MCASP_AMUTE_MUTEN_M 0x00000003 // AMUTE pin enable 0x0 0x1 0x2 +#define MCASP_AMUTE_MUTEN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_LBCTL register. +// +//****************************************************************************** +#define MCASP_LBCTL_IOLBEN 0x00000010 // IO loopback enable 0 1 +#define MCASP_LBCTL_MODE_M 0x0000000C // Loop back clock source generator + // 0x0 0x1 0x2 0x3 +#define MCASP_LBCTL_MODE_S 2 +#define MCASP_LBCTL_ORD 0x00000002 // Loopback order 0 1 +#define MCASP_LBCTL_DLBEN 0x00000001 // Loop back mode 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXDITCTL register. +// +//****************************************************************************** +#define MCASP_TXDITCTL_VB 0x00000008 // Valib bit for odd TDM 0 1 +#define MCASP_TXDITCTL_VA 0x00000004 // Valib bit for even TDM 0 1 +#define MCASP_TXDITCTL_DITEN 0x00000001 // XMT DIT Mode Enable 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_GBLCTLR register. +// +//****************************************************************************** +#define MCASP_GBLCTLR_XFRST 0x00001000 +#define MCASP_GBLCTLR_XSMRST 0x00000800 +#define MCASP_GBLCTLR_XSRCLR 0x00000400 +#define MCASP_GBLCTLR_XHCLKRST 0x00000200 +#define MCASP_GBLCTLR_XCLKRST 0x00000100 +#define MCASP_GBLCTLR_RFRST 0x00000010 // Frame sync generator reset 0 1 +#define MCASP_GBLCTLR_RSMRST 0x00000008 // RCV state machine reset 0 1 +#define MCASP_GBLCTLR_RSRCLR 0x00000004 // RCV serializer clear 0 1 +#define MCASP_GBLCTLR_RHCLKRST 0x00000002 // RCV High Freq. clk Divider 0 1 +#define MCASP_GBLCTLR_RCLKRST 0x00000001 // RCV clock divder reset 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXMASK register. +// +//****************************************************************************** +#define MCASP_RXMASK_RMASK31 0x80000000 // RMASK BIT 31 0 1 +#define MCASP_RXMASK_RMASK30 0x40000000 // RMASK BIT 30 0 1 +#define MCASP_RXMASK_RMASK29 0x20000000 // RMASK BIT 29 0 1 +#define MCASP_RXMASK_RMASK28 0x10000000 // RMASK BIT 28 0 1 +#define MCASP_RXMASK_RMASK27 0x08000000 // RMASK BIT 27 0 1 +#define MCASP_RXMASK_RMASK26 0x04000000 // RMASK BIT 26 0 1 +#define MCASP_RXMASK_RMASK25 0x02000000 // RMASK BIT 25 0 1 +#define MCASP_RXMASK_RMASK24 0x01000000 // RMASK BIT 24 0 1 +#define MCASP_RXMASK_RMASK23 0x00800000 // RMASK BIT 23 0 1 +#define MCASP_RXMASK_RMASK22 0x00400000 // RMASK BIT 22 0 1 +#define MCASP_RXMASK_RMASK21 0x00200000 // RMASK BIT 21 0 1 +#define MCASP_RXMASK_RMASK20 0x00100000 // RMASK BIT 20 0 1 +#define MCASP_RXMASK_RMASK19 0x00080000 // RMASK BIT 19 0 1 +#define MCASP_RXMASK_RMASK18 0x00040000 // RMASK BIT 18 0 1 +#define MCASP_RXMASK_RMASK17 0x00020000 // RMASK BIT 17 0 1 +#define MCASP_RXMASK_RMASK16 0x00010000 // RMASK BIT 16 0 1 +#define MCASP_RXMASK_RMASK15 0x00008000 // RMASK BIT 15 0 1 +#define MCASP_RXMASK_RMASK14 0x00004000 // RMASK BIT 14 0 1 +#define MCASP_RXMASK_RMASK13 0x00002000 // RMASK BIT 13 0 1 +#define MCASP_RXMASK_RMASK12 0x00001000 // RMASK BIT 12 0 1 +#define MCASP_RXMASK_RMASK11 0x00000800 // RMASK BIT 11 0 1 +#define MCASP_RXMASK_RMASK10 0x00000400 // RMASK BIT 10 0 1 +#define MCASP_RXMASK_RMASK9 0x00000200 // RMASK BIT 9 0 1 +#define MCASP_RXMASK_RMASK8 0x00000100 // RMASK BIT 8 0 1 +#define MCASP_RXMASK_RMASK7 0x00000080 // RMASK BIT 7 0 1 +#define MCASP_RXMASK_RMASK6 0x00000040 // RMASK BIT 6 0 1 +#define MCASP_RXMASK_RMASK5 0x00000020 // RMASK BIT 5 0 1 +#define MCASP_RXMASK_RMASK4 0x00000010 // RMASK BIT 4 0 1 +#define MCASP_RXMASK_RMASK3 0x00000008 // RMASK BIT 3 0 1 +#define MCASP_RXMASK_RMASK2 0x00000004 // RMASK BIT 2 0 1 +#define MCASP_RXMASK_RMASK1 0x00000002 // RMASK BIT 1 0 1 +#define MCASP_RXMASK_RMASK0 0x00000001 // RMASK BIT 0 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXFMT register. +// +//****************************************************************************** +#define MCASP_RXFMT_RDATDLY_M 0x00030000 // RCV Frame sync delay 0x0 0 Bit + // delay 0x1 1 Bit delay 0x2 2 Bit + // delay +#define MCASP_RXFMT_RDATDLY_S 16 +#define MCASP_RXFMT_RRVRS 0x00008000 // RCV serial stream bit order 0 1 +#define MCASP_RXFMT_RPAD_M 0x00006000 // Pad value 0x0 0x1 0x2 +#define MCASP_RXFMT_RPAD_S 13 +#define MCASP_RXFMT_RPBIT_M 0x00001F00 // Pad bit position +#define MCASP_RXFMT_RPBIT_S 8 +#define MCASP_RXFMT_RSSZ_M 0x000000F0 // RCV slot Size 0x0 0x1 0x2 0x3 + // 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB + // 0xC 0xD 0xE 0xF +#define MCASP_RXFMT_RSSZ_S 4 +#define MCASP_RXFMT_RBUSEL 0x00000008 // Write to RBUF using CPU/DMA 0 + // DMA port access 1 CPU port Access +#define MCASP_RXFMT_RROT_M 0x00000007 // Right Rotate Value 0x0 0x1 0x2 + // 0x3 0x4 0x5 0x6 0x7 +#define MCASP_RXFMT_RROT_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXFMCTL register. +// +//****************************************************************************** +#define MCASP_RXFMCTL_RMOD_M 0x0000FF80 // RCV Frame sync mode +#define MCASP_RXFMCTL_RMOD_S 7 +#define MCASP_RXFMCTL_FRWID 0x00000010 // RCV Frame sync Duration 0 1 +#define MCASP_RXFMCTL_FSRM 0x00000002 // RCV frame sync External 0 1 +#define MCASP_RXFMCTL_FSRP 0x00000001 // RCV Frame sync Polarity 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_ACLKRCTL register. +// +//****************************************************************************** +#define MCASP_ACLKRCTL_BUSY 0x00100000 +#define MCASP_ACLKRCTL_DIVBUSY 0x00080000 +#define MCASP_ACLKRCTL_ADJBUSY 0x00040000 +#define MCASP_ACLKRCTL_CLKRADJ_M \ + 0x00030000 + +#define MCASP_ACLKRCTL_CLKRADJ_S 16 +#define MCASP_ACLKRCTL_CLKRP 0x00000080 // RCV Clock Polarity 0 1 +#define MCASP_ACLKRCTL_CLKRM 0x00000020 // RCV clock source 0 1 +#define MCASP_ACLKRCTL_CLKRDIV_M \ + 0x0000001F // RCV clock devide ratio + +#define MCASP_ACLKRCTL_CLKRDIV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_AHCLKRCTL register. +// +//****************************************************************************** +#define MCASP_AHCLKRCTL_BUSY 0x00100000 +#define MCASP_AHCLKRCTL_DIVBUSY 0x00080000 +#define MCASP_AHCLKRCTL_ADJBUSY 0x00040000 +#define MCASP_AHCLKRCTL_HCLKRADJ_M \ + 0x00030000 + +#define MCASP_AHCLKRCTL_HCLKRADJ_S 16 +#define MCASP_AHCLKRCTL_HCLKRM 0x00008000 // High Freq. RCV clock Source 0 1 +#define MCASP_AHCLKRCTL_HCLKRP 0x00004000 // High Freq. clock Polarity Before + // diviser 0 1 +#define MCASP_AHCLKRCTL_HCLKRDIV_M \ + 0x00000FFF // RCV clock Divide Ratio + +#define MCASP_AHCLKRCTL_HCLKRDIV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXTDM register. +// +//****************************************************************************** +#define MCASP_RXTDM_RTDMS31 0x80000000 // RCV mode during TDM time slot 31 + // 0 1 +#define MCASP_RXTDM_RTDMS30 0x40000000 // RCV mode during TDM time slot 30 + // 0 1 +#define MCASP_RXTDM_RTDMS29 0x20000000 // RCV mode during TDM time slot 29 + // 0 1 +#define MCASP_RXTDM_RTDMS28 0x10000000 // RCV mode during TDM time slot 28 + // 0 1 +#define MCASP_RXTDM_RTDMS27 0x08000000 // RCV mode during TDM time slot 27 + // 0 1 +#define MCASP_RXTDM_RTDMS26 0x04000000 // RCV mode during TDM time slot 26 + // 0 1 +#define MCASP_RXTDM_RTDMS25 0x02000000 // RCV mode during TDM time slot 25 + // 0 1 +#define MCASP_RXTDM_RTDMS24 0x01000000 // RCV mode during TDM time slot 24 + // 0 1 +#define MCASP_RXTDM_RTDMS23 0x00800000 // RCV mode during TDM time slot 23 + // 0 1 +#define MCASP_RXTDM_RTDMS22 0x00400000 // RCV mode during TDM time slot 22 + // 0 1 +#define MCASP_RXTDM_RTDMS21 0x00200000 // RCV mode during TDM time slot 21 + // 0 1 +#define MCASP_RXTDM_RTDMS20 0x00100000 // RCV mode during TDM time slot 20 + // 0 1 +#define MCASP_RXTDM_RTDMS19 0x00080000 // RCV mode during TDM time slot 19 + // 0 1 +#define MCASP_RXTDM_RTDMS18 0x00040000 // RCV mode during TDM time slot 18 + // 0 1 +#define MCASP_RXTDM_RTDMS17 0x00020000 // RCV mode during TDM time slot 17 + // 0 1 +#define MCASP_RXTDM_RTDMS16 0x00010000 // RCV mode during TDM time slot 16 + // 0 1 +#define MCASP_RXTDM_RTDMS15 0x00008000 // RCV mode during TDM time slot 15 + // 0 1 +#define MCASP_RXTDM_RTDMS14 0x00004000 // RCV mode during TDM time slot 14 + // 0 1 +#define MCASP_RXTDM_RTDMS13 0x00002000 // RCV mode during TDM time slot 13 + // 0 1 +#define MCASP_RXTDM_RTDMS12 0x00001000 // RCV mode during TDM time slot 12 + // 0 1 +#define MCASP_RXTDM_RTDMS11 0x00000800 // RCV mode during TDM time slot 11 + // 0 1 +#define MCASP_RXTDM_RTDMS10 0x00000400 // RCV mode during TDM time slot 10 + // 0 1 +#define MCASP_RXTDM_RTDMS9 0x00000200 // RCV mode during TDM time slot 9 + // 0 1 +#define MCASP_RXTDM_RTDMS8 0x00000100 // RCV mode during TDM time slot 8 + // 0 1 +#define MCASP_RXTDM_RTDMS7 0x00000080 // RCV mode during TDM time slot 7 + // 0 1 +#define MCASP_RXTDM_RTDMS6 0x00000040 // RCV mode during TDM time slot 6 + // 0 1 +#define MCASP_RXTDM_RTDMS5 0x00000020 // RCV mode during TDM time slot 5 + // 0 1 +#define MCASP_RXTDM_RTDMS4 0x00000010 // RCV mode during TDM time slot 4 + // 0 1 +#define MCASP_RXTDM_RTDMS3 0x00000008 // RCV mode during TDM time slot 3 + // 0 1 +#define MCASP_RXTDM_RTDMS2 0x00000004 // RCV mode during TDM time slot 2 + // 0 1 +#define MCASP_RXTDM_RTDMS1 0x00000002 // RCV mode during TDM time slot 1 + // 0 1 +#define MCASP_RXTDM_RTDMS0 0x00000001 // RCV mode during TDM time slot 0 + // 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_EVTCTLR register. +// +//****************************************************************************** +#define MCASP_EVTCTLR_RSTAFRM 0x00000080 // RCV Start of Frame Interrupt 0 1 +#define MCASP_EVTCTLR_RDATA 0x00000020 // RCV Data Interrupt 0 1 +#define MCASP_EVTCTLR_RLAST 0x00000010 // RCV Last Slot Interrupt 0 1 +#define MCASP_EVTCTLR_RDMAERR 0x00000008 // RCV DMA Bus Error 0 1 +#define MCASP_EVTCTLR_RCKFAIL 0x00000004 // Bad Clock Interrupt 0 1 +#define MCASP_EVTCTLR_RSYNCERR 0x00000002 // RCV Unexpected FSR Interrupt 0 1 +#define MCASP_EVTCTLR_ROVRN 0x00000001 // RCV Underrun Flag 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXSTAT register. +// +//****************************************************************************** +#define MCASP_RXSTAT_RERR 0x00000100 // RCV Error 0 1 +#define MCASP_RXSTAT_RDMAERR 0x00000080 // RCV DMA bus error 0 1 +#define MCASP_RXSTAT_RSTAFRM 0x00000040 // Start of Frame-RCV 0 1 +#define MCASP_RXSTAT_RDATA 0x00000020 // Data Ready Flag 0 1 +#define MCASP_RXSTAT_RLAST 0x00000010 // Last Slot Interrupt Flag 0 1 +#define MCASP_RXSTAT_RTDMSLOT 0x00000008 // EvenOdd Slot 0 1 +#define MCASP_RXSTAT_RCKFAIL 0x00000004 // Bad Transmit Flag 0 1 +#define MCASP_RXSTAT_RSYNCERR 0x00000002 // Unexpected RCV Frame sync flag 0 + // 1 +#define MCASP_RXSTAT_ROVRN 0x00000001 // RCV Underrun Flag 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXTDMSLOT register. +// +//****************************************************************************** +#define MCASP_RXTDMSLOT_RSLOTCNT_M \ + 0x000003FF // Current RCV time slot count + +#define MCASP_RXTDMSLOT_RSLOTCNT_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXCLKCHK register. +// +//****************************************************************************** +#define MCASP_RXCLKCHK_RCNT_M 0xFF000000 // RCV clock count value +#define MCASP_RXCLKCHK_RCNT_S 24 +#define MCASP_RXCLKCHK_RMAX_M 0x00FF0000 // RCV clock maximum boundary +#define MCASP_RXCLKCHK_RMAX_S 16 +#define MCASP_RXCLKCHK_RMIN_M 0x0000FF00 // RCV clock minimum boundary +#define MCASP_RXCLKCHK_RMIN_S 8 +#define MCASP_RXCLKCHK_RPS_M 0x0000000F // RCV clock check prescaler 0x0 + // 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 +#define MCASP_RXCLKCHK_RPS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_REVTCTL register. +// +//****************************************************************************** +#define MCASP_REVTCTL_RDATDMA 0x00000001 // RCV data DMA request 0 Enable + // DMA Transfer 1 Disable DMA + // Transfer +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_GBLCTLX register. +// +//****************************************************************************** +#define MCASP_GBLCTLX_XFRST 0x00001000 // Frame sync generator reset 0 1 +#define MCASP_GBLCTLX_XSMRST 0x00000800 // XMT state machine reset 0 1 +#define MCASP_GBLCTLX_XSRCLR 0x00000400 // XMT serializer clear 0 1 +#define MCASP_GBLCTLX_XHCLKRST 0x00000200 // XMT High Freq. clk Divider 0 1 +#define MCASP_GBLCTLX_XCLKRST 0x00000100 // XMT clock divder reset 0 1 +#define MCASP_GBLCTLX_RFRST 0x00000010 +#define MCASP_GBLCTLX_RSMRST 0x00000008 +#define MCASP_GBLCTLX_RSRCLKR 0x00000004 +#define MCASP_GBLCTLX_RHCLKRST 0x00000002 +#define MCASP_GBLCTLX_RCLKRST 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXMASK register. +// +//****************************************************************************** +#define MCASP_TXMASK_XMASK31 0x80000000 // XMASK BIT 31 0 1 +#define MCASP_TXMASK_XMASK30 0x40000000 // XMASK BIT 30 0 1 +#define MCASP_TXMASK_XMASK29 0x20000000 // XMASK BIT 29 0 1 +#define MCASP_TXMASK_XMASK28 0x10000000 // XMASK BIT 28 0 1 +#define MCASP_TXMASK_XMASK27 0x08000000 // XMASK BIT 27 0 1 +#define MCASP_TXMASK_XMASK26 0x04000000 // XMASK BIT 26 0 1 +#define MCASP_TXMASK_XMASK25 0x02000000 // XMASK BIT 25 0 1 +#define MCASP_TXMASK_XMASK24 0x01000000 // XMASK BIT 24 0 1 +#define MCASP_TXMASK_XMASK23 0x00800000 // XMASK BIT 23 0 1 +#define MCASP_TXMASK_XMASK22 0x00400000 // XMASK BIT 22 0 1 +#define MCASP_TXMASK_XMASK21 0x00200000 // XMASK BIT 21 0 1 +#define MCASP_TXMASK_XMASK20 0x00100000 // XMASK BIT 20 0 1 +#define MCASP_TXMASK_XMASK19 0x00080000 // XMASK BIT 19 0 1 +#define MCASP_TXMASK_XMASK18 0x00040000 // XMASK BIT 18 0 1 +#define MCASP_TXMASK_XMASK17 0x00020000 // XMASK BIT 17 0 1 +#define MCASP_TXMASK_XMASK16 0x00010000 // XMASK BIT 16 0 1 +#define MCASP_TXMASK_XMASK15 0x00008000 // XMASK BIT 15 0 1 +#define MCASP_TXMASK_XMASK14 0x00004000 // XMASK BIT 14 0 1 +#define MCASP_TXMASK_XMASK13 0x00002000 // XMASK BIT 13 0 1 +#define MCASP_TXMASK_XMASK12 0x00001000 // XMASK BIT 12 0 1 +#define MCASP_TXMASK_XMASK11 0x00000800 // XMASK BIT 11 0 1 +#define MCASP_TXMASK_XMASK10 0x00000400 // XMASK BIT 10 0 1 +#define MCASP_TXMASK_XMASK9 0x00000200 // XMASK BIT 9 0 1 +#define MCASP_TXMASK_XMASK8 0x00000100 // XMASK BIT 8 0 1 +#define MCASP_TXMASK_XMASK7 0x00000080 // XMASK BIT 7 0 1 +#define MCASP_TXMASK_XMASK6 0x00000040 // XMASK BIT 6 0 1 +#define MCASP_TXMASK_XMASK5 0x00000020 // XMASK BIT 5 0 1 +#define MCASP_TXMASK_XMASK4 0x00000010 // XMASK BIT 4 0 1 +#define MCASP_TXMASK_XMASK3 0x00000008 // XMASK BIT 3 0 1 +#define MCASP_TXMASK_XMASK2 0x00000004 // XMASK BIT 2 0 1 +#define MCASP_TXMASK_XMASK1 0x00000002 // XMASK BIT 1 0 1 +#define MCASP_TXMASK_XMASK0 0x00000001 // XMASK BIT 0 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXFMT register. +// +//****************************************************************************** +#define MCASP_TXFMT_XDATDLY_M 0x00030000 // XMT Frame sync delay 0x0 0 Bit + // delay 0x1 1 Bit delay 0x2 2 Bit + // delay +#define MCASP_TXFMT_XDATDLY_S 16 +#define MCASP_TXFMT_XRVRS 0x00008000 // XMT serial stream bit order 0 1 +#define MCASP_TXFMT_XPAD_M 0x00006000 // Pad value 0x0 0x1 0x2 +#define MCASP_TXFMT_XPAD_S 13 +#define MCASP_TXFMT_XPBIT_M 0x00001F00 // Pad bit position +#define MCASP_TXFMT_XPBIT_S 8 +#define MCASP_TXFMT_XSSZ_M 0x000000F0 // XMT slot Size 0x0 0x1 0x2 0x3 + // 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB + // 0xC 0xD 0xE 0xF +#define MCASP_TXFMT_XSSZ_S 4 +#define MCASP_TXFMT_XBUSEL 0x00000008 // Write to XBUF using CPU/DMA 0 + // DMA port access 1 CPU port Access +#define MCASP_TXFMT_XROT_M 0x00000007 // Right Rotate Value 0x0 0x1 0x2 + // 0x3 0x4 0x5 0x6 0x7 +#define MCASP_TXFMT_XROT_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXFMCTL register. +// +//****************************************************************************** +#define MCASP_TXFMCTL_XMOD_M 0x0000FF80 // XMT Frame sync mode +#define MCASP_TXFMCTL_XMOD_S 7 +#define MCASP_TXFMCTL_FXWID 0x00000010 // XMT Frame sync Duration 0 1 +#define MCASP_TXFMCTL_FSXM 0x00000002 // XMT frame sync External 0 1 +#define MCASP_TXFMCTL_FSXP 0x00000001 // XMT Frame sync Polarity 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_ACLKXCTL register. +// +//****************************************************************************** +#define MCASP_ACLKXCTL_BUSY 0x00100000 +#define MCASP_ACLKXCTL_DIVBUSY 0x00080000 +#define MCASP_ACLKXCTL_ADJBUSY 0x00040000 +#define MCASP_ACLKXCTL_CLKXADJ_M \ + 0x00030000 + +#define MCASP_ACLKXCTL_CLKXADJ_S 16 +#define MCASP_ACLKXCTL_CLKXP 0x00000080 // XMT Clock Polarity 0 1 +#define MCASP_ACLKXCTL_ASYNC 0x00000040 // XMT/RCV operation sync /Async 0 + // 1 +#define MCASP_ACLKXCTL_CLKXM 0x00000020 // XMT clock source 0 1 +#define MCASP_ACLKXCTL_CLKXDIV_M \ + 0x0000001F // XMT clock devide ratio + +#define MCASP_ACLKXCTL_CLKXDIV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_AHCLKXCTL register. +// +//****************************************************************************** +#define MCASP_AHCLKXCTL_BUSY 0x00100000 +#define MCASP_AHCLKXCTL_DIVBUSY 0x00080000 +#define MCASP_AHCLKXCTL_ADJBUSY 0x00040000 +#define MCASP_AHCLKXCTL_HCLKXADJ_M \ + 0x00030000 + +#define MCASP_AHCLKXCTL_HCLKXADJ_S 16 +#define MCASP_AHCLKXCTL_HCLKXM 0x00008000 // High Freq. XMT clock Source 0 1 +#define MCASP_AHCLKXCTL_HCLKXP 0x00004000 // High Freq. clock Polarity Before + // diviser 0 1 +#define MCASP_AHCLKXCTL_HCLKXDIV_M \ + 0x00000FFF // XMT clock Divide Ratio + +#define MCASP_AHCLKXCTL_HCLKXDIV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXTDM register. +// +//****************************************************************************** +#define MCASP_TXTDM_XTDMS31 0x80000000 // XMT mode during TDM time slot 31 + // 0 1 +#define MCASP_TXTDM_XTDMS30 0x40000000 // XMT mode during TDM time slot 30 + // 0 1 +#define MCASP_TXTDM_XTDMS29 0x20000000 // XMT mode during TDM time slot 29 + // 0 1 +#define MCASP_TXTDM_XTDMS28 0x10000000 // XMT mode during TDM time slot 28 + // 0 1 +#define MCASP_TXTDM_XTDMS27 0x08000000 // XMT mode during TDM time slot 27 + // 0 1 +#define MCASP_TXTDM_XTDMS26 0x04000000 // XMT mode during TDM time slot 26 + // 0 1 +#define MCASP_TXTDM_XTDMS25 0x02000000 // XMT mode during TDM time slot 25 + // 0 1 +#define MCASP_TXTDM_XTDMS24 0x01000000 // XMT mode during TDM time slot 24 + // 0 1 +#define MCASP_TXTDM_XTDMS23 0x00800000 // XMT mode during TDM time slot 23 + // 0 1 +#define MCASP_TXTDM_XTDMS22 0x00400000 // XMT mode during TDM time slot 22 + // 0 1 +#define MCASP_TXTDM_XTDMS21 0x00200000 // XMT mode during TDM time slot 21 + // 0 1 +#define MCASP_TXTDM_XTDMS20 0x00100000 // XMT mode during TDM time slot 20 + // 0 1 +#define MCASP_TXTDM_XTDMS19 0x00080000 // XMT mode during TDM time slot 19 + // 0 1 +#define MCASP_TXTDM_XTDMS18 0x00040000 // XMT mode during TDM time slot 18 + // 0 1 +#define MCASP_TXTDM_XTDMS17 0x00020000 // XMT mode during TDM time slot 17 + // 0 1 +#define MCASP_TXTDM_XTDMS16 0x00010000 // XMT mode during TDM time slot 16 + // 0 1 +#define MCASP_TXTDM_XTDMS15 0x00008000 // XMT mode during TDM time slot 15 + // 0 1 +#define MCASP_TXTDM_XTDMS14 0x00004000 // XMT mode during TDM time slot 14 + // 0 1 +#define MCASP_TXTDM_XTDMS13 0x00002000 // XMT mode during TDM time slot 13 + // 0 1 +#define MCASP_TXTDM_XTDMS12 0x00001000 // XMT mode during TDM time slot 12 + // 0 1 +#define MCASP_TXTDM_XTDMS11 0x00000800 // XMT mode during TDM time slot 11 + // 0 1 +#define MCASP_TXTDM_XTDMS10 0x00000400 // XMT mode during TDM time slot 10 + // 0 1 +#define MCASP_TXTDM_XTDMS9 0x00000200 // XMT mode during TDM time slot 9 + // 0 1 +#define MCASP_TXTDM_XTDMS8 0x00000100 // XMT mode during TDM time slot 8 + // 0 1 +#define MCASP_TXTDM_XTDMS7 0x00000080 // XMT mode during TDM time slot 7 + // 0 1 +#define MCASP_TXTDM_XTDMS6 0x00000040 // XMT mode during TDM time slot 6 + // 0 1 +#define MCASP_TXTDM_XTDMS5 0x00000020 // XMT mode during TDM time slot 5 + // 0 1 +#define MCASP_TXTDM_XTDMS4 0x00000010 // XMT mode during TDM time slot 4 + // 0 1 +#define MCASP_TXTDM_XTDMS3 0x00000008 // XMT mode during TDM time slot 3 + // 0 1 +#define MCASP_TXTDM_XTDMS2 0x00000004 // XMT mode during TDM time slot 2 + // 0 1 +#define MCASP_TXTDM_XTDMS1 0x00000002 // XMT mode during TDM time slot 1 + // 0 1 +#define MCASP_TXTDM_XTDMS0 0x00000001 // XMT mode during TDM time slot 0 + // 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_EVTCTLX register. +// +//****************************************************************************** +#define MCASP_EVTCTLX_XSTAFRM 0x00000080 // XMT Start of Frame Interrupt 0 1 +#define MCASP_EVTCTLX_XDATA 0x00000020 // XMT Data Interrupt 0 1 +#define MCASP_EVTCTLX_XLAST 0x00000010 // XMT Last Slot Interrupt 0 1 +#define MCASP_EVTCTLX_XDMAERR 0x00000008 // XMT DMA Bus Error 0 1 +#define MCASP_EVTCTLX_XCKFAIL 0x00000004 // Bad Clock Interrupt 0 1 +#define MCASP_EVTCTLX_XSYNCERR 0x00000002 // XMT Unexpected FSR Interrupt 0 1 +#define MCASP_EVTCTLX_XUNDRN 0x00000001 // XMT Underrun Interrupt 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXSTAT register. +// +//****************************************************************************** +#define MCASP_TXSTAT_XERR 0x00000100 // XMT Error 0 1 +#define MCASP_TXSTAT_XDMAERR 0x00000080 // XMT DMA bus error 0 1 +#define MCASP_TXSTAT_XSTAFRM 0x00000040 // Start of Frame-XMT 0 1 +#define MCASP_TXSTAT_XDATA 0x00000020 // Data Ready Flag 0 1 +#define MCASP_TXSTAT_XLAST 0x00000010 // Last Slot Interrupt Flag 0 1 +#define MCASP_TXSTAT_XTDMSLOT 0x00000008 // EvenOdd Slot 0 1 +#define MCASP_TXSTAT_XCKFAIL 0x00000004 // Bad Transmit Flag 0 1 +#define MCASP_TXSTAT_XSYNCERR 0x00000002 // Unexpected XMT Frame sync flag 0 + // 1 +#define MCASP_TXSTAT_XUNDRN 0x00000001 // XMT Underrun Flag 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXTDMSLOT register. +// +//****************************************************************************** +#define MCASP_TXTDMSLOT_XSLOTCNT_M \ + 0x000003FF // Current XMT time slot count + // during reset the value of this + // register is 0b0101111111 (0x17f) + // and after reset 0 + +#define MCASP_TXTDMSLOT_XSLOTCNT_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXCLKCHK register. +// +//****************************************************************************** +#define MCASP_TXCLKCHK_XCNT_M 0xFF000000 // XMT clock count value +#define MCASP_TXCLKCHK_XCNT_S 24 +#define MCASP_TXCLKCHK_XMAX_M 0x00FF0000 // XMT clock maximum boundary +#define MCASP_TXCLKCHK_XMAX_S 16 +#define MCASP_TXCLKCHK_XMIN_M 0x0000FF00 // XMT clock minimum boundary +#define MCASP_TXCLKCHK_XMIN_S 8 +#define MCASP_TXCLKCHK_RESV 0x00000080 // Reserved +#define MCASP_TXCLKCHK_XPS_M 0x0000000F // XMT clock check prescaler 0x0 + // 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 +#define MCASP_TXCLKCHK_XPS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XEVTCTL register. +// +//****************************************************************************** +#define MCASP_XEVTCTL_XDATDMA 0x00000001 // XMT data DMA request 0 Enable + // DMA Transfer 1 Disable DMA + // Transfer +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_CLKADJEN register. +// +//****************************************************************************** +#define MCASP_CLKADJEN_ENABLE 0x00000001 // One-shot clock adjust enable 0 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRA0 register. +// +//****************************************************************************** +#define MCASP_DITCSRA0_DITCSRA0_M \ + 0xFFFFFFFF // Left (Even TDM slot ) Channel + // status + +#define MCASP_DITCSRA0_DITCSRA0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRA1 register. +// +//****************************************************************************** +#define MCASP_DITCSRA1_DITCSRA1_M \ + 0xFFFFFFFF // Left (Even TDM slot ) Channel + // status + +#define MCASP_DITCSRA1_DITCSRA1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRA2 register. +// +//****************************************************************************** +#define MCASP_DITCSRA2_DITCSRA2_M \ + 0xFFFFFFFF // Left (Even TDM slot ) Channel + // status Register + +#define MCASP_DITCSRA2_DITCSRA2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRA3 register. +// +//****************************************************************************** +#define MCASP_DITCSRA3_DITCSRA3_M \ + 0xFFFFFFFF // Left (Even TDM slot ) Channel + // status Register + +#define MCASP_DITCSRA3_DITCSRA3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRA4 register. +// +//****************************************************************************** +#define MCASP_DITCSRA4_DITCSRA4_M \ + 0xFFFFFFFF // Left (Even TDM slot ) Channel + // status + +#define MCASP_DITCSRA4_DITCSRA4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRA5 register. +// +//****************************************************************************** +#define MCASP_DITCSRA5_DITCSRA5_M \ + 0xFFFFFFFF // Left (Even TDM slot ) Channel + // status + +#define MCASP_DITCSRA5_DITCSRA5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRB0 register. +// +//****************************************************************************** +#define MCASP_DITCSRB0_DITCSRB0_M \ + 0xFFFFFFFF // Right (odd TDM slot ) Channel + // status + +#define MCASP_DITCSRB0_DITCSRB0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRB1 register. +// +//****************************************************************************** +#define MCASP_DITCSRB1_DITCSRB1_M \ + 0xFFFFFFFF // Right (odd TDM slot ) Channel + // status + +#define MCASP_DITCSRB1_DITCSRB1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRB2 register. +// +//****************************************************************************** +#define MCASP_DITCSRB2_DITCSRB2_M \ + 0xFFFFFFFF // Right (odd TDM slot ) Channel + // status + +#define MCASP_DITCSRB2_DITCSRB2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRB3 register. +// +//****************************************************************************** +#define MCASP_DITCSRB3_DITCSRB3_M \ + 0xFFFFFFFF // Right (odd TDM slot ) Channel + // status + +#define MCASP_DITCSRB3_DITCSRB3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRB4 register. +// +//****************************************************************************** +#define MCASP_DITCSRB4_DITCSRB4_M \ + 0xFFFFFFFF // Right (odd TDM slot ) Channel + // status + +#define MCASP_DITCSRB4_DITCSRB4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITCSRB5 register. +// +//****************************************************************************** +#define MCASP_DITCSRB5_DITCSRB5_M \ + 0xFFFFFFFF // Right (odd TDM slot ) Channel + // status + +#define MCASP_DITCSRB5_DITCSRB5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRA0 register. +// +//****************************************************************************** +#define MCASP_DITUDRA0_DITUDRA0_M \ + 0xFFFFFFFF // Left (Even TDM slot ) User Data + +#define MCASP_DITUDRA0_DITUDRA0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRA1 register. +// +//****************************************************************************** +#define MCASP_DITUDRA1_DITUDRA1_M \ + 0xFFFFFFFF // Left (Even TDM slot ) User Data + +#define MCASP_DITUDRA1_DITUDRA1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRA2 register. +// +//****************************************************************************** +#define MCASP_DITUDRA2_DITUDRA2_M \ + 0xFFFFFFFF // Left (Even TDM slot ) User Data + +#define MCASP_DITUDRA2_DITUDRA2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRA3 register. +// +//****************************************************************************** +#define MCASP_DITUDRA3_DITUDRA3_M \ + 0xFFFFFFFF // Left (Even TDM slot ) User Data + +#define MCASP_DITUDRA3_DITUDRA3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRA4 register. +// +//****************************************************************************** +#define MCASP_DITUDRA4_DITUDRA4_M \ + 0xFFFFFFFF // Left (Even TDM slot ) User Data + +#define MCASP_DITUDRA4_DITUDRA4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRA5 register. +// +//****************************************************************************** +#define MCASP_DITUDRA5_DITUDRA5_M \ + 0xFFFFFFFF // Left (Even TDM slot ) User Data + +#define MCASP_DITUDRA5_DITUDRA5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRB0 register. +// +//****************************************************************************** +#define MCASP_DITUDRB0_DITUDRB0_M \ + 0xFFFFFFFF // Right (odd TDM slot ) User Data + +#define MCASP_DITUDRB0_DITUDRB0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRB1 register. +// +//****************************************************************************** +#define MCASP_DITUDRB1_DITUDRB1_M \ + 0xFFFFFFFF // Right (odd TDM slot ) User Data + +#define MCASP_DITUDRB1_DITUDRB1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRB2 register. +// +//****************************************************************************** +#define MCASP_DITUDRB2_DITUDRB2_M \ + 0xFFFFFFFF // Right (odd TDM slot ) User Data + +#define MCASP_DITUDRB2_DITUDRB2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRB3 register. +// +//****************************************************************************** +#define MCASP_DITUDRB3_DITUDRB3_M \ + 0xFFFFFFFF // Right (odd TDM slot ) User Data + +#define MCASP_DITUDRB3_DITUDRB3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRB4 register. +// +//****************************************************************************** +#define MCASP_DITUDRB4_DITUDRB4_M \ + 0xFFFFFFFF // Right (odd TDM slot ) User Data + +#define MCASP_DITUDRB4_DITUDRB4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_DITUDRB5 register. +// +//****************************************************************************** +#define MCASP_DITUDRB5_DITUDRB5_M \ + 0xFFFFFFFF // Right (odd TDM slot ) User Data + +#define MCASP_DITUDRB5_DITUDRB5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL0 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL0_RRDY 0x00000020 +#define MCASP_XRSRCTL0_XRDY 0x00000010 +#define MCASP_XRSRCTL0_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL0_DISMOD_S 2 +#define MCASP_XRSRCTL0_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL0_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL1 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL1_RRDY 0x00000020 +#define MCASP_XRSRCTL1_XRDY 0x00000010 +#define MCASP_XRSRCTL1_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL1_DISMOD_S 2 +#define MCASP_XRSRCTL1_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL1_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL2 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL2_RRDY 0x00000020 +#define MCASP_XRSRCTL2_XRDY 0x00000010 +#define MCASP_XRSRCTL2_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL2_DISMOD_S 2 +#define MCASP_XRSRCTL2_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL2_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL3 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL3_RRDY 0x00000020 +#define MCASP_XRSRCTL3_XRDY 0x00000010 +#define MCASP_XRSRCTL3_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL3_DISMOD_S 2 +#define MCASP_XRSRCTL3_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL3_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL4 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL4_RRDY 0x00000020 +#define MCASP_XRSRCTL4_XRDY 0x00000010 +#define MCASP_XRSRCTL4_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL4_DISMOD_S 2 +#define MCASP_XRSRCTL4_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL4_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL5 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL5_RRDY 0x00000020 +#define MCASP_XRSRCTL5_XRDY 0x00000010 +#define MCASP_XRSRCTL5_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL5_DISMOD_S 2 +#define MCASP_XRSRCTL5_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL5_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL6 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL6_RRDY 0x00000020 +#define MCASP_XRSRCTL6_XRDY 0x00000010 +#define MCASP_XRSRCTL6_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL6_DISMOD_S 2 +#define MCASP_XRSRCTL6_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL6_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL7 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL7_RRDY 0x00000020 +#define MCASP_XRSRCTL7_XRDY 0x00000010 +#define MCASP_XRSRCTL7_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL7_DISMOD_S 2 +#define MCASP_XRSRCTL7_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL7_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL8 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL8_RRDY 0x00000020 +#define MCASP_XRSRCTL8_XRDY 0x00000010 +#define MCASP_XRSRCTL8_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL8_DISMOD_S 2 +#define MCASP_XRSRCTL8_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL8_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL9 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL9_RRDY 0x00000020 +#define MCASP_XRSRCTL9_XRDY 0x00000010 +#define MCASP_XRSRCTL9_DISMOD_M 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high +#define MCASP_XRSRCTL9_DISMOD_S 2 +#define MCASP_XRSRCTL9_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL9_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL10 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL10_RRDY 0x00000020 +#define MCASP_XRSRCTL10_XRDY 0x00000010 +#define MCASP_XRSRCTL10_DISMOD_M \ + 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high + +#define MCASP_XRSRCTL10_DISMOD_S 2 +#define MCASP_XRSRCTL10_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL10_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL11 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL11_RRDY 0x00000020 +#define MCASP_XRSRCTL11_XRDY 0x00000010 +#define MCASP_XRSRCTL11_DISMOD_M \ + 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high + +#define MCASP_XRSRCTL11_DISMOD_S 2 +#define MCASP_XRSRCTL11_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL11_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL12 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL12_RRDY 0x00000020 +#define MCASP_XRSRCTL12_XRDY 0x00000010 +#define MCASP_XRSRCTL12_DISMOD_M \ + 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high + +#define MCASP_XRSRCTL12_DISMOD_S 2 +#define MCASP_XRSRCTL12_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL12_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL13 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL13_RRDY 0x00000020 +#define MCASP_XRSRCTL13_XRDY 0x00000010 +#define MCASP_XRSRCTL13_DISMOD_M \ + 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high + +#define MCASP_XRSRCTL13_DISMOD_S 2 +#define MCASP_XRSRCTL13_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL13_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL14 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL14_RRDY 0x00000020 +#define MCASP_XRSRCTL14_XRDY 0x00000010 +#define MCASP_XRSRCTL14_DISMOD_M \ + 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high + +#define MCASP_XRSRCTL14_DISMOD_S 2 +#define MCASP_XRSRCTL14_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL14_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_XRSRCTL15 register. +// +//****************************************************************************** +#define MCASP_XRSRCTL15_RRDY 0x00000020 +#define MCASP_XRSRCTL15_XRDY 0x00000010 +#define MCASP_XRSRCTL15_DISMOD_M \ + 0x0000000C // Serializer drive state 0x0 Tri + // state 0x1 Reserved 0x2 Drive pin + // low 0x3 Drive pin high + +#define MCASP_XRSRCTL15_DISMOD_S 2 +#define MCASP_XRSRCTL15_SRMOD_M 0x00000003 // Serializer Mode 0x0 InActive + // mode 0x1 Transmit mode 0x2 + // Receive mode +#define MCASP_XRSRCTL15_SRMOD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF0 register. +// +//****************************************************************************** +#define MCASP_TXBUF0_XBUF0_M 0xFFFFFFFF // Transmit Buffer 0 +#define MCASP_TXBUF0_XBUF0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF1 register. +// +//****************************************************************************** +#define MCASP_TXBUF1_XBUF1_M 0xFFFFFFFF // Transmit Buffer 1 +#define MCASP_TXBUF1_XBUF1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF2 register. +// +//****************************************************************************** +#define MCASP_TXBUF2_XBUF2_M 0xFFFFFFFF // Transmit Buffer 2 +#define MCASP_TXBUF2_XBUF2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF3 register. +// +//****************************************************************************** +#define MCASP_TXBUF3_XBUF3_M 0xFFFFFFFF // Transmit Buffer 3 +#define MCASP_TXBUF3_XBUF3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF4 register. +// +//****************************************************************************** +#define MCASP_TXBUF4_XBUF4_M 0xFFFFFFFF // Transmit Buffer 4 +#define MCASP_TXBUF4_XBUF4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF5 register. +// +//****************************************************************************** +#define MCASP_TXBUF5_XBUF5_M 0xFFFFFFFF // Transmit Buffer 5 +#define MCASP_TXBUF5_XBUF5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF6 register. +// +//****************************************************************************** +#define MCASP_TXBUF6_XBUF6_M 0xFFFFFFFF // Transmit Buffer 6 +#define MCASP_TXBUF6_XBUF6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF7 register. +// +//****************************************************************************** +#define MCASP_TXBUF7_XBUF7_M 0xFFFFFFFF // Transmit Buffer 7 +#define MCASP_TXBUF7_XBUF7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF8 register. +// +//****************************************************************************** +#define MCASP_TXBUF8_XBUF8_M 0xFFFFFFFF // Transmit Buffer 8 +#define MCASP_TXBUF8_XBUF8_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF9 register. +// +//****************************************************************************** +#define MCASP_TXBUF9_XBUF9_M 0xFFFFFFFF // Transmit Buffer 9 +#define MCASP_TXBUF9_XBUF9_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF10 register. +// +//****************************************************************************** +#define MCASP_TXBUF10_XBUF10_M 0xFFFFFFFF // Transmit Buffer 10 +#define MCASP_TXBUF10_XBUF10_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF11 register. +// +//****************************************************************************** +#define MCASP_TXBUF11_XBUF11_M 0xFFFFFFFF // Transmit Buffer 11 +#define MCASP_TXBUF11_XBUF11_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF12 register. +// +//****************************************************************************** +#define MCASP_TXBUF12_XBUF12_M 0xFFFFFFFF // Transmit Buffer 12 +#define MCASP_TXBUF12_XBUF12_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF13 register. +// +//****************************************************************************** +#define MCASP_TXBUF13_XBUF13_M 0xFFFFFFFF // Transmit Buffer 13 +#define MCASP_TXBUF13_XBUF13_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF14 register. +// +//****************************************************************************** +#define MCASP_TXBUF14_XBUF14_M 0xFFFFFFFF // Transmit Buffer 14 +#define MCASP_TXBUF14_XBUF14_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_TXBUF15 register. +// +//****************************************************************************** +#define MCASP_TXBUF15_XBUF15_M 0xFFFFFFFF // Transmit Buffer 15 +#define MCASP_TXBUF15_XBUF15_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF0 register. +// +//****************************************************************************** +#define MCASP_RXBUF0_RBUF0_M 0xFFFFFFFF // Receive Buffer 0 +#define MCASP_RXBUF0_RBUF0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF1 register. +// +//****************************************************************************** +#define MCASP_RXBUF1_RBUF1_M 0xFFFFFFFF // Receive Buffer 1 +#define MCASP_RXBUF1_RBUF1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF2 register. +// +//****************************************************************************** +#define MCASP_RXBUF2_RBUF2_M 0xFFFFFFFF // Receive Buffer 2 +#define MCASP_RXBUF2_RBUF2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF3 register. +// +//****************************************************************************** +#define MCASP_RXBUF3_RBUF3_M 0xFFFFFFFF // Receive Buffer 3 +#define MCASP_RXBUF3_RBUF3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF4 register. +// +//****************************************************************************** +#define MCASP_RXBUF4_RBUF4_M 0xFFFFFFFF // Receive Buffer 4 +#define MCASP_RXBUF4_RBUF4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF5 register. +// +//****************************************************************************** +#define MCASP_RXBUF5_RBUF5_M 0xFFFFFFFF // Receive Buffer 5 +#define MCASP_RXBUF5_RBUF5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF6 register. +// +//****************************************************************************** +#define MCASP_RXBUF6_RBUF6_M 0xFFFFFFFF // Receive Buffer 6 +#define MCASP_RXBUF6_RBUF6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF7 register. +// +//****************************************************************************** +#define MCASP_RXBUF7_RBUF7_M 0xFFFFFFFF // Receive Buffer 7 +#define MCASP_RXBUF7_RBUF7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF8 register. +// +//****************************************************************************** +#define MCASP_RXBUF8_RBUF8_M 0xFFFFFFFF // Receive Buffer 8 +#define MCASP_RXBUF8_RBUF8_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF9 register. +// +//****************************************************************************** +#define MCASP_RXBUF9_RBUF9_M 0xFFFFFFFF // Receive Buffer 9 +#define MCASP_RXBUF9_RBUF9_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF10 register. +// +//****************************************************************************** +#define MCASP_RXBUF10_RBUF10_M 0xFFFFFFFF // Receive Buffer 10 +#define MCASP_RXBUF10_RBUF10_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF11 register. +// +//****************************************************************************** +#define MCASP_RXBUF11_RBUF11_M 0xFFFFFFFF // Receive Buffer 11 +#define MCASP_RXBUF11_RBUF11_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF12 register. +// +//****************************************************************************** +#define MCASP_RXBUF12_RBUF12_M 0xFFFFFFFF // Receive Buffer 12 +#define MCASP_RXBUF12_RBUF12_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF13 register. +// +//****************************************************************************** +#define MCASP_RXBUF13_RBUF13_M 0xFFFFFFFF // Receive Buffer 13 +#define MCASP_RXBUF13_RBUF13_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF14 register. +// +//****************************************************************************** +#define MCASP_RXBUF14_RBUF14_M 0xFFFFFFFF // Receive Buffer 14 +#define MCASP_RXBUF14_RBUF14_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCASP_O_RXBUF15 register. +// +//****************************************************************************** +#define MCASP_RXBUF15_RBUF15_M 0xFFFFFFFF // Receive Buffer 15 +#define MCASP_RXBUF15_RBUF15_S 0 + + + +#endif // __HW_MCASP_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcspi.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcspi.h new file mode 100644 index 00000000..079e4b6b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mcspi.h @@ -0,0 +1,1745 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_MCSPI_H__ +#define __HW_MCSPI_H__ + +//***************************************************************************** +// +// The following are defines for the MCSPI register offsets. +// +//***************************************************************************** +#define MCSPI_O_HL_REV 0x00000000 // IP Revision Identifier (X.Y.R) + // Used by software to track + // features bugs and compatibility +#define MCSPI_O_HL_HWINFO 0x00000004 // Information about the IP + // module's hardware configuration + // i.e. typically the module's HDL + // generics (if any). Actual field + // format and encoding is up to the + // module's designer to decide. +#define MCSPI_O_HL_SYSCONFIG 0x00000010 // 0x4402 1010 0x4402 2010 Clock + // management configuration +#define MCSPI_O_REVISION 0x00000100 // 0x4402 1100 0x4402 2100 This + // register contains the hard coded + // RTL revision number. +#define MCSPI_O_SYSCONFIG 0x00000110 // 0x4402 1110 0x4402 2110 This + // register allows controlling + // various parameters of the OCP + // interface. +#define MCSPI_O_SYSSTATUS 0x00000114 // 0x4402 1114 0x4402 2114 This + // register provides status + // information about the module + // excluding the interrupt status + // information +#define MCSPI_O_IRQSTATUS 0x00000118 // 0x4402 1118 0x4402 2118 The + // interrupt status regroups all the + // status of the module internal + // events that can generate an + // interrupt +#define MCSPI_O_IRQENABLE 0x0000011C // 0x4402 111C 0x4402 211C This + // register allows to enable/disable + // the module internal sources of + // interrupt on an event-by-event + // basis. +#define MCSPI_O_WAKEUPENABLE 0x00000120 // 0x4402 1120 0x4402 2120 The + // wakeup enable register allows to + // enable/disable the module + // internal sources of wakeup on + // event-by-event basis. +#define MCSPI_O_SYST 0x00000124 // 0x4402 1124 0x4402 2124 This + // register is used to check the + // correctness of the system + // interconnect either internally to + // peripheral bus or externally to + // device IO pads when the module is + // configured in system test + // (SYSTEST) mode. +#define MCSPI_O_MODULCTRL 0x00000128 // 0x4402 1128 0x4402 2128 This + // register is dedicated to the + // configuration of the serial port + // interface. +#define MCSPI_O_CH0CONF 0x0000012C // 0x4402 112C 0x4402 212C This + // register is dedicated to the + // configuration of the channel 0 +#define MCSPI_O_CH0STAT 0x00000130 // 0x4402 1130 0x4402 2130 This + // register provides status + // information about transmitter and + // receiver registers of channel 0 +#define MCSPI_O_CH0CTRL 0x00000134 // 0x4402 1134 0x4402 2134 This + // register is dedicated to enable + // the channel 0 +#define MCSPI_O_TX0 0x00000138 // 0x4402 1138 0x4402 2138 This + // register contains a single SPI + // word to transmit on the serial + // link what ever SPI word length + // is. +#define MCSPI_O_RX0 0x0000013C // 0x4402 113C 0x4402 213C This + // register contains a single SPI + // word received through the serial + // link what ever SPI word length + // is. +#define MCSPI_O_CH1CONF 0x00000140 // 0x4402 1140 0x4402 2140 This + // register is dedicated to the + // configuration of the channel. +#define MCSPI_O_CH1STAT 0x00000144 // 0x4402 1144 0x4402 2144 This + // register provides status + // information about transmitter and + // receiver registers of channel 1 +#define MCSPI_O_CH1CTRL 0x00000148 // 0x4402 1148 0x4402 2148 This + // register is dedicated to enable + // the channel 1 +#define MCSPI_O_TX1 0x0000014C // 0x4402 114C 0x4402 214C This + // register contains a single SPI + // word to transmit on the serial + // link what ever SPI word length + // is. +#define MCSPI_O_RX1 0x00000150 // 0x4402 1150 0x4402 2150 This + // register contains a single SPI + // word received through the serial + // link what ever SPI word length + // is. +#define MCSPI_O_CH2CONF 0x00000154 // 0x4402 1154 0x4402 2154 This + // register is dedicated to the + // configuration of the channel 2 +#define MCSPI_O_CH2STAT 0x00000158 // 0x4402 1158 0x4402 2158 This + // register provides status + // information about transmitter and + // receiver registers of channel 2 +#define MCSPI_O_CH2CTRL 0x0000015C // 0x4402 115C 0x4402 215C This + // register is dedicated to enable + // the channel 2 +#define MCSPI_O_TX2 0x00000160 // 0x4402 1160 0x4402 2160 This + // register contains a single SPI + // word to transmit on the serial + // link what ever SPI word length + // is. +#define MCSPI_O_RX2 0x00000164 // 0x4402 1164 0x4402 2164 This + // register contains a single SPI + // word received through the serial + // link what ever SPI word length + // is. +#define MCSPI_O_CH3CONF 0x00000168 // 0x4402 1168 0x4402 2168 This + // register is dedicated to the + // configuration of the channel 3 +#define MCSPI_O_CH3STAT 0x0000016C // 0x4402 116C 0x4402 216C This + // register provides status + // information about transmitter and + // receiver registers of channel 3 +#define MCSPI_O_CH3CTRL 0x00000170 // 0x4402 1170 0x4402 2170 This + // register is dedicated to enable + // the channel 3 +#define MCSPI_O_TX3 0x00000174 // 0x4402 1174 0x4402 2174 This + // register contains a single SPI + // word to transmit on the serial + // link what ever SPI word length + // is. +#define MCSPI_O_RX3 0x00000178 // 0x4402 1178 0x4402 2178 This + // register contains a single SPI + // word received through the serial + // link what ever SPI word length + // is. +#define MCSPI_O_XFERLEVEL 0x0000017C // 0x4402 117C 0x4402 217C This + // register provides transfer levels + // needed while using FIFO buffer + // during transfer. +#define MCSPI_O_DAFTX 0x00000180 // 0x4402 1180 0x4402 2180 This + // register contains the SPI words + // to transmit on the serial link + // when FIFO used and DMA address is + // aligned on 256 bit.This register + // is an image of one of MCSPI_TX(i) + // register corresponding to the + // channel which have its FIFO + // enabled. +#define MCSPI_O_DAFRX 0x000001A0 // 0x4402 11A0 0x4402 21A0 This + // register contains the SPI words + // to received on the serial link + // when FIFO used and DMA address is + // aligned on 256 bit.This register + // is an image of one of MCSPI_RX(i) + // register corresponding to the + // channel which have its FIFO + // enabled. + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_HL_REV register. +// +//****************************************************************************** +#define MCSPI_HL_REV_SCHEME_M 0xC0000000 +#define MCSPI_HL_REV_SCHEME_S 30 +#define MCSPI_HL_REV_RSVD_M 0x30000000 // Reserved These bits are + // initialized to zero and writes to + // them are ignored. +#define MCSPI_HL_REV_RSVD_S 28 +#define MCSPI_HL_REV_FUNC_M 0x0FFF0000 // Function indicates a software + // compatible module family. If + // there is no level of software + // compatibility a new Func number + // (and hence REVISION) should be + // assigned. +#define MCSPI_HL_REV_FUNC_S 16 +#define MCSPI_HL_REV_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP + // design owner. RTL follows a + // numbering such as X.Y.R.Z which + // are explained in this table. R + // changes ONLY when: (1) PDS + // uploads occur which may have been + // due to spec changes (2) Bug fixes + // occur (3) Resets to '0' when X or + // Y changes. Design team has an + // internal 'Z' (customer invisible) + // number which increments on every + // drop that happens due to DV and + // RTL updates. Z resets to 0 when R + // increments. +#define MCSPI_HL_REV_R_RTL_S 11 +#define MCSPI_HL_REV_X_MAJOR_M 0x00000700 // Major Revision (X) maintained by + // IP specification owner. X changes + // ONLY when: (1) There is a major + // feature addition. An example + // would be adding Master Mode to + // Utopia Level2. The Func field (or + // Class/Type in old PID format) + // will remain the same. X does NOT + // change due to: (1) Bug fixes (2) + // Change in feature parameters. +#define MCSPI_HL_REV_X_MAJOR_S 8 +#define MCSPI_HL_REV_CUSTOM_M 0x000000C0 +#define MCSPI_HL_REV_CUSTOM_S 6 +#define MCSPI_HL_REV_Y_MINOR_M 0x0000003F // Minor Revision (Y) maintained by + // IP specification owner. Y changes + // ONLY when: (1) Features are + // scaled (up or down). Flexibility + // exists in that this feature + // scalability may either be + // represented in the Y change or a + // specific register in the IP that + // indicates which features are + // exactly available. (2) When + // feature creeps from Is-Not list + // to Is list. But this may not be + // the case once it sees silicon; in + // which case X will change. Y does + // NOT change due to: (1) Bug fixes + // (2) Typos or clarifications (3) + // major functional/feature + // change/addition/deletion. Instead + // these changes may be reflected + // via R S X as applicable. Spec + // owner maintains a + // customer-invisible number 'S' + // which changes due to: (1) + // Typos/clarifications (2) Bug + // documentation. Note that this bug + // is not due to a spec change but + // due to implementation. + // Nevertheless the spec tracks the + // IP bugs. An RTL release (say for + // silicon PG1.1) that occurs due to + // bug fix should document the + // corresponding spec number (X.Y.S) + // in its release notes. +#define MCSPI_HL_REV_Y_MINOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_HL_HWINFO register. +// +//****************************************************************************** +#define MCSPI_HL_HWINFO_RETMODE 0x00000040 +#define MCSPI_HL_HWINFO_FFNBYTE_M \ + 0x0000003E + +#define MCSPI_HL_HWINFO_FFNBYTE_S 1 +#define MCSPI_HL_HWINFO_USEFIFO 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// MCSPI_O_HL_SYSCONFIG register. +// +//****************************************************************************** +#define MCSPI_HL_SYSCONFIG_IDLEMODE_M \ + 0x0000000C // Configuration of the local + // target state management mode. By + // definition target can handle + // read/write transaction as long as + // it is out of IDLE state. 0x0 + // Force-idle mode: local target's + // idle state follows (acknowledges) + // the system's idle requests + // unconditionally i.e. regardless + // of the IP module's internal + // requirements.Backup mode for + // debug only. 0x1 No-idle mode: + // local target never enters idle + // state.Backup mode for debug only. + // 0x2 Smart-idle mode: local + // target's idle state eventually + // follows (acknowledges) the + // system's idle requests depending + // on the IP module's internal + // requirements.IP module shall not + // generate (IRQ- or + // DMA-request-related) wakeup + // events. 0x3 "Smart-idle + // wakeup-capable mode: local + // target's idle state eventually + // follows (acknowledges) the + // system's idle requests depending + // on the IP module's internal + // requirements.IP module may + // generate (IRQ- or + // DMA-request-related) wakeup + // events when in idle state.Mode is + // only relevant if the appropriate + // IP module ""swakeup"" output(s) + // is (are) implemented." + +#define MCSPI_HL_SYSCONFIG_IDLEMODE_S 2 +#define MCSPI_HL_SYSCONFIG_FREEEMU \ + 0x00000002 // Sensitivity to emulation (debug) + // suspend input signal. 0 IP module + // is sensitive to emulation suspend + // 1 IP module is not sensitive to + // emulation suspend + +#define MCSPI_HL_SYSCONFIG_SOFTRESET \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_REVISION register. +// +//****************************************************************************** +#define MCSPI_REVISION_REV_M 0x000000FF // IP revision [7:4] Major revision + // [3:0] Minor revision Examples: + // 0x10 for 1.0 0x21 for 2.1 +#define MCSPI_REVISION_REV_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_SYSCONFIG register. +// +//****************************************************************************** +#define MCSPI_SYSCONFIG_CLOCKACTIVITY_M \ + 0x00000300 // Clocks activity during wake up + // mode period 0x0 OCP and + // Functional clocks may be switched + // off. 0x1 OCP clock is maintained. + // Functional clock may be + // switched-off. 0x2 Functional + // clock is maintained. OCP clock + // may be switched-off. 0x3 OCP and + // Functional clocks are maintained. + +#define MCSPI_SYSCONFIG_CLOCKACTIVITY_S 8 +#define MCSPI_SYSCONFIG_SIDLEMODE_M \ + 0x00000018 // Power management 0x0 If an idle + // request is detected the McSPI + // acknowledges it unconditionally + // and goes in Inactive mode. + // Interrupt DMA requests and wake + // up lines are unconditionally + // de-asserted and the module wakeup + // capability is deactivated even if + // the bit + // MCSPI_SYSCONFIG[EnaWakeUp] is + // set. 0x1 If an idle request is + // detected the request is ignored + // and the module does not switch to + // wake up mode and keeps on + // behaving normally. 0x2 If an idle + // request is detected the module + // will switch to idle mode based on + // its internal activity. The wake + // up capability cannot be used. 0x3 + // If an idle request is detected + // the module will switch to idle + // mode based on its internal + // activity and the wake up + // capability can be used if the bit + // MCSPI_SYSCONFIG[EnaWakeUp] is + // set. + +#define MCSPI_SYSCONFIG_SIDLEMODE_S 3 +#define MCSPI_SYSCONFIG_ENAWAKEUP \ + 0x00000004 // WakeUp feature control 0 WakeUp + // capability is disabled 1 WakeUp + // capability is enabled + +#define MCSPI_SYSCONFIG_SOFTRESET \ + 0x00000002 // Software reset. During reads it + // always returns 0. 0 (write) + // Normal mode 1 (write) Set this + // bit to 1 to trigger a module + // reset.The bit is automatically + // reset by the hardware. + +#define MCSPI_SYSCONFIG_AUTOIDLE \ + 0x00000001 // Internal OCP Clock gating + // strategy 0 OCP clock is + // free-running 1 Automatic OCP + // clock gating strategy is applied + // based on the OCP interface + // activity + +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_SYSSTATUS register. +// +//****************************************************************************** +#define MCSPI_SYSSTATUS_RESETDONE \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_IRQSTATUS register. +// +//****************************************************************************** +#define MCSPI_IRQSTATUS_EOW 0x00020000 +#define MCSPI_IRQSTATUS_WKS 0x00010000 +#define MCSPI_IRQSTATUS_RX3_FULL \ + 0x00004000 + +#define MCSPI_IRQSTATUS_TX3_UNDERFLOW \ + 0x00002000 + +#define MCSPI_IRQSTATUS_TX3_EMPTY \ + 0x00001000 + +#define MCSPI_IRQSTATUS_RX2_FULL \ + 0x00000400 + +#define MCSPI_IRQSTATUS_TX2_UNDERFLOW \ + 0x00000200 + +#define MCSPI_IRQSTATUS_TX2_EMPTY \ + 0x00000100 + +#define MCSPI_IRQSTATUS_RX1_FULL \ + 0x00000040 + +#define MCSPI_IRQSTATUS_TX1_UNDERFLOW \ + 0x00000020 + +#define MCSPI_IRQSTATUS_TX1_EMPTY \ + 0x00000010 + +#define MCSPI_IRQSTATUS_RX0_OVERFLOW \ + 0x00000008 + +#define MCSPI_IRQSTATUS_RX0_FULL \ + 0x00000004 + +#define MCSPI_IRQSTATUS_TX0_UNDERFLOW \ + 0x00000002 + +#define MCSPI_IRQSTATUS_TX0_EMPTY \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_IRQENABLE register. +// +//****************************************************************************** +#define MCSPI_IRQENABLE_EOW_ENABLE \ + 0x00020000 // End of Word count Interrupt + // Enable. 0 Interrupt disabled 1 + // Interrupt enabled + +#define MCSPI_IRQENABLE_WKE 0x00010000 // Wake Up event interrupt Enable + // in slave mode when an active + // control signal is detected on the + // SPIEN line programmed in the + // field MCSPI_CH0CONF[SPIENSLV] 0 + // Interrupt disabled 1 Interrupt + // enabled +#define MCSPI_IRQENABLE_RX3_FULL_ENABLE \ + 0x00004000 // Receiver register Full Interrupt + // Enable. Ch 3 0 Interrupt disabled + // 1 Interrupt enabled + +#define MCSPI_IRQENABLE_TX3_UNDERFLOW_ENABLE \ + 0x00002000 // Transmitter register Underflow + // Interrupt Enable. Ch 3 0 + // Interrupt disabled 1 Interrupt + // enabled + +#define MCSPI_IRQENABLE_TX3_EMPTY_ENABLE \ + 0x00001000 // Transmitter register Empty + // Interrupt Enable. Ch3 0 Interrupt + // disabled 1 Interrupt enabled + +#define MCSPI_IRQENABLE_RX2_FULL_ENABLE \ + 0x00000400 // Receiver register Full Interrupt + // Enable. Ch 2 0 Interrupt disabled + // 1 Interrupt enabled + +#define MCSPI_IRQENABLE_TX2_UNDERFLOW_ENABLE \ + 0x00000200 // Transmitter register Underflow + // Interrupt Enable. Ch 2 0 + // Interrupt disabled 1 Interrupt + // enabled + +#define MCSPI_IRQENABLE_TX2_EMPTY_ENABLE \ + 0x00000100 // Transmitter register Empty + // Interrupt Enable. Ch 2 0 + // Interrupt disabled 1 Interrupt + // enabled + +#define MCSPI_IRQENABLE_RX1_FULL_ENABLE \ + 0x00000040 // Receiver register Full Interrupt + // Enable. Ch 1 0 Interrupt disabled + // 1 Interrupt enabled + +#define MCSPI_IRQENABLE_TX1_UNDERFLOW_ENABLE \ + 0x00000020 // Transmitter register Underflow + // Interrupt Enable. Ch 1 0 + // Interrupt disabled 1 Interrupt + // enabled + +#define MCSPI_IRQENABLE_TX1_EMPTY_ENABLE \ + 0x00000010 // Transmitter register Empty + // Interrupt Enable. Ch 1 0 + // Interrupt disabled 1 Interrupt + // enabled + +#define MCSPI_IRQENABLE_RX0_OVERFLOW_ENABLE \ + 0x00000008 // Receiver register Overflow + // Interrupt Enable. Ch 0 0 + // Interrupt disabled 1 Interrupt + // enabled + +#define MCSPI_IRQENABLE_RX0_FULL_ENABLE \ + 0x00000004 // Receiver register Full Interrupt + // Enable. Ch 0 0 Interrupt disabled + // 1 Interrupt enabled + +#define MCSPI_IRQENABLE_TX0_UNDERFLOW_ENABLE \ + 0x00000002 // Transmitter register Underflow + // Interrupt Enable. Ch 0 0 + // Interrupt disabled 1 Interrupt + // enabled + +#define MCSPI_IRQENABLE_TX0_EMPTY_ENABLE \ + 0x00000001 // Transmitter register Empty + // Interrupt Enable. Ch 0 0 + // Interrupt disabled 1 Interrupt + // enabled + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// MCSPI_O_WAKEUPENABLE register. +// +//****************************************************************************** +#define MCSPI_WAKEUPENABLE_WKEN 0x00000001 // WakeUp functionality in slave + // mode when an active control + // signal is detected on the SPIEN + // line programmed in the field + // MCSPI_CH0CONF[SPIENSLV] 0 The + // event is not allowed to wakeup + // the system even if the global + // control bit + // MCSPI_SYSCONF[EnaWakeUp] is set. + // 1 The event is allowed to wakeup + // the system if the global control + // bit MCSPI_SYSCONF[EnaWakeUp] is + // set. +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_SYST register. +// +//****************************************************************************** +#define MCSPI_SYST_SSB 0x00000800 // Set status bit 0 No action. + // Writing 0 does not clear already + // set status bits; This bit must be + // cleared prior attempting to clear + // a status bit of the + // register. 1 + // Force to 1 all status bits of + // MCSPI_IRQSTATUS register. Writing + // 1 into this bit sets to 1 all + // status bits contained in the + // register. +#define MCSPI_SYST_SPIENDIR 0x00000400 // Set the direction of the + // SPIEN[3:0] lines and SPICLK line + // 0 output (as in master mode) 1 + // input (as in slave mode) +#define MCSPI_SYST_SPIDATDIR1 0x00000200 // Set the direction of the + // SPIDAT[1] 0 output 1 input +#define MCSPI_SYST_SPIDATDIR0 0x00000100 // Set the direction of the + // SPIDAT[0] 0 output 1 input +#define MCSPI_SYST_WAKD 0x00000080 // SWAKEUP output (signal data + // value of internal signal to + // system). The signal is driven + // high or low according to the + // value written into this register + // bit. 0 The pin is driven low. 1 + // The pin is driven high. +#define MCSPI_SYST_SPICLK 0x00000040 // SPICLK line (signal data value) + // If MCSPI_SYST[SPIENDIR] = 1 + // (input mode direction) this bit + // returns the value on the CLKSPI + // line (high or low) and a write + // into this bit has no effect. If + // MCSPI_SYST[SPIENDIR] = 0 (output + // mode direction) the CLKSPI line + // is driven high or low according + // to the value written into this + // register. +#define MCSPI_SYST_SPIDAT_1 0x00000020 // SPIDAT[1] line (signal data + // value) If MCSPI_SYST[SPIDATDIR1] + // = 0 (output mode direction) the + // SPIDAT[1] line is driven high or + // low according to the value + // written into this register. If + // MCSPI_SYST[SPIDATDIR1] = 1 (input + // mode direction) this bit returns + // the value on the SPIDAT[1] line + // (high or low) and a write into + // this bit has no effect. +#define MCSPI_SYST_SPIDAT_0 0x00000010 // SPIDAT[0] line (signal data + // value) If MCSPI_SYST[SPIDATDIR0] + // = 0 (output mode direction) the + // SPIDAT[0] line is driven high or + // low according to the value + // written into this register. If + // MCSPI_SYST[SPIDATDIR0] = 1 (input + // mode direction) this bit returns + // the value on the SPIDAT[0] line + // (high or low) and a write into + // this bit has no effect. +#define MCSPI_SYST_SPIEN_3 0x00000008 // SPIEN[3] line (signal data + // value) If MCSPI_SYST[SPIENDIR] = + // 0 (output mode direction) the + // SPIENT[3] line is driven high or + // low according to the value + // written into this register. If + // MCSPI_SYST[SPIENDIR] = 1 (input + // mode direction) this bit returns + // the value on the SPIEN[3] line + // (high or low) and a write into + // this bit has no effect. +#define MCSPI_SYST_SPIEN_2 0x00000004 // SPIEN[2] line (signal data + // value) If MCSPI_SYST[SPIENDIR] = + // 0 (output mode direction) the + // SPIENT[2] line is driven high or + // low according to the value + // written into this register. If + // MCSPI_SYST[SPIENDIR] = 1 (input + // mode direction) this bit returns + // the value on the SPIEN[2] line + // (high or low) and a write into + // this bit has no effect. +#define MCSPI_SYST_SPIEN_1 0x00000002 // SPIEN[1] line (signal data + // value) If MCSPI_SYST[SPIENDIR] = + // 0 (output mode direction) the + // SPIENT[1] line is driven high or + // low according to the value + // written into this register. If + // MCSPI_SYST[SPIENDIR] = 1 (input + // mode direction) this bit returns + // the value on the SPIEN[1] line + // (high or low) and a write into + // this bit has no effect. +#define MCSPI_SYST_SPIEN_0 0x00000001 // SPIEN[0] line (signal data + // value) If MCSPI_SYST[SPIENDIR] = + // 0 (output mode direction) the + // SPIENT[0] line is driven high or + // low according to the value + // written into this register. If + // MCSPI_SYST[SPIENDIR] = 1 (input + // mode direction) this bit returns + // the value on the SPIEN[0] line + // (high or low) and a write into + // this bit has no effect. +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_MODULCTRL register. +// +//****************************************************************************** +#define MCSPI_MODULCTRL_FDAA 0x00000100 // FIFO DMA Address 256-bit aligned + // This register is used when a FIFO + // is managed by the module and DMA + // connected to the controller + // provides only 256 bit aligned + // address. If this bit is set the + // enabled channel which uses the + // FIFO has its datas managed + // through MCSPI_DAFTX and + // MCSPI_DAFRX registers instead of + // MCSPI_TX(i) and MCSPI_RX(i) + // registers. 0 FIFO data managed by + // MCSPI_TX(i) and MCSPI_RX(i) + // registers. 1 FIFO data managed by + // MCSPI_DAFTX and MCSPI_DAFRX + // registers. +#define MCSPI_MODULCTRL_MOA 0x00000080 // Multiple word ocp access: This + // register can only be used when a + // channel is enabled using a FIFO. + // It allows the system to perform + // multiple SPI word access for a + // single 32-bit OCP word access. + // This is possible for WL < 16. 0 + // Multiple word access disabled 1 + // Multiple word access enabled with + // FIFO +#define MCSPI_MODULCTRL_INITDLY_M \ + 0x00000070 // Initial spi delay for first + // transfer: This register is an + // option only available in SINGLE + // master mode The controller waits + // for a delay to transmit the first + // spi word after channel enabled + // and corresponding TX register + // filled. This Delay is based on + // SPI output frequency clock No + // clock output provided to the + // boundary and chip select is not + // active in 4 pin mode within this + // period. 0x0 No delay for first + // spi transfer. 0x1 The controller + // wait 4 spi bus clock 0x2 The + // controller wait 8 spi bus clock + // 0x3 The controller wait 16 spi + // bus clock 0x4 The controller wait + // 32 spi bus clock + +#define MCSPI_MODULCTRL_INITDLY_S 4 +#define MCSPI_MODULCTRL_SYSTEM_TEST \ + 0x00000008 // Enables the system test mode 0 + // Functional mode 1 System test + // mode (SYSTEST) + +#define MCSPI_MODULCTRL_MS 0x00000004 // Master/ Slave 0 Master - The + // module generates the SPICLK and + // SPIEN[3:0] 1 Slave - The module + // receives the SPICLK and + // SPIEN[3:0] +#define MCSPI_MODULCTRL_PIN34 0x00000002 // Pin mode selection: This + // register is used to configure the + // SPI pin mode in master or slave + // mode. If asserted the controller + // only use SIMOSOMI and SPICLK + // clock pin for spi transfers. 0 + // SPIEN is used as a chip select. 1 + // SPIEN is not used.In this mode + // all related option to chip select + // have no meaning. +#define MCSPI_MODULCTRL_SINGLE 0x00000001 // Single channel / Multi Channel + // (master mode only) 0 More than + // one channel will be used in + // master mode. 1 Only one channel + // will be used in master mode. This + // bit must be set in Force SPIEN + // mode. +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH0CONF register. +// +//****************************************************************************** +#define MCSPI_CH0CONF_CLKG 0x20000000 // Clock divider granularity This + // register defines the granularity + // of channel clock divider: power + // of two or one clock cycle + // granularity. When this bit is set + // the register MCSPI_CHCTRL[EXTCLK] + // must be configured to reach a + // maximum of 4096 clock divider + // ratio. Then The clock divider + // ratio is a concatenation of + // MCSPI_CHCONF[CLKD] and + // MCSPI_CHCTRL[EXTCLK] values 0 + // Clock granularity of power of two + // 1 One clock cycle ganularity +#define MCSPI_CH0CONF_FFER 0x10000000 // FIFO enabled for receive:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to receive data. 1 The + // buffer is used to receive data. +#define MCSPI_CH0CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to transmit data. 1 The + // buffer is used to transmit data. +#define MCSPI_CH0CONF_TCS0_M 0x06000000 // Chip Select Time Control This + // 2-bits field defines the number + // of interface clock cycles between + // CS toggling and first or last + // edge of SPI clock. 0x0 0.5 clock + // cycle 0x1 1.5 clock cycle 0x2 2.5 + // clock cycle 0x3 3.5 clock cycle +#define MCSPI_CH0CONF_TCS0_S 25 +#define MCSPI_CH0CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit + // polarity is held to 0 during SPI + // transfer. 1 Start bit polarity is + // held to 1 during SPI transfer. +#define MCSPI_CH0CONF_SBE 0x00800000 // Start bit enable for SPI + // transfer 0 Default SPI transfer + // length as specified by WL bit + // field 1 Start bit D/CX added + // before SPI transfer polarity is + // defined by MCSPI_CH0CONF[SBPOL] +#define MCSPI_CH0CONF_SPIENSLV_M \ + 0x00600000 // Channel 0 only and slave mode + // only: SPI slave select signal + // detection. Reserved bits for + // other cases. 0x0 Detection + // enabled only on SPIEN[0] 0x1 + // Detection enabled only on + // SPIEN[1] 0x2 Detection enabled + // only on SPIEN[2] 0x3 Detection + // enabled only on SPIEN[3] + +#define MCSPI_CH0CONF_SPIENSLV_S 21 +#define MCSPI_CH0CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep + // SPIEN active between SPI words. + // (single channel master mode only) + // 0 Writing 0 into this bit drives + // low the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it high when + // MCSPI_CHCONF(i)[EPOL]=1. 1 + // Writing 1 into this bit drives + // high the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it low when + // MCSPI_CHCONF(i)[EPOL]=1 +#define MCSPI_CH0CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is + // deactivated (recommended for + // single SPI word transfer) 1 Turbo + // is activated to maximize the + // throughput for multi SPI words + // transfer. +#define MCSPI_CH0CONF_IS 0x00040000 // Input Select 0 Data Line0 + // (SPIDAT[0]) selected for + // reception. 1 Data Line1 + // (SPIDAT[1]) selected for + // reception +#define MCSPI_CH0CONF_DPE1 0x00020000 // Transmission Enable for data + // line 1 (SPIDATAGZEN[1]) 0 Data + // Line1 (SPIDAT[1]) selected for + // transmission 1 No transmission on + // Data Line1 (SPIDAT[1]) +#define MCSPI_CH0CONF_DPE0 0x00010000 // Transmission Enable for data + // line 0 (SPIDATAGZEN[0]) 0 Data + // Line0 (SPIDAT[0]) selected for + // transmission 1 No transmission on + // Data Line0 (SPIDAT[0]) +#define MCSPI_CH0CONF_DMAR 0x00008000 // DMA Read request The DMA Read + // request line is asserted when the + // channel is enabled and a new data + // is available in the receive + // register of the channel. The DMA + // Read request line is deasserted + // on read completion of the receive + // register of the channel. 0 DMA + // Read Request disabled 1 DMA Read + // Request enabled +#define MCSPI_CH0CONF_DMAW 0x00004000 // DMA Write request. The DMA Write + // request line is asserted when The + // channel is enabled and the + // transmitter register of the + // channel is empty. The DMA Write + // request line is deasserted on + // load completion of the + // transmitter register of the + // channel. 0 DMA Write Request + // disabled 1 DMA Write Request + // enabled +#define MCSPI_CH0CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 + // Transmit and Receive mode 0x1 + // Receive only mode 0x2 Transmit + // only mode 0x3 Reserved +#define MCSPI_CH0CONF_TRM_S 12 +#define MCSPI_CH0CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved + // 0x01 Reserved 0x02 Reserved 0x03 + // The SPI word is 4-bits long 0x04 + // The SPI word is 5-bits long 0x05 + // The SPI word is 6-bits long 0x06 + // The SPI word is 7-bits long 0x07 + // The SPI word is 8-bits long 0x08 + // The SPI word is 9-bits long 0x09 + // The SPI word is 10-bits long 0x0A + // The SPI word is 11-bits long 0x0B + // The SPI word is 12-bits long 0x0C + // The SPI word is 13-bits long 0x0D + // The SPI word is 14-bits long 0x0E + // The SPI word is 15-bits long 0x0F + // The SPI word is 16-bits long 0x10 + // The SPI word is 17-bits long 0x11 + // The SPI word is 18-bits long 0x12 + // The SPI word is 19-bits long 0x13 + // The SPI word is 20-bits long 0x14 + // The SPI word is 21-bits long 0x15 + // The SPI word is 22-bits long 0x16 + // The SPI word is 23-bits long 0x17 + // The SPI word is 24-bits long 0x18 + // The SPI word is 25-bits long 0x19 + // The SPI word is 26-bits long 0x1A + // The SPI word is 27-bits long 0x1B + // The SPI word is 28-bits long 0x1C + // The SPI word is 29-bits long 0x1D + // The SPI word is 30-bits long 0x1E + // The SPI word is 31-bits long 0x1F + // The SPI word is 32-bits long +#define MCSPI_CH0CONF_WL_S 7 +#define MCSPI_CH0CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held + // high during the active state. 1 + // SPIEN is held low during the + // active state. +#define MCSPI_CH0CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. + // (only when the module is a Master + // SPI device). A programmable clock + // divider divides the SPI reference + // clock (CLKSPIREF) with a 4-bit + // value and results in a new clock + // SPICLK available to shift-in and + // shift-out data. By default the + // clock divider ratio has a power + // of two granularity when + // MCSPI_CHCONF[CLKG] is cleared + // Otherwise this register is the 4 + // LSB bit of a 12-bit register + // concatenated with clock divider + // extension MCSPI_CHCTRL[EXTCLK] + // register.The value description + // below defines the clock ratio + // when MCSPI_CHCONF[CLKG] is set to + // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 + // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 + // 512 0xA 1024 0xB 2048 0xC 4096 + // 0xD 8192 0xE 16384 0xF 32768 +#define MCSPI_CH0CONF_CLKD_S 2 +#define MCSPI_CH0CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held + // high during the active state 1 + // SPICLK is held low during the + // active state +#define MCSPI_CH0CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched + // on odd numbered edges of SPICLK. + // 1 Data are latched on even + // numbered edges of SPICLK. +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH0STAT register. +// +//****************************************************************************** +#define MCSPI_CH0STAT_RXFFF 0x00000040 +#define MCSPI_CH0STAT_RXFFE 0x00000020 +#define MCSPI_CH0STAT_TXFFF 0x00000010 +#define MCSPI_CH0STAT_TXFFE 0x00000008 +#define MCSPI_CH0STAT_EOT 0x00000004 +#define MCSPI_CH0STAT_TXS 0x00000002 +#define MCSPI_CH0STAT_RXS 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH0CTRL register. +// +//****************************************************************************** +#define MCSPI_CH0CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This + // register is used to concatenate + // with MCSPI_CHCONF[CLKD] register + // for clock ratio only when + // granularity is one clock cycle + // (MCSPI_CHCONF[CLKG] set to 1). + // Then the max value reached is + // 4096 clock divider ratio. 0x00 + // Clock ratio is CLKD + 1 0x01 + // Clock ratio is CLKD + 1 + 16 0xFF + // Clock ratio is CLKD + 1 + 4080 +#define MCSPI_CH0CTRL_EXTCLK_S 8 +#define MCSPI_CH0CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" + // is not active" 1 "Channel ""i"" + // is active" +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_TX0 register. +// +//****************************************************************************** +#define MCSPI_TX0_TDATA_M 0xFFFFFFFF // Channel 0 Data to transmit +#define MCSPI_TX0_TDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_RX0 register. +// +//****************************************************************************** +#define MCSPI_RX0_RDATA_M 0xFFFFFFFF // Channel 0 Received Data +#define MCSPI_RX0_RDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH1CONF register. +// +//****************************************************************************** +#define MCSPI_CH1CONF_CLKG 0x20000000 // Clock divider granularity This + // register defines the granularity + // of channel clock divider: power + // of two or one clock cycle + // granularity. When this bit is set + // the register MCSPI_CHCTRL[EXTCLK] + // must be configured to reach a + // maximum of 4096 clock divider + // ratio. Then The clock divider + // ratio is a concatenation of + // MCSPI_CHCONF[CLKD] and + // MCSPI_CHCTRL[EXTCLK] values 0 + // Clock granularity of power of two + // 1 One clock cycle ganularity +#define MCSPI_CH1CONF_FFER 0x10000000 // FIFO enabled for receive:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to receive data. 1 The + // buffer is used to receive data. +#define MCSPI_CH1CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to transmit data. 1 The + // buffer is used to transmit data. +#define MCSPI_CH1CONF_TCS1_M 0x06000000 // Chip Select Time Control This + // 2-bits field defines the number + // of interface clock cycles between + // CS toggling and first or last + // edge of SPI clock. 0x0 0.5 clock + // cycle 0x1 1.5 clock cycle 0x2 2.5 + // clock cycle 0x3 3.5 clock cycle +#define MCSPI_CH1CONF_TCS1_S 25 +#define MCSPI_CH1CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit + // polarity is held to 0 during SPI + // transfer. 1 Start bit polarity is + // held to 1 during SPI transfer. +#define MCSPI_CH1CONF_SBE 0x00800000 // Start bit enable for SPI + // transfer 0 Default SPI transfer + // length as specified by WL bit + // field 1 Start bit D/CX added + // before SPI transfer polarity is + // defined by MCSPI_CH1CONF[SBPOL] +#define MCSPI_CH1CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep + // SPIEN active between SPI words. + // (single channel master mode only) + // 0 Writing 0 into this bit drives + // low the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it high when + // MCSPI_CHCONF(i)[EPOL]=1. 1 + // Writing 1 into this bit drives + // high the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it low when + // MCSPI_CHCONF(i)[EPOL]=1 +#define MCSPI_CH1CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is + // deactivated (recommended for + // single SPI word transfer) 1 Turbo + // is activated to maximize the + // throughput for multi SPI words + // transfer. +#define MCSPI_CH1CONF_IS 0x00040000 // Input Select 0 Data Line0 + // (SPIDAT[0]) selected for + // reception. 1 Data Line1 + // (SPIDAT[1]) selected for + // reception +#define MCSPI_CH1CONF_DPE1 0x00020000 // Transmission Enable for data + // line 1 (SPIDATAGZEN[1]) 0 Data + // Line1 (SPIDAT[1]) selected for + // transmission 1 No transmission on + // Data Line1 (SPIDAT[1]) +#define MCSPI_CH1CONF_DPE0 0x00010000 // Transmission Enable for data + // line 0 (SPIDATAGZEN[0]) 0 Data + // Line0 (SPIDAT[0]) selected for + // transmission 1 No transmission on + // Data Line0 (SPIDAT[0]) +#define MCSPI_CH1CONF_DMAR 0x00008000 // DMA Read request The DMA Read + // request line is asserted when the + // channel is enabled and a new data + // is available in the receive + // register of the channel. The DMA + // Read request line is deasserted + // on read completion of the receive + // register of the channel. 0 DMA + // Read Request disabled 1 DMA Read + // Request enabled +#define MCSPI_CH1CONF_DMAW 0x00004000 // DMA Write request. The DMA Write + // request line is asserted when The + // channel is enabled and the + // transmitter register of the + // channel is empty. The DMA Write + // request line is deasserted on + // load completion of the + // transmitter register of the + // channel. 0 DMA Write Request + // disabled 1 DMA Write Request + // enabled +#define MCSPI_CH1CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 + // Transmit and Receive mode 0x1 + // Receive only mode 0x2 Transmit + // only mode 0x3 Reserved +#define MCSPI_CH1CONF_TRM_S 12 +#define MCSPI_CH1CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved + // 0x01 Reserved 0x02 Reserved 0x03 + // The SPI word is 4-bits long 0x04 + // The SPI word is 5-bits long 0x05 + // The SPI word is 6-bits long 0x06 + // The SPI word is 7-bits long 0x07 + // The SPI word is 8-bits long 0x08 + // The SPI word is 9-bits long 0x09 + // The SPI word is 10-bits long 0x0A + // The SPI word is 11-bits long 0x0B + // The SPI word is 12-bits long 0x0C + // The SPI word is 13-bits long 0x0D + // The SPI word is 14-bits long 0x0E + // The SPI word is 15-bits long 0x0F + // The SPI word is 16-bits long 0x10 + // The SPI word is 17-bits long 0x11 + // The SPI word is 18-bits long 0x12 + // The SPI word is 19-bits long 0x13 + // The SPI word is 20-bits long 0x14 + // The SPI word is 21-bits long 0x15 + // The SPI word is 22-bits long 0x16 + // The SPI word is 23-bits long 0x17 + // The SPI word is 24-bits long 0x18 + // The SPI word is 25-bits long 0x19 + // The SPI word is 26-bits long 0x1A + // The SPI word is 27-bits long 0x1B + // The SPI word is 28-bits long 0x1C + // The SPI word is 29-bits long 0x1D + // The SPI word is 30-bits long 0x1E + // The SPI word is 31-bits long 0x1F + // The SPI word is 32-bits long +#define MCSPI_CH1CONF_WL_S 7 +#define MCSPI_CH1CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held + // high during the active state. 1 + // SPIEN is held low during the + // active state. +#define MCSPI_CH1CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. + // (only when the module is a Master + // SPI device). A programmable clock + // divider divides the SPI reference + // clock (CLKSPIREF) with a 4-bit + // value and results in a new clock + // SPICLK available to shift-in and + // shift-out data. By default the + // clock divider ratio has a power + // of two granularity when + // MCSPI_CHCONF[CLKG] is cleared + // Otherwise this register is the 4 + // LSB bit of a 12-bit register + // concatenated with clock divider + // extension MCSPI_CHCTRL[EXTCLK] + // register.The value description + // below defines the clock ratio + // when MCSPI_CHCONF[CLKG] is set to + // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 + // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 + // 512 0xA 1024 0xB 2048 0xC 4096 + // 0xD 8192 0xE 16384 0xF 32768 +#define MCSPI_CH1CONF_CLKD_S 2 +#define MCSPI_CH1CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held + // high during the active state 1 + // SPICLK is held low during the + // active state +#define MCSPI_CH1CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched + // on odd numbered edges of SPICLK. + // 1 Data are latched on even + // numbered edges of SPICLK. +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH1STAT register. +// +//****************************************************************************** +#define MCSPI_CH1STAT_RXFFF 0x00000040 +#define MCSPI_CH1STAT_RXFFE 0x00000020 +#define MCSPI_CH1STAT_TXFFF 0x00000010 +#define MCSPI_CH1STAT_TXFFE 0x00000008 +#define MCSPI_CH1STAT_EOT 0x00000004 +#define MCSPI_CH1STAT_TXS 0x00000002 +#define MCSPI_CH1STAT_RXS 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH1CTRL register. +// +//****************************************************************************** +#define MCSPI_CH1CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This + // register is used to concatenate + // with MCSPI_CHCONF[CLKD] register + // for clock ratio only when + // granularity is one clock cycle + // (MCSPI_CHCONF[CLKG] set to 1). + // Then the max value reached is + // 4096 clock divider ratio. 0x00 + // Clock ratio is CLKD + 1 0x01 + // Clock ratio is CLKD + 1 + 16 0xFF + // Clock ratio is CLKD + 1 + 4080 +#define MCSPI_CH1CTRL_EXTCLK_S 8 +#define MCSPI_CH1CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" + // is not active" 1 "Channel ""i"" + // is active" +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_TX1 register. +// +//****************************************************************************** +#define MCSPI_TX1_TDATA_M 0xFFFFFFFF // Channel 1 Data to transmit +#define MCSPI_TX1_TDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_RX1 register. +// +//****************************************************************************** +#define MCSPI_RX1_RDATA_M 0xFFFFFFFF // Channel 1 Received Data +#define MCSPI_RX1_RDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH2CONF register. +// +//****************************************************************************** +#define MCSPI_CH2CONF_CLKG 0x20000000 // Clock divider granularity This + // register defines the granularity + // of channel clock divider: power + // of two or one clock cycle + // granularity. When this bit is set + // the register MCSPI_CHCTRL[EXTCLK] + // must be configured to reach a + // maximum of 4096 clock divider + // ratio. Then The clock divider + // ratio is a concatenation of + // MCSPI_CHCONF[CLKD] and + // MCSPI_CHCTRL[EXTCLK] values 0 + // Clock granularity of power of two + // 1 One clock cycle ganularity +#define MCSPI_CH2CONF_FFER 0x10000000 // FIFO enabled for receive:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to receive data. 1 The + // buffer is used to receive data. +#define MCSPI_CH2CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to transmit data. 1 The + // buffer is used to transmit data. +#define MCSPI_CH2CONF_TCS2_M 0x06000000 // Chip Select Time Control This + // 2-bits field defines the number + // of interface clock cycles between + // CS toggling and first or last + // edge of SPI clock. 0x0 0.5 clock + // cycle 0x1 1.5 clock cycle 0x2 2.5 + // clock cycle 0x3 3.5 clock cycle +#define MCSPI_CH2CONF_TCS2_S 25 +#define MCSPI_CH2CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit + // polarity is held to 0 during SPI + // transfer. 1 Start bit polarity is + // held to 1 during SPI transfer. +#define MCSPI_CH2CONF_SBE 0x00800000 // Start bit enable for SPI + // transfer 0 Default SPI transfer + // length as specified by WL bit + // field 1 Start bit D/CX added + // before SPI transfer polarity is + // defined by MCSPI_CH2CONF[SBPOL] +#define MCSPI_CH2CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep + // SPIEN active between SPI words. + // (single channel master mode only) + // 0 Writing 0 into this bit drives + // low the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it high when + // MCSPI_CHCONF(i)[EPOL]=1. 1 + // Writing 1 into this bit drives + // high the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it low when + // MCSPI_CHCONF(i)[EPOL]=1 +#define MCSPI_CH2CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is + // deactivated (recommended for + // single SPI word transfer) 1 Turbo + // is activated to maximize the + // throughput for multi SPI words + // transfer. +#define MCSPI_CH2CONF_IS 0x00040000 // Input Select 0 Data Line0 + // (SPIDAT[0]) selected for + // reception. 1 Data Line1 + // (SPIDAT[1]) selected for + // reception +#define MCSPI_CH2CONF_DPE1 0x00020000 // Transmission Enable for data + // line 1 (SPIDATAGZEN[1]) 0 Data + // Line1 (SPIDAT[1]) selected for + // transmission 1 No transmission on + // Data Line1 (SPIDAT[1]) +#define MCSPI_CH2CONF_DPE0 0x00010000 // Transmission Enable for data + // line 0 (SPIDATAGZEN[0]) 0 Data + // Line0 (SPIDAT[0]) selected for + // transmission 1 No transmission on + // Data Line0 (SPIDAT[0]) +#define MCSPI_CH2CONF_DMAR 0x00008000 // DMA Read request The DMA Read + // request line is asserted when the + // channel is enabled and a new data + // is available in the receive + // register of the channel. The DMA + // Read request line is deasserted + // on read completion of the receive + // register of the channel. 0 DMA + // Read Request disabled 1 DMA Read + // Request enabled +#define MCSPI_CH2CONF_DMAW 0x00004000 // DMA Write request. The DMA Write + // request line is asserted when The + // channel is enabled and the + // transmitter register of the + // channel is empty. The DMA Write + // request line is deasserted on + // load completion of the + // transmitter register of the + // channel. 0 DMA Write Request + // disabled 1 DMA Write Request + // enabled +#define MCSPI_CH2CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 + // Transmit and Receive mode 0x1 + // Receive only mode 0x2 Transmit + // only mode 0x3 Reserved +#define MCSPI_CH2CONF_TRM_S 12 +#define MCSPI_CH2CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved + // 0x01 Reserved 0x02 Reserved 0x03 + // The SPI word is 4-bits long 0x04 + // The SPI word is 5-bits long 0x05 + // The SPI word is 6-bits long 0x06 + // The SPI word is 7-bits long 0x07 + // The SPI word is 8-bits long 0x08 + // The SPI word is 9-bits long 0x09 + // The SPI word is 10-bits long 0x0A + // The SPI word is 11-bits long 0x0B + // The SPI word is 12-bits long 0x0C + // The SPI word is 13-bits long 0x0D + // The SPI word is 14-bits long 0x0E + // The SPI word is 15-bits long 0x0F + // The SPI word is 16-bits long 0x10 + // The SPI word is 17-bits long 0x11 + // The SPI word is 18-bits long 0x12 + // The SPI word is 19-bits long 0x13 + // The SPI word is 20-bits long 0x14 + // The SPI word is 21-bits long 0x15 + // The SPI word is 22-bits long 0x16 + // The SPI word is 23-bits long 0x17 + // The SPI word is 24-bits long 0x18 + // The SPI word is 25-bits long 0x19 + // The SPI word is 26-bits long 0x1A + // The SPI word is 27-bits long 0x1B + // The SPI word is 28-bits long 0x1C + // The SPI word is 29-bits long 0x1D + // The SPI word is 30-bits long 0x1E + // The SPI word is 31-bits long 0x1F + // The SPI word is 32-bits long +#define MCSPI_CH2CONF_WL_S 7 +#define MCSPI_CH2CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held + // high during the active state. 1 + // SPIEN is held low during the + // active state. +#define MCSPI_CH2CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. + // (only when the module is a Master + // SPI device). A programmable clock + // divider divides the SPI reference + // clock (CLKSPIREF) with a 4-bit + // value and results in a new clock + // SPICLK available to shift-in and + // shift-out data. By default the + // clock divider ratio has a power + // of two granularity when + // MCSPI_CHCONF[CLKG] is cleared + // Otherwise this register is the 4 + // LSB bit of a 12-bit register + // concatenated with clock divider + // extension MCSPI_CHCTRL[EXTCLK] + // register.The value description + // below defines the clock ratio + // when MCSPI_CHCONF[CLKG] is set to + // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 + // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 + // 512 0xA 1024 0xB 2048 0xC 4096 + // 0xD 8192 0xE 16384 0xF 32768 +#define MCSPI_CH2CONF_CLKD_S 2 +#define MCSPI_CH2CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held + // high during the active state 1 + // SPICLK is held low during the + // active state +#define MCSPI_CH2CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched + // on odd numbered edges of SPICLK. + // 1 Data are latched on even + // numbered edges of SPICLK. +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH2STAT register. +// +//****************************************************************************** +#define MCSPI_CH2STAT_RXFFF 0x00000040 +#define MCSPI_CH2STAT_RXFFE 0x00000020 +#define MCSPI_CH2STAT_TXFFF 0x00000010 +#define MCSPI_CH2STAT_TXFFE 0x00000008 +#define MCSPI_CH2STAT_EOT 0x00000004 +#define MCSPI_CH2STAT_TXS 0x00000002 +#define MCSPI_CH2STAT_RXS 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH2CTRL register. +// +//****************************************************************************** +#define MCSPI_CH2CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This + // register is used to concatenate + // with MCSPI_CHCONF[CLKD] register + // for clock ratio only when + // granularity is one clock cycle + // (MCSPI_CHCONF[CLKG] set to 1). + // Then the max value reached is + // 4096 clock divider ratio. 0x00 + // Clock ratio is CLKD + 1 0x01 + // Clock ratio is CLKD + 1 + 16 0xFF + // Clock ratio is CLKD + 1 + 4080 +#define MCSPI_CH2CTRL_EXTCLK_S 8 +#define MCSPI_CH2CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" + // is not active" 1 "Channel ""i"" + // is active" +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_TX2 register. +// +//****************************************************************************** +#define MCSPI_TX2_TDATA_M 0xFFFFFFFF // Channel 2 Data to transmit +#define MCSPI_TX2_TDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_RX2 register. +// +//****************************************************************************** +#define MCSPI_RX2_RDATA_M 0xFFFFFFFF // Channel 2 Received Data +#define MCSPI_RX2_RDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH3CONF register. +// +//****************************************************************************** +#define MCSPI_CH3CONF_CLKG 0x20000000 // Clock divider granularity This + // register defines the granularity + // of channel clock divider: power + // of two or one clock cycle + // granularity. When this bit is set + // the register MCSPI_CHCTRL[EXTCLK] + // must be configured to reach a + // maximum of 4096 clock divider + // ratio. Then The clock divider + // ratio is a concatenation of + // MCSPI_CHCONF[CLKD] and + // MCSPI_CHCTRL[EXTCLK] values 0 + // Clock granularity of power of two + // 1 One clock cycle ganularity +#define MCSPI_CH3CONF_FFER 0x10000000 // FIFO enabled for receive:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to receive data. 1 The + // buffer is used to receive data. +#define MCSPI_CH3CONF_FFEW 0x08000000 // FIFO enabled for Transmit:Only + // one channel can have this bit + // field set. 0 The buffer is not + // used to transmit data. 1 The + // buffer is used to transmit data. +#define MCSPI_CH3CONF_TCS3_M 0x06000000 // Chip Select Time Control This + // 2-bits field defines the number + // of interface clock cycles between + // CS toggling and first or last + // edge of SPI clock. 0x0 0.5 clock + // cycle 0x1 1.5 clock cycle 0x2 2.5 + // clock cycle 0x3 3.5 clock cycle +#define MCSPI_CH3CONF_TCS3_S 25 +#define MCSPI_CH3CONF_SBPOL 0x01000000 // Start bit polarity 0 Start bit + // polarity is held to 0 during SPI + // transfer. 1 Start bit polarity is + // held to 1 during SPI transfer. +#define MCSPI_CH3CONF_SBE 0x00800000 // Start bit enable for SPI + // transfer 0 Default SPI transfer + // length as specified by WL bit + // field 1 Start bit D/CX added + // before SPI transfer polarity is + // defined by MCSPI_CH3CONF[SBPOL] +#define MCSPI_CH3CONF_FORCE 0x00100000 // Manual SPIEN assertion to keep + // SPIEN active between SPI words. + // (single channel master mode only) + // 0 Writing 0 into this bit drives + // low the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it high when + // MCSPI_CHCONF(i)[EPOL]=1. 1 + // Writing 1 into this bit drives + // high the SPIEN line when + // MCSPI_CHCONF(i)[EPOL]=0 and + // drives it low when + // MCSPI_CHCONF(i)[EPOL]=1 +#define MCSPI_CH3CONF_TURBO 0x00080000 // Turbo mode 0 Turbo is + // deactivated (recommended for + // single SPI word transfer) 1 Turbo + // is activated to maximize the + // throughput for multi SPI words + // transfer. +#define MCSPI_CH3CONF_IS 0x00040000 // Input Select 0 Data Line0 + // (SPIDAT[0]) selected for + // reception. 1 Data Line1 + // (SPIDAT[1]) selected for + // reception +#define MCSPI_CH3CONF_DPE1 0x00020000 // Transmission Enable for data + // line 1 (SPIDATAGZEN[1]) 0 Data + // Line1 (SPIDAT[1]) selected for + // transmission 1 No transmission on + // Data Line1 (SPIDAT[1]) +#define MCSPI_CH3CONF_DPE0 0x00010000 // Transmission Enable for data + // line 0 (SPIDATAGZEN[0]) 0 Data + // Line0 (SPIDAT[0]) selected for + // transmission 1 No transmission on + // Data Line0 (SPIDAT[0]) +#define MCSPI_CH3CONF_DMAR 0x00008000 // DMA Read request The DMA Read + // request line is asserted when the + // channel is enabled and a new data + // is available in the receive + // register of the channel. The DMA + // Read request line is deasserted + // on read completion of the receive + // register of the channel. 0 DMA + // Read Request disabled 1 DMA Read + // Request enabled +#define MCSPI_CH3CONF_DMAW 0x00004000 // DMA Write request. The DMA Write + // request line is asserted when The + // channel is enabled and the + // transmitter register of the + // channel is empty. The DMA Write + // request line is deasserted on + // load completion of the + // transmitter register of the + // channel. 0 DMA Write Request + // disabled 1 DMA Write Request + // enabled +#define MCSPI_CH3CONF_TRM_M 0x00003000 // Transmit/Receive modes 0x0 + // Transmit and Receive mode 0x1 + // Receive only mode 0x2 Transmit + // only mode 0x3 Reserved +#define MCSPI_CH3CONF_TRM_S 12 +#define MCSPI_CH3CONF_WL_M 0x00000F80 // SPI word length 0x00 Reserved + // 0x01 Reserved 0x02 Reserved 0x03 + // The SPI word is 4-bits long 0x04 + // The SPI word is 5-bits long 0x05 + // The SPI word is 6-bits long 0x06 + // The SPI word is 7-bits long 0x07 + // The SPI word is 8-bits long 0x08 + // The SPI word is 9-bits long 0x09 + // The SPI word is 10-bits long 0x0A + // The SPI word is 11-bits long 0x0B + // The SPI word is 12-bits long 0x0C + // The SPI word is 13-bits long 0x0D + // The SPI word is 14-bits long 0x0E + // The SPI word is 15-bits long 0x0F + // The SPI word is 16-bits long 0x10 + // The SPI word is 17-bits long 0x11 + // The SPI word is 18-bits long 0x12 + // The SPI word is 19-bits long 0x13 + // The SPI word is 20-bits long 0x14 + // The SPI word is 21-bits long 0x15 + // The SPI word is 22-bits long 0x16 + // The SPI word is 23-bits long 0x17 + // The SPI word is 24-bits long 0x18 + // The SPI word is 25-bits long 0x19 + // The SPI word is 26-bits long 0x1A + // The SPI word is 27-bits long 0x1B + // The SPI word is 28-bits long 0x1C + // The SPI word is 29-bits long 0x1D + // The SPI word is 30-bits long 0x1E + // The SPI word is 31-bits long 0x1F + // The SPI word is 32-bits long +#define MCSPI_CH3CONF_WL_S 7 +#define MCSPI_CH3CONF_EPOL 0x00000040 // SPIEN polarity 0 SPIEN is held + // high during the active state. 1 + // SPIEN is held low during the + // active state. +#define MCSPI_CH3CONF_CLKD_M 0x0000003C // Frequency divider for SPICLK. + // (only when the module is a Master + // SPI device). A programmable clock + // divider divides the SPI reference + // clock (CLKSPIREF) with a 4-bit + // value and results in a new clock + // SPICLK available to shift-in and + // shift-out data. By default the + // clock divider ratio has a power + // of two granularity when + // MCSPI_CHCONF[CLKG] is cleared + // Otherwise this register is the 4 + // LSB bit of a 12-bit register + // concatenated with clock divider + // extension MCSPI_CHCTRL[EXTCLK] + // register.The value description + // below defines the clock ratio + // when MCSPI_CHCONF[CLKG] is set to + // 0. 0x0 1 0x1 2 0x2 4 0x3 8 0x4 16 + // 0x5 32 0x6 64 0x7 128 0x8 256 0x9 + // 512 0xA 1024 0xB 2048 0xC 4096 + // 0xD 8192 0xE 16384 0xF 32768 +#define MCSPI_CH3CONF_CLKD_S 2 +#define MCSPI_CH3CONF_POL 0x00000002 // SPICLK polarity 0 SPICLK is held + // high during the active state 1 + // SPICLK is held low during the + // active state +#define MCSPI_CH3CONF_PHA 0x00000001 // SPICLK phase 0 Data are latched + // on odd numbered edges of SPICLK. + // 1 Data are latched on even + // numbered edges of SPICLK. +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH3STAT register. +// +//****************************************************************************** +#define MCSPI_CH3STAT_RXFFF 0x00000040 +#define MCSPI_CH3STAT_RXFFE 0x00000020 +#define MCSPI_CH3STAT_TXFFF 0x00000010 +#define MCSPI_CH3STAT_TXFFE 0x00000008 +#define MCSPI_CH3STAT_EOT 0x00000004 +#define MCSPI_CH3STAT_TXS 0x00000002 +#define MCSPI_CH3STAT_RXS 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_CH3CTRL register. +// +//****************************************************************************** +#define MCSPI_CH3CTRL_EXTCLK_M 0x0000FF00 // Clock ratio extension: This + // register is used to concatenate + // with MCSPI_CHCONF[CLKD] register + // for clock ratio only when + // granularity is one clock cycle + // (MCSPI_CHCONF[CLKG] set to 1). + // Then the max value reached is + // 4096 clock divider ratio. 0x00 + // Clock ratio is CLKD + 1 0x01 + // Clock ratio is CLKD + 1 + 16 0xFF + // Clock ratio is CLKD + 1 + 4080 +#define MCSPI_CH3CTRL_EXTCLK_S 8 +#define MCSPI_CH3CTRL_EN 0x00000001 // Channel Enable 0 "Channel ""i"" + // is not active" 1 "Channel ""i"" + // is active" +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_TX3 register. +// +//****************************************************************************** +#define MCSPI_TX3_TDATA_M 0xFFFFFFFF // Channel 3 Data to transmit +#define MCSPI_TX3_TDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_RX3 register. +// +//****************************************************************************** +#define MCSPI_RX3_RDATA_M 0xFFFFFFFF // Channel 3 Received Data +#define MCSPI_RX3_RDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_XFERLEVEL register. +// +//****************************************************************************** +#define MCSPI_XFERLEVEL_WCNT_M 0xFFFF0000 // Spi word counterThis register + // holds the programmable value of + // number of SPI word to be + // transferred on channel which is + // using the FIFO buffer.When + // transfer had started a read back + // in this register returns the + // current SPI word transfer index. + // 0x0000 Counter not used 0x0001 + // one word 0xFFFE 65534 spi word + // 0xFFFF 65535 spi word +#define MCSPI_XFERLEVEL_WCNT_S 16 +#define MCSPI_XFERLEVEL_AFL_M 0x0000FF00 // Buffer Almost Full This register + // holds the programmable almost + // full level value used to + // determine almost full buffer + // condition. If the user wants an + // interrupt or a DMA read request + // to be issued during a receive + // operation when the data buffer + // holds at least n bytes then the + // buffer MCSPI_MODULCTRL[AFL] must + // be set with n-1.The size of this + // register is defined by the + // generic parameter FFNBYTE. 0x00 + // one byte 0x01 2 bytes 0xFE + // 255bytes 0xFF 256bytes +#define MCSPI_XFERLEVEL_AFL_S 8 +#define MCSPI_XFERLEVEL_AEL_M 0x000000FF // Buffer Almost EmptyThis register + // holds the programmable almost + // empty level value used to + // determine almost empty buffer + // condition. If the user wants an + // interrupt or a DMA write request + // to be issued during a transmit + // operation when the data buffer is + // able to receive n bytes then the + // buffer MCSPI_MODULCTRL[AEL] must + // be set with n-1. 0x00 one byte + // 0x01 2 bytes 0xFE 255 bytes 0xFF + // 256bytes +#define MCSPI_XFERLEVEL_AEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_DAFTX register. +// +//****************************************************************************** +#define MCSPI_DAFTX_DAFTDATA_M 0xFFFFFFFF // FIFO Data to transmit with DMA + // 256 bit aligned address. "This + // Register is only is used when + // MCSPI_MODULCTRL[FDAA] is set to + // ""1"" and only one of the + // MCSPI_CH(i)CONF[FFEW] of enabled + // channels is set. If these + // conditions are not respected any + // access to this register return a + // null value." +#define MCSPI_DAFTX_DAFTDATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MCSPI_O_DAFRX register. +// +//****************************************************************************** +#define MCSPI_DAFRX_DAFRDATA_M 0xFFFFFFFF // FIFO Data to transmit with DMA + // 256 bit aligned address. "This + // Register is only is used when + // MCSPI_MODULCTRL[FDAA] is set to + // ""1"" and only one of the + // MCSPI_CH(i)CONF[FFEW] of enabled + // channels is set. If these + // conditions are not respected any + // access to this register return a + // null value." +#define MCSPI_DAFRX_DAFRDATA_S 0 + + + +#endif // __HW_MCSPI_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_memmap.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_memmap.h new file mode 100644 index 00000000..244905dd --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_memmap.h @@ -0,0 +1,84 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_MEMMAP_H__ +#define __HW_MEMMAP_H__ + +//***************************************************************************** +// +// The following are defines for the base address of the memories and +// peripherals on the slave_1 interface. +// +//***************************************************************************** +#define FLASH_BASE 0x01000000 +#define SRAM_BASE 0x20000000 +#define WDT_BASE 0x40000000 +#define GPIOA0_BASE 0x40004000 +#define GPIOA1_BASE 0x40005000 +#define GPIOA2_BASE 0x40006000 +#define GPIOA3_BASE 0x40007000 +#define GPIOA4_BASE 0x40024000 +#define UARTA0_BASE 0x4000C000 +#define UARTA1_BASE 0x4000D000 +#define I2CA0_BASE 0x40020000 +#define TIMERA0_BASE 0x40030000 +#define TIMERA1_BASE 0x40031000 +#define TIMERA2_BASE 0x40032000 +#define TIMERA3_BASE 0x40033000 +#define STACKDIE_CTRL_BASE 0x400F5000 +#define COMMON_REG_BASE 0x400F7000 +#define FLASH_CONTROL_BASE 0x400FD000 +#define SYSTEM_CONTROL_BASE 0x400FE000 +#define UDMA_BASE 0x400FF000 +#define SDHOST_BASE 0x44010000 +#define CAMERA_BASE 0x44018000 +#define I2S_BASE 0x4401C000 +#define SSPI_BASE 0x44020000 +#define GSPI_BASE 0x44021000 +#define LSPI_BASE 0x44022000 +#define ARCM_BASE 0x44025000 +#define APPS_CONFIG_BASE 0x44026000 +#define GPRCM_BASE 0x4402D000 +#define OCP_SHARED_BASE 0x4402E000 +#define ADC_BASE 0x4402E800 +#define HIB1P2_BASE 0x4402F000 +#define HIB3P3_BASE 0x4402F800 +#define DTHE_BASE 0x44030000 +#define SHAMD5_BASE 0x44035000 +#define AES_BASE 0x44037000 +#define DES_BASE 0x44039000 + + +#endif // __HW_MEMMAP_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mmchs.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mmchs.h new file mode 100644 index 00000000..3096d13a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_mmchs.h @@ -0,0 +1,1919 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_MMCHS_H__ +#define __HW_MMCHS_H__ + +//***************************************************************************** +// +// The following are defines for the MMCHS register offsets. +// +//***************************************************************************** +#define MMCHS_O_HL_REV 0x00000000 // IP Revision Identifier (X.Y.R) + // Used by software to track + // features bugs and compatibility +#define MMCHS_O_HL_HWINFO 0x00000004 // Information about the IP + // module's hardware configuration + // i.e. typically the module's HDL + // generics (if any). Actual field + // format and encoding is up to the + // module's designer to decide. +#define MMCHS_O_HL_SYSCONFIG 0x00000010 // Clock management configuration +#define MMCHS_O_SYSCONFIG 0x00000110 // System Configuration Register + // This register allows controlling + // various parameters of the OCP + // interface. +#define MMCHS_O_SYSSTATUS 0x00000114 // System Status Register This + // register provides status + // information about the module + // excluding the interrupt status + // information +#define MMCHS_O_CSRE 0x00000124 // Card status response error This + // register enables the host + // controller to detect card status + // errors of response type R1 R1b + // for all cards and of R5 R5b and + // R6 response for cards types SD or + // SDIO. When a bit MMCHS_CSRE[i] is + // set to 1 if the corresponding bit + // at the same position in the + // response MMCHS_RSP0[i] is set to + // 1 the host controller indicates a + // card error (MMCHS_STAT[CERR]) + // interrupt status to avoid the + // host driver reading the response + // register (MMCHS_RSP0). Note: No + // automatic card error detection + // for autoCMD12 is implemented; the + // host system has to check + // autoCMD12 response register + // (MMCHS_RESP76) for possible card + // errors. +#define MMCHS_O_SYSTEST 0x00000128 // System Test register This + // register is used to control the + // signals that connect to I/O pins + // when the module is configured in + // system test (SYSTEST) mode for + // boundary connectivity + // verification. Note: In SYSTEST + // mode a write into MMCHS_CMD + // register will not start a + // transfer. The buffer behaves as a + // stack accessible only by the + // local host (push and pop + // operations). In this mode the + // Transfer Block Size + // (MMCHS_BLK[BLEN]) and the Blocks + // count for current transfer + // (MMCHS_BLK[NBLK]) are needed to + // generate a Buffer write ready + // interrupt (MMCHS_STAT[BWR]) or a + // Buffer read ready interrupt + // (MMCHS_STAT[BRR]) and DMA + // requests if enabled. +#define MMCHS_O_CON 0x0000012C // Configuration register This + // register is used: - to select the + // functional mode or the SYSTEST + // mode for any card. - to send an + // initialization sequence to any + // card. - to enable the detection + // on DAT[1] of a card interrupt for + // SDIO cards only. and also to + // configure : - specific data and + // command transfers for MMC cards + // only. - the parameters related to + // the card detect and write protect + // input signals. +#define MMCHS_O_PWCNT 0x00000130 // Power counter register This + // register is used to program a mmc + // counter to delay command + // transfers after activating the + // PAD power this value depends on + // PAD characteristics and voltage. +#define MMCHS_O_BLK 0x00000204 // Transfer Length Configuration + // register MMCHS_BLK[BLEN] is the + // block size register. + // MMCHS_BLK[NBLK] is the block + // count register. This register + // shall be used for any card. +#define MMCHS_O_ARG 0x00000208 // Command argument Register This + // register contains command + // argument specified as bit 39-8 of + // Command-Format These registers + // must be initialized prior to + // sending the command itself to the + // card (write action into the + // register MMCHS_CMD register). + // Only exception is for a command + // index specifying stuff bits in + // arguments making a write + // unnecessary. +#define MMCHS_O_CMD 0x0000020C // Command and transfer mode + // register MMCHS_CMD[31:16] = the + // command register MMCHS_CMD[15:0] + // = the transfer mode. This + // register configures the data and + // command transfers. A write into + // the most significant byte send + // the command. A write into + // MMCHS_CMD[15:0] registers during + // data transfer has no effect. This + // register shall be used for any + // card. Note: In SYSTEST mode a + // write into MMCHS_CMD register + // will not start a transfer. +#define MMCHS_O_RSP10 0x00000210 // Command response[31:0] Register + // This 32-bit register holds bits + // positions [31:0] of command + // response type + // R1/R1b/R2/R3/R4/R5/R5b/R6 +#define MMCHS_O_RSP32 0x00000214 // Command response[63:32] Register + // This 32-bit register holds bits + // positions [63:32] of command + // response type R2 +#define MMCHS_O_RSP54 0x00000218 // Command response[95:64] Register + // This 32-bit register holds bits + // positions [95:64] of command + // response type R2 +#define MMCHS_O_RSP76 0x0000021C // Command response[127:96] + // Register This 32-bit register + // holds bits positions [127:96] of + // command response type R2 +#define MMCHS_O_DATA 0x00000220 // Data Register This register is + // the 32-bit entry point of the + // buffer for read or write data + // transfers. The buffer size is + // 32bits x256(1024 bytes). Bytes + // within a word are stored and read + // in little endian format. This + // buffer can be used as two 512 + // byte buffers to transfer data + // efficiently without reducing the + // throughput. Sequential and + // contiguous access is necessary to + // increment the pointer correctly. + // Random or skipped access is not + // allowed. In little endian if the + // local host accesses this register + // byte-wise or 16bit-wise the least + // significant byte (bits [7:0]) + // must always be written/read + // first. The update of the buffer + // address is done on the most + // significant byte write for full + // 32-bit DATA register or on the + // most significant byte of the last + // word of block transfer. Example + // 1: Byte or 16-bit access + // Mbyteen[3:0]=0001 (1-byte) => + // Mbyteen[3:0]=0010 (1-byte) => + // Mbyteen[3:0]=1100 (2-bytes) OK + // Mbyteen[3:0]=0001 (1-byte) => + // Mbyteen[3:0]=0010 (1-byte) => + // Mbyteen[3:0]=0100 (1-byte) OK + // Mbyteen[3:0]=0001 (1-byte) => + // Mbyteen[3:0]=0010 (1-byte) => + // Mbyteen[3:0]=1000 (1-byte) Bad +#define MMCHS_O_PSTATE 0x00000224 // Present state register The Host + // can get status of the Host + // Controller from this 32-bit read + // only register. +#define MMCHS_O_HCTL 0x00000228 // Control register This register + // defines the host controls to set + // power wakeup and transfer + // parameters. MMCHS_HCTL[31:24] = + // Wakeup control MMCHS_HCTL[23:16] + // = Block gap control + // MMCHS_HCTL[15:8] = Power control + // MMCHS_HCTL[7:0] = Host control +#define MMCHS_O_SYSCTL 0x0000022C // SD system control register This + // register defines the system + // controls to set software resets + // clock frequency management and + // data timeout. MMCHS_SYSCTL[31:24] + // = Software resets + // MMCHS_SYSCTL[23:16] = Timeout + // control MMCHS_SYSCTL[15:0] = + // Clock control +#define MMCHS_O_STAT 0x00000230 // Interrupt status register The + // interrupt status regroups all the + // status of the module internal + // events that can generate an + // interrupt. MMCHS_STAT[31:16] = + // Error Interrupt Status + // MMCHS_STAT[15:0] = Normal + // Interrupt Status +#define MMCHS_O_IE 0x00000234 // Interrupt SD enable register + // This register allows to + // enable/disable the module to set + // status bits on an event-by-event + // basis. MMCHS_IE[31:16] = Error + // Interrupt Status Enable + // MMCHS_IE[15:0] = Normal Interrupt + // Status Enable +#define MMCHS_O_ISE 0x00000238 // Interrupt signal enable register + // This register allows to + // enable/disable the module + // internal sources of status on an + // event-by-event basis. + // MMCHS_ISE[31:16] = Error + // Interrupt Signal Enable + // MMCHS_ISE[15:0] = Normal + // Interrupt Signal Enable +#define MMCHS_O_AC12 0x0000023C // Auto CMD12 Error Status Register + // The host driver may determine + // which of the errors cases related + // to Auto CMD12 has occurred by + // checking this MMCHS_AC12 register + // when an Auto CMD12 Error + // interrupt occurs. This register + // is valid only when Auto CMD12 is + // enabled (MMCHS_CMD[ACEN]) and + // Auto CMD12Error (MMCHS_STAT[ACE]) + // is set to 1. Note: These bits are + // automatically reset when starting + // a new adtc command with data. +#define MMCHS_O_CAPA 0x00000240 // Capabilities register This + // register lists the capabilities + // of the MMC/SD/SDIO host + // controller. +#define MMCHS_O_CUR_CAPA 0x00000248 // Maximum current capabilities + // Register This register indicates + // the maximum current capability + // for each voltage. The value is + // meaningful if the voltage support + // is set in the capabilities + // register (MMCHS_CAPA). + // Initialization of this register + // (via a write access to this + // register) depends on the system + // capabilities. The host driver + // shall not modify this register + // after the initilaization. This + // register is only reinitialized by + // a hard reset (via RESETN signal) +#define MMCHS_O_FE 0x00000250 // Force Event Register for Error + // Interrupt status The force Event + // Register is not a physically + // implemented register. Rather it + // is an address at which the Error + // Interrupt Status register can be + // written. The effect of a write to + // this address will be reflected in + // the Error Interrupt Status + // Register if corresponding bit of + // the Error Interrupt Status Enable + // Register is set. +#define MMCHS_O_ADMAES 0x00000254 // ADMA Error Status Register When + // ADMA Error Interrupt is occurred + // the ADMA Error States field in + // this register holds the ADMA + // state and the ADMA System Address + // Register holds the address around + // the error descriptor. For + // recovering the error the Host + // Driver requires the ADMA state to + // identify the error descriptor + // address as follows: ST_STOP: + // Previous location set in the ADMA + // System Address register is the + // error descriptor address ST_FDS: + // Current location set in the ADMA + // System Address register is the + // error descriptor address ST_CADR: + // This sate is never set because do + // not generate ADMA error in this + // state. ST_TFR: Previous location + // set in the ADMA System Address + // register is the error descriptor + // address In case of write + // operation the Host Driver should + // use ACMD22 to get the number of + // written block rather than using + // this information since unwritten + // data may exist in the Host + // Controller. The Host Controller + // generates the ADMA Error + // Interrupt when it detects invalid + // descriptor data (Valid=0) at the + // ST_FDS state. In this case ADMA + // Error State indicates that an + // error occurs at ST_FDS state. The + // Host Driver may find that the + // Valid bit is not set in the error + // descriptor. +#define MMCHS_O_ADMASAL 0x00000258 // ADMA System address Low bits +#define MMCHS_O_REV 0x000002FC // Versions Register This register + // contains the hard coded RTL + // vendor revision number the + // version number of SD + // specification compliancy and a + // slot status bit. MMCHS_REV[31:16] + // = Host controller version + // MMCHS_REV[15:0] = Slot Interrupt + // Status + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_HL_REV register. +// +//****************************************************************************** +#define MMCHS_HL_REV_SCHEME_M 0xC0000000 +#define MMCHS_HL_REV_SCHEME_S 30 +#define MMCHS_HL_REV_FUNC_M 0x0FFF0000 // Function indicates a software + // compatible module family. If + // there is no level of software + // compatibility a new Func number + // (and hence REVISION) should be + // assigned. +#define MMCHS_HL_REV_FUNC_S 16 +#define MMCHS_HL_REV_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP + // design owner. RTL follows a + // numbering such as X.Y.R.Z which + // are explained in this table. R + // changes ONLY when: (1) PDS + // uploads occur which may have been + // due to spec changes (2) Bug fixes + // occur (3) Resets to '0' when X or + // Y changes. Design team has an + // internal 'Z' (customer invisible) + // number which increments on every + // drop that happens due to DV and + // RTL updates. Z resets to 0 when R + // increments. +#define MMCHS_HL_REV_R_RTL_S 11 +#define MMCHS_HL_REV_X_MAJOR_M 0x00000700 // Major Revision (X) maintained by + // IP specification owner. X changes + // ONLY when: (1) There is a major + // feature addition. An example + // would be adding Master Mode to + // Utopia Level2. The Func field (or + // Class/Type in old PID format) + // will remain the same. X does NOT + // change due to: (1) Bug fixes (2) + // Change in feature parameters. +#define MMCHS_HL_REV_X_MAJOR_S 8 +#define MMCHS_HL_REV_CUSTOM_M 0x000000C0 +#define MMCHS_HL_REV_CUSTOM_S 6 +#define MMCHS_HL_REV_Y_MINOR_M 0x0000003F // Minor Revision (Y) maintained by + // IP specification owner. Y changes + // ONLY when: (1) Features are + // scaled (up or down). Flexibility + // exists in that this feature + // scalability may either be + // represented in the Y change or a + // specific register in the IP that + // indicates which features are + // exactly available. (2) When + // feature creeps from Is-Not list + // to Is list. But this may not be + // the case once it sees silicon; in + // which case X will change. Y does + // NOT change due to: (1) Bug fixes + // (2) Typos or clarifications (3) + // major functional/feature + // change/addition/deletion. Instead + // these changes may be reflected + // via R S X as applicable. Spec + // owner maintains a + // customer-invisible number 'S' + // which changes due to: (1) + // Typos/clarifications (2) Bug + // documentation. Note that this bug + // is not due to a spec change but + // due to implementation. + // Nevertheless the spec tracks the + // IP bugs. An RTL release (say for + // silicon PG1.1) that occurs due to + // bug fix should document the + // corresponding spec number (X.Y.S) + // in its release notes. +#define MMCHS_HL_REV_Y_MINOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_HL_HWINFO register. +// +//****************************************************************************** +#define MMCHS_HL_HWINFO_RETMODE 0x00000040 +#define MMCHS_HL_HWINFO_MEM_SIZE_M \ + 0x0000003C + +#define MMCHS_HL_HWINFO_MEM_SIZE_S 2 +#define MMCHS_HL_HWINFO_MERGE_MEM \ + 0x00000002 + +#define MMCHS_HL_HWINFO_MADMA_EN \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// MMCHS_O_HL_SYSCONFIG register. +// +//****************************************************************************** +#define MMCHS_HL_SYSCONFIG_STANDBYMODE_M \ + 0x00000030 // Configuration of the local + // initiator state management mode. + // By definition initiator may + // generate read/write transaction + // as long as it is out of STANDBY + // state. 0x0 Force-standby mode: + // local initiator is + // unconditionally placed in standby + // state.Backup mode for debug only. + // 0x1 No-standby mode: local + // initiator is unconditionally + // placed out of standby + // state.Backup mode for debug only. + // 0x2 Smart-standby mode: local + // initiator standby status depends + // on local conditions i.e. the + // module's functional requirement + // from the initiator.IP module + // shall not generate + // (initiator-related) wakeup + // events. 0x3 "Smart-Standby + // wakeup-capable mode: local + // initiator standby status depends + // on local conditions i.e. the + // module's functional requirement + // from the initiator. IP module may + // generate (master-related) wakeup + // events when in standby state.Mode + // is only relevant if the + // appropriate IP module ""mwakeup"" + // output is implemented." + +#define MMCHS_HL_SYSCONFIG_STANDBYMODE_S 4 +#define MMCHS_HL_SYSCONFIG_IDLEMODE_M \ + 0x0000000C // Configuration of the local + // target state management mode. By + // definition target can handle + // read/write transaction as long as + // it is out of IDLE state. 0x0 + // Force-idle mode: local target's + // idle state follows (acknowledges) + // the system's idle requests + // unconditionally i.e. regardless + // of the IP module's internal + // requirements.Backup mode for + // debug only. 0x1 No-idle mode: + // local target never enters idle + // state.Backup mode for debug only. + // 0x2 Smart-idle mode: local + // target's idle state eventually + // follows (acknowledges) the + // system's idle requests depending + // on the IP module's internal + // requirements.IP module shall not + // generate (IRQ- or + // DMA-request-related) wakeup + // events. 0x3 "Smart-idle + // wakeup-capable mode: local + // target's idle state eventually + // follows (acknowledges) the + // system's idle requests depending + // on the IP module's internal + // requirements.IP module may + // generate (IRQ- or + // DMA-request-related) wakeup + // events when in idle state.Mode is + // only relevant if the appropriate + // IP module ""swakeup"" output(s) + // is (are) implemented." + +#define MMCHS_HL_SYSCONFIG_IDLEMODE_S 2 +#define MMCHS_HL_SYSCONFIG_FREEEMU \ + 0x00000002 // Sensitivity to emulation (debug) + // suspend input signal. + // Functionality NOT implemented in + // MMCHS. 0 IP module is sensitive + // to emulation suspend 1 IP module + // is not sensitive to emulation + // suspend + +#define MMCHS_HL_SYSCONFIG_SOFTRESET \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_SYSCONFIG register. +// +//****************************************************************************** +#define MMCHS_SYSCONFIG_STANDBYMODE_M \ + 0x00003000 // Master interface power + // Management standby/wait control. + // The bit field is only useful when + // generic parameter MADMA_EN + // (Master ADMA enable) is set as + // active otherwise it is a read + // only register read a '0'. 0x0 + // Force-standby. Mstandby is forced + // unconditionnaly. 0x1 No-standby. + // Mstandby is never asserted. 0x2 + // Smart-standby mode: local + // initiator standby status depends + // on local conditions i.e. the + // module's functional requirement + // from the initiator.IP module + // shall not generate + // (initiator-related) wakeup + // events. 0x3 Smart-Standby + // wakeup-capable mode: "local + // initiator standby status depends + // on local conditions i.e. the + // module's functional requirement + // from the initiator. IP module may + // generate (master-related) wakeup + // events when in standby state.Mode + // is only relevant if the + // appropriate IP module ""mwakeup"" + // output is implemented." + +#define MMCHS_SYSCONFIG_STANDBYMODE_S 12 +#define MMCHS_SYSCONFIG_CLOCKACTIVITY_M \ + 0x00000300 // Clocks activity during wake up + // mode period. Bit8: OCP interface + // clock Bit9: Functional clock 0x0 + // OCP and Functional clock may be + // switched off. 0x1 OCP clock is + // maintained. Functional clock may + // be switched-off. 0x2 Functional + // clock is maintained. OCP clock + // may be switched-off. 0x3 OCP and + // Functional clocks are maintained. + +#define MMCHS_SYSCONFIG_CLOCKACTIVITY_S 8 +#define MMCHS_SYSCONFIG_SIDLEMODE_M \ + 0x00000018 // Power management 0x0 If an idle + // request is detected the MMCHS + // acknowledges it unconditionally + // and goes in Inactive mode. + // Interrupt and DMA requests are + // unconditionally de-asserted. 0x1 + // If an idle request is detected + // the request is ignored and the + // module keeps on behaving + // normally. 0x2 Smart-idle mode: + // local target's idle state + // eventually follows (acknowledges) + // the system's idle requests + // depending on the IP module's + // internal requirements.IP module + // shall not generate (IRQ- or + // DMA-request-related) wakeup + // events. 0x3 Smart-idle + // wakeup-capable mode: "local + // target's idle state eventually + // follows (acknowledges) the + // system's idle requests depending + // on the IP module's internal + // requirements.IP module may + // generate (IRQ- or + // DMA-request-related) wakeup + // events when in idle state.Mode is + // only relevant if the appropriate + // IP module ""swakeup"" output(s) + // is (are) implemented." + +#define MMCHS_SYSCONFIG_SIDLEMODE_S 3 +#define MMCHS_SYSCONFIG_ENAWAKEUP \ + 0x00000004 // Wakeup feature control 0 Wakeup + // capability is disabled 1 Wakeup + // capability is enabled + +#define MMCHS_SYSCONFIG_SOFTRESET \ + 0x00000002 + +#define MMCHS_SYSCONFIG_AUTOIDLE \ + 0x00000001 // Internal Clock gating strategy 0 + // Clocks are free-running 1 + // Automatic clock gating strategy + // is applied based on the OCP and + // MMC interface activity + +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_SYSSTATUS register. +// +//****************************************************************************** +#define MMCHS_SYSSTATUS_RESETDONE \ + 0x00000001 + +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_CSRE register. +// +//****************************************************************************** +#define MMCHS_CSRE_CSRE_M 0xFFFFFFFF // Card status response error +#define MMCHS_CSRE_CSRE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_SYSTEST register. +// +//****************************************************************************** +#define MMCHS_SYSTEST_OBI 0x00010000 +#define MMCHS_SYSTEST_SDCD 0x00008000 +#define MMCHS_SYSTEST_SDWP 0x00004000 +#define MMCHS_SYSTEST_WAKD 0x00002000 +#define MMCHS_SYSTEST_SSB 0x00001000 +#define MMCHS_SYSTEST_D7D 0x00000800 +#define MMCHS_SYSTEST_D6D 0x00000400 +#define MMCHS_SYSTEST_D5D 0x00000200 +#define MMCHS_SYSTEST_D4D 0x00000100 +#define MMCHS_SYSTEST_D3D 0x00000080 +#define MMCHS_SYSTEST_D2D 0x00000040 +#define MMCHS_SYSTEST_D1D 0x00000020 +#define MMCHS_SYSTEST_D0D 0x00000010 +#define MMCHS_SYSTEST_DDIR 0x00000008 +#define MMCHS_SYSTEST_CDAT 0x00000004 +#define MMCHS_SYSTEST_CDIR 0x00000002 +#define MMCHS_SYSTEST_MCKD 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_CON register. +// +//****************************************************************************** +#define MMCHS_CON_SDMA_LNE 0x00200000 // Slave DMA Level/Edge Request: + // The waveform of the DMA request + // can be configured either edge + // sensitive with early de-assertion + // on first access to MMCHS_DATA + // register or late de-assertion + // request remains active until last + // allowed data written into + // MMCHS_DATA. 0 Slave DMA edge + // sensitive Early DMA de-assertion + // 1 Slave DMA level sensitive Late + // DMA de-assertion +#define MMCHS_CON_DMA_MNS 0x00100000 // DMA Master or Slave selection: + // When this bit is set and the + // controller is configured to use + // the DMA Ocp master interface is + // used to get datas from system + // using ADMA2 procedure (direct + // access to the memory).This option + // is only available if generic + // parameter MADMA_EN is asserted to + // '1'. 0 The controller is slave on + // data transfers with system. 1 The + // controller is master on data + // exchange with system controller + // must be configured as using DMA. +#define MMCHS_CON_DDR 0x00080000 // Dual Data Rate mode: When this + // register is set the controller + // uses both clock edge to emit or + // receive data. Odd bytes are + // transmitted on falling edges and + // even bytes are transmitted on + // rise edges. It only applies on + // Data bytes and CRC Start end bits + // and CRC status are kept full + // cycle. This bit field is only + // meaningful and active for even + // clock divider ratio of + // MMCHS_SYSCTL[CLKD] it is + // insensitive to MMCHS_HCTL[HSPE] + // setting. 0 Standard mode : data + // are transmitted on a single edge + // depending on MMCHS_HCTRL[HSPE]. 1 + // Data Bytes and CRC are + // transmitted on both edge. +#define MMCHS_CON_BOOT_CF0 0x00040000 +#define MMCHS_CON_BOOT_ACK 0x00020000 // Book acknowledge received: When + // this bit is set the controller + // should receive a boot status on + // DAT0 line after next command + // issued. If no status is received + // a data timeout will be generated. + // 0 No acknowledge to be received 1 + // A boot status will be received on + // DAT0 line after issuing a + // command. +#define MMCHS_CON_CLKEXTFREE 0x00010000 // External clock free running: + // This register is used to maintain + // card clock out of transfer + // transaction to enable slave + // module for example to generate a + // synchronous interrupt on DAT[1]. + // The Clock will be maintain only + // if MMCHS_SYSCTL[CEN] is set. 0 + // External card clock is cut off + // outside active transaction + // period. 1 External card clock is + // maintain even out of active + // transaction period only if + // MMCHS_SYSCTL[CEN] is set. +#define MMCHS_CON_PADEN 0x00008000 // Control Power for MMC Lines: + // This register is only useful when + // MMC PADs contain power saving + // mechanism to minimize its leakage + // power. It works as a GPIO that + // directly control the ACTIVE pin + // of PADs. Excepted for DAT[1] the + // signal is also combine outside + // the module with the dedicated + // power control MMCHS_CON[CTPL] + // bit. 0 ADPIDLE module pin is not + // forced it is automatically + // generated by the MMC fsms. 1 + // ADPIDLE module pin is forced to + // active state. +#define MMCHS_CON_OBIE 0x00004000 // Out-of-Band Interrupt Enable MMC + // cards only: This bit enables the + // detection of Out-of-Band + // Interrupt on MMCOBI input pin. + // The usage of the Out-of-Band + // signal (OBI) is optional and + // depends on the system + // integration. 0 Out-of-Band + // interrupt detection disabled 1 + // Out-of-Band interrupt detection + // enabled +#define MMCHS_CON_OBIP 0x00002000 // Out-of-Band Interrupt Polarity + // MMC cards only: This bit selects + // the active level of the + // out-of-band interrupt coming from + // MMC cards. The usage of the + // Out-of-Band signal (OBI) is + // optional and depends on the + // system integration. 0 active high + // level 1 active low level +#define MMCHS_CON_CEATA 0x00001000 // CE-ATA control mode MMC cards + // compliant with CE-ATA:By default + // this bit is set to 0. It is use + // to indicate that next commands + // are considered as specific CE-ATA + // commands that potentially use + // 'command completion' features. 0 + // Standard MMC/SD/SDIO mode. 1 + // CE-ATA mode next commands are + // considered as CE-ATA commands. +#define MMCHS_CON_CTPL 0x00000800 // Control Power for DAT[1] line + // MMC and SD cards: By default this + // bit is set to 0 and the host + // controller automatically disables + // all the input buffers outside of + // a transaction to minimize the + // leakage current. SDIO cards: When + // this bit is set to 1 the host + // controller automatically disables + // all the input buffers except the + // buffer of DAT[1] outside of a + // transaction in order to detect + // asynchronous card interrupt on + // DAT[1] line and minimize the + // leakage current of the buffers. 0 + // Disable all the input buffers + // outside of a transaction. 1 + // Disable all the input buffers + // except the buffer of DAT[1] + // outside of a transaction. +#define MMCHS_CON_DVAL_M 0x00000600 // Debounce filter value All cards + // This register is used to define a + // debounce period to filter the + // card detect input signal (SDCD). + // The usage of the card detect + // input signal (SDCD) is optional + // and depends on the system + // integration and the type of the + // connector housing that + // accommodates the card. 0x0 33 us + // debounce period 0x1 231 us + // debounce period 0x2 1 ms debounce + // period 0x3 84 ms debounce period +#define MMCHS_CON_DVAL_S 9 +#define MMCHS_CON_WPP 0x00000100 // Write protect polarity For SD + // and SDIO cards only This bit + // selects the active level of the + // write protect input signal + // (SDWP). The usage of the write + // protect input signal (SDWP) is + // optional and depends on the + // system integration and the type + // of the connector housing that + // accommodates the card. 0 active + // high level 1 active low level +#define MMCHS_CON_CDP 0x00000080 // Card detect polarity All cards + // This bit selects the active level + // of the card detect input signal + // (SDCD). The usage of the card + // detect input signal (SDCD) is + // optional and depends on the + // system integration and the type + // of the connector housing that + // accommodates the card. 0 active + // high level 1 active low level +#define MMCHS_CON_MIT 0x00000040 // MMC interrupt command Only for + // MMC cards. This bit must be set + // to 1 when the next write access + // to the command register + // (MMCHS_CMD) is for writing a MMC + // interrupt command (CMD40) + // requiring the command timeout + // detection to be disabled for the + // command response. 0 Command + // timeout enabled 1 Command timeout + // disabled +#define MMCHS_CON_DW8 0x00000020 // 8-bit mode MMC select For + // SD/SDIO cards this bit must be + // set to 0. For MMC card this bit + // must be set following a valid + // SWITCH command (CMD6) with the + // correct value and extend CSD + // index written in the argument. + // Prior to this command the MMC + // card configuration register (CSD + // and EXT_CSD) must be verified for + // compliancy with MMC standard + // specification 4.x (see section + // 3.6). 0 1-bit or 4-bit Data width + // (DAT[0] used MMC SD cards) 1 + // 8-bit Data width (DAT[7:0] used + // MMC cards) +#define MMCHS_CON_MODE 0x00000010 // Mode select All cards These bits + // select between Functional mode + // and SYSTEST mode. 0 Functional + // mode. Transfers to the + // MMC/SD/SDIO cards follow the card + // protocol. MMC clock is enabled. + // MMC/SD transfers are operated + // under the control of the CMD + // register. 1 SYSTEST mode The + // signal pins are configured as + // general-purpose input/output and + // the 1024-byte buffer is + // configured as a stack memory + // accessible only by the local host + // or system DMA. The pins retain + // their default type (input output + // or in-out). SYSTEST mode is + // operated under the control of the + // SYSTEST register. +#define MMCHS_CON_STR 0x00000008 // Stream command Only for MMC + // cards. This bit must be set to 1 + // only for the stream data + // transfers (read or write) of the + // adtc commands. Stream read is a + // class 1 command (CMD11: + // READ_DAT_UNTIL_STOP). Stream + // write is a class 3 command + // (CMD20: WRITE_DAT_UNTIL_STOP). 0 + // Block oriented data transfer 1 + // Stream oriented data transfer +#define MMCHS_CON_HR 0x00000004 // Broadcast host response Only for + // MMC cards. This register is used + // to force the host to generate a + // 48-bit response for bc command + // type. "It can be used to + // terminate the interrupt mode by + // generating a CMD40 response by + // the core (see section 4.3 + // ""Interrupt Mode"" in the MMC [1] + // specification). In order to have + // the host response to be generated + // in open drain mode the register + // MMCHS_CON[OD] must be set to 1." + // When MMCHS_CON[CEATA] is set to 1 + // and MMCHS_ARG set to 0x00000000 + // when writing 0x00000000 into + // MMCHS_CMD register the host + // controller performs a 'command + // completion signal disable' token + // i.e. CMD line held to '0' during + // 47 cycles followed by a 1. 0 The + // host does not generate a 48-bit + // response instead of a command. 1 + // The host generates a 48-bit + // response instead of a command or + // a command completion signal + // disable token. +#define MMCHS_CON_INIT 0x00000002 // Send initialization stream All + // cards. When this bit is set to 1 + // and the card is idle an + // initialization sequence is sent + // to the card. "An initialization + // sequence consists of setting the + // CMD line to 1 during 80 clock + // cycles. The initialisation + // sequence is mandatory - but it is + // not required to do it through + // this bit - this bit makes it + // easier. Clock divider + // (MMCHS_SYSCTL[CLKD]) should be + // set to ensure that 80 clock + // periods are greater than 1ms. + // (see section 9.3 ""Power-Up"" in + // the MMC card specification [1] or + // section 6.4 in the SD card + // specification [2])." Note: in + // this mode there is no command + // sent to the card and no response + // is expected 0 The host does not + // send an initialization sequence. + // 1 The host sends an + // initialization sequence. +#define MMCHS_CON_OD 0x00000001 // Card open drain mode. Only for + // MMC cards. This bit must be set + // to 1 for MMC card commands 1 2 3 + // and 40 and if the MMC card bus is + // operating in open-drain mode + // during the response phase to the + // command sent. Typically during + // card identification mode when the + // card is either in idle ready or + // ident state. It is also necessary + // to set this bit to 1 for a + // broadcast host response (see + // Broadcast host response register + // MMCHS_CON[HR]) 0 No Open Drain 1 + // Open Drain or Broadcast host + // response +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_PWCNT register. +// +//****************************************************************************** +#define MMCHS_PWCNT_PWRCNT_M 0x0000FFFF // Power counter register. This + // register is used to introduce a + // delay between the PAD ACTIVE pin + // assertion and the command issued. + // 0x0000 No additional delay added + // 0x0001 TCF delay (card clock + // period) 0x0002 TCF x 2 delay + // (card clock period) 0xFFFE TCF x + // 65534 delay (card clock period) + // 0xFFFF TCF x 65535 delay (card + // clock period) +#define MMCHS_PWCNT_PWRCNT_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_BLK register. +// +//****************************************************************************** +#define MMCHS_BLK_NBLK_M 0xFFFF0000 // Blocks count for current + // transfer This register is enabled + // when Block count Enable + // (MMCHS_CMD[BCE]) is set to 1 and + // is valid only for multiple block + // transfers. Setting the block + // count to 0 results no data blocks + // being transferred. Note: The host + // controller decrements the block + // count after each block transfer + // and stops when the count reaches + // zero. This register can be + // accessed only if no transaction + // is executing (i.e after a + // transaction has stopped). Read + // operations during transfers may + // return an invalid value and write + // operation will be ignored. In + // suspend context the number of + // blocks yet to be transferred can + // be determined by reading this + // register. When restoring transfer + // context prior to issuing a Resume + // command The local host shall + // restore the previously saved + // block count. 0x0000 Stop count + // 0x0001 1 block 0x0002 2 blocks + // 0xFFFF 65535 blocks +#define MMCHS_BLK_NBLK_S 16 +#define MMCHS_BLK_BLEN_M 0x00000FFF // Transfer Block Size. This + // register specifies the block size + // for block data transfers. Read + // operations during transfers may + // return an invalid value and write + // operations are ignored. When a + // CMD12 command is issued to stop + // the transfer a read of the BLEN + // field after transfer completion + // (MMCHS_STAT[TC] set to 1) will + // not return the true byte number + // of data length while the stop + // occurs but the value written in + // this register before transfer is + // launched. 0x000 No data transfer + // 0x001 1 byte block length 0x002 2 + // bytes block length 0x003 3 bytes + // block length 0x1FF 511 bytes + // block length 0x200 512 bytes + // block length 0x7FF 2047 bytes + // block length 0x800 2048 bytes + // block length +#define MMCHS_BLK_BLEN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_ARG register. +// +//****************************************************************************** +#define MMCHS_ARG_ARG_M 0xFFFFFFFF // Command argument bits [31:0] +#define MMCHS_ARG_ARG_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_CMD register. +// +//****************************************************************************** +#define MMCHS_CMD_INDX_M 0x3F000000 // Command index Binary encoded + // value from 0 to 63 specifying the + // command number send to card 0x00 + // CMD0 or ACMD0 0x01 CMD1 or ACMD1 + // 0x02 CMD2 or ACMD2 0x03 CMD3 or + // ACMD3 0x04 CMD4 or ACMD4 0x05 + // CMD5 or ACMD5 0x06 CMD6 or ACMD6 + // 0x07 CMD7 or ACMD7 0x08 CMD8 or + // ACMD8 0x09 CMD9 or ACMD9 0x0A + // CMD10 or ACMD10 0x0B CMD11 or + // ACMD11 0x0C CMD12 or ACMD12 0x0D + // CMD13 or ACMD13 0x0E CMD14 or + // ACMD14 0x0F CMD15 or ACMD15 0x10 + // CMD16 or ACMD16 0x11 CMD17 or + // ACMD17 0x12 CMD18 or ACMD18 0x13 + // CMD19 or ACMD19 0x14 CMD20 or + // ACMD20 0x15 CMD21 or ACMD21 0x16 + // CMD22 or ACMD22 0x17 CMD23 or + // ACMD23 0x18 CMD24 or ACMD24 0x19 + // CMD25 or ACMD25 0x1A CMD26 or + // ACMD26 0x1B CMD27 or ACMD27 0x1C + // CMD28 or ACMD28 0x1D CMD29 or + // ACMD29 0x1E CMD30 or ACMD30 0x1F + // CMD31 or ACMD31 0x20 CMD32 or + // ACMD32 0x21 CMD33 or ACMD33 0x22 + // CMD34 or ACMD34 0x23 CMD35 or + // ACMD35 0x24 CMD36 or ACMD36 0x25 + // CMD37 or ACMD37 0x26 CMD38 or + // ACMD38 0x27 CMD39 or ACMD39 0x28 + // CMD40 or ACMD40 0x29 CMD41 or + // ACMD41 0x2A CMD42 or ACMD42 0x2B + // CMD43 or ACMD43 0x2C CMD44 or + // ACMD44 0x2D CMD45 or ACMD45 0x2E + // CMD46 or ACMD46 0x2F CMD47 or + // ACMD47 0x30 CMD48 or ACMD48 0x31 + // CMD49 or ACMD49 0x32 CMD50 or + // ACMD50 0x33 CMD51 or ACMD51 0x34 + // CMD52 or ACMD52 0x35 CMD53 or + // ACMD53 0x36 CMD54 or ACMD54 0x37 + // CMD55 or ACMD55 0x38 CMD56 or + // ACMD56 0x39 CMD57 or ACMD57 0x3A + // CMD58 or ACMD58 0x3B CMD59 or + // ACMD59 0x3C CMD60 or ACMD60 0x3D + // CMD61 or ACMD61 0x3E CMD62 or + // ACMD62 0x3F CMD63 or ACMD63 +#define MMCHS_CMD_INDX_S 24 +#define MMCHS_CMD_CMD_TYPE_M 0x00C00000 // Command type This register + // specifies three types of special + // command: Suspend Resume and + // Abort. These bits shall be set to + // 00b for all other commands. 0x0 + // Others Commands 0x1 "CMD52 for + // writing ""Bus Suspend"" in CCCR" + // 0x2 "CMD52 for writing ""Function + // Select"" in CCCR" 0x3 "Abort + // command CMD12 CMD52 for writing + // "" I/O Abort"" in CCCR" +#define MMCHS_CMD_CMD_TYPE_S 22 +#define MMCHS_CMD_DP 0x00200000 // Data present select This + // register indicates that data is + // present and DAT line shall be + // used. It must be set to 0 in the + // following conditions: - command + // using only CMD line - command + // with no data transfer but using + // busy signal on DAT[0] - Resume + // command 0 Command with no data + // transfer 1 Command with data + // transfer +#define MMCHS_CMD_CICE 0x00100000 // Command Index check enable This + // bit must be set to 1 to enable + // index check on command response + // to compare the index field in the + // response against the index of the + // command. If the index is not the + // same in the response as in the + // command it is reported as a + // command index error + // (MMCHS_STAT[CIE] set to1) Note: + // The register CICE cannot be + // configured for an Auto CMD12 then + // index check is automatically + // checked when this command is + // issued. 0 Index check disable 1 + // Index check enable +#define MMCHS_CMD_CCCE 0x00080000 // Command CRC check enable This + // bit must be set to 1 to enable + // CRC7 check on command response to + // protect the response against + // transmission errors on the bus. + // If an error is detected it is + // reported as a command CRC error + // (MMCHS_STAT[CCRC] set to 1). + // Note: The register CCCE cannot be + // configured for an Auto CMD12 and + // then CRC check is automatically + // checked when this command is + // issued. 0 CRC7 check disable 1 + // CRC7 check enable +#define MMCHS_CMD_RSP_TYPE_M 0x00030000 // Response type This bits defines + // the response type of the command + // 0x0 No response 0x1 Response + // Length 136 bits 0x2 Response + // Length 48 bits 0x3 Response + // Length 48 bits with busy after + // response +#define MMCHS_CMD_RSP_TYPE_S 16 +#define MMCHS_CMD_MSBS 0x00000020 // Multi/Single block select This + // bit must be set to 1 for data + // transfer in case of multi block + // command. For any others command + // this bit shall be set to 0. 0 + // Single block. If this bit is 0 it + // is not necessary to set the + // register MMCHS_BLK[NBLK]. 1 Multi + // block. When Block Count is + // disabled (MMCHS_CMD[BCE] is set + // to 0) in Multiple block transfers + // (MMCHS_CMD[MSBS] is set to 1) the + // module can perform infinite + // transfer. +#define MMCHS_CMD_DDIR 0x00000010 // Data transfer Direction Select + // This bit defines either data + // transfer will be a read or a + // write. 0 Data Write (host to + // card) 1 Data Read (card to host) +#define MMCHS_CMD_ACEN 0x00000004 // Auto CMD12 Enable SD card only. + // When this bit is set to 1 the + // host controller issues a CMD12 + // automatically after the transfer + // completion of the last block. The + // Host Driver shall not set this + // bit to issue commands that do not + // require CMD12 to stop data + // transfer. In particular secure + // commands do not require CMD12. 0 + // Auto CMD12 disable 1 Auto CMD12 + // enable or CCS detection enabled. +#define MMCHS_CMD_BCE 0x00000002 // Block Count Enable Multiple + // block transfers only. This bit is + // used to enable the block count + // register (MMCHS_BLK[NBLK]). When + // Block Count is disabled + // (MMCHS_CMD[BCE] is set to 0) in + // Multiple block transfers + // (MMCHS_CMD[MSBS] is set to 1) the + // module can perform infinite + // transfer. 0 Block count disabled + // for infinite transfer. 1 Block + // count enabled for multiple block + // transfer with known number of + // blocks +#define MMCHS_CMD_DE 0x00000001 // DMA Enable This bit is used to + // enable DMA mode for host data + // access. 0 DMA mode disable 1 DMA + // mode enable +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_RSP10 register. +// +//****************************************************************************** +#define MMCHS_RSP10_RSP1_M 0xFFFF0000 // Command Response [31:16] +#define MMCHS_RSP10_RSP1_S 16 +#define MMCHS_RSP10_RSP0_M 0x0000FFFF // Command Response [15:0] +#define MMCHS_RSP10_RSP0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_RSP32 register. +// +//****************************************************************************** +#define MMCHS_RSP32_RSP3_M 0xFFFF0000 // Command Response [63:48] +#define MMCHS_RSP32_RSP3_S 16 +#define MMCHS_RSP32_RSP2_M 0x0000FFFF // Command Response [47:32] +#define MMCHS_RSP32_RSP2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_RSP54 register. +// +//****************************************************************************** +#define MMCHS_RSP54_RSP5_M 0xFFFF0000 // Command Response [95:80] +#define MMCHS_RSP54_RSP5_S 16 +#define MMCHS_RSP54_RSP4_M 0x0000FFFF // Command Response [79:64] +#define MMCHS_RSP54_RSP4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_RSP76 register. +// +//****************************************************************************** +#define MMCHS_RSP76_RSP7_M 0xFFFF0000 // Command Response [127:112] +#define MMCHS_RSP76_RSP7_S 16 +#define MMCHS_RSP76_RSP6_M 0x0000FFFF // Command Response [111:96] +#define MMCHS_RSP76_RSP6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_DATA register. +// +//****************************************************************************** +#define MMCHS_DATA_DATA_M 0xFFFFFFFF // Data Register [31:0] In + // functional mode (MMCHS_CON[MODE] + // set to the default value 0) A + // read access to this register is + // allowed only when the buffer read + // enable status is set to 1 + // (MMCHS_PSTATE[BRE]) otherwise a + // bad access (MMCHS_STAT[BADA]) is + // signaled. A write access to this + // register is allowed only when the + // buffer write enable status is set + // to 1(MMCHS_STATE[BWE]) otherwise + // a bad access (MMCHS_STAT[BADA]) + // is signaled and the data is not + // written. +#define MMCHS_DATA_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_PSTATE register. +// +//****************************************************************************** +#define MMCHS_PSTATE_CLEV 0x01000000 +#define MMCHS_PSTATE_DLEV_M 0x00F00000 // DAT[3:0] line signal level + // DAT[3] => bit 23 DAT[2] => bit 22 + // DAT[1] => bit 21 DAT[0] => bit 20 + // This status is used to check DAT + // line level to recover from errors + // and for debugging. This is + // especially useful in detecting + // the busy signal level from + // DAT[0]. The value of these + // registers after reset depends on + // the DAT lines level at that time. +#define MMCHS_PSTATE_DLEV_S 20 +#define MMCHS_PSTATE_WP 0x00080000 +#define MMCHS_PSTATE_CDPL 0x00040000 +#define MMCHS_PSTATE_CSS 0x00020000 +#define MMCHS_PSTATE_CINS 0x00010000 +#define MMCHS_PSTATE_BRE 0x00000800 +#define MMCHS_PSTATE_BWE 0x00000400 +#define MMCHS_PSTATE_RTA 0x00000200 +#define MMCHS_PSTATE_WTA 0x00000100 +#define MMCHS_PSTATE_DLA 0x00000004 +#define MMCHS_PSTATE_DATI 0x00000002 +#define MMCHS_PSTATE_CMDI 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_HCTL register. +// +//****************************************************************************** +#define MMCHS_HCTL_OBWE 0x08000000 // Wakeup event enable for + // 'Out-of-Band' Interrupt. This bit + // enables wakeup events for + // 'Out-of-Band' assertion. Wakeup + // is generated if the wakeup + // feature is enabled + // (MMCHS_SYSCONFIG[ENAWAKEUP]). The + // write to this register is ignored + // when MMCHS_CON[OBIE] is not set. + // 0 Disable wakeup on 'Out-of-Band' + // Interrupt 1 Enable wakeup on + // 'Out-of-Band' Interrupt +#define MMCHS_HCTL_REM 0x04000000 // Wakeup event enable on SD card + // removal This bit enables wakeup + // events for card removal + // assertion. Wakeup is generated if + // the wakeup feature is enabled + // (MMCHS_SYSCONFIG[ENAWAKEUP]). 0 + // Disable wakeup on card removal 1 + // Enable wakeup on card removal +#define MMCHS_HCTL_INS 0x02000000 // Wakeup event enable on SD card + // insertion This bit enables wakeup + // events for card insertion + // assertion. Wakeup is generated if + // the wakeup feature is enabled + // (MMCHS_SYSCONFIG[ENAWAKEUP]). 0 + // Disable wakeup on card insertion + // 1 Enable wakeup on card insertion +#define MMCHS_HCTL_IWE 0x01000000 // Wakeup event enable on SD card + // interrupt This bit enables wakeup + // events for card interrupt + // assertion. Wakeup is generated if + // the wakeup feature is enabled + // (MMCHS_SYSCONFIG[ENAWAKEUP]). 0 + // Disable wakeup on card interrupt + // 1 Enable wakeup on card interrupt +#define MMCHS_HCTL_IBG 0x00080000 // Interrupt block at gap This bit + // is valid only in 4-bit mode of + // SDIO card to enable interrupt + // detection in the interrupt cycle + // at block gap for a multiple block + // transfer. For MMC cards and for + // SD card this bit should be set to + // 0. 0 Disable interrupt detection + // at the block gap in 4-bit mode 1 + // Enable interrupt detection at the + // block gap in 4-bit mode +#define MMCHS_HCTL_RWC 0x00040000 // Read wait control The read wait + // function is optional only for + // SDIO cards. If the card supports + // read wait this bit must be + // enabled then requesting a stop at + // block gap (MMCHS_HCTL[SBGR]) + // generates a read wait period + // after the current end of block. + // Be careful if read wait is not + // supported it may cause a conflict + // on DAT line. 0 Disable Read Wait + // Control. Suspend/Resume cannot be + // supported. 1 Enable Read Wait + // Control +#define MMCHS_HCTL_CR 0x00020000 // Continue request This bit is + // used to restart a transaction + // that was stopped by requesting a + // stop at block gap + // (MMCHS_HCTL[SBGR]). Set this bit + // to 1 restarts the transfer. The + // bit is automatically set to 0 by + // the host controller when transfer + // has restarted i.e DAT line is + // active (MMCHS_PSTATE[DLA]) or + // transferring data + // (MMCHS_PSTATE[WTA]). The Stop at + // block gap request must be + // disabled (MMCHS_HCTL[SBGR]=0) + // before setting this bit. 0 No + // affect 1 transfer restart +#define MMCHS_HCTL_SBGR 0x00010000 // Stop at block gap request This + // bit is used to stop executing a + // transaction at the next block + // gap. The transfer can restart + // with a continue request + // (MMHS_HCTL[CR]) or during a + // suspend/resume sequence. In case + // of read transfer the card must + // support read wait control. In + // case of write transfer the host + // driver shall set this bit after + // all block data written. Until the + // transfer completion + // (MMCHS_STAT[TC] set to 1) the + // host driver shall leave this bit + // set to 1. If this bit is set the + // local host shall not write to the + // data register (MMCHS_DATA). 0 + // Transfer mode 1 Stop at block gap +#define MMCHS_HCTL_SDVS_M 0x00000E00 // SD bus voltage select All cards. + // The host driver should set to + // these bits to select the voltage + // level for the card according to + // the voltage supported by the + // system (MMCHS_CAPA[VS18VS30VS33]) + // before starting a transfer. 0x5 + // 1.8V (Typical) 0x6 3.0V (Typical) + // 0x7 3.3V (Typical) +#define MMCHS_HCTL_SDVS_S 9 +#define MMCHS_HCTL_SDBP 0x00000100 // SD bus power Before setting this + // bit the host driver shall select + // the SD bus voltage + // (MMCHS_HCTL[SDVS]). If the host + // controller detects the No card + // state this bit is automatically + // set to 0. If the module is power + // off a write in the command + // register (MMCHS_CMD) will not + // start the transfer. A write to + // this bit has no effect if the + // selected SD bus voltage + // MMCHS_HCTL[SDVS] is not supported + // according to capability register + // (MMCHS_CAPA[VS*]). 0 Power off 1 + // Power on +#define MMCHS_HCTL_CDSS 0x00000080 // Card Detect Signal Selection + // This bit selects source for the + // card detection.When the source + // for the card detection is + // switched the interrupt should be + // disabled during the switching + // period by clearing the Interrupt + // Status/Signal Enable register in + // order to mask unexpected + // interrupt being caused by the + // glitch. The Interrupt + // Status/Signal Enable should be + // disabled during over the period + // of debouncing. 0 SDCD# is + // selected (for normal use) 1 The + // Card Detect Test Level is + // selected (for test purpose) +#define MMCHS_HCTL_CDTL 0x00000040 // Card Detect Test Level: This bit + // is enabled while the Card Detect + // Signal Selection is set to 1 and + // it indicates card inserted or + // not. 0 No Card 1 Card Inserted +#define MMCHS_HCTL_DMAS_M 0x00000018 // DMA Select Mode: One of + // supported DMA modes can be + // selected. The host driver shall + // check support of DMA modes by + // referring the Capabilities + // register. Use of selected DMA is + // determined by DMA Enable of the + // Transfer Mode register. This + // register is only meaningful when + // MADMA_EN is set to 1. When + // MADMA_EN is set to 0 the bit + // field is read only and returned + // value is 0. 0x0 Reserved 0x1 + // Reserved 0x2 32-bit Address ADMA2 + // is selected 0x3 Reserved +#define MMCHS_HCTL_DMAS_S 3 +#define MMCHS_HCTL_HSPE 0x00000004 // High Speed Enable: Before + // setting this bit the Host Driver + // shall check the High Speed + // Support in the Capabilities + // register. If this bit is set to 0 + // (default) the Host Controller + // outputs CMD line and DAT lines at + // the falling edge of the SD Clock. + // If this bit is set to 1 the Host + // Controller outputs CMD line and + // DAT lines at the rising edge of + // the SD Clock.This bit shall not + // be set when dual data rate mode + // is activated in MMCHS_CON[DDR]. 0 + // Normal speed mode 1 High speed + // mode +#define MMCHS_HCTL_DTW 0x00000002 // Data transfer width For MMC card + // this bit must be set following a + // valid SWITCH command (CMD6) with + // the correct value and extend CSD + // index written in the argument. + // Prior to this command the MMC + // card configuration register (CSD + // and EXT_CSD) must be verified for + // compliance with MMC standard + // specification 4.x (see section + // 3.6). This register has no effect + // when the MMC 8-bit mode is + // selected (register MMCHS_CON[DW8] + // set to1 ) For SD/SDIO cards this + // bit must be set following a valid + // SET_BUS_WIDTH command (ACMD6) + // with the value written in bit 1 + // of the argument. Prior to this + // command the SD card configuration + // register (SCR) must be verified + // for the supported bus width by + // the SD card. 0 1-bit Data width + // (DAT[0] used) 1 4-bit Data width + // (DAT[3:0] used) +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_SYSCTL register. +// +//****************************************************************************** +#define MMCHS_SYSCTL_SRD 0x04000000 // Software reset for DAT line This + // bit is set to 1 for reset and + // released to 0 when completed. DAT + // finite state machine in both + // clock domain are also reset. Here + // below are the registers cleared + // by MMCHS_SYSCTL[SRD]: #VALUE! - + // MMCHS_PSTATE: BRE BWE RTA WTA DLA + // and DATI - MMCHS_HCTL: SBGR and + // CR - MMCHS_STAT: BRR BWR BGE and + // TC OCP and MMC buffer data + // management is reinitialized. 0 + // Reset completed 1 Software reset + // for DAT line +#define MMCHS_SYSCTL_SRC 0x02000000 // Software reset for CMD line This + // bit is set to 1 for reset and + // released to 0 when completed. CMD + // finite state machine in both + // clock domain are also reset. Here + // below the registers cleared by + // MMCHS_SYSCTL[SRC]: - + // MMCHS_PSTATE: CMDI - MMCHS_STAT: + // CC OCP and MMC command status + // management is reinitialized. 0 + // Reset completed 1 Software reset + // for CMD line +#define MMCHS_SYSCTL_SRA 0x01000000 // Software reset for all This bit + // is set to 1 for reset and + // released to 0 when completed. + // This reset affects the entire + // host controller except for the + // card detection circuit and + // capabilities registers. 0 Reset + // completed 1 Software reset for + // all the design +#define MMCHS_SYSCTL_DTO_M 0x000F0000 // Data timeout counter value and + // busy timeout. This value + // determines the interval by which + // DAT lines timeouts are detected. + // The host driver needs to set this + // bitfield based on - the maximum + // read access time (NAC) (Refer to + // the SD Specification Part1 + // Physical Layer) - the data read + // access time values (TAAC and + // NSAC) in the card specific data + // register (CSD) of the card - the + // timeout clock base frequency + // (MMCHS_CAPA[TCF]). If the card + // does not respond within the + // specified number of cycles a data + // timeout error occurs + // (MMCHS_STA[DTO]). The + // MMCHS_SYSCTL[DTO] register is + // also used to check busy duration + // to generate busy timeout for + // commands with busy response or + // for busy programming during a + // write command. Timeout on CRC + // status is generated if no CRC + // token is present after a block + // write. 0x0 TCF x 2^13 0x1 TCF x + // 2^14 0xE TCF x 2^27 0xF Reserved +#define MMCHS_SYSCTL_DTO_S 16 +#define MMCHS_SYSCTL_CLKD_M 0x0000FFC0 // Clock frequency select These + // bits define the ratio between a + // reference clock frequency (system + // dependant) and the output clock + // frequency on the CLK pin of + // either the memory card (MMC SD or + // SDIO). 0x000 Clock Ref bypass + // 0x001 Clock Ref bypass 0x002 + // Clock Ref / 2 0x003 Clock Ref / 3 + // 0x3FF Clock Ref / 1023 +#define MMCHS_SYSCTL_CLKD_S 6 +#define MMCHS_SYSCTL_CEN 0x00000004 // Clock enable This bit controls + // if the clock is provided to the + // card or not. 0 The clock is not + // provided to the card . Clock + // frequency can be changed . 1 The + // clock is provided to the card and + // can be automatically gated when + // MMCHS_SYSCONFIG[AUTOIDLE] is set + // to 1 (default value) . The host + // driver shall wait to set this bit + // to 1 until the Internal clock is + // stable (MMCHS_SYSCTL[ICS]). +#define MMCHS_SYSCTL_ICS 0x00000002 +#define MMCHS_SYSCTL_ICE 0x00000001 // Internal clock enable This + // register controls the internal + // clock activity. In very low power + // state the internal clock is + // stopped. Note: The activity of + // the debounce clock (used for + // wakeup events) and the OCP clock + // (used for reads and writes to the + // module register map) are not + // affected by this register. 0 The + // internal clock is stopped (very + // low power state). 1 The internal + // clock oscillates and can be + // automatically gated when + // MMCHS_SYSCONFIG[AUTOIDLE] is set + // to 1 (default value) . +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_STAT register. +// +//****************************************************************************** +#define MMCHS_STAT_BADA 0x20000000 +#define MMCHS_STAT_CERR 0x10000000 +#define MMCHS_STAT_ADMAE 0x02000000 +#define MMCHS_STAT_ACE 0x01000000 +#define MMCHS_STAT_DEB 0x00400000 +#define MMCHS_STAT_DCRC 0x00200000 +#define MMCHS_STAT_DTO 0x00100000 +#define MMCHS_STAT_CIE 0x00080000 +#define MMCHS_STAT_CEB 0x00040000 +#define MMCHS_STAT_CCRC 0x00020000 +#define MMCHS_STAT_CTO 0x00010000 +#define MMCHS_STAT_ERRI 0x00008000 +#define MMCHS_STAT_BSR 0x00000400 +#define MMCHS_STAT_OBI 0x00000200 +#define MMCHS_STAT_CIRQ 0x00000100 +#define MMCHS_STAT_CREM 0x00000080 +#define MMCHS_STAT_CINS 0x00000040 +#define MMCHS_STAT_BRR 0x00000020 +#define MMCHS_STAT_BWR 0x00000010 +#define MMCHS_STAT_DMA 0x00000008 +#define MMCHS_STAT_BGE 0x00000004 +#define MMCHS_STAT_TC 0x00000002 +#define MMCHS_STAT_CC 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_IE register. +// +//****************************************************************************** +#define MMCHS_IE_BADA_ENABLE 0x20000000 // Bad access to data space + // Interrupt Enable 0 Masked 1 + // Enabled +#define MMCHS_IE_CERR_ENABLE 0x10000000 // Card error interrupt Enable 0 + // Masked 1 Enabled +#define MMCHS_IE_ADMAE_ENABLE 0x02000000 // ADMA error Interrupt Enable 0 + // Masked 1 Enabled +#define MMCHS_IE_ACE_ENABLE 0x01000000 // Auto CMD12 error Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_DEB_ENABLE 0x00400000 // Data end bit error Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_DCRC_ENABLE 0x00200000 // Data CRC error Interrupt Enable + // 0 Masked 1 Enabled +#define MMCHS_IE_DTO_ENABLE 0x00100000 // Data timeout error Interrupt + // Enable 0 The data timeout + // detection is deactivated. The + // host controller provides the + // clock to the card until the card + // sends the data or the transfer is + // aborted. 1 The data timeout + // detection is enabled. +#define MMCHS_IE_CIE_ENABLE 0x00080000 // Command index error Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_CEB_ENABLE 0x00040000 // Command end bit error Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_CCRC_ENABLE 0x00020000 // Command CRC error Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_CTO_ENABLE 0x00010000 // Command timeout error Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_NULL 0x00008000 // Fixed to 0 The host driver shall + // control error interrupts using + // the Error Interrupt Signal Enable + // register. Writes to this bit are + // ignored +#define MMCHS_IE_BSR_ENABLE 0x00000400 // Boot status interrupt Enable A + // write to this register when + // MMCHS_CON[BOOT_ACK] is set to 0x0 + // is ignored. 0 Masked 1 Enabled +#define MMCHS_IE_OBI_ENABLE 0x00000200 // Out-of-Band interrupt Enable A + // write to this register when + // MMCHS_CON[OBIE] is set to '0' is + // ignored. 0 Masked 1 Enabled +#define MMCHS_IE_CIRQ_ENABLE 0x00000100 // Card interrupt Enable A clear of + // this bit also clears the + // corresponding status bit. During + // 1-bit mode if the interrupt + // routine doesn't remove the source + // of a card interrupt in the SDIO + // card the status bit is reasserted + // when this bit is set to 1. 0 + // Masked 1 Enabled +#define MMCHS_IE_CREM_ENABLE 0x00000080 // Card removal Interrupt Enable 0 + // Masked 1 Enabled +#define MMCHS_IE_CINS_ENABLE 0x00000040 // Card insertion Interrupt Enable + // 0 Masked 1 Enabled +#define MMCHS_IE_BRR_ENABLE 0x00000020 // Buffer Read Ready Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_BWR_ENABLE 0x00000010 // Buffer Write Ready Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_DMA_ENABLE 0x00000008 // DMA interrupt Enable 0 Masked 1 + // Enabled +#define MMCHS_IE_BGE_ENABLE 0x00000004 // Block Gap Event Interrupt Enable + // 0 Masked 1 Enabled +#define MMCHS_IE_TC_ENABLE 0x00000002 // Transfer completed Interrupt + // Enable 0 Masked 1 Enabled +#define MMCHS_IE_CC_ENABLE 0x00000001 // Command completed Interrupt + // Enable 0 Masked 1 Enabled +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_ISE register. +// +//****************************************************************************** +#define MMCHS_ISE_BADA_SIGEN 0x20000000 // Bad access to data space signal + // status Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CERR_SIGEN 0x10000000 // Card error interrupt signal + // status Enable 0 Masked 1 Enabled +#define MMCHS_ISE_ADMAE_SIGEN 0x02000000 // ADMA error signal status Enable + // 0 Masked 1 Enabled +#define MMCHS_ISE_ACE_SIGEN 0x01000000 // Auto CMD12 error signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_DEB_SIGEN 0x00400000 // Data end bit error signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_DCRC_SIGEN 0x00200000 // Data CRC error signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_DTO_SIGEN 0x00100000 // Data timeout error signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CIE_SIGEN 0x00080000 // Command index error signal + // status Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CEB_SIGEN 0x00040000 // Command end bit error signal + // status Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CCRC_SIGEN 0x00020000 // Command CRC error signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CTO_SIGEN 0x00010000 // Command timeout error signal + // status Enable 0 Masked 1 Enabled +#define MMCHS_ISE_NULL 0x00008000 // Fixed to 0 The host driver shall + // control error interrupts using + // the Error Interrupt Signal Enable + // register. Writes to this bit are + // ignored +#define MMCHS_ISE_BSR_SIGEN 0x00000400 // Boot status signal status + // EnableA write to this register + // when MMCHS_CON[BOOT_ACK] is set + // to 0x0 is ignored. 0 Masked 1 + // Enabled +#define MMCHS_ISE_OBI_SIGEN 0x00000200 // Out-Of-Band Interrupt signal + // status Enable A write to this + // register when MMCHS_CON[OBIE] is + // set to '0' is ignored. 0 Masked 1 + // Enabled +#define MMCHS_ISE_CIRQ_SIGEN 0x00000100 // Card interrupt signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CREM_SIGEN 0x00000080 // Card removal signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CINS_SIGEN 0x00000040 // Card insertion signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_BRR_SIGEN 0x00000020 // Buffer Read Ready signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_BWR_SIGEN 0x00000010 // Buffer Write Ready signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_DMA_SIGEN 0x00000008 // DMA interrupt Signal status + // enable 0 Masked 1 Enabled +#define MMCHS_ISE_BGE_SIGEN 0x00000004 // Black Gap Event signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_TC_SIGEN 0x00000002 // Transfer completed signal status + // Enable 0 Masked 1 Enabled +#define MMCHS_ISE_CC_SIGEN 0x00000001 // Command completed signal status + // Enable 0 Masked 1 Enabled +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_AC12 register. +// +//****************************************************************************** +#define MMCHS_AC12_CNI 0x00000080 +#define MMCHS_AC12_ACIE 0x00000010 +#define MMCHS_AC12_ACEB 0x00000008 +#define MMCHS_AC12_ACCE 0x00000004 +#define MMCHS_AC12_ACTO 0x00000002 +#define MMCHS_AC12_ACNE 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_CAPA register. +// +//****************************************************************************** +#define MMCHS_CAPA_BIT64 0x10000000 +#define MMCHS_CAPA_VS18 0x04000000 +#define MMCHS_CAPA_VS30 0x02000000 +#define MMCHS_CAPA_VS33 0x01000000 +#define MMCHS_CAPA_SRS 0x00800000 +#define MMCHS_CAPA_DS 0x00400000 +#define MMCHS_CAPA_HSS 0x00200000 +#define MMCHS_CAPA_AD2S 0x00080000 +#define MMCHS_CAPA_MBL_M 0x00030000 +#define MMCHS_CAPA_MBL_S 16 +#define MMCHS_CAPA_BCF_M 0x00003F00 +#define MMCHS_CAPA_BCF_S 8 +#define MMCHS_CAPA_TCU 0x00000080 +#define MMCHS_CAPA_TCF_M 0x0000003F +#define MMCHS_CAPA_TCF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_CUR_CAPA register. +// +//****************************************************************************** +#define MMCHS_CUR_CAPA_CUR_1V8_M \ + 0x00FF0000 + +#define MMCHS_CUR_CAPA_CUR_1V8_S 16 +#define MMCHS_CUR_CAPA_CUR_3V0_M \ + 0x0000FF00 + +#define MMCHS_CUR_CAPA_CUR_3V0_S 8 +#define MMCHS_CUR_CAPA_CUR_3V3_M \ + 0x000000FF + +#define MMCHS_CUR_CAPA_CUR_3V3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_FE register. +// +//****************************************************************************** +#define MMCHS_FE_FE_BADA 0x20000000 +#define MMCHS_FE_FE_CERR 0x10000000 +#define MMCHS_FE_FE_ADMAE 0x02000000 +#define MMCHS_FE_FE_ACE 0x01000000 +#define MMCHS_FE_FE_DEB 0x00400000 +#define MMCHS_FE_FE_DCRC 0x00200000 +#define MMCHS_FE_FE_DTO 0x00100000 +#define MMCHS_FE_FE_CIE 0x00080000 +#define MMCHS_FE_FE_CEB 0x00040000 +#define MMCHS_FE_FE_CCRC 0x00020000 +#define MMCHS_FE_FE_CTO 0x00010000 +#define MMCHS_FE_FE_CNI 0x00000080 +#define MMCHS_FE_FE_ACIE 0x00000010 +#define MMCHS_FE_FE_ACEB 0x00000008 +#define MMCHS_FE_FE_ACCE 0x00000004 +#define MMCHS_FE_FE_ACTO 0x00000002 +#define MMCHS_FE_FE_ACNE 0x00000001 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_ADMAES register. +// +//****************************************************************************** +#define MMCHS_ADMAES_LME 0x00000004 // ADMA Length Mismatch Error: (1) + // While Block Count Enable being + // set the total data length + // specified by the Descriptor table + // is different from that specified + // by the Block Count and Block + // Length. (2) Total data length can + // not be divided by the block + // length. 0 No Error 1 Error +#define MMCHS_ADMAES_AES_M 0x00000003 // ADMA Error State his field + // indicates the state of ADMA when + // error is occurred during ADMA + // data transfer. "This field never + // indicates ""10"" because ADMA + // never stops in this state." 0x0 + // ST_STOP (Stop DMA)Contents of + // SYS_SDR register 0x1 ST_STOP + // (Stop DMA)Points the error + // descriptor 0x2 Never set this + // state(Not used) 0x3 ST_TFR + // (Transfer Data)Points the next of + // the error descriptor +#define MMCHS_ADMAES_AES_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_ADMASAL register. +// +//****************************************************************************** +#define MMCHS_ADMASAL_ADMA_A32B_M \ + 0xFFFFFFFF // ADMA System address 32 bits.This + // register holds byte address of + // executing command of the + // Descriptor table. 32-bit Address + // Descriptor uses lower 32-bit of + // this register. At the start of + // ADMA the Host Driver shall set + // start address of the Descriptor + // table. The ADMA increments this + // register address which points to + // next line when every fetching a + // Descriptor line. When the ADMA + // Error Interrupt is generated this + // register shall hold valid + // Descriptor address depending on + // the ADMA state. The Host Driver + // shall program Descriptor Table on + // 32-bit boundary and set 32-bit + // boundary address to this + // register. ADMA2 ignores lower + // 2-bit of this register and + // assumes it to be 00b. + +#define MMCHS_ADMASAL_ADMA_A32B_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the MMCHS_O_REV register. +// +//****************************************************************************** +#define MMCHS_REV_VREV_M 0xFF000000 // Vendor Version Number: IP + // revision [7:4] Major revision + // [3:0] Minor revision Examples: + // 0x10 for 1.0 0x21 for 2.1 +#define MMCHS_REV_VREV_S 24 +#define MMCHS_REV_SREV_M 0x00FF0000 +#define MMCHS_REV_SREV_S 16 +#define MMCHS_REV_SIS 0x00000001 // Slot Interrupt Status This + // status bit indicates the inverted + // state of interrupt signal for the + // module. By a power on reset or by + // setting a software reset for all + // (MMCHS_HCTL[SRA]) the interrupt + // signal shall be de-asserted and + // this status shall read 0. + + + +#endif // __HW_MMCHS_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_nvic.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_nvic.h new file mode 100644 index 00000000..1545f226 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_nvic.h @@ -0,0 +1,1710 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +//***************************************************************************** +// +// hw_nvic.h - Macros used when accessing the NVIC hardware. +// +//***************************************************************************** + +#ifndef __HW_NVIC_H__ +#define __HW_NVIC_H__ + +//***************************************************************************** +// +// The following are defines for the NVIC register addresses. +// +//***************************************************************************** +#define NVIC_INT_TYPE 0xE000E004 // Interrupt Controller Type Reg +#define NVIC_ACTLR 0xE000E008 // Auxiliary Control +#define NVIC_ST_CTRL 0xE000E010 // SysTick Control and Status + // Register +#define NVIC_ST_RELOAD 0xE000E014 // SysTick Reload Value Register +#define NVIC_ST_CURRENT 0xE000E018 // SysTick Current Value Register +#define NVIC_ST_CAL 0xE000E01C // SysTick Calibration Value Reg + +#define NVIC_EN0 0xE000E100 // Interrupt 0-31 Set Enable +#define NVIC_EN1 0xE000E104 // Interrupt 32-54 Set Enable +#define NVIC_EN2 0xE000E108 // Interrupt 64-95 Set Enable +#define NVIC_EN3 0xE000E10C // Interrupt 96-127 Set Enable +#define NVIC_EN4 0xE000E110 // Interrupt 128-131 Set Enable +#define NVIC_EN5 0xE000E114 // Interrupt 160-191 Set Enable + +#define NVIC_DIS0 0xE000E180 // Interrupt 0-31 Clear Enable +#define NVIC_DIS1 0xE000E184 // Interrupt 32-54 Clear Enable + +#define NVIC_DIS2 0xE000E188 // Interrupt 64-95 Clear Enable +#define NVIC_DIS3 0xE000E18C // Interrupt 96-127 Clear Enable +#define NVIC_DIS4 0xE000E190 // Interrupt 128-131 Clear Enable +#define NVIC_DIS5 0xE000E194 // Interrupt 160-191 Clear Enable + +#define NVIC_PEND0 0xE000E200 // Interrupt 0-31 Set Pending +#define NVIC_PEND1 0xE000E204 // Interrupt 32-54 Set Pending + +#define NVIC_PEND2 0xE000E208 // Interrupt 64-95 Set Pending +#define NVIC_PEND3 0xE000E20C // Interrupt 96-127 Set Pending +#define NVIC_PEND4 0xE000E210 // Interrupt 128-131 Set Pending +#define NVIC_PEND5 0xE000E214 // Interrupt 160-191 Set Pending + +#define NVIC_UNPEND0 0xE000E280 // Interrupt 0-31 Clear Pending +#define NVIC_UNPEND1 0xE000E284 // Interrupt 32-54 Clear Pending + +#define NVIC_UNPEND2 0xE000E288 // Interrupt 64-95 Clear Pending +#define NVIC_UNPEND3 0xE000E28C // Interrupt 96-127 Clear Pending +#define NVIC_UNPEND4 0xE000E290 // Interrupt 128-131 Clear Pending +#define NVIC_UNPEND5 0xE000E294 // Interrupt 160-191 Clear Pending + +#define NVIC_ACTIVE0 0xE000E300 // Interrupt 0-31 Active Bit +#define NVIC_ACTIVE1 0xE000E304 // Interrupt 32-54 Active Bit + +#define NVIC_ACTIVE2 0xE000E308 // Interrupt 64-95 Active Bit +#define NVIC_ACTIVE3 0xE000E30C // Interrupt 96-127 Active Bit +#define NVIC_ACTIVE4 0xE000E310 // Interrupt 128-131 Active Bit +#define NVIC_ACTIVE5 0xE000E314 // Interrupt 160-191 Active Bit + +#define NVIC_PRI0 0xE000E400 // Interrupt 0-3 Priority +#define NVIC_PRI1 0xE000E404 // Interrupt 4-7 Priority +#define NVIC_PRI2 0xE000E408 // Interrupt 8-11 Priority +#define NVIC_PRI3 0xE000E40C // Interrupt 12-15 Priority +#define NVIC_PRI4 0xE000E410 // Interrupt 16-19 Priority +#define NVIC_PRI5 0xE000E414 // Interrupt 20-23 Priority +#define NVIC_PRI6 0xE000E418 // Interrupt 24-27 Priority +#define NVIC_PRI7 0xE000E41C // Interrupt 28-31 Priority +#define NVIC_PRI8 0xE000E420 // Interrupt 32-35 Priority +#define NVIC_PRI9 0xE000E424 // Interrupt 36-39 Priority +#define NVIC_PRI10 0xE000E428 // Interrupt 40-43 Priority +#define NVIC_PRI11 0xE000E42C // Interrupt 44-47 Priority +#define NVIC_PRI12 0xE000E430 // Interrupt 48-51 Priority +#define NVIC_PRI13 0xE000E434 // Interrupt 52-53 Priority + +#define NVIC_PRI14 0xE000E438 // Interrupt 56-59 Priority +#define NVIC_PRI15 0xE000E43C // Interrupt 60-63 Priority +#define NVIC_PRI16 0xE000E440 // Interrupt 64-67 Priority +#define NVIC_PRI17 0xE000E444 // Interrupt 68-71 Priority +#define NVIC_PRI18 0xE000E448 // Interrupt 72-75 Priority +#define NVIC_PRI19 0xE000E44C // Interrupt 76-79 Priority +#define NVIC_PRI20 0xE000E450 // Interrupt 80-83 Priority +#define NVIC_PRI21 0xE000E454 // Interrupt 84-87 Priority +#define NVIC_PRI22 0xE000E458 // Interrupt 88-91 Priority +#define NVIC_PRI23 0xE000E45C // Interrupt 92-95 Priority +#define NVIC_PRI24 0xE000E460 // Interrupt 96-99 Priority +#define NVIC_PRI25 0xE000E464 // Interrupt 100-103 Priority +#define NVIC_PRI26 0xE000E468 // Interrupt 104-107 Priority +#define NVIC_PRI27 0xE000E46C // Interrupt 108-111 Priority +#define NVIC_PRI28 0xE000E470 // Interrupt 112-115 Priority +#define NVIC_PRI29 0xE000E474 // Interrupt 116-119 Priority +#define NVIC_PRI30 0xE000E478 // Interrupt 120-123 Priority +#define NVIC_PRI31 0xE000E47C // Interrupt 124-127 Priority +#define NVIC_PRI32 0xE000E480 // Interrupt 128-131 Priority +#define NVIC_PRI33 0xE000E484 // Interrupt 132-135 Priority +#define NVIC_PRI34 0xE000E488 // Interrupt 136-139 Priority +#define NVIC_PRI35 0xE000E48C // Interrupt 140-143 Priority +#define NVIC_PRI36 0xE000E490 // Interrupt 144-147 Priority +#define NVIC_PRI37 0xE000E494 // Interrupt 148-151 Priority +#define NVIC_PRI38 0xE000E498 // Interrupt 152-155 Priority +#define NVIC_PRI39 0xE000E49C // Interrupt 156-159 Priority +#define NVIC_PRI40 0xE000E4A0 // Interrupt 160-163 Priority +#define NVIC_PRI41 0xE000E4A4 // Interrupt 164-167 Priority +#define NVIC_PRI42 0xE000E4A8 // Interrupt 168-171 Priority +#define NVIC_PRI43 0xE000E4AC // Interrupt 172-175 Priority +#define NVIC_PRI44 0xE000E4B0 // Interrupt 176-179 Priority +#define NVIC_PRI45 0xE000E4B4 // Interrupt 180-183 Priority +#define NVIC_PRI46 0xE000E4B8 // Interrupt 184-187 Priority +#define NVIC_PRI47 0xE000E4BC // Interrupt 188-191 Priority +#define NVIC_PRI48 0xE000E4C0 // Interrupt 192-195 Priority + + + +#define NVIC_CPUID 0xE000ED00 // CPU ID Base +#define NVIC_INT_CTRL 0xE000ED04 // Interrupt Control and State +#define NVIC_VTABLE 0xE000ED08 // Vector Table Offset +#define NVIC_APINT 0xE000ED0C // Application Interrupt and Reset + // Control +#define NVIC_SYS_CTRL 0xE000ED10 // System Control +#define NVIC_CFG_CTRL 0xE000ED14 // Configuration and Control +#define NVIC_SYS_PRI1 0xE000ED18 // System Handler Priority 1 +#define NVIC_SYS_PRI2 0xE000ED1C // System Handler Priority 2 +#define NVIC_SYS_PRI3 0xE000ED20 // System Handler Priority 3 +#define NVIC_SYS_HND_CTRL 0xE000ED24 // System Handler Control and State +#define NVIC_FAULT_STAT 0xE000ED28 // Configurable Fault Status +#define NVIC_HFAULT_STAT 0xE000ED2C // Hard Fault Status +#define NVIC_DEBUG_STAT 0xE000ED30 // Debug Status Register +#define NVIC_MM_ADDR 0xE000ED34 // Memory Management Fault Address +#define NVIC_FAULT_ADDR 0xE000ED38 // Bus Fault Address +#define NVIC_MPU_TYPE 0xE000ED90 // MPU Type +#define NVIC_MPU_CTRL 0xE000ED94 // MPU Control +#define NVIC_MPU_NUMBER 0xE000ED98 // MPU Region Number +#define NVIC_MPU_BASE 0xE000ED9C // MPU Region Base Address +#define NVIC_MPU_ATTR 0xE000EDA0 // MPU Region Attribute and Size +#define NVIC_MPU_BASE1 0xE000EDA4 // MPU Region Base Address Alias 1 +#define NVIC_MPU_ATTR1 0xE000EDA8 // MPU Region Attribute and Size + // Alias 1 +#define NVIC_MPU_BASE2 0xE000EDAC // MPU Region Base Address Alias 2 +#define NVIC_MPU_ATTR2 0xE000EDB0 // MPU Region Attribute and Size + // Alias 2 +#define NVIC_MPU_BASE3 0xE000EDB4 // MPU Region Base Address Alias 3 +#define NVIC_MPU_ATTR3 0xE000EDB8 // MPU Region Attribute and Size + // Alias 3 +#define NVIC_DBG_CTRL 0xE000EDF0 // Debug Control and Status Reg +#define NVIC_DBG_XFER 0xE000EDF4 // Debug Core Reg. Transfer Select +#define NVIC_DBG_DATA 0xE000EDF8 // Debug Core Register Data +#define NVIC_DBG_INT 0xE000EDFC // Debug Reset Interrupt Control +#define NVIC_SW_TRIG 0xE000EF00 // Software Trigger Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_INT_TYPE register. +// +//***************************************************************************** +#define NVIC_INT_TYPE_LINES_M 0x0000001F // Number of interrupt lines (x32) +#define NVIC_INT_TYPE_LINES_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ACTLR register. +// +//***************************************************************************** +#define NVIC_ACTLR_DISFOLD 0x00000004 // Disable IT Folding +#define NVIC_ACTLR_DISWBUF 0x00000002 // Disable Write Buffer +#define NVIC_ACTLR_DISMCYC 0x00000001 // Disable Interrupts of Multiple + // Cycle Instructions + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ST_CTRL register. +// +//***************************************************************************** +#define NVIC_ST_CTRL_COUNT 0x00010000 // Count Flag +#define NVIC_ST_CTRL_CLK_SRC 0x00000004 // Clock Source +#define NVIC_ST_CTRL_INTEN 0x00000002 // Interrupt Enable +#define NVIC_ST_CTRL_ENABLE 0x00000001 // Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ST_RELOAD register. +// +//***************************************************************************** +#define NVIC_ST_RELOAD_M 0x00FFFFFF // Reload Value +#define NVIC_ST_RELOAD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ST_CURRENT +// register. +// +//***************************************************************************** +#define NVIC_ST_CURRENT_M 0x00FFFFFF // Current Value +#define NVIC_ST_CURRENT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ST_CAL register. +// +//***************************************************************************** +#define NVIC_ST_CAL_NOREF 0x80000000 // No reference clock +#define NVIC_ST_CAL_SKEW 0x40000000 // Clock skew +#define NVIC_ST_CAL_ONEMS_M 0x00FFFFFF // 1ms reference value +#define NVIC_ST_CAL_ONEMS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_EN0 register. +// +//***************************************************************************** +#define NVIC_EN0_INT_M 0xFFFFFFFF // Interrupt Enable +#define NVIC_EN0_INT0 0x00000001 // Interrupt 0 enable +#define NVIC_EN0_INT1 0x00000002 // Interrupt 1 enable +#define NVIC_EN0_INT2 0x00000004 // Interrupt 2 enable +#define NVIC_EN0_INT3 0x00000008 // Interrupt 3 enable +#define NVIC_EN0_INT4 0x00000010 // Interrupt 4 enable +#define NVIC_EN0_INT5 0x00000020 // Interrupt 5 enable +#define NVIC_EN0_INT6 0x00000040 // Interrupt 6 enable +#define NVIC_EN0_INT7 0x00000080 // Interrupt 7 enable +#define NVIC_EN0_INT8 0x00000100 // Interrupt 8 enable +#define NVIC_EN0_INT9 0x00000200 // Interrupt 9 enable +#define NVIC_EN0_INT10 0x00000400 // Interrupt 10 enable +#define NVIC_EN0_INT11 0x00000800 // Interrupt 11 enable +#define NVIC_EN0_INT12 0x00001000 // Interrupt 12 enable +#define NVIC_EN0_INT13 0x00002000 // Interrupt 13 enable +#define NVIC_EN0_INT14 0x00004000 // Interrupt 14 enable +#define NVIC_EN0_INT15 0x00008000 // Interrupt 15 enable +#define NVIC_EN0_INT16 0x00010000 // Interrupt 16 enable +#define NVIC_EN0_INT17 0x00020000 // Interrupt 17 enable +#define NVIC_EN0_INT18 0x00040000 // Interrupt 18 enable +#define NVIC_EN0_INT19 0x00080000 // Interrupt 19 enable +#define NVIC_EN0_INT20 0x00100000 // Interrupt 20 enable +#define NVIC_EN0_INT21 0x00200000 // Interrupt 21 enable +#define NVIC_EN0_INT22 0x00400000 // Interrupt 22 enable +#define NVIC_EN0_INT23 0x00800000 // Interrupt 23 enable +#define NVIC_EN0_INT24 0x01000000 // Interrupt 24 enable +#define NVIC_EN0_INT25 0x02000000 // Interrupt 25 enable +#define NVIC_EN0_INT26 0x04000000 // Interrupt 26 enable +#define NVIC_EN0_INT27 0x08000000 // Interrupt 27 enable +#define NVIC_EN0_INT28 0x10000000 // Interrupt 28 enable +#define NVIC_EN0_INT29 0x20000000 // Interrupt 29 enable +#define NVIC_EN0_INT30 0x40000000 // Interrupt 30 enable +#define NVIC_EN0_INT31 0x80000000 // Interrupt 31 enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_EN1 register. +// +//***************************************************************************** +#define NVIC_EN1_INT_M 0x007FFFFF // Interrupt Enable + +#undef NVIC_EN1_INT_M +#define NVIC_EN1_INT_M 0xFFFFFFFF // Interrupt Enable + +#define NVIC_EN1_INT32 0x00000001 // Interrupt 32 enable +#define NVIC_EN1_INT33 0x00000002 // Interrupt 33 enable +#define NVIC_EN1_INT34 0x00000004 // Interrupt 34 enable +#define NVIC_EN1_INT35 0x00000008 // Interrupt 35 enable +#define NVIC_EN1_INT36 0x00000010 // Interrupt 36 enable +#define NVIC_EN1_INT37 0x00000020 // Interrupt 37 enable +#define NVIC_EN1_INT38 0x00000040 // Interrupt 38 enable +#define NVIC_EN1_INT39 0x00000080 // Interrupt 39 enable +#define NVIC_EN1_INT40 0x00000100 // Interrupt 40 enable +#define NVIC_EN1_INT41 0x00000200 // Interrupt 41 enable +#define NVIC_EN1_INT42 0x00000400 // Interrupt 42 enable +#define NVIC_EN1_INT43 0x00000800 // Interrupt 43 enable +#define NVIC_EN1_INT44 0x00001000 // Interrupt 44 enable +#define NVIC_EN1_INT45 0x00002000 // Interrupt 45 enable +#define NVIC_EN1_INT46 0x00004000 // Interrupt 46 enable +#define NVIC_EN1_INT47 0x00008000 // Interrupt 47 enable +#define NVIC_EN1_INT48 0x00010000 // Interrupt 48 enable +#define NVIC_EN1_INT49 0x00020000 // Interrupt 49 enable +#define NVIC_EN1_INT50 0x00040000 // Interrupt 50 enable +#define NVIC_EN1_INT51 0x00080000 // Interrupt 51 enable +#define NVIC_EN1_INT52 0x00100000 // Interrupt 52 enable +#define NVIC_EN1_INT53 0x00200000 // Interrupt 53 enable +#define NVIC_EN1_INT54 0x00400000 // Interrupt 54 enable + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_EN2 register. +// +//***************************************************************************** +#define NVIC_EN2_INT_M 0xFFFFFFFF // Interrupt Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_EN3 register. +// +//***************************************************************************** +#define NVIC_EN3_INT_M 0xFFFFFFFF // Interrupt Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_EN4 register. +// +//***************************************************************************** +#define NVIC_EN4_INT_M 0x0000000F // Interrupt Enable + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DIS0 register. +// +//***************************************************************************** +#define NVIC_DIS0_INT_M 0xFFFFFFFF // Interrupt Disable +#define NVIC_DIS0_INT0 0x00000001 // Interrupt 0 disable +#define NVIC_DIS0_INT1 0x00000002 // Interrupt 1 disable +#define NVIC_DIS0_INT2 0x00000004 // Interrupt 2 disable +#define NVIC_DIS0_INT3 0x00000008 // Interrupt 3 disable +#define NVIC_DIS0_INT4 0x00000010 // Interrupt 4 disable +#define NVIC_DIS0_INT5 0x00000020 // Interrupt 5 disable +#define NVIC_DIS0_INT6 0x00000040 // Interrupt 6 disable +#define NVIC_DIS0_INT7 0x00000080 // Interrupt 7 disable +#define NVIC_DIS0_INT8 0x00000100 // Interrupt 8 disable +#define NVIC_DIS0_INT9 0x00000200 // Interrupt 9 disable +#define NVIC_DIS0_INT10 0x00000400 // Interrupt 10 disable +#define NVIC_DIS0_INT11 0x00000800 // Interrupt 11 disable +#define NVIC_DIS0_INT12 0x00001000 // Interrupt 12 disable +#define NVIC_DIS0_INT13 0x00002000 // Interrupt 13 disable +#define NVIC_DIS0_INT14 0x00004000 // Interrupt 14 disable +#define NVIC_DIS0_INT15 0x00008000 // Interrupt 15 disable +#define NVIC_DIS0_INT16 0x00010000 // Interrupt 16 disable +#define NVIC_DIS0_INT17 0x00020000 // Interrupt 17 disable +#define NVIC_DIS0_INT18 0x00040000 // Interrupt 18 disable +#define NVIC_DIS0_INT19 0x00080000 // Interrupt 19 disable +#define NVIC_DIS0_INT20 0x00100000 // Interrupt 20 disable +#define NVIC_DIS0_INT21 0x00200000 // Interrupt 21 disable +#define NVIC_DIS0_INT22 0x00400000 // Interrupt 22 disable +#define NVIC_DIS0_INT23 0x00800000 // Interrupt 23 disable +#define NVIC_DIS0_INT24 0x01000000 // Interrupt 24 disable +#define NVIC_DIS0_INT25 0x02000000 // Interrupt 25 disable +#define NVIC_DIS0_INT26 0x04000000 // Interrupt 26 disable +#define NVIC_DIS0_INT27 0x08000000 // Interrupt 27 disable +#define NVIC_DIS0_INT28 0x10000000 // Interrupt 28 disable +#define NVIC_DIS0_INT29 0x20000000 // Interrupt 29 disable +#define NVIC_DIS0_INT30 0x40000000 // Interrupt 30 disable +#define NVIC_DIS0_INT31 0x80000000 // Interrupt 31 disable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DIS1 register. +// +//***************************************************************************** +#define NVIC_DIS1_INT_M 0x00FFFFFF // Interrupt Disable + +#undef NVIC_DIS1_INT_M +#define NVIC_DIS1_INT_M 0xFFFFFFFF // Interrupt Disable + +#define NVIC_DIS1_INT32 0x00000001 // Interrupt 32 disable +#define NVIC_DIS1_INT33 0x00000002 // Interrupt 33 disable +#define NVIC_DIS1_INT34 0x00000004 // Interrupt 34 disable +#define NVIC_DIS1_INT35 0x00000008 // Interrupt 35 disable +#define NVIC_DIS1_INT36 0x00000010 // Interrupt 36 disable +#define NVIC_DIS1_INT37 0x00000020 // Interrupt 37 disable +#define NVIC_DIS1_INT38 0x00000040 // Interrupt 38 disable +#define NVIC_DIS1_INT39 0x00000080 // Interrupt 39 disable +#define NVIC_DIS1_INT40 0x00000100 // Interrupt 40 disable +#define NVIC_DIS1_INT41 0x00000200 // Interrupt 41 disable +#define NVIC_DIS1_INT42 0x00000400 // Interrupt 42 disable +#define NVIC_DIS1_INT43 0x00000800 // Interrupt 43 disable +#define NVIC_DIS1_INT44 0x00001000 // Interrupt 44 disable +#define NVIC_DIS1_INT45 0x00002000 // Interrupt 45 disable +#define NVIC_DIS1_INT46 0x00004000 // Interrupt 46 disable +#define NVIC_DIS1_INT47 0x00008000 // Interrupt 47 disable +#define NVIC_DIS1_INT48 0x00010000 // Interrupt 48 disable +#define NVIC_DIS1_INT49 0x00020000 // Interrupt 49 disable +#define NVIC_DIS1_INT50 0x00040000 // Interrupt 50 disable +#define NVIC_DIS1_INT51 0x00080000 // Interrupt 51 disable +#define NVIC_DIS1_INT52 0x00100000 // Interrupt 52 disable +#define NVIC_DIS1_INT53 0x00200000 // Interrupt 53 disable +#define NVIC_DIS1_INT54 0x00400000 // Interrupt 54 disable +#define NVIC_DIS1_INT55 0x00800000 // Interrupt 55 disable + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DIS2 register. +// +//***************************************************************************** +#define NVIC_DIS2_INT_M 0xFFFFFFFF // Interrupt Disable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DIS3 register. +// +//***************************************************************************** +#define NVIC_DIS3_INT_M 0xFFFFFFFF // Interrupt Disable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DIS4 register. +// +//***************************************************************************** +#define NVIC_DIS4_INT_M 0x0000000F // Interrupt Disable + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PEND0 register. +// +//***************************************************************************** +#define NVIC_PEND0_INT_M 0xFFFFFFFF // Interrupt Set Pending +#define NVIC_PEND0_INT0 0x00000001 // Interrupt 0 pend +#define NVIC_PEND0_INT1 0x00000002 // Interrupt 1 pend +#define NVIC_PEND0_INT2 0x00000004 // Interrupt 2 pend +#define NVIC_PEND0_INT3 0x00000008 // Interrupt 3 pend +#define NVIC_PEND0_INT4 0x00000010 // Interrupt 4 pend +#define NVIC_PEND0_INT5 0x00000020 // Interrupt 5 pend +#define NVIC_PEND0_INT6 0x00000040 // Interrupt 6 pend +#define NVIC_PEND0_INT7 0x00000080 // Interrupt 7 pend +#define NVIC_PEND0_INT8 0x00000100 // Interrupt 8 pend +#define NVIC_PEND0_INT9 0x00000200 // Interrupt 9 pend +#define NVIC_PEND0_INT10 0x00000400 // Interrupt 10 pend +#define NVIC_PEND0_INT11 0x00000800 // Interrupt 11 pend +#define NVIC_PEND0_INT12 0x00001000 // Interrupt 12 pend +#define NVIC_PEND0_INT13 0x00002000 // Interrupt 13 pend +#define NVIC_PEND0_INT14 0x00004000 // Interrupt 14 pend +#define NVIC_PEND0_INT15 0x00008000 // Interrupt 15 pend +#define NVIC_PEND0_INT16 0x00010000 // Interrupt 16 pend +#define NVIC_PEND0_INT17 0x00020000 // Interrupt 17 pend +#define NVIC_PEND0_INT18 0x00040000 // Interrupt 18 pend +#define NVIC_PEND0_INT19 0x00080000 // Interrupt 19 pend +#define NVIC_PEND0_INT20 0x00100000 // Interrupt 20 pend +#define NVIC_PEND0_INT21 0x00200000 // Interrupt 21 pend +#define NVIC_PEND0_INT22 0x00400000 // Interrupt 22 pend +#define NVIC_PEND0_INT23 0x00800000 // Interrupt 23 pend +#define NVIC_PEND0_INT24 0x01000000 // Interrupt 24 pend +#define NVIC_PEND0_INT25 0x02000000 // Interrupt 25 pend +#define NVIC_PEND0_INT26 0x04000000 // Interrupt 26 pend +#define NVIC_PEND0_INT27 0x08000000 // Interrupt 27 pend +#define NVIC_PEND0_INT28 0x10000000 // Interrupt 28 pend +#define NVIC_PEND0_INT29 0x20000000 // Interrupt 29 pend +#define NVIC_PEND0_INT30 0x40000000 // Interrupt 30 pend +#define NVIC_PEND0_INT31 0x80000000 // Interrupt 31 pend + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PEND1 register. +// +//***************************************************************************** +#define NVIC_PEND1_INT_M 0x00FFFFFF // Interrupt Set Pending + +#undef NVIC_PEND1_INT_M +#define NVIC_PEND1_INT_M 0xFFFFFFFF // Interrupt Set Pending + +#define NVIC_PEND1_INT32 0x00000001 // Interrupt 32 pend +#define NVIC_PEND1_INT33 0x00000002 // Interrupt 33 pend +#define NVIC_PEND1_INT34 0x00000004 // Interrupt 34 pend +#define NVIC_PEND1_INT35 0x00000008 // Interrupt 35 pend +#define NVIC_PEND1_INT36 0x00000010 // Interrupt 36 pend +#define NVIC_PEND1_INT37 0x00000020 // Interrupt 37 pend +#define NVIC_PEND1_INT38 0x00000040 // Interrupt 38 pend +#define NVIC_PEND1_INT39 0x00000080 // Interrupt 39 pend +#define NVIC_PEND1_INT40 0x00000100 // Interrupt 40 pend +#define NVIC_PEND1_INT41 0x00000200 // Interrupt 41 pend +#define NVIC_PEND1_INT42 0x00000400 // Interrupt 42 pend +#define NVIC_PEND1_INT43 0x00000800 // Interrupt 43 pend +#define NVIC_PEND1_INT44 0x00001000 // Interrupt 44 pend +#define NVIC_PEND1_INT45 0x00002000 // Interrupt 45 pend +#define NVIC_PEND1_INT46 0x00004000 // Interrupt 46 pend +#define NVIC_PEND1_INT47 0x00008000 // Interrupt 47 pend +#define NVIC_PEND1_INT48 0x00010000 // Interrupt 48 pend +#define NVIC_PEND1_INT49 0x00020000 // Interrupt 49 pend +#define NVIC_PEND1_INT50 0x00040000 // Interrupt 50 pend +#define NVIC_PEND1_INT51 0x00080000 // Interrupt 51 pend +#define NVIC_PEND1_INT52 0x00100000 // Interrupt 52 pend +#define NVIC_PEND1_INT53 0x00200000 // Interrupt 53 pend +#define NVIC_PEND1_INT54 0x00400000 // Interrupt 54 pend +#define NVIC_PEND1_INT55 0x00800000 // Interrupt 55 pend + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PEND2 register. +// +//***************************************************************************** +#define NVIC_PEND2_INT_M 0xFFFFFFFF // Interrupt Set Pending + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PEND3 register. +// +//***************************************************************************** +#define NVIC_PEND3_INT_M 0xFFFFFFFF // Interrupt Set Pending + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PEND4 register. +// +//***************************************************************************** +#define NVIC_PEND4_INT_M 0x0000000F // Interrupt Set Pending + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_UNPEND0 register. +// +//***************************************************************************** +#define NVIC_UNPEND0_INT_M 0xFFFFFFFF // Interrupt Clear Pending +#define NVIC_UNPEND0_INT0 0x00000001 // Interrupt 0 unpend +#define NVIC_UNPEND0_INT1 0x00000002 // Interrupt 1 unpend +#define NVIC_UNPEND0_INT2 0x00000004 // Interrupt 2 unpend +#define NVIC_UNPEND0_INT3 0x00000008 // Interrupt 3 unpend +#define NVIC_UNPEND0_INT4 0x00000010 // Interrupt 4 unpend +#define NVIC_UNPEND0_INT5 0x00000020 // Interrupt 5 unpend +#define NVIC_UNPEND0_INT6 0x00000040 // Interrupt 6 unpend +#define NVIC_UNPEND0_INT7 0x00000080 // Interrupt 7 unpend +#define NVIC_UNPEND0_INT8 0x00000100 // Interrupt 8 unpend +#define NVIC_UNPEND0_INT9 0x00000200 // Interrupt 9 unpend +#define NVIC_UNPEND0_INT10 0x00000400 // Interrupt 10 unpend +#define NVIC_UNPEND0_INT11 0x00000800 // Interrupt 11 unpend +#define NVIC_UNPEND0_INT12 0x00001000 // Interrupt 12 unpend +#define NVIC_UNPEND0_INT13 0x00002000 // Interrupt 13 unpend +#define NVIC_UNPEND0_INT14 0x00004000 // Interrupt 14 unpend +#define NVIC_UNPEND0_INT15 0x00008000 // Interrupt 15 unpend +#define NVIC_UNPEND0_INT16 0x00010000 // Interrupt 16 unpend +#define NVIC_UNPEND0_INT17 0x00020000 // Interrupt 17 unpend +#define NVIC_UNPEND0_INT18 0x00040000 // Interrupt 18 unpend +#define NVIC_UNPEND0_INT19 0x00080000 // Interrupt 19 unpend +#define NVIC_UNPEND0_INT20 0x00100000 // Interrupt 20 unpend +#define NVIC_UNPEND0_INT21 0x00200000 // Interrupt 21 unpend +#define NVIC_UNPEND0_INT22 0x00400000 // Interrupt 22 unpend +#define NVIC_UNPEND0_INT23 0x00800000 // Interrupt 23 unpend +#define NVIC_UNPEND0_INT24 0x01000000 // Interrupt 24 unpend +#define NVIC_UNPEND0_INT25 0x02000000 // Interrupt 25 unpend +#define NVIC_UNPEND0_INT26 0x04000000 // Interrupt 26 unpend +#define NVIC_UNPEND0_INT27 0x08000000 // Interrupt 27 unpend +#define NVIC_UNPEND0_INT28 0x10000000 // Interrupt 28 unpend +#define NVIC_UNPEND0_INT29 0x20000000 // Interrupt 29 unpend +#define NVIC_UNPEND0_INT30 0x40000000 // Interrupt 30 unpend +#define NVIC_UNPEND0_INT31 0x80000000 // Interrupt 31 unpend + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_UNPEND1 register. +// +//***************************************************************************** +#define NVIC_UNPEND1_INT_M 0x00FFFFFF // Interrupt Clear Pending + +#undef NVIC_UNPEND1_INT_M +#define NVIC_UNPEND1_INT_M 0xFFFFFFFF // Interrupt Clear Pending + +#define NVIC_UNPEND1_INT32 0x00000001 // Interrupt 32 unpend +#define NVIC_UNPEND1_INT33 0x00000002 // Interrupt 33 unpend +#define NVIC_UNPEND1_INT34 0x00000004 // Interrupt 34 unpend +#define NVIC_UNPEND1_INT35 0x00000008 // Interrupt 35 unpend +#define NVIC_UNPEND1_INT36 0x00000010 // Interrupt 36 unpend +#define NVIC_UNPEND1_INT37 0x00000020 // Interrupt 37 unpend +#define NVIC_UNPEND1_INT38 0x00000040 // Interrupt 38 unpend +#define NVIC_UNPEND1_INT39 0x00000080 // Interrupt 39 unpend +#define NVIC_UNPEND1_INT40 0x00000100 // Interrupt 40 unpend +#define NVIC_UNPEND1_INT41 0x00000200 // Interrupt 41 unpend +#define NVIC_UNPEND1_INT42 0x00000400 // Interrupt 42 unpend +#define NVIC_UNPEND1_INT43 0x00000800 // Interrupt 43 unpend +#define NVIC_UNPEND1_INT44 0x00001000 // Interrupt 44 unpend +#define NVIC_UNPEND1_INT45 0x00002000 // Interrupt 45 unpend +#define NVIC_UNPEND1_INT46 0x00004000 // Interrupt 46 unpend +#define NVIC_UNPEND1_INT47 0x00008000 // Interrupt 47 unpend +#define NVIC_UNPEND1_INT48 0x00010000 // Interrupt 48 unpend +#define NVIC_UNPEND1_INT49 0x00020000 // Interrupt 49 unpend +#define NVIC_UNPEND1_INT50 0x00040000 // Interrupt 50 unpend +#define NVIC_UNPEND1_INT51 0x00080000 // Interrupt 51 unpend +#define NVIC_UNPEND1_INT52 0x00100000 // Interrupt 52 unpend +#define NVIC_UNPEND1_INT53 0x00200000 // Interrupt 53 unpend +#define NVIC_UNPEND1_INT54 0x00400000 // Interrupt 54 unpend +#define NVIC_UNPEND1_INT55 0x00800000 // Interrupt 55 unpend + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_UNPEND2 register. +// +//***************************************************************************** +#define NVIC_UNPEND2_INT_M 0xFFFFFFFF // Interrupt Clear Pending + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_UNPEND3 register. +// +//***************************************************************************** +#define NVIC_UNPEND3_INT_M 0xFFFFFFFF // Interrupt Clear Pending + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_UNPEND4 register. +// +//***************************************************************************** +#define NVIC_UNPEND4_INT_M 0x0000000F // Interrupt Clear Pending + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ACTIVE0 register. +// +//***************************************************************************** +#define NVIC_ACTIVE0_INT_M 0xFFFFFFFF // Interrupt Active +#define NVIC_ACTIVE0_INT0 0x00000001 // Interrupt 0 active +#define NVIC_ACTIVE0_INT1 0x00000002 // Interrupt 1 active +#define NVIC_ACTIVE0_INT2 0x00000004 // Interrupt 2 active +#define NVIC_ACTIVE0_INT3 0x00000008 // Interrupt 3 active +#define NVIC_ACTIVE0_INT4 0x00000010 // Interrupt 4 active +#define NVIC_ACTIVE0_INT5 0x00000020 // Interrupt 5 active +#define NVIC_ACTIVE0_INT6 0x00000040 // Interrupt 6 active +#define NVIC_ACTIVE0_INT7 0x00000080 // Interrupt 7 active +#define NVIC_ACTIVE0_INT8 0x00000100 // Interrupt 8 active +#define NVIC_ACTIVE0_INT9 0x00000200 // Interrupt 9 active +#define NVIC_ACTIVE0_INT10 0x00000400 // Interrupt 10 active +#define NVIC_ACTIVE0_INT11 0x00000800 // Interrupt 11 active +#define NVIC_ACTIVE0_INT12 0x00001000 // Interrupt 12 active +#define NVIC_ACTIVE0_INT13 0x00002000 // Interrupt 13 active +#define NVIC_ACTIVE0_INT14 0x00004000 // Interrupt 14 active +#define NVIC_ACTIVE0_INT15 0x00008000 // Interrupt 15 active +#define NVIC_ACTIVE0_INT16 0x00010000 // Interrupt 16 active +#define NVIC_ACTIVE0_INT17 0x00020000 // Interrupt 17 active +#define NVIC_ACTIVE0_INT18 0x00040000 // Interrupt 18 active +#define NVIC_ACTIVE0_INT19 0x00080000 // Interrupt 19 active +#define NVIC_ACTIVE0_INT20 0x00100000 // Interrupt 20 active +#define NVIC_ACTIVE0_INT21 0x00200000 // Interrupt 21 active +#define NVIC_ACTIVE0_INT22 0x00400000 // Interrupt 22 active +#define NVIC_ACTIVE0_INT23 0x00800000 // Interrupt 23 active +#define NVIC_ACTIVE0_INT24 0x01000000 // Interrupt 24 active +#define NVIC_ACTIVE0_INT25 0x02000000 // Interrupt 25 active +#define NVIC_ACTIVE0_INT26 0x04000000 // Interrupt 26 active +#define NVIC_ACTIVE0_INT27 0x08000000 // Interrupt 27 active +#define NVIC_ACTIVE0_INT28 0x10000000 // Interrupt 28 active +#define NVIC_ACTIVE0_INT29 0x20000000 // Interrupt 29 active +#define NVIC_ACTIVE0_INT30 0x40000000 // Interrupt 30 active +#define NVIC_ACTIVE0_INT31 0x80000000 // Interrupt 31 active + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ACTIVE1 register. +// +//***************************************************************************** +#define NVIC_ACTIVE1_INT_M 0x00FFFFFF // Interrupt Active + +#undef NVIC_ACTIVE1_INT_M +#define NVIC_ACTIVE1_INT_M 0xFFFFFFFF // Interrupt Active + +#define NVIC_ACTIVE1_INT32 0x00000001 // Interrupt 32 active +#define NVIC_ACTIVE1_INT33 0x00000002 // Interrupt 33 active +#define NVIC_ACTIVE1_INT34 0x00000004 // Interrupt 34 active +#define NVIC_ACTIVE1_INT35 0x00000008 // Interrupt 35 active +#define NVIC_ACTIVE1_INT36 0x00000010 // Interrupt 36 active +#define NVIC_ACTIVE1_INT37 0x00000020 // Interrupt 37 active +#define NVIC_ACTIVE1_INT38 0x00000040 // Interrupt 38 active +#define NVIC_ACTIVE1_INT39 0x00000080 // Interrupt 39 active +#define NVIC_ACTIVE1_INT40 0x00000100 // Interrupt 40 active +#define NVIC_ACTIVE1_INT41 0x00000200 // Interrupt 41 active +#define NVIC_ACTIVE1_INT42 0x00000400 // Interrupt 42 active +#define NVIC_ACTIVE1_INT43 0x00000800 // Interrupt 43 active +#define NVIC_ACTIVE1_INT44 0x00001000 // Interrupt 44 active +#define NVIC_ACTIVE1_INT45 0x00002000 // Interrupt 45 active +#define NVIC_ACTIVE1_INT46 0x00004000 // Interrupt 46 active +#define NVIC_ACTIVE1_INT47 0x00008000 // Interrupt 47 active +#define NVIC_ACTIVE1_INT48 0x00010000 // Interrupt 48 active +#define NVIC_ACTIVE1_INT49 0x00020000 // Interrupt 49 active +#define NVIC_ACTIVE1_INT50 0x00040000 // Interrupt 50 active +#define NVIC_ACTIVE1_INT51 0x00080000 // Interrupt 51 active +#define NVIC_ACTIVE1_INT52 0x00100000 // Interrupt 52 active +#define NVIC_ACTIVE1_INT53 0x00200000 // Interrupt 53 active +#define NVIC_ACTIVE1_INT54 0x00400000 // Interrupt 54 active +#define NVIC_ACTIVE1_INT55 0x00800000 // Interrupt 55 active + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ACTIVE2 register. +// +//***************************************************************************** +#define NVIC_ACTIVE2_INT_M 0xFFFFFFFF // Interrupt Active + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ACTIVE3 register. +// +//***************************************************************************** +#define NVIC_ACTIVE3_INT_M 0xFFFFFFFF // Interrupt Active + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_ACTIVE4 register. +// +//***************************************************************************** +#define NVIC_ACTIVE4_INT_M 0x0000000F // Interrupt Active + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI0 register. +// +//***************************************************************************** +#define NVIC_PRI0_INT3_M 0xE0000000 // Interrupt 3 Priority Mask +#define NVIC_PRI0_INT2_M 0x00E00000 // Interrupt 2 Priority Mask +#define NVIC_PRI0_INT1_M 0x0000E000 // Interrupt 1 Priority Mask +#define NVIC_PRI0_INT0_M 0x000000E0 // Interrupt 0 Priority Mask +#define NVIC_PRI0_INT3_S 29 +#define NVIC_PRI0_INT2_S 21 +#define NVIC_PRI0_INT1_S 13 +#define NVIC_PRI0_INT0_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI1 register. +// +//***************************************************************************** +#define NVIC_PRI1_INT7_M 0xE0000000 // Interrupt 7 Priority Mask +#define NVIC_PRI1_INT6_M 0x00E00000 // Interrupt 6 Priority Mask +#define NVIC_PRI1_INT5_M 0x0000E000 // Interrupt 5 Priority Mask +#define NVIC_PRI1_INT4_M 0x000000E0 // Interrupt 4 Priority Mask +#define NVIC_PRI1_INT7_S 29 +#define NVIC_PRI1_INT6_S 21 +#define NVIC_PRI1_INT5_S 13 +#define NVIC_PRI1_INT4_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI2 register. +// +//***************************************************************************** +#define NVIC_PRI2_INT11_M 0xE0000000 // Interrupt 11 Priority Mask +#define NVIC_PRI2_INT10_M 0x00E00000 // Interrupt 10 Priority Mask +#define NVIC_PRI2_INT9_M 0x0000E000 // Interrupt 9 Priority Mask +#define NVIC_PRI2_INT8_M 0x000000E0 // Interrupt 8 Priority Mask +#define NVIC_PRI2_INT11_S 29 +#define NVIC_PRI2_INT10_S 21 +#define NVIC_PRI2_INT9_S 13 +#define NVIC_PRI2_INT8_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI3 register. +// +//***************************************************************************** +#define NVIC_PRI3_INT15_M 0xE0000000 // Interrupt 15 Priority Mask +#define NVIC_PRI3_INT14_M 0x00E00000 // Interrupt 14 Priority Mask +#define NVIC_PRI3_INT13_M 0x0000E000 // Interrupt 13 Priority Mask +#define NVIC_PRI3_INT12_M 0x000000E0 // Interrupt 12 Priority Mask +#define NVIC_PRI3_INT15_S 29 +#define NVIC_PRI3_INT14_S 21 +#define NVIC_PRI3_INT13_S 13 +#define NVIC_PRI3_INT12_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI4 register. +// +//***************************************************************************** +#define NVIC_PRI4_INT19_M 0xE0000000 // Interrupt 19 Priority Mask +#define NVIC_PRI4_INT18_M 0x00E00000 // Interrupt 18 Priority Mask +#define NVIC_PRI4_INT17_M 0x0000E000 // Interrupt 17 Priority Mask +#define NVIC_PRI4_INT16_M 0x000000E0 // Interrupt 16 Priority Mask +#define NVIC_PRI4_INT19_S 29 +#define NVIC_PRI4_INT18_S 21 +#define NVIC_PRI4_INT17_S 13 +#define NVIC_PRI4_INT16_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI5 register. +// +//***************************************************************************** +#define NVIC_PRI5_INT23_M 0xE0000000 // Interrupt 23 Priority Mask +#define NVIC_PRI5_INT22_M 0x00E00000 // Interrupt 22 Priority Mask +#define NVIC_PRI5_INT21_M 0x0000E000 // Interrupt 21 Priority Mask +#define NVIC_PRI5_INT20_M 0x000000E0 // Interrupt 20 Priority Mask +#define NVIC_PRI5_INT23_S 29 +#define NVIC_PRI5_INT22_S 21 +#define NVIC_PRI5_INT21_S 13 +#define NVIC_PRI5_INT20_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI6 register. +// +//***************************************************************************** +#define NVIC_PRI6_INT27_M 0xE0000000 // Interrupt 27 Priority Mask +#define NVIC_PRI6_INT26_M 0x00E00000 // Interrupt 26 Priority Mask +#define NVIC_PRI6_INT25_M 0x0000E000 // Interrupt 25 Priority Mask +#define NVIC_PRI6_INT24_M 0x000000E0 // Interrupt 24 Priority Mask +#define NVIC_PRI6_INT27_S 29 +#define NVIC_PRI6_INT26_S 21 +#define NVIC_PRI6_INT25_S 13 +#define NVIC_PRI6_INT24_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI7 register. +// +//***************************************************************************** +#define NVIC_PRI7_INT31_M 0xE0000000 // Interrupt 31 Priority Mask +#define NVIC_PRI7_INT30_M 0x00E00000 // Interrupt 30 Priority Mask +#define NVIC_PRI7_INT29_M 0x0000E000 // Interrupt 29 Priority Mask +#define NVIC_PRI7_INT28_M 0x000000E0 // Interrupt 28 Priority Mask +#define NVIC_PRI7_INT31_S 29 +#define NVIC_PRI7_INT30_S 21 +#define NVIC_PRI7_INT29_S 13 +#define NVIC_PRI7_INT28_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI8 register. +// +//***************************************************************************** +#define NVIC_PRI8_INT35_M 0xE0000000 // Interrupt 35 Priority Mask +#define NVIC_PRI8_INT34_M 0x00E00000 // Interrupt 34 Priority Mask +#define NVIC_PRI8_INT33_M 0x0000E000 // Interrupt 33 Priority Mask +#define NVIC_PRI8_INT32_M 0x000000E0 // Interrupt 32 Priority Mask +#define NVIC_PRI8_INT35_S 29 +#define NVIC_PRI8_INT34_S 21 +#define NVIC_PRI8_INT33_S 13 +#define NVIC_PRI8_INT32_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI9 register. +// +//***************************************************************************** +#define NVIC_PRI9_INT39_M 0xE0000000 // Interrupt 39 Priority Mask +#define NVIC_PRI9_INT38_M 0x00E00000 // Interrupt 38 Priority Mask +#define NVIC_PRI9_INT37_M 0x0000E000 // Interrupt 37 Priority Mask +#define NVIC_PRI9_INT36_M 0x000000E0 // Interrupt 36 Priority Mask +#define NVIC_PRI9_INT39_S 29 +#define NVIC_PRI9_INT38_S 21 +#define NVIC_PRI9_INT37_S 13 +#define NVIC_PRI9_INT36_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI10 register. +// +//***************************************************************************** +#define NVIC_PRI10_INT43_M 0xE0000000 // Interrupt 43 Priority Mask +#define NVIC_PRI10_INT42_M 0x00E00000 // Interrupt 42 Priority Mask +#define NVIC_PRI10_INT41_M 0x0000E000 // Interrupt 41 Priority Mask +#define NVIC_PRI10_INT40_M 0x000000E0 // Interrupt 40 Priority Mask +#define NVIC_PRI10_INT43_S 29 +#define NVIC_PRI10_INT42_S 21 +#define NVIC_PRI10_INT41_S 13 +#define NVIC_PRI10_INT40_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI11 register. +// +//***************************************************************************** +#define NVIC_PRI11_INT47_M 0xE0000000 // Interrupt 47 Priority Mask +#define NVIC_PRI11_INT46_M 0x00E00000 // Interrupt 46 Priority Mask +#define NVIC_PRI11_INT45_M 0x0000E000 // Interrupt 45 Priority Mask +#define NVIC_PRI11_INT44_M 0x000000E0 // Interrupt 44 Priority Mask +#define NVIC_PRI11_INT47_S 29 +#define NVIC_PRI11_INT46_S 21 +#define NVIC_PRI11_INT45_S 13 +#define NVIC_PRI11_INT44_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI12 register. +// +//***************************************************************************** +#define NVIC_PRI12_INT51_M 0xE0000000 // Interrupt 51 Priority Mask +#define NVIC_PRI12_INT50_M 0x00E00000 // Interrupt 50 Priority Mask +#define NVIC_PRI12_INT49_M 0x0000E000 // Interrupt 49 Priority Mask +#define NVIC_PRI12_INT48_M 0x000000E0 // Interrupt 48 Priority Mask +#define NVIC_PRI12_INT51_S 29 +#define NVIC_PRI12_INT50_S 21 +#define NVIC_PRI12_INT49_S 13 +#define NVIC_PRI12_INT48_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI13 register. +// +//***************************************************************************** +#define NVIC_PRI13_INT55_M 0xE0000000 // Interrupt 55 Priority Mask +#define NVIC_PRI13_INT54_M 0x00E00000 // Interrupt 54 Priority Mask +#define NVIC_PRI13_INT53_M 0x0000E000 // Interrupt 53 Priority Mask +#define NVIC_PRI13_INT52_M 0x000000E0 // Interrupt 52 Priority Mask +#define NVIC_PRI13_INT55_S 29 +#define NVIC_PRI13_INT54_S 21 +#define NVIC_PRI13_INT53_S 13 +#define NVIC_PRI13_INT52_S 5 + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI14 register. +// +//***************************************************************************** +#define NVIC_PRI14_INTD_M 0xE0000000 // Interrupt 59 Priority Mask +#define NVIC_PRI14_INTC_M 0x00E00000 // Interrupt 58 Priority Mask +#define NVIC_PRI14_INTB_M 0x0000E000 // Interrupt 57 Priority Mask +#define NVIC_PRI14_INTA_M 0x000000E0 // Interrupt 56 Priority Mask +#define NVIC_PRI14_INTD_S 29 +#define NVIC_PRI14_INTC_S 21 +#define NVIC_PRI14_INTB_S 13 +#define NVIC_PRI14_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI15 register. +// +//***************************************************************************** +#define NVIC_PRI15_INTD_M 0xE0000000 // Interrupt 63 Priority Mask +#define NVIC_PRI15_INTC_M 0x00E00000 // Interrupt 62 Priority Mask +#define NVIC_PRI15_INTB_M 0x0000E000 // Interrupt 61 Priority Mask +#define NVIC_PRI15_INTA_M 0x000000E0 // Interrupt 60 Priority Mask +#define NVIC_PRI15_INTD_S 29 +#define NVIC_PRI15_INTC_S 21 +#define NVIC_PRI15_INTB_S 13 +#define NVIC_PRI15_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI16 register. +// +//***************************************************************************** +#define NVIC_PRI16_INTD_M 0xE0000000 // Interrupt 67 Priority Mask +#define NVIC_PRI16_INTC_M 0x00E00000 // Interrupt 66 Priority Mask +#define NVIC_PRI16_INTB_M 0x0000E000 // Interrupt 65 Priority Mask +#define NVIC_PRI16_INTA_M 0x000000E0 // Interrupt 64 Priority Mask +#define NVIC_PRI16_INTD_S 29 +#define NVIC_PRI16_INTC_S 21 +#define NVIC_PRI16_INTB_S 13 +#define NVIC_PRI16_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI17 register. +// +//***************************************************************************** +#define NVIC_PRI17_INTD_M 0xE0000000 // Interrupt 71 Priority Mask +#define NVIC_PRI17_INTC_M 0x00E00000 // Interrupt 70 Priority Mask +#define NVIC_PRI17_INTB_M 0x0000E000 // Interrupt 69 Priority Mask +#define NVIC_PRI17_INTA_M 0x000000E0 // Interrupt 68 Priority Mask +#define NVIC_PRI17_INTD_S 29 +#define NVIC_PRI17_INTC_S 21 +#define NVIC_PRI17_INTB_S 13 +#define NVIC_PRI17_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI18 register. +// +//***************************************************************************** +#define NVIC_PRI18_INTD_M 0xE0000000 // Interrupt 75 Priority Mask +#define NVIC_PRI18_INTC_M 0x00E00000 // Interrupt 74 Priority Mask +#define NVIC_PRI18_INTB_M 0x0000E000 // Interrupt 73 Priority Mask +#define NVIC_PRI18_INTA_M 0x000000E0 // Interrupt 72 Priority Mask +#define NVIC_PRI18_INTD_S 29 +#define NVIC_PRI18_INTC_S 21 +#define NVIC_PRI18_INTB_S 13 +#define NVIC_PRI18_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI19 register. +// +//***************************************************************************** +#define NVIC_PRI19_INTD_M 0xE0000000 // Interrupt 79 Priority Mask +#define NVIC_PRI19_INTC_M 0x00E00000 // Interrupt 78 Priority Mask +#define NVIC_PRI19_INTB_M 0x0000E000 // Interrupt 77 Priority Mask +#define NVIC_PRI19_INTA_M 0x000000E0 // Interrupt 76 Priority Mask +#define NVIC_PRI19_INTD_S 29 +#define NVIC_PRI19_INTC_S 21 +#define NVIC_PRI19_INTB_S 13 +#define NVIC_PRI19_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI20 register. +// +//***************************************************************************** +#define NVIC_PRI20_INTD_M 0xE0000000 // Interrupt 83 Priority Mask +#define NVIC_PRI20_INTC_M 0x00E00000 // Interrupt 82 Priority Mask +#define NVIC_PRI20_INTB_M 0x0000E000 // Interrupt 81 Priority Mask +#define NVIC_PRI20_INTA_M 0x000000E0 // Interrupt 80 Priority Mask +#define NVIC_PRI20_INTD_S 29 +#define NVIC_PRI20_INTC_S 21 +#define NVIC_PRI20_INTB_S 13 +#define NVIC_PRI20_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI21 register. +// +//***************************************************************************** +#define NVIC_PRI21_INTD_M 0xE0000000 // Interrupt 87 Priority Mask +#define NVIC_PRI21_INTC_M 0x00E00000 // Interrupt 86 Priority Mask +#define NVIC_PRI21_INTB_M 0x0000E000 // Interrupt 85 Priority Mask +#define NVIC_PRI21_INTA_M 0x000000E0 // Interrupt 84 Priority Mask +#define NVIC_PRI21_INTD_S 29 +#define NVIC_PRI21_INTC_S 21 +#define NVIC_PRI21_INTB_S 13 +#define NVIC_PRI21_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI22 register. +// +//***************************************************************************** +#define NVIC_PRI22_INTD_M 0xE0000000 // Interrupt 91 Priority Mask +#define NVIC_PRI22_INTC_M 0x00E00000 // Interrupt 90 Priority Mask +#define NVIC_PRI22_INTB_M 0x0000E000 // Interrupt 89 Priority Mask +#define NVIC_PRI22_INTA_M 0x000000E0 // Interrupt 88 Priority Mask +#define NVIC_PRI22_INTD_S 29 +#define NVIC_PRI22_INTC_S 21 +#define NVIC_PRI22_INTB_S 13 +#define NVIC_PRI22_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI23 register. +// +//***************************************************************************** +#define NVIC_PRI23_INTD_M 0xE0000000 // Interrupt 95 Priority Mask +#define NVIC_PRI23_INTC_M 0x00E00000 // Interrupt 94 Priority Mask +#define NVIC_PRI23_INTB_M 0x0000E000 // Interrupt 93 Priority Mask +#define NVIC_PRI23_INTA_M 0x000000E0 // Interrupt 92 Priority Mask +#define NVIC_PRI23_INTD_S 29 +#define NVIC_PRI23_INTC_S 21 +#define NVIC_PRI23_INTB_S 13 +#define NVIC_PRI23_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI24 register. +// +//***************************************************************************** +#define NVIC_PRI24_INTD_M 0xE0000000 // Interrupt 99 Priority Mask +#define NVIC_PRI24_INTC_M 0x00E00000 // Interrupt 98 Priority Mask +#define NVIC_PRI24_INTB_M 0x0000E000 // Interrupt 97 Priority Mask +#define NVIC_PRI24_INTA_M 0x000000E0 // Interrupt 96 Priority Mask +#define NVIC_PRI24_INTD_S 29 +#define NVIC_PRI24_INTC_S 21 +#define NVIC_PRI24_INTB_S 13 +#define NVIC_PRI24_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI25 register. +// +//***************************************************************************** +#define NVIC_PRI25_INTD_M 0xE0000000 // Interrupt 103 Priority Mask +#define NVIC_PRI25_INTC_M 0x00E00000 // Interrupt 102 Priority Mask +#define NVIC_PRI25_INTB_M 0x0000E000 // Interrupt 101 Priority Mask +#define NVIC_PRI25_INTA_M 0x000000E0 // Interrupt 100 Priority Mask +#define NVIC_PRI25_INTD_S 29 +#define NVIC_PRI25_INTC_S 21 +#define NVIC_PRI25_INTB_S 13 +#define NVIC_PRI25_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI26 register. +// +//***************************************************************************** +#define NVIC_PRI26_INTD_M 0xE0000000 // Interrupt 107 Priority Mask +#define NVIC_PRI26_INTC_M 0x00E00000 // Interrupt 106 Priority Mask +#define NVIC_PRI26_INTB_M 0x0000E000 // Interrupt 105 Priority Mask +#define NVIC_PRI26_INTA_M 0x000000E0 // Interrupt 104 Priority Mask +#define NVIC_PRI26_INTD_S 29 +#define NVIC_PRI26_INTC_S 21 +#define NVIC_PRI26_INTB_S 13 +#define NVIC_PRI26_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI27 register. +// +//***************************************************************************** +#define NVIC_PRI27_INTD_M 0xE0000000 // Interrupt 111 Priority Mask +#define NVIC_PRI27_INTC_M 0x00E00000 // Interrupt 110 Priority Mask +#define NVIC_PRI27_INTB_M 0x0000E000 // Interrupt 109 Priority Mask +#define NVIC_PRI27_INTA_M 0x000000E0 // Interrupt 108 Priority Mask +#define NVIC_PRI27_INTD_S 29 +#define NVIC_PRI27_INTC_S 21 +#define NVIC_PRI27_INTB_S 13 +#define NVIC_PRI27_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI28 register. +// +//***************************************************************************** +#define NVIC_PRI28_INTD_M 0xE0000000 // Interrupt 115 Priority Mask +#define NVIC_PRI28_INTC_M 0x00E00000 // Interrupt 114 Priority Mask +#define NVIC_PRI28_INTB_M 0x0000E000 // Interrupt 113 Priority Mask +#define NVIC_PRI28_INTA_M 0x000000E0 // Interrupt 112 Priority Mask +#define NVIC_PRI28_INTD_S 29 +#define NVIC_PRI28_INTC_S 21 +#define NVIC_PRI28_INTB_S 13 +#define NVIC_PRI28_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI29 register. +// +//***************************************************************************** +#define NVIC_PRI29_INTD_M 0xE0000000 // Interrupt 119 Priority Mask +#define NVIC_PRI29_INTC_M 0x00E00000 // Interrupt 118 Priority Mask +#define NVIC_PRI29_INTB_M 0x0000E000 // Interrupt 117 Priority Mask +#define NVIC_PRI29_INTA_M 0x000000E0 // Interrupt 116 Priority Mask +#define NVIC_PRI29_INTD_S 29 +#define NVIC_PRI29_INTC_S 21 +#define NVIC_PRI29_INTB_S 13 +#define NVIC_PRI29_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI30 register. +// +//***************************************************************************** +#define NVIC_PRI30_INTD_M 0xE0000000 // Interrupt 123 Priority Mask +#define NVIC_PRI30_INTC_M 0x00E00000 // Interrupt 122 Priority Mask +#define NVIC_PRI30_INTB_M 0x0000E000 // Interrupt 121 Priority Mask +#define NVIC_PRI30_INTA_M 0x000000E0 // Interrupt 120 Priority Mask +#define NVIC_PRI30_INTD_S 29 +#define NVIC_PRI30_INTC_S 21 +#define NVIC_PRI30_INTB_S 13 +#define NVIC_PRI30_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI31 register. +// +//***************************************************************************** +#define NVIC_PRI31_INTD_M 0xE0000000 // Interrupt 127 Priority Mask +#define NVIC_PRI31_INTC_M 0x00E00000 // Interrupt 126 Priority Mask +#define NVIC_PRI31_INTB_M 0x0000E000 // Interrupt 125 Priority Mask +#define NVIC_PRI31_INTA_M 0x000000E0 // Interrupt 124 Priority Mask +#define NVIC_PRI31_INTD_S 29 +#define NVIC_PRI31_INTC_S 21 +#define NVIC_PRI31_INTB_S 13 +#define NVIC_PRI31_INTA_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_PRI32 register. +// +//***************************************************************************** +#define NVIC_PRI32_INTD_M 0xE0000000 // Interrupt 131 Priority Mask +#define NVIC_PRI32_INTC_M 0x00E00000 // Interrupt 130 Priority Mask +#define NVIC_PRI32_INTB_M 0x0000E000 // Interrupt 129 Priority Mask +#define NVIC_PRI32_INTA_M 0x000000E0 // Interrupt 128 Priority Mask +#define NVIC_PRI32_INTD_S 29 +#define NVIC_PRI32_INTC_S 21 +#define NVIC_PRI32_INTB_S 13 +#define NVIC_PRI32_INTA_S 5 + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_CPUID register. +// +//***************************************************************************** +#define NVIC_CPUID_IMP_M 0xFF000000 // Implementer Code +#define NVIC_CPUID_IMP_ARM 0x41000000 // ARM +#define NVIC_CPUID_VAR_M 0x00F00000 // Variant Number +#define NVIC_CPUID_CON_M 0x000F0000 // Constant +#define NVIC_CPUID_PARTNO_M 0x0000FFF0 // Part Number +#define NVIC_CPUID_PARTNO_CM3 0x0000C230 // Cortex-M3 processor + +#define NVIC_CPUID_PARTNO_CM4 0x0000C240 // Cortex-M4 processor + +#define NVIC_CPUID_REV_M 0x0000000F // Revision Number + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_INT_CTRL register. +// +//***************************************************************************** +#define NVIC_INT_CTRL_NMI_SET 0x80000000 // NMI Set Pending +#define NVIC_INT_CTRL_PEND_SV 0x10000000 // PendSV Set Pending +#define NVIC_INT_CTRL_UNPEND_SV 0x08000000 // PendSV Clear Pending +#define NVIC_INT_CTRL_PENDSTSET 0x04000000 // SysTick Set Pending +#define NVIC_INT_CTRL_PENDSTCLR 0x02000000 // SysTick Clear Pending +#define NVIC_INT_CTRL_ISR_PRE 0x00800000 // Debug Interrupt Handling +#define NVIC_INT_CTRL_ISR_PEND 0x00400000 // Interrupt Pending +#define NVIC_INT_CTRL_VEC_PEN_M 0x0007F000 // Interrupt Pending Vector Number + +#undef NVIC_INT_CTRL_VEC_PEN_M +#define NVIC_INT_CTRL_VEC_PEN_M 0x000FF000 // Interrupt Pending Vector Number + +#define NVIC_INT_CTRL_VEC_PEN_NMI \ + 0x00002000 // NMI +#define NVIC_INT_CTRL_VEC_PEN_HARD \ + 0x00003000 // Hard fault +#define NVIC_INT_CTRL_VEC_PEN_MEM \ + 0x00004000 // Memory management fault +#define NVIC_INT_CTRL_VEC_PEN_BUS \ + 0x00005000 // Bus fault +#define NVIC_INT_CTRL_VEC_PEN_USG \ + 0x00006000 // Usage fault +#define NVIC_INT_CTRL_VEC_PEN_SVC \ + 0x0000B000 // SVCall +#define NVIC_INT_CTRL_VEC_PEN_PNDSV \ + 0x0000E000 // PendSV +#define NVIC_INT_CTRL_VEC_PEN_TICK \ + 0x0000F000 // SysTick +#define NVIC_INT_CTRL_RET_BASE 0x00000800 // Return to Base +#define NVIC_INT_CTRL_VEC_ACT_M 0x0000007F // Interrupt Pending Vector Number + +#undef NVIC_INT_CTRL_VEC_ACT_M +#define NVIC_INT_CTRL_VEC_ACT_M 0x000000FF // Interrupt Pending Vector Number + +#define NVIC_INT_CTRL_VEC_PEN_S 12 +#define NVIC_INT_CTRL_VEC_ACT_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_VTABLE register. +// +//***************************************************************************** +#define NVIC_VTABLE_BASE 0x20000000 // Vector Table Base +#define NVIC_VTABLE_OFFSET_M 0x1FFFFE00 // Vector Table Offset + +#undef NVIC_VTABLE_OFFSET_M +#define NVIC_VTABLE_OFFSET_M 0x1FFFFC00 // Vector Table Offset + +#define NVIC_VTABLE_OFFSET_S 9 + +#undef NVIC_VTABLE_OFFSET_S +#define NVIC_VTABLE_OFFSET_S 10 + + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_APINT register. +// +//***************************************************************************** +#define NVIC_APINT_VECTKEY_M 0xFFFF0000 // Register Key +#define NVIC_APINT_VECTKEY 0x05FA0000 // Vector key +#define NVIC_APINT_ENDIANESS 0x00008000 // Data Endianess +#define NVIC_APINT_PRIGROUP_M 0x00000700 // Interrupt Priority Grouping +#define NVIC_APINT_PRIGROUP_7_1 0x00000000 // Priority group 7.1 split +#define NVIC_APINT_PRIGROUP_6_2 0x00000100 // Priority group 6.2 split +#define NVIC_APINT_PRIGROUP_5_3 0x00000200 // Priority group 5.3 split +#define NVIC_APINT_PRIGROUP_4_4 0x00000300 // Priority group 4.4 split +#define NVIC_APINT_PRIGROUP_3_5 0x00000400 // Priority group 3.5 split +#define NVIC_APINT_PRIGROUP_2_6 0x00000500 // Priority group 2.6 split +#define NVIC_APINT_PRIGROUP_1_7 0x00000600 // Priority group 1.7 split +#define NVIC_APINT_PRIGROUP_0_8 0x00000700 // Priority group 0.8 split +#define NVIC_APINT_SYSRESETREQ 0x00000004 // System Reset Request +#define NVIC_APINT_VECT_CLR_ACT 0x00000002 // Clear Active NMI / Fault +#define NVIC_APINT_VECT_RESET 0x00000001 // System Reset + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_SYS_CTRL register. +// +//***************************************************************************** +#define NVIC_SYS_CTRL_SEVONPEND 0x00000010 // Wake Up on Pending +#define NVIC_SYS_CTRL_SLEEPDEEP 0x00000004 // Deep Sleep Enable +#define NVIC_SYS_CTRL_SLEEPEXIT 0x00000002 // Sleep on ISR Exit + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_CFG_CTRL register. +// +//***************************************************************************** +#define NVIC_CFG_CTRL_STKALIGN 0x00000200 // Stack Alignment on Exception + // Entry +#define NVIC_CFG_CTRL_BFHFNMIGN 0x00000100 // Ignore Bus Fault in NMI and + // Fault +#define NVIC_CFG_CTRL_DIV0 0x00000010 // Trap on Divide by 0 +#define NVIC_CFG_CTRL_UNALIGNED 0x00000008 // Trap on Unaligned Access +#define NVIC_CFG_CTRL_MAIN_PEND 0x00000002 // Allow Main Interrupt Trigger +#define NVIC_CFG_CTRL_BASE_THR 0x00000001 // Thread State Control + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_SYS_PRI1 register. +// +//***************************************************************************** +#define NVIC_SYS_PRI1_USAGE_M 0x00E00000 // Usage Fault Priority +#define NVIC_SYS_PRI1_BUS_M 0x0000E000 // Bus Fault Priority +#define NVIC_SYS_PRI1_MEM_M 0x000000E0 // Memory Management Fault Priority +#define NVIC_SYS_PRI1_USAGE_S 21 +#define NVIC_SYS_PRI1_BUS_S 13 +#define NVIC_SYS_PRI1_MEM_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_SYS_PRI2 register. +// +//***************************************************************************** +#define NVIC_SYS_PRI2_SVC_M 0xE0000000 // SVCall Priority +#define NVIC_SYS_PRI2_SVC_S 29 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_SYS_PRI3 register. +// +//***************************************************************************** +#define NVIC_SYS_PRI3_TICK_M 0xE0000000 // SysTick Exception Priority +#define NVIC_SYS_PRI3_PENDSV_M 0x00E00000 // PendSV Priority +#define NVIC_SYS_PRI3_DEBUG_M 0x000000E0 // Debug Priority +#define NVIC_SYS_PRI3_TICK_S 29 +#define NVIC_SYS_PRI3_PENDSV_S 21 +#define NVIC_SYS_PRI3_DEBUG_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_SYS_HND_CTRL +// register. +// +//***************************************************************************** +#define NVIC_SYS_HND_CTRL_USAGE 0x00040000 // Usage Fault Enable +#define NVIC_SYS_HND_CTRL_BUS 0x00020000 // Bus Fault Enable +#define NVIC_SYS_HND_CTRL_MEM 0x00010000 // Memory Management Fault Enable +#define NVIC_SYS_HND_CTRL_SVC 0x00008000 // SVC Call Pending +#define NVIC_SYS_HND_CTRL_BUSP 0x00004000 // Bus Fault Pending +#define NVIC_SYS_HND_CTRL_MEMP 0x00002000 // Memory Management Fault Pending +#define NVIC_SYS_HND_CTRL_USAGEP \ + 0x00001000 // Usage Fault Pending +#define NVIC_SYS_HND_CTRL_TICK 0x00000800 // SysTick Exception Active +#define NVIC_SYS_HND_CTRL_PNDSV 0x00000400 // PendSV Exception Active +#define NVIC_SYS_HND_CTRL_MON 0x00000100 // Debug Monitor Active +#define NVIC_SYS_HND_CTRL_SVCA 0x00000080 // SVC Call Active +#define NVIC_SYS_HND_CTRL_USGA 0x00000008 // Usage Fault Active +#define NVIC_SYS_HND_CTRL_BUSA 0x00000002 // Bus Fault Active +#define NVIC_SYS_HND_CTRL_MEMA 0x00000001 // Memory Management Fault Active + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_FAULT_STAT +// register. +// +//***************************************************************************** +#define NVIC_FAULT_STAT_DIV0 0x02000000 // Divide-by-Zero Usage Fault +#define NVIC_FAULT_STAT_UNALIGN 0x01000000 // Unaligned Access Usage Fault +#define NVIC_FAULT_STAT_NOCP 0x00080000 // No Coprocessor Usage Fault +#define NVIC_FAULT_STAT_INVPC 0x00040000 // Invalid PC Load Usage Fault +#define NVIC_FAULT_STAT_INVSTAT 0x00020000 // Invalid State Usage Fault +#define NVIC_FAULT_STAT_UNDEF 0x00010000 // Undefined Instruction Usage + // Fault +#define NVIC_FAULT_STAT_BFARV 0x00008000 // Bus Fault Address Register Valid + +#define NVIC_FAULT_STAT_BLSPERR 0x00002000 // Bus Fault on Floating-Point Lazy + // State Preservation + +#define NVIC_FAULT_STAT_BSTKE 0x00001000 // Stack Bus Fault +#define NVIC_FAULT_STAT_BUSTKE 0x00000800 // Unstack Bus Fault +#define NVIC_FAULT_STAT_IMPRE 0x00000400 // Imprecise Data Bus Error +#define NVIC_FAULT_STAT_PRECISE 0x00000200 // Precise Data Bus Error +#define NVIC_FAULT_STAT_IBUS 0x00000100 // Instruction Bus Error +#define NVIC_FAULT_STAT_MMARV 0x00000080 // Memory Management Fault Address + // Register Valid + +#define NVIC_FAULT_STAT_MLSPERR 0x00000020 // Memory Management Fault on + // Floating-Point Lazy State + // Preservation + +#define NVIC_FAULT_STAT_MSTKE 0x00000010 // Stack Access Violation +#define NVIC_FAULT_STAT_MUSTKE 0x00000008 // Unstack Access Violation +#define NVIC_FAULT_STAT_DERR 0x00000002 // Data Access Violation +#define NVIC_FAULT_STAT_IERR 0x00000001 // Instruction Access Violation + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_HFAULT_STAT +// register. +// +//***************************************************************************** +#define NVIC_HFAULT_STAT_DBG 0x80000000 // Debug Event +#define NVIC_HFAULT_STAT_FORCED 0x40000000 // Forced Hard Fault +#define NVIC_HFAULT_STAT_VECT 0x00000002 // Vector Table Read Fault + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DEBUG_STAT +// register. +// +//***************************************************************************** +#define NVIC_DEBUG_STAT_EXTRNL 0x00000010 // EDBGRQ asserted +#define NVIC_DEBUG_STAT_VCATCH 0x00000008 // Vector catch +#define NVIC_DEBUG_STAT_DWTTRAP 0x00000004 // DWT match +#define NVIC_DEBUG_STAT_BKPT 0x00000002 // Breakpoint instruction +#define NVIC_DEBUG_STAT_HALTED 0x00000001 // Halt request + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MM_ADDR register. +// +//***************************************************************************** +#define NVIC_MM_ADDR_M 0xFFFFFFFF // Fault Address +#define NVIC_MM_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_FAULT_ADDR +// register. +// +//***************************************************************************** +#define NVIC_FAULT_ADDR_M 0xFFFFFFFF // Fault Address +#define NVIC_FAULT_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_TYPE register. +// +//***************************************************************************** +#define NVIC_MPU_TYPE_IREGION_M 0x00FF0000 // Number of I Regions +#define NVIC_MPU_TYPE_DREGION_M 0x0000FF00 // Number of D Regions +#define NVIC_MPU_TYPE_SEPARATE 0x00000001 // Separate or Unified MPU +#define NVIC_MPU_TYPE_IREGION_S 16 +#define NVIC_MPU_TYPE_DREGION_S 8 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_CTRL register. +// +//***************************************************************************** +#define NVIC_MPU_CTRL_PRIVDEFEN 0x00000004 // MPU Default Region +#define NVIC_MPU_CTRL_HFNMIENA 0x00000002 // MPU Enabled During Faults +#define NVIC_MPU_CTRL_ENABLE 0x00000001 // MPU Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_NUMBER +// register. +// +//***************************************************************************** +#define NVIC_MPU_NUMBER_M 0x00000007 // MPU Region to Access +#define NVIC_MPU_NUMBER_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_BASE register. +// +//***************************************************************************** +#define NVIC_MPU_BASE_ADDR_M 0xFFFFFFE0 // Base Address Mask +#define NVIC_MPU_BASE_VALID 0x00000010 // Region Number Valid +#define NVIC_MPU_BASE_REGION_M 0x00000007 // Region Number +#define NVIC_MPU_BASE_ADDR_S 5 +#define NVIC_MPU_BASE_REGION_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_ATTR register. +// +//***************************************************************************** +#define NVIC_MPU_ATTR_M 0xFFFF0000 // Attributes +#define NVIC_MPU_ATTR_XN 0x10000000 // Instruction Access Disable +#define NVIC_MPU_ATTR_AP_M 0x07000000 // Access Privilege +#define NVIC_MPU_ATTR_AP_NO_NO 0x00000000 // prv: no access, usr: no access +#define NVIC_MPU_ATTR_AP_RW_NO 0x01000000 // prv: rw, usr: none +#define NVIC_MPU_ATTR_AP_RW_RO 0x02000000 // prv: rw, usr: read-only +#define NVIC_MPU_ATTR_AP_RW_RW 0x03000000 // prv: rw, usr: rw +#define NVIC_MPU_ATTR_AP_RO_NO 0x05000000 // prv: ro, usr: none +#define NVIC_MPU_ATTR_AP_RO_RO 0x06000000 // prv: ro, usr: ro +#define NVIC_MPU_ATTR_TEX_M 0x00380000 // Type Extension Mask +#define NVIC_MPU_ATTR_SHAREABLE 0x00040000 // Shareable +#define NVIC_MPU_ATTR_CACHEABLE 0x00020000 // Cacheable +#define NVIC_MPU_ATTR_BUFFRABLE 0x00010000 // Bufferable +#define NVIC_MPU_ATTR_SRD_M 0x0000FF00 // Subregion Disable Bits +#define NVIC_MPU_ATTR_SRD_0 0x00000100 // Sub-region 0 disable +#define NVIC_MPU_ATTR_SRD_1 0x00000200 // Sub-region 1 disable +#define NVIC_MPU_ATTR_SRD_2 0x00000400 // Sub-region 2 disable +#define NVIC_MPU_ATTR_SRD_3 0x00000800 // Sub-region 3 disable +#define NVIC_MPU_ATTR_SRD_4 0x00001000 // Sub-region 4 disable +#define NVIC_MPU_ATTR_SRD_5 0x00002000 // Sub-region 5 disable +#define NVIC_MPU_ATTR_SRD_6 0x00004000 // Sub-region 6 disable +#define NVIC_MPU_ATTR_SRD_7 0x00008000 // Sub-region 7 disable +#define NVIC_MPU_ATTR_SIZE_M 0x0000003E // Region Size Mask +#define NVIC_MPU_ATTR_SIZE_32B 0x00000008 // Region size 32 bytes +#define NVIC_MPU_ATTR_SIZE_64B 0x0000000A // Region size 64 bytes +#define NVIC_MPU_ATTR_SIZE_128B 0x0000000C // Region size 128 bytes +#define NVIC_MPU_ATTR_SIZE_256B 0x0000000E // Region size 256 bytes +#define NVIC_MPU_ATTR_SIZE_512B 0x00000010 // Region size 512 bytes +#define NVIC_MPU_ATTR_SIZE_1K 0x00000012 // Region size 1 Kbytes +#define NVIC_MPU_ATTR_SIZE_2K 0x00000014 // Region size 2 Kbytes +#define NVIC_MPU_ATTR_SIZE_4K 0x00000016 // Region size 4 Kbytes +#define NVIC_MPU_ATTR_SIZE_8K 0x00000018 // Region size 8 Kbytes +#define NVIC_MPU_ATTR_SIZE_16K 0x0000001A // Region size 16 Kbytes +#define NVIC_MPU_ATTR_SIZE_32K 0x0000001C // Region size 32 Kbytes +#define NVIC_MPU_ATTR_SIZE_64K 0x0000001E // Region size 64 Kbytes +#define NVIC_MPU_ATTR_SIZE_128K 0x00000020 // Region size 128 Kbytes +#define NVIC_MPU_ATTR_SIZE_256K 0x00000022 // Region size 256 Kbytes +#define NVIC_MPU_ATTR_SIZE_512K 0x00000024 // Region size 512 Kbytes +#define NVIC_MPU_ATTR_SIZE_1M 0x00000026 // Region size 1 Mbytes +#define NVIC_MPU_ATTR_SIZE_2M 0x00000028 // Region size 2 Mbytes +#define NVIC_MPU_ATTR_SIZE_4M 0x0000002A // Region size 4 Mbytes +#define NVIC_MPU_ATTR_SIZE_8M 0x0000002C // Region size 8 Mbytes +#define NVIC_MPU_ATTR_SIZE_16M 0x0000002E // Region size 16 Mbytes +#define NVIC_MPU_ATTR_SIZE_32M 0x00000030 // Region size 32 Mbytes +#define NVIC_MPU_ATTR_SIZE_64M 0x00000032 // Region size 64 Mbytes +#define NVIC_MPU_ATTR_SIZE_128M 0x00000034 // Region size 128 Mbytes +#define NVIC_MPU_ATTR_SIZE_256M 0x00000036 // Region size 256 Mbytes +#define NVIC_MPU_ATTR_SIZE_512M 0x00000038 // Region size 512 Mbytes +#define NVIC_MPU_ATTR_SIZE_1G 0x0000003A // Region size 1 Gbytes +#define NVIC_MPU_ATTR_SIZE_2G 0x0000003C // Region size 2 Gbytes +#define NVIC_MPU_ATTR_SIZE_4G 0x0000003E // Region size 4 Gbytes +#define NVIC_MPU_ATTR_ENABLE 0x00000001 // Region Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_BASE1 register. +// +//***************************************************************************** +#define NVIC_MPU_BASE1_ADDR_M 0xFFFFFFE0 // Base Address Mask +#define NVIC_MPU_BASE1_VALID 0x00000010 // Region Number Valid +#define NVIC_MPU_BASE1_REGION_M 0x00000007 // Region Number +#define NVIC_MPU_BASE1_ADDR_S 5 +#define NVIC_MPU_BASE1_REGION_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_ATTR1 register. +// +//***************************************************************************** +#define NVIC_MPU_ATTR1_XN 0x10000000 // Instruction Access Disable +#define NVIC_MPU_ATTR1_AP_M 0x07000000 // Access Privilege +#define NVIC_MPU_ATTR1_TEX_M 0x00380000 // Type Extension Mask +#define NVIC_MPU_ATTR1_SHAREABLE \ + 0x00040000 // Shareable +#define NVIC_MPU_ATTR1_CACHEABLE \ + 0x00020000 // Cacheable +#define NVIC_MPU_ATTR1_BUFFRABLE \ + 0x00010000 // Bufferable +#define NVIC_MPU_ATTR1_SRD_M 0x0000FF00 // Subregion Disable Bits +#define NVIC_MPU_ATTR1_SIZE_M 0x0000003E // Region Size Mask +#define NVIC_MPU_ATTR1_ENABLE 0x00000001 // Region Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_BASE2 register. +// +//***************************************************************************** +#define NVIC_MPU_BASE2_ADDR_M 0xFFFFFFE0 // Base Address Mask +#define NVIC_MPU_BASE2_VALID 0x00000010 // Region Number Valid +#define NVIC_MPU_BASE2_REGION_M 0x00000007 // Region Number +#define NVIC_MPU_BASE2_ADDR_S 5 +#define NVIC_MPU_BASE2_REGION_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_ATTR2 register. +// +//***************************************************************************** +#define NVIC_MPU_ATTR2_XN 0x10000000 // Instruction Access Disable +#define NVIC_MPU_ATTR2_AP_M 0x07000000 // Access Privilege +#define NVIC_MPU_ATTR2_TEX_M 0x00380000 // Type Extension Mask +#define NVIC_MPU_ATTR2_SHAREABLE \ + 0x00040000 // Shareable +#define NVIC_MPU_ATTR2_CACHEABLE \ + 0x00020000 // Cacheable +#define NVIC_MPU_ATTR2_BUFFRABLE \ + 0x00010000 // Bufferable +#define NVIC_MPU_ATTR2_SRD_M 0x0000FF00 // Subregion Disable Bits +#define NVIC_MPU_ATTR2_SIZE_M 0x0000003E // Region Size Mask +#define NVIC_MPU_ATTR2_ENABLE 0x00000001 // Region Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_BASE3 register. +// +//***************************************************************************** +#define NVIC_MPU_BASE3_ADDR_M 0xFFFFFFE0 // Base Address Mask +#define NVIC_MPU_BASE3_VALID 0x00000010 // Region Number Valid +#define NVIC_MPU_BASE3_REGION_M 0x00000007 // Region Number +#define NVIC_MPU_BASE3_ADDR_S 5 +#define NVIC_MPU_BASE3_REGION_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_MPU_ATTR3 register. +// +//***************************************************************************** +#define NVIC_MPU_ATTR3_XN 0x10000000 // Instruction Access Disable +#define NVIC_MPU_ATTR3_AP_M 0x07000000 // Access Privilege +#define NVIC_MPU_ATTR3_TEX_M 0x00380000 // Type Extension Mask +#define NVIC_MPU_ATTR3_SHAREABLE \ + 0x00040000 // Shareable +#define NVIC_MPU_ATTR3_CACHEABLE \ + 0x00020000 // Cacheable +#define NVIC_MPU_ATTR3_BUFFRABLE \ + 0x00010000 // Bufferable +#define NVIC_MPU_ATTR3_SRD_M 0x0000FF00 // Subregion Disable Bits +#define NVIC_MPU_ATTR3_SIZE_M 0x0000003E // Region Size Mask +#define NVIC_MPU_ATTR3_ENABLE 0x00000001 // Region Enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DBG_CTRL register. +// +//***************************************************************************** +#define NVIC_DBG_CTRL_DBGKEY_M 0xFFFF0000 // Debug key mask +#define NVIC_DBG_CTRL_DBGKEY 0xA05F0000 // Debug key +#define NVIC_DBG_CTRL_S_RESET_ST \ + 0x02000000 // Core has reset since last read +#define NVIC_DBG_CTRL_S_RETIRE_ST \ + 0x01000000 // Core has executed insruction + // since last read +#define NVIC_DBG_CTRL_S_LOCKUP 0x00080000 // Core is locked up +#define NVIC_DBG_CTRL_S_SLEEP 0x00040000 // Core is sleeping +#define NVIC_DBG_CTRL_S_HALT 0x00020000 // Core status on halt +#define NVIC_DBG_CTRL_S_REGRDY 0x00010000 // Register read/write available +#define NVIC_DBG_CTRL_C_SNAPSTALL \ + 0x00000020 // Breaks a stalled load/store +#define NVIC_DBG_CTRL_C_MASKINT 0x00000008 // Mask interrupts when stepping +#define NVIC_DBG_CTRL_C_STEP 0x00000004 // Step the core +#define NVIC_DBG_CTRL_C_HALT 0x00000002 // Halt the core +#define NVIC_DBG_CTRL_C_DEBUGEN 0x00000001 // Enable debug + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DBG_XFER register. +// +//***************************************************************************** +#define NVIC_DBG_XFER_REG_WNR 0x00010000 // Write or not read +#define NVIC_DBG_XFER_REG_SEL_M 0x0000001F // Register +#define NVIC_DBG_XFER_REG_R0 0x00000000 // Register R0 +#define NVIC_DBG_XFER_REG_R1 0x00000001 // Register R1 +#define NVIC_DBG_XFER_REG_R2 0x00000002 // Register R2 +#define NVIC_DBG_XFER_REG_R3 0x00000003 // Register R3 +#define NVIC_DBG_XFER_REG_R4 0x00000004 // Register R4 +#define NVIC_DBG_XFER_REG_R5 0x00000005 // Register R5 +#define NVIC_DBG_XFER_REG_R6 0x00000006 // Register R6 +#define NVIC_DBG_XFER_REG_R7 0x00000007 // Register R7 +#define NVIC_DBG_XFER_REG_R8 0x00000008 // Register R8 +#define NVIC_DBG_XFER_REG_R9 0x00000009 // Register R9 +#define NVIC_DBG_XFER_REG_R10 0x0000000A // Register R10 +#define NVIC_DBG_XFER_REG_R11 0x0000000B // Register R11 +#define NVIC_DBG_XFER_REG_R12 0x0000000C // Register R12 +#define NVIC_DBG_XFER_REG_R13 0x0000000D // Register R13 +#define NVIC_DBG_XFER_REG_R14 0x0000000E // Register R14 +#define NVIC_DBG_XFER_REG_R15 0x0000000F // Register R15 +#define NVIC_DBG_XFER_REG_FLAGS 0x00000010 // xPSR/Flags register +#define NVIC_DBG_XFER_REG_MSP 0x00000011 // Main SP +#define NVIC_DBG_XFER_REG_PSP 0x00000012 // Process SP +#define NVIC_DBG_XFER_REG_DSP 0x00000013 // Deep SP +#define NVIC_DBG_XFER_REG_CFBP 0x00000014 // Control/Fault/BasePri/PriMask + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DBG_DATA register. +// +//***************************************************************************** +#define NVIC_DBG_DATA_M 0xFFFFFFFF // Data temporary cache +#define NVIC_DBG_DATA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_DBG_INT register. +// +//***************************************************************************** +#define NVIC_DBG_INT_HARDERR 0x00000400 // Debug trap on hard fault +#define NVIC_DBG_INT_INTERR 0x00000200 // Debug trap on interrupt errors +#define NVIC_DBG_INT_BUSERR 0x00000100 // Debug trap on bus error +#define NVIC_DBG_INT_STATERR 0x00000080 // Debug trap on usage fault state +#define NVIC_DBG_INT_CHKERR 0x00000040 // Debug trap on usage fault check +#define NVIC_DBG_INT_NOCPERR 0x00000020 // Debug trap on coprocessor error +#define NVIC_DBG_INT_MMERR 0x00000010 // Debug trap on mem manage fault +#define NVIC_DBG_INT_RESET 0x00000008 // Core reset status +#define NVIC_DBG_INT_RSTPENDCLR 0x00000004 // Clear pending core reset +#define NVIC_DBG_INT_RSTPENDING 0x00000002 // Core reset is pending +#define NVIC_DBG_INT_RSTVCATCH 0x00000001 // Reset vector catch + +//***************************************************************************** +// +// The following are defines for the bit fields in the NVIC_SW_TRIG register. +// +//***************************************************************************** +#define NVIC_SW_TRIG_INTID_M 0x0000003F // Interrupt ID + +#undef NVIC_SW_TRIG_INTID_M +#define NVIC_SW_TRIG_INTID_M 0x000000FF // Interrupt ID + +#define NVIC_SW_TRIG_INTID_S 0 + +#endif // __HW_NVIC_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ocp_shared.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ocp_shared.h new file mode 100644 index 00000000..a52f6901 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_ocp_shared.h @@ -0,0 +1,3445 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_OCP_SHARED_H__ +#define __HW_OCP_SHARED_H__ + +//***************************************************************************** +// +// The following are defines for the OCP_SHARED register offsets. +// +//***************************************************************************** +#define OCP_SHARED_O_SEMAPHORE1 0x00000000 +#define OCP_SHARED_O_SEMAPHORE2 0x00000004 +#define OCP_SHARED_O_SEMAPHORE3 0x00000008 +#define OCP_SHARED_O_SEMAPHORE4 0x0000000C +#define OCP_SHARED_O_SEMAPHORE5 0x00000010 +#define OCP_SHARED_O_SEMAPHORE6 0x00000014 +#define OCP_SHARED_O_SEMAPHORE7 0x00000018 +#define OCP_SHARED_O_SEMAPHORE8 0x0000001C +#define OCP_SHARED_O_SEMAPHORE9 0x00000020 +#define OCP_SHARED_O_SEMAPHORE10 \ + 0x00000024 + +#define OCP_SHARED_O_SEMAPHORE11 \ + 0x00000028 + +#define OCP_SHARED_O_SEMAPHORE12 \ + 0x0000002C + +#define OCP_SHARED_O_IC_LOCKER_ID \ + 0x00000030 + +#define OCP_SHARED_O_MCU_SEMAPHORE_PEND \ + 0x00000034 + +#define OCP_SHARED_O_WL_SEMAPHORE_PEND \ + 0x00000038 + +#define OCP_SHARED_O_PLATFORM_DETECTION_RD_ONLY \ + 0x0000003C + +#define OCP_SHARED_O_SEMAPHORES_STATUS_RD_ONLY \ + 0x00000040 + +#define OCP_SHARED_O_CC3XX_CONFIG_CTRL \ + 0x00000044 + +#define OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_LSB \ + 0x00000048 + +#define OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_MSB \ + 0x0000004C + +#define OCP_SHARED_O_WLAN_ELP_WAKE_EN \ + 0x00000050 + +#define OCP_SHARED_O_DEVINIT_ROM_START_ADDR \ + 0x00000054 + +#define OCP_SHARED_O_DEVINIT_ROM_END_ADDR \ + 0x00000058 + +#define OCP_SHARED_O_SSBD_SEED 0x0000005C +#define OCP_SHARED_O_SSBD_CHK 0x00000060 +#define OCP_SHARED_O_SSBD_POLY_SEL \ + 0x00000064 + +#define OCP_SHARED_O_SPARE_REG_0 \ + 0x00000068 + +#define OCP_SHARED_O_SPARE_REG_1 \ + 0x0000006C + +#define OCP_SHARED_O_SPARE_REG_2 \ + 0x00000070 + +#define OCP_SHARED_O_SPARE_REG_3 \ + 0x00000074 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_0 \ + 0x000000A0 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_1 \ + 0x000000A4 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_2 \ + 0x000000A8 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_3 \ + 0x000000AC + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_4 \ + 0x000000B0 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_5 \ + 0x000000B4 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_6 \ + 0x000000B8 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_7 \ + 0x000000BC + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_8 \ + 0x000000C0 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_9 \ + 0x000000C4 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_10 \ + 0x000000C8 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_11 \ + 0x000000CC + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_12 \ + 0x000000D0 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_13 \ + 0x000000D4 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_14 \ + 0x000000D8 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_15 \ + 0x000000DC + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_16 \ + 0x000000E0 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_17 \ + 0x000000E4 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_18 \ + 0x000000E8 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_19 \ + 0x000000EC + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_20 \ + 0x000000F0 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_21 \ + 0x000000F4 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_22 \ + 0x000000F8 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_23 \ + 0x000000FC + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_24 \ + 0x00000100 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_25 \ + 0x00000104 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_26 \ + 0x00000108 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_27 \ + 0x0000010C + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_28 \ + 0x00000110 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_29 \ + 0x00000114 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_30 \ + 0x00000118 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_31 \ + 0x0000011C + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_32 \ + 0x00000120 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_33 \ + 0x00000124 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_34 \ + 0x00000128 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_35 \ + 0x0000012C + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_36 \ + 0x00000130 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_37 \ + 0x00000134 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_38 \ + 0x00000138 + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_39 \ + 0x0000013C + +#define OCP_SHARED_O_GPIO_PAD_CONFIG_40 \ + 0x00000140 + +#define OCP_SHARED_O_GPIO_PAD_CMN_CONFIG \ + 0x00000144 // This register provide control to + // GPIO_CC3XXV1 IO PAD. Common + // control signals to all bottom Die + // IO's are controlled via this. + +#define OCP_SHARED_O_D2D_DEV_PAD_CMN_CONFIG \ + 0x00000148 + +#define OCP_SHARED_O_D2D_TOSTACK_PAD_CONF \ + 0x0000014C + +#define OCP_SHARED_O_D2D_MISC_PAD_CONF \ + 0x00000150 + +#define OCP_SHARED_O_SOP_CONF_OVERRIDE \ + 0x00000154 + +#define OCP_SHARED_O_CC3XX_DEBUGSS_STATUS \ + 0x00000158 + +#define OCP_SHARED_O_CC3XX_DEBUGMUX_SEL \ + 0x0000015C + +#define OCP_SHARED_O_ALT_PC_VAL_NW \ + 0x00000160 + +#define OCP_SHARED_O_ALT_PC_VAL_APPS \ + 0x00000164 + +#define OCP_SHARED_O_SPARE_REG_4 \ + 0x00000168 + +#define OCP_SHARED_O_SPARE_REG_5 \ + 0x0000016C + +#define OCP_SHARED_O_SH_SPI_CS_MASK \ + 0x00000170 + +#define OCP_SHARED_O_CC3XX_DEVICE_TYPE \ + 0x00000174 + +#define OCP_SHARED_O_MEM_TOPMUXCTRL_IFORCE \ + 0x00000178 + +#define OCP_SHARED_O_CC3XX_DEV_PACKAGE_DETECT \ + 0x0000017C + +#define OCP_SHARED_O_AUTONMS_SPICLK_SEL \ + 0x00000180 + +#define OCP_SHARED_O_CC3XX_DEV_PADCONF \ + 0x00000184 + +#define OCP_SHARED_O_SPARE_REG_8 \ + 0x00000188 + +#define OCP_SHARED_O_SPARE_REG_6 \ + 0x0000018C + +#define OCP_SHARED_O_SPARE_REG_7 \ + 0x00000190 + +#define OCP_SHARED_O_APPS_WLAN_ORBIT \ + 0x00000194 + +#define OCP_SHARED_O_APPS_WLAN_SCRATCH_PAD \ + 0x00000198 + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE1 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE1_MEM_SEMAPHORE1_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE1_MEM_SEMAPHORE1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE2 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE2_MEM_SEMAPHORE2_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE2_MEM_SEMAPHORE2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE3 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE3_MEM_SEMAPHORE3_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE3_MEM_SEMAPHORE3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE4 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE4_MEM_SEMAPHORE4_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE4_MEM_SEMAPHORE4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE5 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE5_MEM_SEMAPHORE5_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE5_MEM_SEMAPHORE5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE6 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE6_MEM_SEMAPHORE6_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE6_MEM_SEMAPHORE6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE7 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE7_MEM_SEMAPHORE7_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE7_MEM_SEMAPHORE7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE8 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE8_MEM_SEMAPHORE8_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE8_MEM_SEMAPHORE8_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE9 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE9_MEM_SEMAPHORE9_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE9_MEM_SEMAPHORE9_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE10 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE10_MEM_SEMAPHORE10_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE10_MEM_SEMAPHORE10_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE11 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE11_MEM_SEMAPHORE11_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE11_MEM_SEMAPHORE11_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORE12 register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORE12_MEM_SEMAPHORE12_M \ + 0x00000003 // General Purpose Semaphore for SW + // Usage. If any of the 2 bits of a + // given register is set to 1, it + // means that the semaphore is + // locked by one of the masters. + // Each bit represents a master IP + // as follows: {WLAN,NWP}. The JTAG + // cannot capture the semaphore but + // it can release it. As a master IP + // reads the semaphore, it will be + // caputed and the masters + // correlating bit will be set to 1 + // (set upon read). As any IP writes + // to this address (independent of + // the written data) the semaphore + // will be set to 2'b00. + +#define OCP_SHARED_SEMAPHORE12_MEM_SEMAPHORE12_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_IC_LOCKER_ID register. +// +//****************************************************************************** +#define OCP_SHARED_IC_LOCKER_ID_MEM_IC_LOCKER_ID_M \ + 0x00000007 // This register is used for + // allowing only one master OCP to + // perform write transactions to the + // OCP slaves. Each bit represents + // an IP in the following format: { + // JTAG,WLAN, NWP mcu}. As any of + // the bits is set to one, the + // correlating IP is preventing the + // other IP's from performing write + // transactions to the slaves. As + // the Inter Connect is locked, the + // only the locking IP can write to + // the register and by that + // releasing the lock. 3'b000 => IC + // is not locked. 3'b001 => IC is + // locked by NWP mcu. 3'b010 => IC + // is locked by WLAN. 3'b100 => IC + // is locked by JTAG. + +#define OCP_SHARED_IC_LOCKER_ID_MEM_IC_LOCKER_ID_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_MCU_SEMAPHORE_PEND register. +// +//****************************************************************************** +#define OCP_SHARED_MCU_SEMAPHORE_PEND_MEM_MCU_SEMAPHORE_PEND_M \ + 0x0000FFFF // This register specifies the + // semaphore for which the NWP mcu + // is waiting to be released. It is + // set to the serial number of a + // given locked semaphore after it + // was read by the NWP mcu. Only + // [11:0] is used. + +#define OCP_SHARED_MCU_SEMAPHORE_PEND_MEM_MCU_SEMAPHORE_PEND_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_WL_SEMAPHORE_PEND register. +// +//****************************************************************************** +#define OCP_SHARED_WL_SEMAPHORE_PEND_MEM_WL_SEMAPHORE_PEND_M \ + 0x0000FFFF // This register specifies the + // semaphore for which the WLAN is + // waiting to be released. It is set + // to the serial number of a given + // locked semaphore after it was + // read by the WLAN. Only [11:0] is + // used. + +#define OCP_SHARED_WL_SEMAPHORE_PEND_MEM_WL_SEMAPHORE_PEND_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_PLATFORM_DETECTION_RD_ONLY register. +// +//****************************************************************************** +#define OCP_SHARED_PLATFORM_DETECTION_RD_ONLY_PLATFORM_DETECTION_M \ + 0x0000FFFF // This information serves the IPs + // for knowing in which platform are + // they integrated at: 0 = CC31XX. + +#define OCP_SHARED_PLATFORM_DETECTION_RD_ONLY_PLATFORM_DETECTION_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SEMAPHORES_STATUS_RD_ONLY register. +// +//****************************************************************************** +#define OCP_SHARED_SEMAPHORES_STATUS_RD_ONLY_SEMAPHORES_STATUS_M \ + 0x00000FFF // Captured/released semaphores + // status for the 12 semaphores. + // Each bit of the 12 bits + // represents a semaphore. 0 => + // Semaphore Free. 1 => Semaphore + // Captured. + +#define OCP_SHARED_SEMAPHORES_STATUS_RD_ONLY_SEMAPHORES_STATUS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_CONFIG_CTRL register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_IC_TO_EN \ + 0x00000010 // This bit is used to enable + // timeout mechanism for top_ocp_ic + // (for debug puropse). When 1 value + // , in case any ocp slave doesn't + // give sresponse within 16 cylcles + // top_ic will give error response + // itself to avoid bus hange. + +#define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_ALT_PC_EN_APPS \ + 0x00000008 // 1 bit should be accessible only + // in devinit. This will enable 0x4 + // hack for apps processor + +#define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_ALT_PC_EN_NW \ + 0x00000004 // 1 bit, should be accessible only + // in devinit. This will enable 0x4 + // hack for nw processor + +#define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_EXTEND_NW_ROM \ + 0x00000002 // When set NW can take over apps + // rom and flash via IDCODE bus. + // Apps will able to access this + // register only during devinit and + // reset value should be 0. + +#define OCP_SHARED_CC3XX_CONFIG_CTRL_MEM_WLAN_HOST_INTF_SEL \ + 0x00000001 // When this bit is set to 0 WPSI + // host interface wil be selected, + // when this bit is set to 1 , WLAN + // host async bridge will be + // selected. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_LSB register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_SHARED_MEM_SEL_LSB_MEM_SHARED_MEM_SEL_LSB_M \ + 0x3FFFFFFF // This register provides memss RAM + // column configuration for column 0 + // to 9. 3 bits are allocated per + // column. This register is required + // to be configured before starting + // RAM access. Changing register + // setting while code is running + // will result into unpredictable + // memory behaviour. Register is + // supported to configured ones + // after core is booted up. 3 bit + // encoding per column is as + // follows: when 000 : WLAN, 001: + // NWP, 010: APPS, 011: PHY, 100: + // OCLA column 0 select: bit [2:0] + // :when 000 -> WLAN,001 -> NWP,010 + // -> APPS, 011 -> PHY, 100 -> OCLA + // column 1 select: bit [5:3] + // :column 2 select: bit [8 : 6]: + // column 3 select : bit [11: 9] + // column 4 select : bit [14:12] + // column 5 select : bit [17:15] + // column 6 select : bit [20:18] + // column 7 select : bit [23:21] + // column 8 select : bit [26:24] + // column 9 select : bit [29:27] + // column 10 select + +#define OCP_SHARED_CC3XX_SHARED_MEM_SEL_LSB_MEM_SHARED_MEM_SEL_LSB_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_SHARED_MEM_SEL_MSB register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_SHARED_MEM_SEL_MSB_MEM_SHARED_MEM_SEL_MSB_M \ + 0x00000FFF // This register provides memss RAM + // column configuration for column + // 10 to 15. 3 bits are allocated + // per column. This register is + // required to be configured before + // starting RAM access. Changing + // register setting while code is + // running will result into + // unpredictable memory behaviour. + // Register is supported to + // configured ones after core is + // booted up. 3 bit encoding per + // column is as follows: when 000 : + // WLAN, 001: NWP, 010: APPS, 011: + // PHY, 100: OCLA column 11 select : + // bit [2:0] column 12 select : bit + // [5:3] column 13 select : bit [8 : + // 6] column 14 select : + +#define OCP_SHARED_CC3XX_SHARED_MEM_SEL_MSB_MEM_SHARED_MEM_SEL_MSB_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_WLAN_ELP_WAKE_EN register. +// +//****************************************************************************** +#define OCP_SHARED_WLAN_ELP_WAKE_EN_MEM_WLAN_ELP_WAKE_EN \ + 0x00000001 // when '1' : signal will enabled + // ELP power doamin when '0': ELP is + // not powered up. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_DEVINIT_ROM_START_ADDR register. +// +//****************************************************************************** +#define OCP_SHARED_DEVINIT_ROM_START_ADDR_MEM_DEVINIT_ROM_START_ADDR_M \ + 0xFFFFFFFF // 32 bit, Writable only during + // devinit, and whole 32 bit should + // be output of the config register + // module. This register is not used + // , similar register availble in + // GPRCM space. + +#define OCP_SHARED_DEVINIT_ROM_START_ADDR_MEM_DEVINIT_ROM_START_ADDR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_DEVINIT_ROM_END_ADDR register. +// +//****************************************************************************** +#define OCP_SHARED_DEVINIT_ROM_END_ADDR_MEM_DEVINIT_ROM_END_ADDR_M \ + 0xFFFFFFFF // 32 bit, Writable only during + // devinit, and whole 32 bit should + // be output of the config register + // module. + +#define OCP_SHARED_DEVINIT_ROM_END_ADDR_MEM_DEVINIT_ROM_END_ADDR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SSBD_SEED register. +// +//****************************************************************************** +#define OCP_SHARED_SSBD_SEED_MEM_SSBD_SEED_M \ + 0xFFFFFFFF // 32 bit, Writable only during + // devinit, and whole 32 bit should + // be output of the config register + // module. + +#define OCP_SHARED_SSBD_SEED_MEM_SSBD_SEED_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SSBD_CHK register. +// +//****************************************************************************** +#define OCP_SHARED_SSBD_CHK_MEM_SSBD_CHK_M \ + 0xFFFFFFFF // 32 bit, Writable only during + // devinit, and whole 32 bit should + // be output of the config register + // module. + +#define OCP_SHARED_SSBD_CHK_MEM_SSBD_CHK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SSBD_POLY_SEL register. +// +//****************************************************************************** +#define OCP_SHARED_SSBD_POLY_SEL_MEM_SSBD_POLY_SEL_M \ + 0x00000003 // 2 bit, Writable only during + // devinit, and whole 2 bit should + // be output of the config register + // module. + +#define OCP_SHARED_SSBD_POLY_SEL_MEM_SSBD_POLY_SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_0 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_0_MEM_SPARE_REG_0_M \ + 0xFFFFFFFF // Devinit code should look for + // whether corresponding fuse is + // blown and if blown write to the + // 11th bit of this register to + // disable flshtst interface + +#define OCP_SHARED_SPARE_REG_0_MEM_SPARE_REG_0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_1 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_1_MEM_SPARE_REG_1_M \ + 0xFFFFFFFF // NWP Software register + +#define OCP_SHARED_SPARE_REG_1_MEM_SPARE_REG_1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_2 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_2_MEM_SPARE_REG_2_M \ + 0xFFFFFFFF // NWP Software register + +#define OCP_SHARED_SPARE_REG_2_MEM_SPARE_REG_2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_3 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_3_MEM_SPARE_REG_3_M \ + 0xFFFFFFFF // APPS Software register + +#define OCP_SHARED_SPARE_REG_3_MEM_SPARE_REG_3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_0 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_0_MEM_GPIO_PAD_CONFIG_0_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." "For example in + // case of I2C Value gets latched at + // rising edge of RET33.""" """ 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_0_MEM_GPIO_PAD_CONFIG_0_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_1 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_1_MEM_GPIO_PAD_CONFIG_1_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_1_MEM_GPIO_PAD_CONFIG_1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_2 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_2_MEM_GPIO_PAD_CONFIG_2_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_2_MEM_GPIO_PAD_CONFIG_2_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_3 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_3_MEM_GPIO_PAD_CONFIG_3_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_3_MEM_GPIO_PAD_CONFIG_3_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_4 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_4_MEM_GPIO_PAD_CONFIG_4_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_4_MEM_GPIO_PAD_CONFIG_4_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_5 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_5_MEM_GPIO_PAD_CONFIG_5_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_5_MEM_GPIO_PAD_CONFIG_5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_6 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_6_MEM_GPIO_PAD_CONFIG_6_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_6_MEM_GPIO_PAD_CONFIG_6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_7 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_7_MEM_GPIO_PAD_CONFIG_7_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_7_MEM_GPIO_PAD_CONFIG_7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_8 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_8_MEM_GPIO_PAD_CONFIG_8_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_8_MEM_GPIO_PAD_CONFIG_8_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_9 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_9_MEM_GPIO_PAD_CONFIG_9_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_9_MEM_GPIO_PAD_CONFIG_9_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_10 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_10_MEM_GPIO_PAD_CONFIG_10_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_10_MEM_GPIO_PAD_CONFIG_10_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_11 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_11_MEM_GPIO_PAD_CONFIG_11_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_11_MEM_GPIO_PAD_CONFIG_11_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_12 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_12_MEM_GPIO_PAD_CONFIG_12_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_12_MEM_GPIO_PAD_CONFIG_12_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_13 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_13_MEM_GPIO_PAD_CONFIG_13_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_13_MEM_GPIO_PAD_CONFIG_13_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_14 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_14_MEM_GPIO_PAD_CONFIG_14_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_14_MEM_GPIO_PAD_CONFIG_14_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_15 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_15_MEM_GPIO_PAD_CONFIG_15_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_15_MEM_GPIO_PAD_CONFIG_15_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_16 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_16_MEM_GPIO_PAD_CONFIG_16_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_16_MEM_GPIO_PAD_CONFIG_16_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_17 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_17_MEM_GPIO_PAD_CONFIG_17_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_17_MEM_GPIO_PAD_CONFIG_17_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_18 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_18_MEM_GPIO_PAD_CONFIG_18_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_18_MEM_GPIO_PAD_CONFIG_18_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_19 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_19_MEM_GPIO_PAD_CONFIG_19_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_19_MEM_GPIO_PAD_CONFIG_19_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_20 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_20_MEM_GPIO_PAD_CONFIG_20_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_20_MEM_GPIO_PAD_CONFIG_20_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_21 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_21_MEM_GPIO_PAD_CONFIG_21_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_21_MEM_GPIO_PAD_CONFIG_21_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_22 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_22_MEM_GPIO_PAD_CONFIG_22_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_22_MEM_GPIO_PAD_CONFIG_22_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_23 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_23_MEM_GPIO_PAD_CONFIG_23_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_23_MEM_GPIO_PAD_CONFIG_23_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_24 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_24_MEM_GPIO_PAD_CONFIG_24_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_24_MEM_GPIO_PAD_CONFIG_24_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_25 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_25_MEM_GPIO_PAD_CONFIG_25_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_25_MEM_GPIO_PAD_CONFIG_25_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_26 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_26_MEM_GPIO_PAD_CONFIG_26_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_26_MEM_GPIO_PAD_CONFIG_26_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_27 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_27_MEM_GPIO_PAD_CONFIG_27_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_27_MEM_GPIO_PAD_CONFIG_27_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_28 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_28_MEM_GPIO_PAD_CONFIG_28_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_28_MEM_GPIO_PAD_CONFIG_28_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_29 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_29_MEM_GPIO_PAD_CONFIG_29_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_29_MEM_GPIO_PAD_CONFIG_29_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_30 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_30_MEM_GPIO_PAD_CONFIG_30_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_30_MEM_GPIO_PAD_CONFIG_30_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_31 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_31_MEM_GPIO_PAD_CONFIG_31_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_31_MEM_GPIO_PAD_CONFIG_31_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_32 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_32_MEM_GPIO_PAD_CONFIG_32_M \ + 0x00000FFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." it can be used + // for I2C type of peripherals. 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_32_MEM_GPIO_PAD_CONFIG_32_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_33 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_33_MEM_GPIO_PAD_CONFIG_33_M \ + 0x0000003F // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 5 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. IODEN and I8MAEN + // is diesabled for all development + // IO's. These signals are tied to + // logic level '0'. common control + // is implemented for I2MAEN, + // I4MAEN, WKPU, WKPD control . + // refer dev_pad_cmn_config register + // bits. + +#define OCP_SHARED_GPIO_PAD_CONFIG_33_MEM_GPIO_PAD_CONFIG_33_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_34 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_34_MEM_GPIO_PAD_CONFIG_34_M \ + 0x0000003F // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 5 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. IODEN and I8MAEN + // is diesabled for all development + // IO's. These signals are tied to + // logic level '0'. common control + // is implemented for I2MAEN, + // I4MAEN, WKPU, WKPD control . + // refer dev_pad_cmn_config register + // bits. + +#define OCP_SHARED_GPIO_PAD_CONFIG_34_MEM_GPIO_PAD_CONFIG_34_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_35 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_35_MEM_GPIO_PAD_CONFIG_35_M \ + 0x0000003F // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 5 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. IODEN and I8MAEN + // is diesabled for all development + // IO's. These signals are tied to + // logic level '0'. common control + // is implemented for I2MAEN, + // I4MAEN, WKPU, WKPD control . + // refer dev_pad_cmn_config register + // bits. + +#define OCP_SHARED_GPIO_PAD_CONFIG_35_MEM_GPIO_PAD_CONFIG_35_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_36 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_36_MEM_GPIO_PAD_CONFIG_36_M \ + 0x0000003F // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 5 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. IODEN and I8MAEN + // is diesabled for all development + // IO's. These signals are tied to + // logic level '0'. common control + // is implemented for I2MAEN, + // I4MAEN, WKPU, WKPD control . + // refer dev_pad_cmn_config register + // bits. + +#define OCP_SHARED_GPIO_PAD_CONFIG_36_MEM_GPIO_PAD_CONFIG_36_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_37 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_37_MEM_GPIO_PAD_CONFIG_37_M \ + 0x0000003F // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 5 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. IODEN and I8MAEN + // is diesabled for all development + // IO's. These signals are tied to + // logic level '0'. common control + // is implemented for I2MAEN, + // I4MAEN, WKPU, WKPD control . + // refer dev_pad_cmn_config register + // bits. + +#define OCP_SHARED_GPIO_PAD_CONFIG_37_MEM_GPIO_PAD_CONFIG_37_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_38 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_38_MEM_GPIO_PAD_CONFIG_38_M \ + 0x0000003F // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 5 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. IODEN and I8MAEN + // is diesabled for all development + // IO's. These signals are tied to + // logic level '0'. common control + // is implemented for I2MAEN, + // I4MAEN, WKPU, WKPD control . + // refer dev_pad_cmn_config register + // bits. + +#define OCP_SHARED_GPIO_PAD_CONFIG_38_MEM_GPIO_PAD_CONFIG_38_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_39 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_39_MEM_GPIO_PAD_CONFIG_39_M \ + 0x0000003F // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 5 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. IODEN and I8MAEN + // is diesabled for all development + // IO's. These signals are tied to + // logic level '0'. common control + // is implemented for I2MAEN, + // I4MAEN, WKPU, WKPD control . + // refer dev_pad_cmn_config register + // bits. + +#define OCP_SHARED_GPIO_PAD_CONFIG_39_MEM_GPIO_PAD_CONFIG_39_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CONFIG_40 register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CONFIG_40_MEM_GPIO_PAD_CONFIG_40_M \ + 0x0007FFFF // GPIO 0 register: "Bit 0 - 3 is + // used for PAD IO mode selection. + // io_register={ "" 0 => + // """"CONFMODE[0]"""""" "" 1 => + // """"CONFMODE[1]"""""" "" 2 => + // """"CONFMODE[2]"""""" "" 3 => + // """"CONFMODE[3]"""" 4 => + // """"IODEN"""" --> When level ‘1’ + // this disables the PMOS xtors of + // the output stages making them + // open-drain type." "For example in + // case of I2C Value gets latched at + // rising edge of RET33.""" """ 5 => + // """"I2MAEN"""" --> Level ‘1’ + // enables the approx 2mA output + // stage""" """ 6 => """"I4MAEN"""" + // --> Level ‘1’ enables the approx + // 4mA output stage""" """ 7 => + // """"I8MAEN"""" --> Level ‘1’ + // enables the approx 8mA output + // stage. Note: any drive strength + // between 2mA and 14mA can be + // obtained with combination of 2mA + // 4mA and 8mA.""" """ 8 => + // """"IWKPUEN"""" --> 10uA pull up + // (weak strength)""" """ 9 => + // """"IWKPDEN"""" --> 10uA pull + // down (weak strength)""" """ 10 => + // """"IOE_N"""" --> output enable + // value. level ‘0’ enables the IDO + // to PAD path. Else PAD is + // tristated (except for the PU/PD + // which are independent)." "Value + // gets latched at rising edge of + // RET33""" """ 11 =>"""" + // IOE_N_OV"""" --> output enable + // overirde. when bit is set to + // logic '1' IOE_N (bit 4) value + // will control IO IOE_N signal else + // IOE_N is control via selected HW + // logic. strong PULL UP and PULL + // Down control is disabled for all + // IO's. both controls are tied to + // logic level '0'. + +#define OCP_SHARED_GPIO_PAD_CONFIG_40_MEM_GPIO_PAD_CONFIG_40_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_GPIO_PAD_CMN_CONFIG register. +// +//****************************************************************************** +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_D2D_ISO_A_EN \ + 0x00000080 // when '1' enable ISO A control to + // D2D Pads else ISO is disabled. + // For these PADS to be functional + // this signals should be set 0. + +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_D2D_ISO_Y_EN \ + 0x00000040 // when '1' enable ISO Y control to + // D2D Pads else ISO is disabled. + // For these PADS to be functional + // this signals should be set 0. + +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_JTAG_IDIEN \ + 0x00000020 // If level ‘1’ enables the PAD to + // ODI path for JTAG PADS [PAD 23, + // 24, 28, 29]. Else ODI is pulled + // ‘Low’ regardless of PAD level." + // "Value gets latched at rising + // edge of RET33.""" """ + +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_HYSTVAL_M \ + 0x00000018 // 00’: hysteriris = 10% of VDDS + // (difference between upper and + // lower threshold of the schmit + // trigger) ‘01’: hysteriris = 20% + // of VDDS (difference between upper + // and lower threshold of the schmit + // trigger) ‘10’: hysteriris = 30% + // of VDDS (difference between upper + // and lower threshold of the schmit + // trigger) ‘11’: hysteriris = 40% + // of VDDS (difference between upper + // and lower threshold of the schmit + // trigger)" """ + +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_HYSTVAL_S 3 +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_HYSTEN \ + 0x00000004 // If logic ‘0’ there is no + // hysteresis. Set to ‘1’ to enable + // hysteresis. Leave the choice to + // customers""" + +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_IBIASEN \ + 0x00000002 // Normal functional operation set + // this to logic ‘1’ to increase the + // speed of the o/p buffer at the + // cost of 0.2uA static current + // consumption per IO. During IDDQ + // test and during Hibernate this + // would be forced to logic ‘0’. + // Value is not latched at rising + // edge of RET33."" + +#define OCP_SHARED_GPIO_PAD_CMN_CONFIG_MEM_PAD_IDIEN \ + 0x00000001 // If level ‘1’ enables the PAD to + // ODI path. Else ODI is pulled + // ‘Low’ regardless of PAD level." + // "Value gets latched at rising + // edge of RET33.""" """ + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_D2D_DEV_PAD_CMN_CONFIG register. +// +//****************************************************************************** +#define OCP_SHARED_D2D_DEV_PAD_CMN_CONFIG_MEM_DEV_PAD_CMN_CONF_M \ + 0x0000003F // this register implements common + // IO control to all devement mode + // PADs; these PADs are DEV_PAD33 to + // DEV_PAD39. Bit [1:0] : Drive + // strength control. These 2 bits + // are connected to DEV PAD drive + // strength control. possible drive + // stregnths are 2MA, 4MA and 6 MA + // for the these IO's. bit 0: when + // set to logic value '1' enable 2MA + // drive strength for DEVPAD01 to 07 + // bit 1: when set to logic value + // '1' enable 4MA drive strength for + // DEVPAD01 to 07. bit[3:2] : WK + // PULL UP and PULL down control. + // These 2 bits provide IWKPUEN and + // IWKPDEN control for all DEV IO's. + // bit 2: when set to logic value + // '1' enable WKPU to DEVPAD01 to 07 + // bit 3: when set to logic value + // '1' enable WKPD to DEVPAD01 to + // 07. bit 4: WK PULL control for + // DEV_PKG_DETECT pin. when '1' + // pullup enabled else it is + // disable. bit 5: when set to logic + // value '1' enable 8MA drive + // strength for DEVPAD01 to 07. + +#define OCP_SHARED_D2D_DEV_PAD_CMN_CONFIG_MEM_DEV_PAD_CMN_CONF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_D2D_TOSTACK_PAD_CONF register. +// +//****************************************************************************** +#define OCP_SHARED_D2D_TOSTACK_PAD_CONF_MEM_D2D_TOSTACK_PAD_CONF_M \ + 0x1FFFFFFF // OEN/OEN2X control. When 0 : Act + // as input buffer else output + // buffer with drive strength 2. + // this register control OEN2X pin + // of D2D TOSTACK PAD: OEN1X and + // OEN2X decoding is as follows: + // "when ""00"" :" "when ""01"" : + // dirve strength is '1' and output + // buffer enabled." "when ""10"" : + // drive strength is 2 and output + // buffer is disabled." "when ""11"" + // : dirve strength is '3' and + // output buffer enabled." + +#define OCP_SHARED_D2D_TOSTACK_PAD_CONF_MEM_D2D_TOSTACK_PAD_CONF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_D2D_MISC_PAD_CONF register. +// +//****************************************************************************** +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_POR_RESET_N \ + 0x00000200 // This register provide OEN2X + // control to D2D PADS OEN/OEN2X + // control. When 0 : Act as input + // buffer else output buffer with + // drive strength 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_RESET_N \ + 0x00000100 // OEN/OEN2X control. When 0 : Act + // as input buffer else output + // buffer with drive strength 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_HCLK \ + 0x00000080 // OEN/OEN2X control. When 0 : Act + // as input buffer else output + // buffer with drive strength 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_JTAG_TCK \ + 0x00000040 // OEN/OEN2X control. When 0 : Act + // as input buffer else output + // buffer with drive strength 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_JTAG_TMS \ + 0x00000020 // OEN/OEN2X control. When 0 : Act + // as input buffer else output + // buffer with drive strength 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_JTAG_TDI \ + 0x00000010 // OEN/OEN2X control. When 0 : Act + // as input buffer else output + // buffer with drive strength 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_PIOSC \ + 0x00000008 // OEN/OEN2X control. When 0 : Act + // as input buffer else output + // buffer with drive strength 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_SPARE_M \ + 0x00000007 // D2D SPARE PAD OEN/OEN2X control. + // When 0: Act as input buffer else + // output buffer with drive strength + // 2. + +#define OCP_SHARED_D2D_MISC_PAD_CONF_MEM_D2D_SPARE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SOP_CONF_OVERRIDE register. +// +//****************************************************************************** +#define OCP_SHARED_SOP_CONF_OVERRIDE_MEM_SOP_CONF_OVERRIDE \ + 0x00000001 // when '1' : signal will ovberride + // SoP setting of JTAG PADS. when + // '0': SoP setting will control + // JTAG PADs [ TDI, TDO, TMS, TCK] + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_DEBUGSS_STATUS register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_DEBUGSS_STATUS_APPS_MCU_JTAGNSW \ + 0x00000020 // This register contains debug + // subsystem status bits From APPS + // MCU status bit to indicates + // whether serial wire or 4 pins + // jtag select. + +#define OCP_SHARED_CC3XX_DEBUGSS_STATUS_CJTAG_BYPASS_STATUS \ + 0x00000010 // cjtag bypass bit select + +#define OCP_SHARED_CC3XX_DEBUGSS_STATUS_SW_INTERFACE_SEL_STATUS \ + 0x00000008 // serial wire interface bit select + +#define OCP_SHARED_CC3XX_DEBUGSS_STATUS_APPS_TAP_ENABLE_STATUS \ + 0x00000004 // apps tap enable status + +#define OCP_SHARED_CC3XX_DEBUGSS_STATUS_TAPS_ENABLE_STATUS \ + 0x00000002 // tap enable status + +#define OCP_SHARED_CC3XX_DEBUGSS_STATUS_SSBD_UNLOCK \ + 0x00000001 // ssbd unlock status + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_DEBUGMUX_SEL register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_DEBUGMUX_SEL_MEM_CC3XX_DEBUGMUX_SEL_M \ + 0x0000FFFF // debug mux select register. Upper + // 8 bits are used for debug module + // selection. Lower 8 bit [7:0] used + // inside debug module for selecting + // module specific signals. + // Bits[15:8: when set x"00" : GPRCM + // debug bus. When "o1" : SDIO debug + // debug bus when x"02" : + // autonoumous SPI when x"03" : + // TOPIC when x"04": memss when + // x"25": mcu debug bus : APPS debug + // when x"45": mcu debug bus : NWP + // debug when x"65": mcu debug bus : + // AHB2VBUS debug when x"85": mcu + // debug bus : VBUS2HAB debug when + // x"95": mcu debug bus : RCM debug + // when x"A5": mcu debug bus : + // crypto debug when x"06": WLAN + // debug bus when x"07": debugss bus + // when x"08": ADC debug when x"09": + // SDIO PHY debug bus then "others" + // : no debug is selected + +#define OCP_SHARED_CC3XX_DEBUGMUX_SEL_MEM_CC3XX_DEBUGMUX_SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_ALT_PC_VAL_NW register. +// +//****************************************************************************** +#define OCP_SHARED_ALT_PC_VAL_NW_MEM_ALT_PC_VAL_NW_M \ + 0xFFFFFFFF // 32 bit. Program counter value + // for 0x4 address when Alt_pc_en_nw + // is set. + +#define OCP_SHARED_ALT_PC_VAL_NW_MEM_ALT_PC_VAL_NW_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_ALT_PC_VAL_APPS register. +// +//****************************************************************************** +#define OCP_SHARED_ALT_PC_VAL_APPS_MEM_ALT_PC_VAL_APPS_M \ + 0xFFFFFFFF // 32 bit. Program counter value + // for 0x4 address when + // Alt_pc_en_apps is set + +#define OCP_SHARED_ALT_PC_VAL_APPS_MEM_ALT_PC_VAL_APPS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_4 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_4_MEM_SPARE_REG_4_M \ + 0xFFFFFFFE // HW register + +#define OCP_SHARED_SPARE_REG_4_MEM_SPARE_REG_4_S 1 +#define OCP_SHARED_SPARE_REG_4_INVERT_D2D_INTERFACE \ + 0x00000001 // Data to the top die launched at + // negative edge instead of positive + // edge. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_5 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_5_MEM_SPARE_REG_5_M \ + 0xFFFFFFFF // HW register + +#define OCP_SHARED_SPARE_REG_5_MEM_SPARE_REG_5_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SH_SPI_CS_MASK register. +// +//****************************************************************************** +#define OCP_SHARED_SH_SPI_CS_MASK_MEM_SH_SPI_CS_MASK_M \ + 0x0000000F // ( chip select 0 is unmasked + // after reset. When ‘1’ : CS is + // unmasked or else masked. Valid + // configurations are 1000, 0100, + // 0010 or 0001. Any other setting + // can lead to unpredictable + // behavior. + +#define OCP_SHARED_SH_SPI_CS_MASK_MEM_SH_SPI_CS_MASK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_DEVICE_TYPE register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_reserved_M \ + 0x00000060 // reserved bits tied off "00". + +#define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_reserved_S 5 +#define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_M \ + 0x0000001F // CC3XX Device type information. + +#define OCP_SHARED_CC3XX_DEVICE_TYPE_DEVICE_TYPE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_MEM_TOPMUXCTRL_IFORCE register. +// +//****************************************************************************** +#define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE1_M \ + 0x000000F0 // [4] 1: switch between + // WLAN_I2C_SCL and + // TOP_GPIO_PORT4_I2C closes 0: + // switch opens [5] 1: switch + // between WLAN_I2C_SCL and + // TOP_VSENSE_PORT closes 0: switch + // opens [6] 1: switch between + // WLAN_I2C_SCL and WLAN_ANA_TP4 + // closes 0: switch opens [7] + // Reserved + +#define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE1_S 4 +#define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE_M \ + 0x0000000F // [0] 1: switch between + // WLAN_I2C_SDA and + // TOP_GPIO_PORT3_I2C closes 0: + // switch opens [1] 1: switch + // between WLAN_I2C_SDA and + // TOP_IFORCE_PORT closes 0: switch + // opens [2] 1: switch between + // WLAN_I2C_SDA and WLAN_ANA_TP3 + // closes 0: switch opens [3] + // Reserved + +#define OCP_SHARED_MEM_TOPMUXCTRL_IFORCE_MEM_TOPMUXCTRL_IFORCE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_DEV_PACKAGE_DETECT register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_DEV_PACKAGE_DETECT_DEV_PKG_DETECT \ + 0x00000001 // when '0' indicates package type + // is development. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_AUTONMS_SPICLK_SEL register. +// +//****************************************************************************** +#define OCP_SHARED_AUTONMS_SPICLK_SEL_MEM_AUTONOMOUS_BYPASS \ + 0x00000002 // This bit is used to bypass MCPSI + // autonomous mode .if this bit is 1 + // autonomous MCSPI logic will be + // bypassed and it will act as link + // SPI + +#define OCP_SHARED_AUTONMS_SPICLK_SEL_MEM_AUTONMS_SPICLK_SEL \ + 0x00000001 // This bit is used in SPI + // Autonomous mode to switch clock + // from system clock to SPI clk that + // is coming from PAD. When value 1 + // PAD SPI clk is used as system + // clock in LPDS mode by SPI as well + // as autonomous wrapper logic. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_CC3XX_DEV_PADCONF register. +// +//****************************************************************************** +#define OCP_SHARED_CC3XX_DEV_PADCONF_MEM_CC3XX_DEV_PADCONF_M \ + 0x0000FFFF + +#define OCP_SHARED_CC3XX_DEV_PADCONF_MEM_CC3XX_DEV_PADCONF_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_IDMEM_TIM_UPDATE register. +// +//****************************************************************************** +#define OCP_SHARED_IDMEM_TIM_UPDATE_MEM_IDMEM_TIM_UPDATE_M \ + 0xFFFFFFFF + +#define OCP_SHARED_IDMEM_TIM_UPDATE_MEM_IDMEM_TIM_UPDATE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_6 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_6_MEM_SPARE_REG_6_M \ + 0xFFFFFFFF // NWP Software register + +#define OCP_SHARED_SPARE_REG_6_MEM_SPARE_REG_6_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_SPARE_REG_7 register. +// +//****************************************************************************** +#define OCP_SHARED_SPARE_REG_7_MEM_SPARE_REG_7_M \ + 0xFFFFFFFF // NWP Software register + +#define OCP_SHARED_SPARE_REG_7_MEM_SPARE_REG_7_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_APPS_WLAN_ORBIT register. +// +//****************************************************************************** +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_spare_M \ + 0xFFFFFC00 // Spare bit + +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_spare_S 10 +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_status \ + 0x00000200 // A rising edge on this bit + // indicates that the test case + // passes. This bit would be brought + // out on the pin interface during + // ORBIT. + +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_exec \ + 0x00000100 // This register bit is writable by + // the FW and when set to 1 it + // indicates the start of a test + // execution. A failing edge on this + // bit indicates that the test + // execution is complete. This bit + // would be brought out on the pin + // interface during ORBIT. + +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_id_M \ + 0x000000FC // Implies the test case ID that + // needs to run. + +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_id_S 2 +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_halt_proc \ + 0x00000002 // This bit is used to trigger the + // execution of test cases within + // the (ROM based) IP. + +#define OCP_SHARED_APPS_WLAN_ORBIT_mem_orbit_test_mode \ + 0x00000001 // When this bit is 1 it implies + // ORBIT mode of operation and the + // (ROM based) IP start the + // execution from a test case + // perspective + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// OCP_SHARED_O_APPS_WLAN_SCRATCH_PAD register. +// +//****************************************************************************** +#define OCP_SHARED_APPS_WLAN_SCRATCH_PAD_MEM_APPS_WLAN_SCRATCH_PAD_M \ + 0xFFFFFFFF // scratch pad register. + +#define OCP_SHARED_APPS_WLAN_SCRATCH_PAD_MEM_APPS_WLAN_SCRATCH_PAD_S 0 + + + +#endif // __HW_OCP_SHARED_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_shamd5.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_shamd5.h new file mode 100644 index 00000000..cf6254f5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_shamd5.h @@ -0,0 +1,1242 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_SHAMD5_H__ +#define __HW_SHAMD5_H__ + +//***************************************************************************** +// +// The following are defines for the SHAMD5_P register offsets. +// +//***************************************************************************** +#define SHAMD5_O_ODIGEST_A 0x00000000 // WRITE: Outer Digest [127:96] for + // MD5 [159:128] for SHA-1 [255:224] + // for SHA-2 / HMAC Key [31:0] for + // HMAC key proc READ: Outer Digest + // [127:96] for MD5 [159:128] for + // SHA-1 [255:224] for SHA-2 +#define SHAMD5_O_ODIGEST_B 0x00000004 // WRITE: Outer Digest [95:64] for + // MD5 [127:96] for SHA-1 [223:192] + // for SHA-2 / HMAC Key [63:32] for + // HMAC key proc READ: Outer Digest + // [95:64] for MD5 [127:96] for + // SHA-1 [223:192] for SHA-2 +#define SHAMD5_O_ODIGEST_C 0x00000008 // WRITE: Outer Digest [63:32] for + // MD5 [95:64] for SHA-1 [191:160] + // for SHA-2 / HMAC Key [95:64] for + // HMAC key proc READ: Outer Digest + // [63:32] for MD5 [95:64] for SHA-1 + // [191:160] for SHA-2 +#define SHAMD5_O_ODIGEST_D 0x0000000C // WRITE: Outer Digest [31:0] for + // MD5 [63:31] for SHA-1 [159:128] + // for SHA-2 / HMAC Key [127:96] for + // HMAC key proc READ: Outer Digest + // [31:0] for MD5 [63:32] for SHA-1 + // [159:128] for SHA-2 +#define SHAMD5_O_ODIGEST_E 0x00000010 // WRITE: Outer Digest [31:0] for + // SHA-1 [127:96] for SHA-2 / HMAC + // Key [159:128] for HMAC key proc + // READ: Outer Digest [31:0] for + // SHA-1 [127:96] for SHA-2 +#define SHAMD5_O_ODIGEST_F 0x00000014 // WRITE: Outer Digest [95:64] for + // SHA-2 / HMAC Key [191:160] for + // HMAC key proc READ: Outer Digest + // [95:64] for SHA-2 +#define SHAMD5_O_ODIGEST_G 0x00000018 // WRITE: Outer Digest [63:32] for + // SHA-2 / HMAC Key [223:192] for + // HMAC key proc READ: Outer Digest + // [63:32] for SHA-2 +#define SHAMD5_O_ODIGEST_H 0x0000001C // WRITE: Outer Digest [31:0] for + // SHA-2 / HMAC Key [255:224] for + // HMAC key proc READ: Outer Digest + // [31:0] for SHA-2 +#define SHAMD5_O_IDIGEST_A 0x00000020 // WRITE: Inner / Initial Digest + // [127:96] for MD5 [159:128] for + // SHA-1 [255:224] for SHA-2 / HMAC + // Key [287:256] for HMAC key proc + // READ: Intermediate / Inner Digest + // [127:96] for MD5 [159:128] for + // SHA-1 [255:224] for SHA-2 / + // Result Digest/MAC [127:96] for + // MD5 [159:128] for SHA-1 [223:192] + // for SHA-2 224 [255:224] for SHA-2 + // 256 +#define SHAMD5_O_IDIGEST_B 0x00000024 // WRITE: Inner / Initial Digest + // [95:64] for MD5 [127:96] for + // SHA-1 [223:192] for SHA-2 / HMAC + // Key [319:288] for HMAC key proc + // READ: Intermediate / Inner Digest + // [95:64] for MD5 [127:96] for + // SHA-1 [223:192] for SHA-2 / + // Result Digest/MAC [95:64] for MD5 + // [127:96] for SHA-1 [191:160] for + // SHA-2 224 [223:192] for SHA-2 256 +#define SHAMD5_O_IDIGEST_C 0x00000028 // WRITE: Inner / Initial Digest + // [63:32] for MD5 [95:64] for SHA-1 + // [191:160] for SHA- 2 / HMAC Key + // [351:320] for HMAC key proc READ: + // Intermediate / Inner Digest + // [63:32] for MD5 [95:64] for SHA-1 + // [191:160] for SHA-2 / Result + // Digest/MAC [63:32] for MD5 + // [95:64] for SHA-1 [159:128] for + // SHA-2 224 [191:160] for SHA-2 256 +#define SHAMD5_O_IDIGEST_D 0x0000002C // WRITE: Inner / Initial Digest + // [31:0] for MD5 [63:32] for SHA-1 + // [159:128] for SHA-2 / HMAC Key + // [383:352] for HMAC key proc READ: + // Intermediate / Inner Digest + // [31:0] for MD5 [63:32] for SHA-1 + // [159:128] for SHA-2 / Result + // Digest/MAC [31:0] for MD5 [63:32] + // for SHA-1 [127:96] for SHA-2 224 + // [159:128] for SHA-2 256 +#define SHAMD5_O_IDIGEST_E 0x00000030 // WRITE: Inner / Initial Digest + // [31:0] for SHA-1 [127:96] for + // SHA-2 / HMAC Key [415:384] for + // HMAC key proc READ: Intermediate + // / Inner Digest [31:0] for SHA-1 + // [127:96] for SHA-2 / Result + // Digest/MAC [31:0] for SHA-1 + // [95:64] for SHA-2 224 [127:96] + // for SHA-2 256 +#define SHAMD5_O_IDIGEST_F 0x00000034 // WRITE: Inner / Initial Digest + // [95:64] for SHA-2 / HMAC Key + // [447:416] for HMAC key proc READ: + // Intermediate / Inner Digest + // [95:64] for SHA-2 / Result + // Digest/MAC [63:32] for SHA-2 224 + // [95:64] for SHA-2 256 +#define SHAMD5_O_IDIGEST_G 0x00000038 // WRITE: Inner / Initial Digest + // [63:32] for SHA-2 / HMAC Key + // [479:448] for HMAC key proc READ: + // Intermediate / Inner Digest + // [63:32] for SHA-2 / Result + // Digest/MAC [31:0] for SHA-2 224 + // [63:32] for SHA-2 256 +#define SHAMD5_O_IDIGEST_H 0x0000003C // WRITE: Inner / Initial Digest + // [31:0] for SHA-2 / HMAC Key + // [511:480] for HMAC key proc READ: + // Intermediate / Inner Digest + // [31:0] for SHA-2 / Result + // Digest/MAC [31:0] for SHA-2 256 +#define SHAMD5_O_DIGEST_COUNT 0x00000040 // WRITE: Initial Digest Count + // ([31:6] only [5:0] assumed 0) + // READ: Result / IntermediateDigest + // Count The initial digest byte + // count for hash/HMAC continue + // operations (HMAC Key Processing = + // 0 and Use Algorithm Constants = + // 0) on the Secure World must be + // written to this register prior to + // starting the operation by writing + // to S_HASH_MODE. When either HMAC + // Key Processing is 1 or Use + // Algorithm Constants is 1 this + // register does not need to be + // written it will be overwritten + // with 64 (1 hash block of key XOR + // ipad) or 0 respectively + // automatically. When starting a + // HMAC operation from pre-computes + // (HMAC Key Processing is 0) then + // the value 64 must be written here + // to compensate for the appended + // key XOR ipad block. Note that the + // value written should always be a + // 64 byte multiple the lower 6 bits + // written are ignored. The updated + // digest byte count (initial digest + // byte count + bytes processed) can + // be read from this register when + // the status register indicates + // that the operation is done or + // suspended due to a context switch + // request or when a Secure World + // context out DMA is requested. In + // Advanced DMA mode when not + // suspended with a partial result + // reading the SHAMD5_DIGEST_COUNT + // register triggers the Hash/HMAC + // Engine to start the next context + // input DMA. Therefore reading the + // SHAMD5_DIGEST_COUNT register + // should always be the last + // context-read action if not + // suspended with a partial result + // (i.e. PartHashReady interrupt not + // pending). +#define SHAMD5_O_MODE 0x00000044 // Register SHAMD5_MODE +#define SHAMD5_O_LENGTH 0x00000048 // WRITE: Block Length / Remaining + // Byte Count (bytes) READ: + // Remaining Byte Count. The value + // programmed MUST be a 64-byte + // multiple if Close Hash is set to + // 0. This register is also the + // trigger to start processing: once + // this register is written the core + // will commence requesting input + // data via DMA or IRQ (if + // programmed length > 0) and start + // processing. The remaining byte + // count for the active operation + // can be read from this register + // when the interrupt status + // register indicates that the + // operation is suspended due to a + // context switch request. +#define SHAMD5_O_DATA0_IN 0x00000080 // Data input message 0 +#define SHAMD5_O_DATA1_IN 0x00000084 // Data input message 1 +#define SHAMD5_O_DATA2_IN 0x00000088 // Data input message 2 +#define SHAMD5_O_DATA3_IN 0x0000008C // Data input message 3 +#define SHAMD5_O_DATA4_IN 0x00000090 // Data input message 4 +#define SHAMD5_O_DATA5_IN 0x00000094 // Data input message 5 +#define SHAMD5_O_DATA6_IN 0x00000098 // Data input message 6 +#define SHAMD5_O_DATA7_IN 0x0000009C // Data input message 7 +#define SHAMD5_O_DATA8_IN 0x000000A0 // Data input message 8 +#define SHAMD5_O_DATA9_IN 0x000000A4 // Data input message 9 +#define SHAMD5_O_DATA10_IN 0x000000A8 // Data input message 10 +#define SHAMD5_O_DATA11_IN 0x000000AC // Data input message 11 +#define SHAMD5_O_DATA12_IN 0x000000B0 // Data input message 12 +#define SHAMD5_O_DATA13_IN 0x000000B4 // Data input message 13 +#define SHAMD5_O_DATA14_IN 0x000000B8 // Data input message 14 +#define SHAMD5_O_DATA15_IN 0x000000BC // Data input message 15 +#define SHAMD5_O_REVISION 0x00000100 // Register SHAMD5_REV +#define SHAMD5_O_SYSCONFIG 0x00000110 // Register SHAMD5_SYSCONFIG +#define SHAMD5_O_SYSSTATUS 0x00000114 // Register SHAMD5_SYSSTATUS +#define SHAMD5_O_IRQSTATUS 0x00000118 // Register SHAMD5_IRQSTATUS +#define SHAMD5_O_IRQENABLE 0x0000011C // Register SHAMD5_IRQENABLE. The + // SHAMD5_IRQENABLE register contains + // an enable bit for each unique + // interrupt for the public side. An + // interrupt is enabled when both + // the global enable in + // SHAMD5_SYSCONFIG (PIT_en) and the + // bit in this register are both set + // to 1. An interrupt that is + // enabled is propagated to the + // SINTREQUEST_P output. Please note + // that the dedicated partial hash + // output (SINTREQUEST_PART_P) is + // not affected by this register it + // is only affected by the global + // enable SHAMD5_SYSCONFIG (PIT_en). +#define SHAMD5_O_HASH512_ODIGEST_A \ + 0x00000200 + +#define SHAMD5_O_HASH512_ODIGEST_B \ + 0x00000204 + +#define SHAMD5_O_HASH512_ODIGEST_C \ + 0x00000208 + +#define SHAMD5_O_HASH512_ODIGEST_D \ + 0x0000020C + +#define SHAMD5_O_HASH512_ODIGEST_E \ + 0x00000210 + +#define SHAMD5_O_HASH512_ODIGEST_F \ + 0x00000214 + +#define SHAMD5_O_HASH512_ODIGEST_G \ + 0x00000218 + +#define SHAMD5_O_HASH512_ODIGEST_H \ + 0x0000021C + +#define SHAMD5_O_HASH512_ODIGEST_I \ + 0x00000220 + +#define SHAMD5_O_HASH512_ODIGEST_J \ + 0x00000224 + +#define SHAMD5_O_HASH512_ODIGEST_K \ + 0x00000228 + +#define SHAMD5_O_HASH512_ODIGEST_L \ + 0x0000022C + +#define SHAMD5_O_HASH512_ODIGEST_M \ + 0x00000230 + +#define SHAMD5_O_HASH512_ODIGEST_N \ + 0x00000234 + +#define SHAMD5_O_HASH512_ODIGEST_O \ + 0x00000238 + +#define SHAMD5_O_HASH512_ODIGEST_P \ + 0x0000023C + +#define SHAMD5_O_HASH512_IDIGEST_A \ + 0x00000240 + +#define SHAMD5_O_HASH512_IDIGEST_B \ + 0x00000244 + +#define SHAMD5_O_HASH512_IDIGEST_C \ + 0x00000248 + +#define SHAMD5_O_HASH512_IDIGEST_D \ + 0x0000024C + +#define SHAMD5_O_HASH512_IDIGEST_E \ + 0x00000250 + +#define SHAMD5_O_HASH512_IDIGEST_F \ + 0x00000254 + +#define SHAMD5_O_HASH512_IDIGEST_G \ + 0x00000258 + +#define SHAMD5_O_HASH512_IDIGEST_H \ + 0x0000025C + +#define SHAMD5_O_HASH512_IDIGEST_I \ + 0x00000260 + +#define SHAMD5_O_HASH512_IDIGEST_J \ + 0x00000264 + +#define SHAMD5_O_HASH512_IDIGEST_K \ + 0x00000268 + +#define SHAMD5_O_HASH512_IDIGEST_L \ + 0x0000026C + +#define SHAMD5_O_HASH512_IDIGEST_M \ + 0x00000270 + +#define SHAMD5_O_HASH512_IDIGEST_N \ + 0x00000274 + +#define SHAMD5_O_HASH512_IDIGEST_O \ + 0x00000278 + +#define SHAMD5_O_HASH512_IDIGEST_P \ + 0x0000027C + +#define SHAMD5_O_HASH512_DIGEST_COUNT \ + 0x00000280 + +#define SHAMD5_O_HASH512_MODE 0x00000284 +#define SHAMD5_O_HASH512_LENGTH 0x00000288 + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_A register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_A_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_A_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_B register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_B_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_B_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_C register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_C_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_C_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_D register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_D_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_D_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_E register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_E_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_E_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_F register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_F_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_F_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_G register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_G_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_G_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_ODIGEST_H register. +// +//****************************************************************************** +#define SHAMD5_ODIGEST_H_DATA_M 0xFFFFFFFF // data +#define SHAMD5_ODIGEST_H_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_A register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_A_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_A_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_B register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_B_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_B_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_C register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_C_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_C_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_D register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_D_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_D_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_E register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_E_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_E_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_F register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_F_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_F_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_G register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_G_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_G_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IDIGEST_H register. +// +//****************************************************************************** +#define SHAMD5_IDIGEST_H_DATA_M 0xFFFFFFFF // data +#define SHAMD5_IDIGEST_H_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_DIGEST_COUNT register. +// +//****************************************************************************** +#define SHAMD5_DIGEST_COUNT_DATA_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DIGEST_COUNT_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_MODE register. +// +//****************************************************************************** +#define SHAMD5_MODE_HMAC_OUTER_HASH \ + 0x00000080 // The HMAC Outer Hash is performed + // on the hash digest when the inner + // hash hash finished (block length + // exhausted and final hash + // performed if close_hash is 1). + // This bit should normally be set + // together with close_hash to + // finish the inner hash first or + // Block Length should be zero (HMAC + // continue with the just outer hash + // to be done). Auto cleared + // internally when outer hash + // performed. 0 No operation 1 hmac + // processing + +#define SHAMD5_MODE_HMAC_KEY_PROC \ + 0x00000020 // Performs HMAC key processing on + // the 512 bit HMAC key loaded into + // the SHAMD5_IDIGEST_{A to H} and + // SHAMD5_ODIGEST_{A to H} register + // block. Once HMAC key processing + // is finished this bit is + // automatically cleared and the + // resulting Inner and Outer digest + // is available from + // SHAMD5_IDIGEST_{A to H} and + // SHAMD5_ODIGEST_{A to H} + // respectively after which regular + // hash processing (using + // SHAMD5_IDIGEST_{A to H} as initial + // digest) will commence until the + // Block Length is exhausted. 0 No + // operation. 1 Hmac processing. + +#define SHAMD5_MODE_CLOSE_HASH 0x00000010 // Performs the padding the + // hash/HMAC will be 'closed' at the + // end of the block as per + // MD5/SHA-1/SHA-2 specification + // (i.e. appropriate padding is + // added) or no padding is done + // allowing the hash to be continued + // later. However if the hash/HMAC + // is not closed then the Block + // Length MUST be a multiple of 64 + // bytes to ensure correct + // operation. Auto cleared + // internally when hash closed. 0 No + // padding hash computation can be + // contimued. 1 Last packet will be + // padded. +#define SHAMD5_MODE_ALGO_CONSTANT \ + 0x00000008 // The initial digest register will + // be overwritten with the algorithm + // constants for the selected + // algorithm when hashing and the + // initial digest count register + // will be reset to 0. This will + // start a normal hash operation. + // When continuing an existing hash + // or when performing an HMAC + // operation this register must be + // set to 0 and the + // intermediate/inner digest or HMAC + // key and digest count need to be + // written to the context input + // registers prior to writing + // SHAMD5_MODE. Auto cleared + // internally after first block + // processed. 0 Use pre-calculated + // digest (from an other operation) + // 1 Use constants of the selected + // algo. + +#define SHAMD5_MODE_ALGO_M 0x00000006 // These bits select the hash + // algorithm to be used for + // processing: 0x0 md5_128 algorithm + // 0x1 sha1_160 algorithm 0x2 + // sha2_224 algorithm 0x3 sha2_256 + // algorithm +#define SHAMD5_MODE_ALGO_S 1 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_LENGTH register. +// +//****************************************************************************** +#define SHAMD5_LENGTH_DATA_M 0xFFFFFFFF // data +#define SHAMD5_LENGTH_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA0_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA0_IN_DATA0_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA0_IN_DATA0_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA1_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA1_IN_DATA1_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA1_IN_DATA1_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA2_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA2_IN_DATA2_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA2_IN_DATA2_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA3_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA3_IN_DATA3_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA3_IN_DATA3_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA4_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA4_IN_DATA4_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA4_IN_DATA4_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA5_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA5_IN_DATA5_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA5_IN_DATA5_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA6_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA6_IN_DATA6_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA6_IN_DATA6_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA7_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA7_IN_DATA7_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA7_IN_DATA7_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA8_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA8_IN_DATA8_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA8_IN_DATA8_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA9_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA9_IN_DATA9_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA9_IN_DATA9_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA10_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA10_IN_DATA10_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA10_IN_DATA10_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA11_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA11_IN_DATA11_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA11_IN_DATA11_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA12_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA12_IN_DATA12_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA12_IN_DATA12_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA13_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA13_IN_DATA13_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA13_IN_DATA13_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA14_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA14_IN_DATA14_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA14_IN_DATA14_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_DATA15_IN register. +// +//****************************************************************************** +#define SHAMD5_DATA15_IN_DATA15_IN_M \ + 0xFFFFFFFF // data + +#define SHAMD5_DATA15_IN_DATA15_IN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_REVISION register. +// +//****************************************************************************** +#define SHAMD5_REVISION_SCHEME_M 0xC0000000 +#define SHAMD5_REVISION_SCHEME_S 30 +#define SHAMD5_REVISION_FUNC_M 0x0FFF0000 // Function indicates a software + // compatible module family. If + // there is no level of software + // compatibility a new Func number + // (and hence REVISION) should be + // assigned. +#define SHAMD5_REVISION_FUNC_S 16 +#define SHAMD5_REVISION_R_RTL_M 0x0000F800 // RTL Version (R) maintained by IP + // design owner. RTL follows a + // numbering such as X.Y.R.Z which + // are explained in this table. R + // changes ONLY when: (1) PDS + // uploads occur which may have been + // due to spec changes (2) Bug fixes + // occur (3) Resets to '0' when X or + // Y changes. Design team has an + // internal 'Z' (customer invisible) + // number which increments on every + // drop that happens due to DV and + // RTL updates. Z resets to 0 when R + // increments. +#define SHAMD5_REVISION_R_RTL_S 11 +#define SHAMD5_REVISION_X_MAJOR_M \ + 0x00000700 // Major Revision (X) maintained by + // IP specification owner. X changes + // ONLY when: (1) There is a major + // feature addition. An example + // would be adding Master Mode to + // Utopia Level2. The Func field (or + // Class/Type in old PID format) + // will remain the same. X does NOT + // change due to: (1) Bug fixes (2) + // Change in feature parameters. + +#define SHAMD5_REVISION_X_MAJOR_S 8 +#define SHAMD5_REVISION_CUSTOM_M 0x000000C0 +#define SHAMD5_REVISION_CUSTOM_S 6 +#define SHAMD5_REVISION_Y_MINOR_M \ + 0x0000003F // Minor Revision (Y) maintained by + // IP specification owner. Y changes + // ONLY when: (1) Features are + // scaled (up or down). Flexibility + // exists in that this feature + // scalability may either be + // represented in the Y change or a + // specific register in the IP that + // indicates which features are + // exactly available. (2) When + // feature creeps from Is-Not list + // to Is list. But this may not be + // the case once it sees silicon; in + // which case X will change. Y does + // NOT change due to: (1) Bug fixes + // (2) Typos or clarifications (3) + // major functional/feature + // change/addition/deletion. Instead + // these changes may be reflected + // via R S X as applicable. Spec + // owner maintains a + // customer-invisible number 'S' + // which changes due to: (1) + // Typos/clarifications (2) Bug + // documentation. Note that this bug + // is not due to a spec change but + // due to implementation. + // Nevertheless the spec tracks the + // IP bugs. An RTL release (say for + // silicon PG1.1) that occurs due to + // bug fix should document the + // corresponding spec number (X.Y.S) + // in its release notes. + +#define SHAMD5_REVISION_Y_MINOR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_SYSCONFIG register. +// +//****************************************************************************** +#define SHAMD5_SYSCONFIG_PADVANCED \ + 0x00000080 // If set to 1 Advanced mode is + // enabled for the Secure World. If + // set to 0 Legacy mode is enabled + // for the Secure World. + +#define SHAMD5_SYSCONFIG_PCONT_SWT \ + 0x00000040 // Finish all pending data and + // context DMA input requests (but + // will not assert any new requests) + // finish processing all data in the + // module and provide a saved + // context (partial hash result + // updated digest count remaining + // length updated mode information + // where applicable) for the last + // operation that was interrupted so + // that it can be resumed later. + +#define SHAMD5_SYSCONFIG_PDMA_EN 0x00000008 +#define SHAMD5_SYSCONFIG_PIT_EN 0x00000004 +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_SYSSTATUS register. +// +//****************************************************************************** +#define SHAMD5_SYSSTATUS_RESETDONE \ + 0x00000001 // data + +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IRQSTATUS register. +// +//****************************************************************************** +#define SHAMD5_IRQSTATUS_CONTEXT_READY \ + 0x00000008 // indicates that the secure side + // context input registers are + // available for a new context for + // the next packet to be processed. + +#define SHAMD5_IRQSTATUS_PARTHASH_READY \ + 0x00000004 // After a secure side context + // switch request this bit will read + // as 1 indicating that the saved + // context is available from the + // secure side context output + // registers. Note that if the + // context switch request coincides + // with a final hash (when hashing) + // or an outer hash (when doing + // HMAC) that PartHashReady will not + // become active but a regular + // Output Ready will occur instead + // (indicating that the result is + // final and therefore no + // continuation is required). + +#define SHAMD5_IRQSTATUS_INPUT_READY \ + 0x00000002 // indicates that the secure side + // data FIFO is ready to receive the + // next 64 byte data block. + +#define SHAMD5_IRQSTATUS_OUTPUT_READY \ + 0x00000001 // Indicates that a (partial) + // result or saved context is + // available from the secure side + // context output registers. + +//****************************************************************************** +// +// The following are defines for the bit fields in the SHAMD5_O_IRQENABLE register. +// +//****************************************************************************** +#define SHAMD5_IRQENABLE_M_CONTEXT_READY \ + 0x00000008 // mask for context ready + +#define SHAMD5_IRQENABLE_M_PARTHASH_READY \ + 0x00000004 // mask for partial hash + +#define SHAMD5_IRQENABLE_M_INPUT_READY \ + 0x00000002 // mask for input_ready + +#define SHAMD5_IRQENABLE_M_OUTPUT_READY \ + 0x00000001 // mask for output_ready + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_A register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_A_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_A_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_B register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_B_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_B_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_C register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_C_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_C_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_D register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_D_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_D_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_E register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_E_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_E_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_F register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_F_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_F_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_G register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_G_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_G_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_H register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_H_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_H_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_I register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_I_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_I_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_J register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_J_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_J_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_K register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_K_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_K_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_L register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_L_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_L_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_M register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_M_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_M_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_N register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_N_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_N_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_O register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_O_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_O_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_ODIGEST_P register. +// +//****************************************************************************** +#define SHAMD5_HASH512_ODIGEST_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_ODIGEST_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_A register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_A_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_A_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_B register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_B_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_B_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_C register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_C_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_C_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_D register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_D_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_D_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_E register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_E_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_E_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_F register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_F_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_F_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_G register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_G_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_G_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_H register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_H_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_H_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_I register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_I_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_I_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_J register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_J_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_J_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_K register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_K_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_K_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_L register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_L_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_L_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_M register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_M_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_M_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_N register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_N_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_N_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_O register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_O_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_O_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_IDIGEST_P register. +// +//****************************************************************************** +#define SHAMD5_HASH512_IDIGEST_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_IDIGEST_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_DIGEST_COUNT register. +// +//****************************************************************************** +#define SHAMD5_HASH512_DIGEST_COUNT_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_DIGEST_COUNT_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_MODE register. +// +//****************************************************************************** +#define SHAMD5_HASH512_MODE_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_MODE_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// SHAMD5_O_HASH512_LENGTH register. +// +//****************************************************************************** +#define SHAMD5_HASH512_LENGTH_DATA_M \ + 0xFFFFFFFF + +#define SHAMD5_HASH512_LENGTH_DATA_S 0 + + + +#endif // __HW_SHAMD5_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_stack_die_ctrl.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_stack_die_ctrl.h new file mode 100644 index 00000000..eba31e4f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_stack_die_ctrl.h @@ -0,0 +1,764 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + + +#ifndef __HW_STACK_DIE_CTRL_H__ +#define __HW_STACK_DIE_CTRL_H__ + +//***************************************************************************** +// +// The following are defines for the STACK_DIE_CTRL register offsets. +// +//***************************************************************************** +#define STACK_DIE_CTRL_O_STK_UP_RESET \ + 0x00000000 // Can be written only by Base + // Processor. Writing to this + // register will reset the stack + // processor reset will be + // de-asserted upon clearing this + // register. + +#define STACK_DIE_CTRL_O_SR_MASTER_PRIORITY \ + 0x00000004 // This register defines who among + // base processor and stack + // processor have highest priority + // for Sram Access. Can be written + // only by Base Processor. + +#define STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK2 \ + 0x00000008 // In Spinlock mode this Register + // defines who among base processor + // and stack processor have access + // to Sram Bank2 right now. In + // Handshake mode this Register + // defines who among base processor + // and stack processor have access + // to Sram Bank2 and Bank3 right + // now. Its Clear only register and + // is set by hardware. Lower bit can + // be cleared only by Base Processor + // and Upper bit Cleared only by the + // Stack processor. + +#define STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK2 \ + 0x0000000C // In Spinlock mode whenever Base + // processor wants the access to + // Sram Bank2 it should request for + // it by writing into this register. + // It'll get interrupt whenever it + // is granted. In Handshake mode + // this bit will be set by Stack + // processor. Its a set only bit and + // is cleared by HW when the request + // is granted. + +#define STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK2 \ + 0x00000010 // In Spinlock mode Whenever Stack + // processor wants the access to + // Sram Bank2 it should request for + // it by writing into this register. + // It'll get interrupt whenever it + // is granted. In Handshake mode + // this bit will be set by the Base + // processor. Its a set only bit and + // is cleared by HW when the request + // is granted. + +#define STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK3 \ + 0x00000014 // Register defines who among base + // processor and stack processor + // have access to Sram Bank3 right + // now. Its Clear only register and + // is set by hardware. Lower bit can + // be cleared only by Base Processor + // and Upper bit Cleared only by the + // Stack processor. + +#define STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK3 \ + 0x00000018 // In Spinlock mode whenever Base + // processor wants the access to + // Sram Bank3 it should request for + // it by writing into this register. + // It'll get interrupt whenever it + // is granted. In Handshake mode + // this bit will be set by Stack + // processor. Its a set only bit and + // is cleared by HW when the request + // is granted. + +#define STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK3 \ + 0x0000001C // In Spinlock mode Whenever Stack + // processor wants the access to + // Sram Bank3 it should request for + // it by writing into this register. + // It'll get interrupt whenever it + // is granted. In Handshake mode + // this bit will be set by the Base + // processor. Its a set only bit and + // is cleared by HW when the request + // is granted. + +#define STACK_DIE_CTRL_O_RDSM_CFG_CPU \ + 0x00000020 // Read State Machine timing + // configuration register. Generally + // Bit 4 and 3 will be identical. + // For stacked die always 43 are 0 + // and 6:5 == 1 for 120Mhz. + +#define STACK_DIE_CTRL_O_RDSM_CFG_EE \ + 0x00000024 // Read State Machine timing + // configuration register. Generally + // Bit 4 and 3 will be identical. + // For stacked die always 43 are 0 + // and 6:5 == 1 for 120Mhz. + +#define STACK_DIE_CTRL_O_BASE_UP_IRQ_LOG \ + 0x00000028 // Reading this register Base + // procesor will able to know the + // reason for the interrupt. This is + // clear only register - set by HW + // upon an interrupt to Base + // processor and can be cleared only + // by BASE processor. + +#define STACK_DIE_CTRL_O_STK_UP_IRQ_LOG \ + 0x0000002C // Reading this register Stack + // procesor will able to know the + // reason for the interrupt. This is + // clear only register - set by HW + // upon an interrupt to Stack + // processor and can be cleared only + // by Stack processor. + +#define STACK_DIE_CTRL_O_STK_CLK_EN \ + 0x00000030 // Can be written only by base + // processor. Controls the enable + // pin of the cgcs for the clocks + // going to CM3 dft ctrl block and + // Sram. + +#define STACK_DIE_CTRL_O_SPIN_LOCK_MODE \ + 0x00000034 // Can be written only by the base + // processor. Decides the ram + // sharing mode :: handshake or + // Spinlock mode. + +#define STACK_DIE_CTRL_O_BUS_FAULT_ADDR \ + 0x00000038 // Stores the last bus fault + // address. + +#define STACK_DIE_CTRL_O_BUS_FAULT_CLR \ + 0x0000003C // write only registers on read + // returns 0.W Write 1 to clear the + // bust fault to store the new bus + // fault address + +#define STACK_DIE_CTRL_O_RESET_CAUSE \ + 0x00000040 // Reset cause value captured from + // the ICR_CLKRST block. + +#define STACK_DIE_CTRL_O_WDOG_TIMER_EVENT \ + 0x00000044 // Watchdog timer event value + // captured from the ICR_CLKRST + // block + +#define STACK_DIE_CTRL_O_DMA_REQ \ + 0x00000048 // To send Dma Request to bottom + // die. + +#define STACK_DIE_CTRL_O_SRAM_JUMP_OFFSET_ADDR \ + 0x0000004C // Address offset within SRAM to + // which CM3 should jump after + // reset. + +#define STACK_DIE_CTRL_O_SW_REG1 \ + 0x00000050 // These are sw registers for + // topdie processor and bottom die + // processor to communicate. Both + // can set and read these registers. + // In case of write clash bottom + // die's processor wins and top die + // processor access is ignored. + +#define STACK_DIE_CTRL_O_SW_REG2 \ + 0x00000054 // These are sw registers for + // topdie processor and bottom die + // processor to communicate. Both + // can set and read these registers. + // In case of write clash bottom + // die's processor wins and top die + // processor access is ignored. + +#define STACK_DIE_CTRL_O_FMC_SLEEP_CTL \ + 0x00000058 // By posting the request Flash can + // be put into low-power mode + // (Sleep) without powering down the + // Flash. Earlier (in Garnet) this + // was fully h/w controlled and the + // control for this was coming from + // SysCtl while entering into Cortex + // Deep-sleep mode. But for our + // device the D2D i/f doesnt support + // this. The Firmware has to program + // the register in the top-die for + // entering into this mode and wait + // for an interrupt. + +#define STACK_DIE_CTRL_O_MISC_CTL \ + 0x0000005C // Miscellanious control register. + +#define STACK_DIE_CTRL_O_SW_DFT_CTL \ + 0x000000FC // DFT control and status bits + +#define STACK_DIE_CTRL_O_PADN_CTL_0 \ + 0x00000100 // Mainly for For controlling the + // pads OEN pins. There are total 60 + // pads and hence 60 control registe + // i.e n value varies from 0 to 59. + // Here is the mapping for the + // pad_ctl register number and the + // functionality : 0 D2DPAD_DMAREQ1 + // 1 D2DPAD_DMAREQ0 2 + // D2DPAD_INT2BASE 3 D2DPAD_PIOSC 4 + // D2DPAD_RST_N 5 D2DPAD_POR_RST_N 6 + // D2DPAD_HCLK 7 D2DPAD_JTAG_TDO 8 + // D2DPAD_JTAG_TCK 9 D2DPAD_JTAG_TMS + // 10 D2DPAD_JTAG_TDI 11-27 + // D2DPAD_FROMSTACK[D2D_FROMSTACK_SIZE + // -1:0] 28-56 D2DPAD_TOSTACK + // [D2D_TOSTACK_SIZE -1:0] 57-59 + // D2DPAD_SPARE [D2D_SPARE_PAD_SIZE + // -1:0] 0:00 + + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_STK_UP_RESET register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_STK_UP_RESET_UP_RESET \ + 0x00000001 // 1 :Assert Reset 0 : Deassert the + // Reset + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_SR_MASTER_PRIORITY register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_SR_MASTER_PRIORITY_PRIORITY_M \ + 0x00000003 // 00 : Equal Priority 01 : Stack + // Processor have priority 10 : Base + // Processor have priority 11 : + // Unused + +#define STACK_DIE_CTRL_SR_MASTER_PRIORITY_PRIORITY_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK2 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK2_STK_UP_ACCSS \ + 0x00000002 // Stack Processor should clear it + // when it is done with the sram + // bank usage. Set by HW It is set + // when Stack Processor is granted + // the access to this bank + +#define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK2_BASE_UP_ACCSS \ + 0x00000001 // Base Processor should clear it + // when it is done wth the sram + // usage. Set by HW It is set when + // Base Processor is granted the + // access to this bank + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK2 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_BASE_UP_ACC_REQ_BK2_ACCSS_REQ \ + 0x00000001 // Base Processor will set when + // Sram access is needed in Spin + // Lock mode. In Handshake mode + // Stack Processor will set to + // inform Base Processor that it is + // done with the processing of data + // in SRAM and is now ready to use + // by the base processor. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK2 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_STK_UP_ACC_REQ_BK2_ACCSS_REQ \ + 0x00000001 // Stack Processor will set when + // Sram access is needed in Spin + // Lock mode. In Handshake mode Base + // Processor will set to inform + // Stack Processor to start + // processing the data in the Ram. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_STK_SR_ACC_CTL_BK3 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK3_STK_UP_ACCSS \ + 0x00000002 // Stack Processor should clear it + // when it is done with the sram + // bank usage. Set by HW It is set + // when Stack Processor is granted + // the access to this bank. + +#define STACK_DIE_CTRL_STK_SR_ACC_CTL_BK3_BASE_UP_ACCSS \ + 0x00000001 // Base Processor should clear it + // when it is done wth the sram + // usage. Set by HW it is set when + // Base Processor is granted the + // access to this bank. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_BASE_UP_ACC_REQ_BK3 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_BASE_UP_ACC_REQ_BK3_ACCSS_REQ \ + 0x00000001 // Base Processor will set when + // Sram access is needed in Spin + // Lock mode. Not used in handshake + // mode. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_STK_UP_ACC_REQ_BK3 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_STK_UP_ACC_REQ_BK3_ACCSS_REQ \ + 0x00000001 // Stack Processor will set when + // Sram access is needed in Spin + // Lock mode. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_RDSM_CFG_CPU register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_RDSM_CFG_CPU_FLCLK_PULSE_WIDTH_M \ + 0x000000C0 // Bank Clock Hi Time 00 : HCLK + // pulse 01 : 1 cycle of HCLK 10 : + // 1.5 cycles of HCLK 11 : 2 cycles + // of HCLK + +#define STACK_DIE_CTRL_RDSM_CFG_CPU_FLCLK_PULSE_WIDTH_S 6 +#define STACK_DIE_CTRL_RDSM_CFG_CPU_FLCLK_SENSE \ + 0x00000020 // FLCLK 0 : indicates flash clock + // rise aligns on HCLK rise 1 : + // indicates flash clock rise aligns + // on HCLK fall + +#define STACK_DIE_CTRL_RDSM_CFG_CPU_PIPELINE_FLDATA \ + 0x00000010 // 0 : Always register flash rdata + // before sending to CPU 1 : Drive + // Flash rdata directly out on MISS + // (Both ICODE / DCODE) + +#define STACK_DIE_CTRL_RDSM_CFG_CPU_READ_WAIT_STATE_M \ + 0x0000000F // Number of wait states inserted + +#define STACK_DIE_CTRL_RDSM_CFG_CPU_READ_WAIT_STATE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_RDSM_CFG_EE register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_RDSM_CFG_EE_FLCLK_PULSE_WIDTH_M \ + 0x000000C0 // Bank Clock Hi Time 00 : HCLK + // pulse 01 : 1 cycle of HCLK 10 : + // 1.5 cycles of HCLK 11 : 2 cycles + // of HCLK + +#define STACK_DIE_CTRL_RDSM_CFG_EE_FLCLK_PULSE_WIDTH_S 6 +#define STACK_DIE_CTRL_RDSM_CFG_EE_FLCLK_SENSE \ + 0x00000020 // FLCLK 0 : indicates flash clock + // rise aligns on HCLK rise 1 : + // indicates flash clock rise aligns + // on HCLK fall + +#define STACK_DIE_CTRL_RDSM_CFG_EE_PIPELINE_FLDATA \ + 0x00000010 // 0 : Always register flash rdata + // before sending to CPU 1 : Drive + // Flash rdata directly out on MISS + // (Both ICODE / DCODE) + +#define STACK_DIE_CTRL_RDSM_CFG_EE_READ_WAIT_STATE_M \ + 0x0000000F // Number of wait states inserted + +#define STACK_DIE_CTRL_RDSM_CFG_EE_READ_WAIT_STATE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_BASE_UP_IRQ_LOG register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK3_REL \ + 0x00000010 // Set when Relinquish Interrupt + // sent to Base processor for Bank3. + +#define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK2_RELEASE \ + 0x00000008 // Set when Relinquish Interrupt + // sent to Base processor for Bank2. + +#define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK3_GRANT \ + 0x00000004 // Set when Bank3 is granted to + // Base processor. + +#define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_BK2_GRANT \ + 0x00000002 // Set when Bank2 is granted to + // BAse processor. + +#define STACK_DIE_CTRL_BASE_UP_IRQ_LOG_SR_INVAL_ACCSS \ + 0x00000001 // Set when there Base processor do + // an Invalid access to Sram. Ex : + // Accessing the bank which is not + // granted for BAse processor. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_STK_UP_IRQ_LOG register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK3_REL \ + 0x00000008 // Set when Relinquish Interrupt + // sent to Stack processor for + // Bank3. + +#define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK2_REL \ + 0x00000004 // Set when Relinquish Interrupt + // sent to Stack processor for + // Bank2. + +#define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK3_GRANT \ + 0x00000002 // Set when Bank3 is granted to + // Stack processor. + +#define STACK_DIE_CTRL_STK_UP_IRQ_LOG_SR_BK2_GRANT \ + 0x00000001 // Set when Bank2 is granted to + // Stack processor. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_STK_CLK_EN register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_STK_CLK_EN_SR_CLK \ + 0x00000004 // Enable the clock going to sram. + +#define STACK_DIE_CTRL_STK_CLK_EN_DFT_CTRL_CLK \ + 0x00000002 // Enable the clock going to dft + // control block + +#define STACK_DIE_CTRL_STK_CLK_EN_STK_UP_CLK \ + 0x00000001 // Enable the clock going to Cm3 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_SPIN_LOCK_MODE register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_SPIN_LOCK_MODE_MODE \ + 0x00000001 // 0 : Handshake Mode 1 : Spinlock + // mode. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_BUS_FAULT_ADDR register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_BUS_FAULT_ADDR_ADDRESS_M \ + 0xFFFFFFFF // Fault Address + +#define STACK_DIE_CTRL_BUS_FAULT_ADDR_ADDRESS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_BUS_FAULT_CLR register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_BUS_FAULT_CLR_CLEAR \ + 0x00000001 // When set it'll clear the bust + // fault address register to store + // the new bus fault address + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_RESET_CAUSE register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_RESET_CAUSE_RST_CAUSE_M \ + 0xFFFFFFFF + +#define STACK_DIE_CTRL_RESET_CAUSE_RST_CAUSE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_WDOG_TIMER_EVENT register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_WDOG_TIMER_EVENT_WDOG_TMR_EVNT_M \ + 0xFFFFFFFF + +#define STACK_DIE_CTRL_WDOG_TIMER_EVENT_WDOG_TMR_EVNT_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_DMA_REQ register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_DMA_REQ_DMAREQ1 \ + 0x00000002 // Generate DMAREQ1 on setting this + // bit. + +#define STACK_DIE_CTRL_DMA_REQ_DMAREQ0 \ + 0x00000001 // Generate DMAREQ0 on setting this + // bit. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_SRAM_JUMP_OFFSET_ADDR register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_SRAM_JUMP_OFFSET_ADDR_ADDR_M \ + 0xFFFFFFFF + +#define STACK_DIE_CTRL_SRAM_JUMP_OFFSET_ADDR_ADDR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_SW_REG1 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_SW_REG1_NEWBITFIELD1_M \ + 0xFFFFFFFF + +#define STACK_DIE_CTRL_SW_REG1_NEWBITFIELD1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_SW_REG2 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_SW_REG2_NEWBITFIELD1_M \ + 0xFFFFFFFF + +#define STACK_DIE_CTRL_SW_REG2_NEWBITFIELD1_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_FMC_SLEEP_CTL register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_FMC_SLEEP_CTL_FMC_LPM_ACK \ + 0x00000002 // captures the status of of + // fmc_lpm_ack + +#define STACK_DIE_CTRL_FMC_SLEEP_CTL_FMC_LPM_REQ \ + 0x00000001 // When set assert + // iflpe2fmc_lpm_req to FMC. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_MISC_CTL register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_MISC_CTL_WDOG_RESET \ + 0x00000080 // 1 : will reset the async wdog + // timer runing on piosc clock + +#define STACK_DIE_CTRL_MISC_CTL_FW_IRQ2 \ + 0x00000020 // Setting this Will send to + // interttupt to CM3 + +#define STACK_DIE_CTRL_MISC_CTL_FW_IRQ1 \ + 0x00000010 // Setting this Will send to + // interttupt to CM3 + +#define STACK_DIE_CTRL_MISC_CTL_FW_IRQ0 \ + 0x00000008 // Setting this Will send to + // interttupt to CM3 + +#define STACK_DIE_CTRL_MISC_CTL_FLB_TEST_MUX_CTL_BK3 \ + 0x00000004 // While testing Flash Setting this + // bit will Control the + // CE/STR/AIN/CLKIN going to flash + // banks 12 and 3. 0 : Control + // signals coming from FMC for Bank + // 3 goes to Bank3 1 : Control + // signals coming from FMC for Bank + // 0 goes to Bank2 + +#define STACK_DIE_CTRL_MISC_CTL_FLB_TEST_MUX_CTL_BK2 \ + 0x00000002 // While testing Flash Setting this + // bit will Control the + // CE/STR/AIN/CLKIN going to flash + // banks 12 and 3. 0 : Control + // signals coming from FMC for Bank + // 2 goes to Bank2 1 : Control + // signals coming from FMC for Bank + // 0 goes to Bank2 + +#define STACK_DIE_CTRL_MISC_CTL_FLB_TEST_MUX_CTL_BK1 \ + 0x00000001 // While testing Flash Setting this + // bit will Control the + // CE/STR/AIN/CLKIN going to flash + // banks 12 and 3. 0 : Control + // signals coming from FMC for Bank + // 1 goes to Bank1 1 : Control + // signals coming from FMC for Bank + // 0 goes to Bank1 + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_SW_DFT_CTL register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_SW_DFT_CTL_FL_CTRL_OWNS \ + 0x20000000 // when set to '1' all flash + // control signals switch over to + // CM3 control when '0' it is under + // the D2D interface control + +#define STACK_DIE_CTRL_SW_DFT_CTL_SWIF_CPU_READ \ + 0x10000000 // 1 indicates in SWIF mode the + // control signals to flash are from + // FMC CPU read controls the clock + // and address. that is one can give + // address via FMC and read through + // IDMEM. + +#define STACK_DIE_CTRL_SW_DFT_CTL_CPU_DONE \ + 0x00800000 // 'CPU Done' bit for PBIST. Write + // '1' to indicate test done. + +#define STACK_DIE_CTRL_SW_DFT_CTL_CPU_FAIL \ + 0x00400000 // 'CPU Fail' bit for PBIST. Write + // '1' to indicate test failed. + +#define STACK_DIE_CTRL_SW_DFT_CTL_FLBK4_OWNS \ + 0x00001000 // when set to '1' flash bank 4 + // (EEPROM) is owned by the CM3for + // reads over DCODE bus. When '0' + // access control given to D2D + // interface. + +#define STACK_DIE_CTRL_SW_DFT_CTL_FLBK3_OWNS \ + 0x00000800 // when set to '1' flash bank 3 is + // owned by the CM3for reads over + // DCODE bus. When '0' access + // control given to D2D interface. + +#define STACK_DIE_CTRL_SW_DFT_CTL_FLBK2_OWNS \ + 0x00000400 // when set to '1' flash bank 2 is + // owned by the CM3for reads over + // DCODE bus. When '0' access + // control given to D2D interface. + +#define STACK_DIE_CTRL_SW_DFT_CTL_FLBK1_OWNS \ + 0x00000200 // when set to '1' flash bank 1 is + // owned by the CM3for reads over + // DCODE bus. When '0' access + // control given to D2D interface. + +#define STACK_DIE_CTRL_SW_DFT_CTL_FLBK0_OWNS \ + 0x00000100 // when set to '1' flash bank 0 is + // owned by the CM3 for reads over + // DCODE bus. When '0' access + // control given to D2D interface. + +//****************************************************************************** +// +// The following are defines for the bit fields in the +// STACK_DIE_CTRL_O_PADN_CTL_0 register. +// +//****************************************************************************** +#define STACK_DIE_CTRL_PADN_CTL_0_SPARE_PAD_DOUT \ + 0x00000008 // This bit is valid for only the + // spare pads ie for n=57 to 59. + // value to drive at the output of + // the pad + +#define STACK_DIE_CTRL_PADN_CTL_0_SPARE_PAD_DIN \ + 0x00000004 // This bit is valid for only the + // spare pads ie for n=57 to 59. + // captures the 'Y' pin of the pad + // which is the data being driven + // into the die + +#define STACK_DIE_CTRL_PADN_CTL_0_OEN2X \ + 0x00000002 // OEN2X control when '1' enables + // the output with 1x. Total drive + // strength is decided bu oen1x + // setting + oen2x setting. + +#define STACK_DIE_CTRL_PADN_CTL_0_OEN1X \ + 0x00000001 // OEN1X control when '1' enables + // the output with 1x . Total drive + // strength is decided bu oen1x + // setting + oen2x setting. + + + + +#endif // __HW_STACK_DIE_CTRL_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_timer.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_timer.h new file mode 100644 index 00000000..b6844ec6 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_timer.h @@ -0,0 +1,778 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +//***************************************************************************** +// +// hw_timer.h - Defines and macros used when accessing the timer. +// +//***************************************************************************** + +//##### INTERNAL BEGIN ##### +// +// This is an auto-generated file. Do not edit by hand. +// Created by version 6779 of DriverLib. +// +//##### INTERNAL END ##### + +#ifndef __HW_TIMER_H__ +#define __HW_TIMER_H__ + +//***************************************************************************** +// +// The following are defines for the Timer register offsets. +// +//***************************************************************************** +#define TIMER_O_CFG 0x00000000 // GPTM Configuration +#define TIMER_O_TAMR 0x00000004 // GPTM Timer A Mode +#define TIMER_O_TBMR 0x00000008 // GPTM Timer B Mode +#define TIMER_O_CTL 0x0000000C // GPTM Control +//##### GARNET BEGIN ##### +#define TIMER_O_SYNC 0x00000010 // GPTM Synchronize +//##### GARNET END ##### +#define TIMER_O_IMR 0x00000018 // GPTM Interrupt Mask +#define TIMER_O_RIS 0x0000001C // GPTM Raw Interrupt Status +#define TIMER_O_MIS 0x00000020 // GPTM Masked Interrupt Status +#define TIMER_O_ICR 0x00000024 // GPTM Interrupt Clear +#define TIMER_O_TAILR 0x00000028 // GPTM Timer A Interval Load +#define TIMER_O_TBILR 0x0000002C // GPTM Timer B Interval Load +#define TIMER_O_TAMATCHR 0x00000030 // GPTM Timer A Match +#define TIMER_O_TBMATCHR 0x00000034 // GPTM Timer B Match +#define TIMER_O_TAPR 0x00000038 // GPTM Timer A Prescale +#define TIMER_O_TBPR 0x0000003C // GPTM Timer B Prescale +#define TIMER_O_TAPMR 0x00000040 // GPTM TimerA Prescale Match +#define TIMER_O_TBPMR 0x00000044 // GPTM TimerB Prescale Match +#define TIMER_O_TAR 0x00000048 // GPTM Timer A +#define TIMER_O_TBR 0x0000004C // GPTM Timer B +#define TIMER_O_TAV 0x00000050 // GPTM Timer A Value +#define TIMER_O_TBV 0x00000054 // GPTM Timer B Value +#define TIMER_O_RTCPD 0x00000058 // GPTM RTC Predivide +#define TIMER_O_TAPS 0x0000005C // GPTM Timer A Prescale Snapshot +#define TIMER_O_TBPS 0x00000060 // GPTM Timer B Prescale Snapshot +#define TIMER_O_TAPV 0x00000064 // GPTM Timer A Prescale Value +#define TIMER_O_TBPV 0x00000068 // GPTM Timer B Prescale Value +#define TIMER_O_DMAEV 0x0000006C // GPTM DMA Event +#define TIMER_O_PP 0x00000FC0 // GPTM Peripheral Properties + + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_CFG register. +// +//***************************************************************************** +#define TIMER_CFG_M 0x00000007 // GPTM Configuration +#define TIMER_CFG_32_BIT_TIMER 0x00000000 // 32-bit timer configuration +#define TIMER_CFG_32_BIT_RTC 0x00000001 // 32-bit real-time clock (RTC) + // counter configuration +#define TIMER_CFG_16_BIT 0x00000004 // 16-bit timer configuration. The + // function is controlled by bits + // 1:0 of GPTMTAMR and GPTMTBMR + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAMR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TAMR_TAPLO 0x00000800 // GPTM Timer A PWM Legacy + // Operation +#define TIMER_TAMR_TAMRSU 0x00000400 // GPTM Timer A Match Register + // Update +#define TIMER_TAMR_TAPWMIE 0x00000200 // GPTM Timer A PWM Interrupt + // Enable +#define TIMER_TAMR_TAILD 0x00000100 // GPTM Timer A Interval Load Write +//##### GARNET END ##### +#define TIMER_TAMR_TASNAPS 0x00000080 // GPTM Timer A Snap-Shot Mode +#define TIMER_TAMR_TAWOT 0x00000040 // GPTM Timer A Wait-on-Trigger +#define TIMER_TAMR_TAMIE 0x00000020 // GPTM Timer A Match Interrupt + // Enable +#define TIMER_TAMR_TACDIR 0x00000010 // GPTM Timer A Count Direction +#define TIMER_TAMR_TAAMS 0x00000008 // GPTM Timer A Alternate Mode + // Select +#define TIMER_TAMR_TACMR 0x00000004 // GPTM Timer A Capture Mode +#define TIMER_TAMR_TAMR_M 0x00000003 // GPTM Timer A Mode +#define TIMER_TAMR_TAMR_1_SHOT 0x00000001 // One-Shot Timer mode +#define TIMER_TAMR_TAMR_PERIOD 0x00000002 // Periodic Timer mode +#define TIMER_TAMR_TAMR_CAP 0x00000003 // Capture mode + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBMR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TBMR_TBPLO 0x00000800 // GPTM Timer B PWM Legacy + // Operation +#define TIMER_TBMR_TBMRSU 0x00000400 // GPTM Timer B Match Register + // Update +#define TIMER_TBMR_TBPWMIE 0x00000200 // GPTM Timer B PWM Interrupt + // Enable +#define TIMER_TBMR_TBILD 0x00000100 // GPTM Timer B Interval Load Write +//##### GARNET END ##### +#define TIMER_TBMR_TBSNAPS 0x00000080 // GPTM Timer B Snap-Shot Mode +#define TIMER_TBMR_TBWOT 0x00000040 // GPTM Timer B Wait-on-Trigger +#define TIMER_TBMR_TBMIE 0x00000020 // GPTM Timer B Match Interrupt + // Enable +#define TIMER_TBMR_TBCDIR 0x00000010 // GPTM Timer B Count Direction +#define TIMER_TBMR_TBAMS 0x00000008 // GPTM Timer B Alternate Mode + // Select +#define TIMER_TBMR_TBCMR 0x00000004 // GPTM Timer B Capture Mode +#define TIMER_TBMR_TBMR_M 0x00000003 // GPTM Timer B Mode +#define TIMER_TBMR_TBMR_1_SHOT 0x00000001 // One-Shot Timer mode +#define TIMER_TBMR_TBMR_PERIOD 0x00000002 // Periodic Timer mode +#define TIMER_TBMR_TBMR_CAP 0x00000003 // Capture mode + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_CTL register. +// +//***************************************************************************** +#define TIMER_CTL_TBPWML 0x00004000 // GPTM Timer B PWM Output Level +#define TIMER_CTL_TBOTE 0x00002000 // GPTM Timer B Output Trigger + // Enable +#define TIMER_CTL_TBEVENT_M 0x00000C00 // GPTM Timer B Event Mode +#define TIMER_CTL_TBEVENT_POS 0x00000000 // Positive edge +#define TIMER_CTL_TBEVENT_NEG 0x00000400 // Negative edge +#define TIMER_CTL_TBEVENT_BOTH 0x00000C00 // Both edges +#define TIMER_CTL_TBSTALL 0x00000200 // GPTM Timer B Stall Enable +#define TIMER_CTL_TBEN 0x00000100 // GPTM Timer B Enable +#define TIMER_CTL_TAPWML 0x00000040 // GPTM Timer A PWM Output Level +#define TIMER_CTL_TAOTE 0x00000020 // GPTM Timer A Output Trigger + // Enable +#define TIMER_CTL_RTCEN 0x00000010 // GPTM RTC Enable +#define TIMER_CTL_TAEVENT_M 0x0000000C // GPTM Timer A Event Mode +#define TIMER_CTL_TAEVENT_POS 0x00000000 // Positive edge +#define TIMER_CTL_TAEVENT_NEG 0x00000004 // Negative edge +#define TIMER_CTL_TAEVENT_BOTH 0x0000000C // Both edges +#define TIMER_CTL_TASTALL 0x00000002 // GPTM Timer A Stall Enable +#define TIMER_CTL_TAEN 0x00000001 // GPTM Timer A Enable +//##### GARNET BEGIN ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_SYNC register. +// +//***************************************************************************** +#define TIMER_SYNC_SYNC11_M 0x00C00000 // Synchronize GPTM Timer 11 +#define TIMER_SYNC_SYNC11_TA 0x00400000 // A timeout event for Timer A of + // GPTM11 is triggered +#define TIMER_SYNC_SYNC11_TB 0x00800000 // A timeout event for Timer B of + // GPTM11 is triggered +#define TIMER_SYNC_SYNC11_TATB 0x00C00000 // A timeout event for both Timer A + // and Timer B of GPTM11 is + // triggered +#define TIMER_SYNC_SYNC10_M 0x00300000 // Synchronize GPTM Timer 10 +#define TIMER_SYNC_SYNC10_TA 0x00100000 // A timeout event for Timer A of + // GPTM10 is triggered +#define TIMER_SYNC_SYNC10_TB 0x00200000 // A timeout event for Timer B of + // GPTM10 is triggered +#define TIMER_SYNC_SYNC10_TATB 0x00300000 // A timeout event for both Timer A + // and Timer B of GPTM10 is + // triggered +#define TIMER_SYNC_SYNC9_M 0x000C0000 // Synchronize GPTM Timer 9 +#define TIMER_SYNC_SYNC9_TA 0x00040000 // A timeout event for Timer A of + // GPTM9 is triggered +#define TIMER_SYNC_SYNC9_TB 0x00080000 // A timeout event for Timer B of + // GPTM9 is triggered +#define TIMER_SYNC_SYNC9_TATB 0x000C0000 // A timeout event for both Timer A + // and Timer B of GPTM9 is + // triggered +#define TIMER_SYNC_SYNC8_M 0x00030000 // Synchronize GPTM Timer 8 +#define TIMER_SYNC_SYNC8_TA 0x00010000 // A timeout event for Timer A of + // GPTM8 is triggered +#define TIMER_SYNC_SYNC8_TB 0x00020000 // A timeout event for Timer B of + // GPTM8 is triggered +#define TIMER_SYNC_SYNC8_TATB 0x00030000 // A timeout event for both Timer A + // and Timer B of GPTM8 is + // triggered +#define TIMER_SYNC_SYNC7_M 0x0000C000 // Synchronize GPTM Timer 7 +#define TIMER_SYNC_SYNC7_TA 0x00004000 // A timeout event for Timer A of + // GPTM7 is triggered +#define TIMER_SYNC_SYNC7_TB 0x00008000 // A timeout event for Timer B of + // GPTM7 is triggered +#define TIMER_SYNC_SYNC7_TATB 0x0000C000 // A timeout event for both Timer A + // and Timer B of GPTM7 is + // triggered +#define TIMER_SYNC_SYNC6_M 0x00003000 // Synchronize GPTM Timer 6 +#define TIMER_SYNC_SYNC6_TA 0x00001000 // A timeout event for Timer A of + // GPTM6 is triggered +#define TIMER_SYNC_SYNC6_TB 0x00002000 // A timeout event for Timer B of + // GPTM6 is triggered +#define TIMER_SYNC_SYNC6_TATB 0x00003000 // A timeout event for both Timer A + // and Timer B of GPTM6 is + // triggered +#define TIMER_SYNC_SYNC5_M 0x00000C00 // Synchronize GPTM Timer 5 +#define TIMER_SYNC_SYNC5_TA 0x00000400 // A timeout event for Timer A of + // GPTM5 is triggered +#define TIMER_SYNC_SYNC5_TB 0x00000800 // A timeout event for Timer B of + // GPTM5 is triggered +#define TIMER_SYNC_SYNC5_TATB 0x00000C00 // A timeout event for both Timer A + // and Timer B of GPTM5 is + // triggered +#define TIMER_SYNC_SYNC4_M 0x00000300 // Synchronize GPTM Timer 4 +#define TIMER_SYNC_SYNC4_TA 0x00000100 // A timeout event for Timer A of + // GPTM4 is triggered +#define TIMER_SYNC_SYNC4_TB 0x00000200 // A timeout event for Timer B of + // GPTM4 is triggered +#define TIMER_SYNC_SYNC4_TATB 0x00000300 // A timeout event for both Timer A + // and Timer B of GPTM4 is + // triggered +#define TIMER_SYNC_SYNC3_M 0x000000C0 // Synchronize GPTM Timer 3 +#define TIMER_SYNC_SYNC3_TA 0x00000040 // A timeout event for Timer A of + // GPTM3 is triggered +#define TIMER_SYNC_SYNC3_TB 0x00000080 // A timeout event for Timer B of + // GPTM3 is triggered +#define TIMER_SYNC_SYNC3_TATB 0x000000C0 // A timeout event for both Timer A + // and Timer B of GPTM3 is + // triggered +#define TIMER_SYNC_SYNC2_M 0x00000030 // Synchronize GPTM Timer 2 +#define TIMER_SYNC_SYNC2_TA 0x00000010 // A timeout event for Timer A of + // GPTM2 is triggered +#define TIMER_SYNC_SYNC2_TB 0x00000020 // A timeout event for Timer B of + // GPTM2 is triggered +#define TIMER_SYNC_SYNC2_TATB 0x00000030 // A timeout event for both Timer A + // and Timer B of GPTM2 is + // triggered +#define TIMER_SYNC_SYNC1_M 0x0000000C // Synchronize GPTM Timer 1 +#define TIMER_SYNC_SYNC1_TA 0x00000004 // A timeout event for Timer A of + // GPTM1 is triggered +#define TIMER_SYNC_SYNC1_TB 0x00000008 // A timeout event for Timer B of + // GPTM1 is triggered +#define TIMER_SYNC_SYNC1_TATB 0x0000000C // A timeout event for both Timer A + // and Timer B of GPTM1 is + // triggered +#define TIMER_SYNC_SYNC0_M 0x00000003 // Synchronize GPTM Timer 0 +#define TIMER_SYNC_SYNC0_TA 0x00000001 // A timeout event for Timer A of + // GPTM0 is triggered +#define TIMER_SYNC_SYNC0_TB 0x00000002 // A timeout event for Timer B of + // GPTM0 is triggered +#define TIMER_SYNC_SYNC0_TATB 0x00000003 // A timeout event for both Timer A + // and Timer B of GPTM0 is + // triggered +//##### GARNET END ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_IMR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_IMR_WUEIM 0x00010000 // 32/64-Bit GPTM Write Update + // Error Interrupt Mask +//##### GARNET END ##### +#define TIMER_IMR_TBMIM 0x00000800 // GPTM Timer B Mode Match + // Interrupt Mask +#define TIMER_IMR_CBEIM 0x00000400 // GPTM Capture B Event Interrupt + // Mask +#define TIMER_IMR_CBMIM 0x00000200 // GPTM Capture B Match Interrupt + // Mask +#define TIMER_IMR_TBTOIM 0x00000100 // GPTM Timer B Time-Out Interrupt + // Mask +#define TIMER_IMR_TAMIM 0x00000010 // GPTM Timer A Mode Match + // Interrupt Mask +#define TIMER_IMR_RTCIM 0x00000008 // GPTM RTC Interrupt Mask +#define TIMER_IMR_CAEIM 0x00000004 // GPTM Capture A Event Interrupt + // Mask +#define TIMER_IMR_CAMIM 0x00000002 // GPTM Capture A Match Interrupt + // Mask +#define TIMER_IMR_TATOIM 0x00000001 // GPTM Timer A Time-Out Interrupt + // Mask + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_RIS register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_RIS_WUERIS 0x00010000 // 32/64-Bit GPTM Write Update + // Error Raw Interrupt Status +//##### GARNET END ##### +#define TIMER_RIS_TBMRIS 0x00000800 // GPTM Timer B Mode Match Raw + // Interrupt +#define TIMER_RIS_CBERIS 0x00000400 // GPTM Capture B Event Raw + // Interrupt +#define TIMER_RIS_CBMRIS 0x00000200 // GPTM Capture B Match Raw + // Interrupt +#define TIMER_RIS_TBTORIS 0x00000100 // GPTM Timer B Time-Out Raw + // Interrupt +#define TIMER_RIS_TAMRIS 0x00000010 // GPTM Timer A Mode Match Raw + // Interrupt +#define TIMER_RIS_RTCRIS 0x00000008 // GPTM RTC Raw Interrupt +#define TIMER_RIS_CAERIS 0x00000004 // GPTM Capture A Event Raw + // Interrupt +#define TIMER_RIS_CAMRIS 0x00000002 // GPTM Capture A Match Raw + // Interrupt +#define TIMER_RIS_TATORIS 0x00000001 // GPTM Timer A Time-Out Raw + // Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_MIS register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_MIS_WUEMIS 0x00010000 // 32/64-Bit GPTM Write Update + // Error Masked Interrupt Status +//##### GARNET END ##### +#define TIMER_MIS_TBMMIS 0x00000800 // GPTM Timer B Mode Match Masked + // Interrupt +#define TIMER_MIS_CBEMIS 0x00000400 // GPTM Capture B Event Masked + // Interrupt +#define TIMER_MIS_CBMMIS 0x00000200 // GPTM Capture B Match Masked + // Interrupt +#define TIMER_MIS_TBTOMIS 0x00000100 // GPTM Timer B Time-Out Masked + // Interrupt +#define TIMER_MIS_TAMMIS 0x00000010 // GPTM Timer A Mode Match Masked + // Interrupt +#define TIMER_MIS_RTCMIS 0x00000008 // GPTM RTC Masked Interrupt +#define TIMER_MIS_CAEMIS 0x00000004 // GPTM Capture A Event Masked + // Interrupt +#define TIMER_MIS_CAMMIS 0x00000002 // GPTM Capture A Match Masked + // Interrupt +#define TIMER_MIS_TATOMIS 0x00000001 // GPTM Timer A Time-Out Masked + // Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_ICR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_ICR_WUECINT 0x00010000 // 32/64-Bit GPTM Write Update + // Error Interrupt Clear +//##### GARNET END ##### +#define TIMER_ICR_TBMCINT 0x00000800 // GPTM Timer B Mode Match + // Interrupt Clear +#define TIMER_ICR_CBECINT 0x00000400 // GPTM Capture B Event Interrupt + // Clear +#define TIMER_ICR_CBMCINT 0x00000200 // GPTM Capture B Match Interrupt + // Clear +#define TIMER_ICR_TBTOCINT 0x00000100 // GPTM Timer B Time-Out Interrupt + // Clear +#define TIMER_ICR_TAMCINT 0x00000010 // GPTM Timer A Mode Match + // Interrupt Clear +#define TIMER_ICR_RTCCINT 0x00000008 // GPTM RTC Interrupt Clear +#define TIMER_ICR_CAECINT 0x00000004 // GPTM Capture A Event Interrupt + // Clear +#define TIMER_ICR_CAMCINT 0x00000002 // GPTM Capture A Match Interrupt + // Clear +#define TIMER_ICR_TATOCINT 0x00000001 // GPTM Timer A Time-Out Raw + // Interrupt + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAILR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TAILR_M 0xFFFFFFFF // GPTM Timer A Interval Load + // Register +//##### GARNET END ##### +#define TIMER_TAILR_TAILRH_M 0xFFFF0000 // GPTM Timer A Interval Load + // Register High +#define TIMER_TAILR_TAILRL_M 0x0000FFFF // GPTM Timer A Interval Load + // Register Low +#define TIMER_TAILR_TAILRH_S 16 +#define TIMER_TAILR_TAILRL_S 0 +//##### GARNET BEGIN ##### +#define TIMER_TAILR_S 0 +//##### GARNET END ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBILR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TBILR_M 0xFFFFFFFF // GPTM Timer B Interval Load + // Register +//##### GARNET END ##### +#define TIMER_TBILR_TBILRL_M 0x0000FFFF // GPTM Timer B Interval Load + // Register +#define TIMER_TBILR_TBILRL_S 0 +//##### GARNET BEGIN ##### +#define TIMER_TBILR_S 0 +//##### GARNET END ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAMATCHR +// register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TAMATCHR_TAMR_M 0xFFFFFFFF // GPTM Timer A Match Register +//##### GARNET END ##### +#define TIMER_TAMATCHR_TAMRH_M 0xFFFF0000 // GPTM Timer A Match Register High +#define TIMER_TAMATCHR_TAMRL_M 0x0000FFFF // GPTM Timer A Match Register Low +#define TIMER_TAMATCHR_TAMRH_S 16 +#define TIMER_TAMATCHR_TAMRL_S 0 +//##### GARNET BEGIN ##### +#define TIMER_TAMATCHR_TAMR_S 0 +//##### GARNET END ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBMATCHR +// register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TBMATCHR_TBMR_M 0xFFFFFFFF // GPTM Timer B Match Register +//##### GARNET END ##### +#define TIMER_TBMATCHR_TBMRL_M 0x0000FFFF // GPTM Timer B Match Register Low +//##### GARNET BEGIN ##### +#define TIMER_TBMATCHR_TBMR_S 0 +//##### GARNET END ##### +#define TIMER_TBMATCHR_TBMRL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAPR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TAPR_TAPSRH_M 0x0000FF00 // GPTM Timer A Prescale High Byte +//##### GARNET END ##### +#define TIMER_TAPR_TAPSR_M 0x000000FF // GPTM Timer A Prescale +//##### GARNET BEGIN ##### +#define TIMER_TAPR_TAPSRH_S 8 +//##### GARNET END ##### +#define TIMER_TAPR_TAPSR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBPR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TBPR_TBPSRH_M 0x0000FF00 // GPTM Timer B Prescale High Byte +//##### GARNET END ##### +#define TIMER_TBPR_TBPSR_M 0x000000FF // GPTM Timer B Prescale +//##### GARNET BEGIN ##### +#define TIMER_TBPR_TBPSRH_S 8 +//##### GARNET END ##### +#define TIMER_TBPR_TBPSR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAPMR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TAPMR_TAPSMRH_M 0x0000FF00 // GPTM Timer A Prescale Match High + // Byte +//##### GARNET END ##### +#define TIMER_TAPMR_TAPSMR_M 0x000000FF // GPTM TimerA Prescale Match +//##### GARNET BEGIN ##### +#define TIMER_TAPMR_TAPSMRH_S 8 +//##### GARNET END ##### +#define TIMER_TAPMR_TAPSMR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBPMR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TBPMR_TBPSMRH_M 0x0000FF00 // GPTM Timer B Prescale Match High + // Byte +//##### GARNET END ##### +#define TIMER_TBPMR_TBPSMR_M 0x000000FF // GPTM TimerB Prescale Match +//##### GARNET BEGIN ##### +#define TIMER_TBPMR_TBPSMRH_S 8 +//##### GARNET END ##### +#define TIMER_TBPMR_TBPSMR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TAR_M 0xFFFFFFFF // GPTM Timer A Register +//##### GARNET END ##### +#define TIMER_TAR_TARH_M 0xFFFF0000 // GPTM Timer A Register High +#define TIMER_TAR_TARL_M 0x0000FFFF // GPTM Timer A Register Low +#define TIMER_TAR_TARH_S 16 +#define TIMER_TAR_TARL_S 0 +//##### GARNET BEGIN ##### +#define TIMER_TAR_S 0 +//##### GARNET END ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBR register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TBR_M 0xFFFFFFFF // GPTM Timer B Register +//##### GARNET END ##### +#define TIMER_TBR_TBRL_M 0x00FFFFFF // GPTM Timer B +#define TIMER_TBR_TBRL_S 0 +//##### GARNET BEGIN ##### +#define TIMER_TBR_S 0 +//##### GARNET END ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAV register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TAV_M 0xFFFFFFFF // GPTM Timer A Value +//##### GARNET END ##### +#define TIMER_TAV_TAVH_M 0xFFFF0000 // GPTM Timer A Value High +#define TIMER_TAV_TAVL_M 0x0000FFFF // GPTM Timer A Register Low +#define TIMER_TAV_TAVH_S 16 +#define TIMER_TAV_TAVL_S 0 +//##### GARNET BEGIN ##### +#define TIMER_TAV_S 0 +//##### GARNET END ##### + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBV register. +// +//***************************************************************************** +//##### GARNET BEGIN ##### +#define TIMER_TBV_M 0xFFFFFFFF // GPTM Timer B Value +//##### GARNET END ##### +#define TIMER_TBV_TBVL_M 0x0000FFFF // GPTM Timer B Register +#define TIMER_TBV_TBVL_S 0 +//##### GARNET BEGIN ##### +#define TIMER_TBV_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_RTCPD register. +// +//***************************************************************************** +#define TIMER_RTCPD_RTCPD_M 0x0000FFFF // RTC Predivide Counter Value +#define TIMER_RTCPD_RTCPD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAPS register. +// +//***************************************************************************** +#define TIMER_TAPS_PSS_M 0x0000FFFF // GPTM Timer A Prescaler Snapshot +#define TIMER_TAPS_PSS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBPS register. +// +//***************************************************************************** +#define TIMER_TBPS_PSS_M 0x0000FFFF // GPTM Timer A Prescaler Value +#define TIMER_TBPS_PSS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TAPV register. +// +//***************************************************************************** +#define TIMER_TAPV_PSV_M 0x0000FFFF // GPTM Timer A Prescaler Value +#define TIMER_TAPV_PSV_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_TBPV register. +// +//***************************************************************************** +#define TIMER_TBPV_PSV_M 0x0000FFFF // GPTM Timer B Prescaler Value +#define TIMER_TBPV_PSV_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TIMER_O_PP register. +// +//***************************************************************************** +#define TIMER_PP_SYNCCNT 0x00000020 // Synchronize Start +#define TIMER_PP_CHAIN 0x00000010 // Chain with Other Timers +#define TIMER_PP_SIZE_M 0x0000000F // Count Size +#define TIMER_PP_SIZE__0 0x00000000 // Timer A and Timer B counters are + // 16 bits each with an 8-bit + // prescale counter +#define TIMER_PP_SIZE__1 0x00000001 // Timer A and Timer B counters are + // 32 bits each with an 16-bit + // prescale counter +//##### GARNET END ##### + +//***************************************************************************** +// +// The following definitions are deprecated. +// +//***************************************************************************** +#ifndef DEPRECATED + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_O_CFG +// register. +// +//***************************************************************************** +#define TIMER_CFG_CFG_MSK 0x00000007 // Configuration options mask + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_O_CTL +// register. +// +//***************************************************************************** +#define TIMER_CTL_TBEVENT_MSK 0x00000C00 // TimerB event mode mask +#define TIMER_CTL_TAEVENT_MSK 0x0000000C // TimerA event mode mask + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_O_RIS +// register. +// +//***************************************************************************** +#define TIMER_RIS_CBEMIS 0x00000400 // CaptureB event masked int status +#define TIMER_RIS_CBMMIS 0x00000200 // CaptureB match masked int status +#define TIMER_RIS_TBTOMIS 0x00000100 // TimerB time out masked int stat +#define TIMER_RIS_RTCMIS 0x00000008 // RTC masked int status +#define TIMER_RIS_CAEMIS 0x00000004 // CaptureA event masked int status +#define TIMER_RIS_CAMMIS 0x00000002 // CaptureA match masked int status +#define TIMER_RIS_TATOMIS 0x00000001 // TimerA time out masked int stat + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_O_TAILR +// register. +// +//***************************************************************************** +#define TIMER_TAILR_TAILRH 0xFFFF0000 // TimerB load val in 32 bit mode +#define TIMER_TAILR_TAILRL 0x0000FFFF // TimerA interval load value + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_O_TBILR +// register. +// +//***************************************************************************** +#define TIMER_TBILR_TBILRL 0x0000FFFF // TimerB interval load value + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the +// TIMER_O_TAMATCHR register. +// +//***************************************************************************** +#define TIMER_TAMATCHR_TAMRH 0xFFFF0000 // TimerB match val in 32 bit mode +#define TIMER_TAMATCHR_TAMRL 0x0000FFFF // TimerA match value + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the +// TIMER_O_TBMATCHR register. +// +//***************************************************************************** +#define TIMER_TBMATCHR_TBMRL 0x0000FFFF // TimerB match load value + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_O_TAR +// register. +// +//***************************************************************************** +#define TIMER_TAR_TARH 0xFFFF0000 // TimerB val in 32 bit mode +#define TIMER_TAR_TARL 0x0000FFFF // TimerA value + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_O_TBR +// register. +// +//***************************************************************************** +#define TIMER_TBR_TBRL 0x0000FFFF // TimerB value + +//***************************************************************************** +// +// The following are deprecated defines for the reset values of the timer +// registers. +// +//***************************************************************************** +#define TIMER_RV_TAILR 0xFFFFFFFF // TimerA interval load reg RV +#define TIMER_RV_TAR 0xFFFFFFFF // TimerA register RV +#define TIMER_RV_TAMATCHR 0xFFFFFFFF // TimerA match register RV +#define TIMER_RV_TBILR 0x0000FFFF // TimerB interval load reg RV +#define TIMER_RV_TBMATCHR 0x0000FFFF // TimerB match register RV +#define TIMER_RV_TBR 0x0000FFFF // TimerB register RV +#define TIMER_RV_TAPR 0x00000000 // TimerA prescale register RV +#define TIMER_RV_CFG 0x00000000 // Configuration register RV +#define TIMER_RV_TBPMR 0x00000000 // TimerB prescale match regi RV +#define TIMER_RV_TAPMR 0x00000000 // TimerA prescale match reg RV +#define TIMER_RV_CTL 0x00000000 // Control register RV +#define TIMER_RV_ICR 0x00000000 // Interrupt clear register RV +#define TIMER_RV_TBMR 0x00000000 // TimerB mode register RV +#define TIMER_RV_MIS 0x00000000 // Masked interrupt status reg RV +#define TIMER_RV_RIS 0x00000000 // Interrupt status register RV +#define TIMER_RV_TBPR 0x00000000 // TimerB prescale register RV +#define TIMER_RV_IMR 0x00000000 // Interrupt mask register RV +#define TIMER_RV_TAMR 0x00000000 // TimerA mode register RV + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_TnMR +// register. +// +//***************************************************************************** +#define TIMER_TNMR_TNAMS 0x00000008 // Alternate mode select +#define TIMER_TNMR_TNCMR 0x00000004 // Capture mode - count or time +#define TIMER_TNMR_TNTMR_MSK 0x00000003 // Timer mode mask +#define TIMER_TNMR_TNTMR_1_SHOT 0x00000001 // Mode - one shot +#define TIMER_TNMR_TNTMR_PERIOD 0x00000002 // Mode - periodic +#define TIMER_TNMR_TNTMR_CAP 0x00000003 // Mode - capture + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_TnPR +// register. +// +//***************************************************************************** +#define TIMER_TNPR_TNPSR 0x000000FF // TimerN prescale value + +//***************************************************************************** +// +// The following are deprecated defines for the bit fields in the TIMER_TnPMR +// register. +// +//***************************************************************************** +#define TIMER_TNPMR_TNPSMR 0x000000FF // TimerN prescale match value + +#endif + +#endif // __HW_TIMER_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_types.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_types.h new file mode 100644 index 00000000..d7a6ab4f --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_types.h @@ -0,0 +1,76 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_TYPES_H__ +#define __HW_TYPES_H__ + +//***************************************************************************** +// +// Define a boolean type, and values for true and false. +// +//***************************************************************************** +typedef unsigned char tBoolean; + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +//***************************************************************************** +// +// Macros for hardware access, both direct and via the bit-band region. +// +//***************************************************************************** +#define HWREG(x) \ + (*((volatile unsigned long *)(x))) +#define HWREGH(x) \ + (*((volatile unsigned short *)(x))) +#define HWREGB(x) \ + (*((volatile unsigned char *)(x))) +#define HWREGBITW(x, b) \ + HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ + (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) +#define HWREGBITH(x, b) \ + HWREGH(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ + (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) +#define HWREGBITB(x, b) \ + HWREGB(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ + (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) + + +#endif // __HW_TYPES_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_uart.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_uart.h new file mode 100644 index 00000000..ae50ac38 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_uart.h @@ -0,0 +1,417 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_UART_H__ +#define __HW_UART_H__ + +//***************************************************************************** +// +// The following are defines for the UART register offsets. +// +//***************************************************************************** +#define UART_O_DR 0x00000000 +#define UART_O_RSR 0x00000004 +#define UART_O_ECR 0x00000004 +#define UART_O_FR 0x00000018 +#define UART_O_ILPR 0x00000020 +#define UART_O_IBRD 0x00000024 +#define UART_O_FBRD 0x00000028 +#define UART_O_LCRH 0x0000002C +#define UART_O_CTL 0x00000030 +#define UART_O_IFLS 0x00000034 +#define UART_O_IM 0x00000038 +#define UART_O_RIS 0x0000003C +#define UART_O_MIS 0x00000040 +#define UART_O_ICR 0x00000044 +#define UART_O_DMACTL 0x00000048 +#define UART_O_LCTL 0x00000090 +#define UART_O_LSS 0x00000094 +#define UART_O_LTIM 0x00000098 +#define UART_O_9BITADDR 0x000000A4 +#define UART_O_9BITAMASK 0x000000A8 +#define UART_O_PP 0x00000FC0 +#define UART_O_CC 0x00000FC8 + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_DR register. +// +//****************************************************************************** +#define UART_DR_OE 0x00000800 // UART Overrun Error +#define UART_DR_BE 0x00000400 // UART Break Error +#define UART_DR_PE 0x00000200 // UART Parity Error +#define UART_DR_FE 0x00000100 // UART Framing Error +#define UART_DR_DATA_M 0x000000FF // Data Transmitted or Received +#define UART_DR_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_RSR register. +// +//****************************************************************************** +#define UART_RSR_OE 0x00000008 // UART Overrun Error +#define UART_RSR_BE 0x00000004 // UART Break Error +#define UART_RSR_PE 0x00000002 // UART Parity Error +#define UART_RSR_FE 0x00000001 // UART Framing Error +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_ECR register. +// +//****************************************************************************** +#define UART_ECR_DATA_M 0x000000FF // Error Clear +#define UART_ECR_DATA_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_FR register. +// +//****************************************************************************** +#define UART_FR_RI 0x00000100 // Ring Indicator +#define UART_FR_TXFE 0x00000080 // UART Transmit FIFO Empty +#define UART_FR_RXFF 0x00000040 // UART Receive FIFO Full +#define UART_FR_TXFF 0x00000020 // UART Transmit FIFO Full +#define UART_FR_RXFE 0x00000010 // UART Receive FIFO Empty +#define UART_FR_BUSY 0x00000008 // UART Busy +#define UART_FR_DCD 0x00000004 // Data Carrier Detect +#define UART_FR_DSR 0x00000002 // Data Set Ready +#define UART_FR_CTS 0x00000001 // Clear To Send +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_ILPR register. +// +//****************************************************************************** +#define UART_ILPR_ILPDVSR_M 0x000000FF // IrDA Low-Power Divisor +#define UART_ILPR_ILPDVSR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_IBRD register. +// +//****************************************************************************** +#define UART_IBRD_DIVINT_M 0x0000FFFF // Integer Baud-Rate Divisor +#define UART_IBRD_DIVINT_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_FBRD register. +// +//****************************************************************************** +#define UART_FBRD_DIVFRAC_M 0x0000003F // Fractional Baud-Rate Divisor +#define UART_FBRD_DIVFRAC_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_LCRH register. +// +//****************************************************************************** +#define UART_LCRH_SPS 0x00000080 // UART Stick Parity Select +#define UART_LCRH_WLEN_M 0x00000060 // UART Word Length 0x00000000 : + // UART_LCRH_WLEN_5 : 5 bits + // (default) 0x00000020 : + // UART_LCRH_WLEN_6 : 6 bits + // 0x00000040 : UART_LCRH_WLEN_7 : 7 + // bits 0x00000060 : + // UART_LCRH_WLEN_8 : 8 bits +#define UART_LCRH_WLEN_S 5 +#define UART_LCRH_FEN 0x00000010 // UART Enable FIFOs +#define UART_LCRH_STP2 0x00000008 // UART Two Stop Bits Select +#define UART_LCRH_EPS 0x00000004 // UART Even Parity Select +#define UART_LCRH_PEN 0x00000002 // UART Parity Enable +#define UART_LCRH_BRK 0x00000001 // UART Send Break +#define UART_LCRH_WLEN_M 0x00000060 // UART Word Length +#define UART_LCRH_WLEN_5 0x00000000 // 5 bits (default) +#define UART_LCRH_WLEN_6 0x00000020 // 6 bits +#define UART_LCRH_WLEN_7 0x00000040 // 7 bits +#define UART_LCRH_WLEN_8 0x00000060 // 8 bits +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_CTL register. +// +//****************************************************************************** +#define UART_CTL_CTSEN 0x00008000 // Enable Clear To Send +#define UART_CTL_RTSEN 0x00004000 // Enable Request to Send +#define UART_CTL_RI 0x00002000 // Ring Indicator +#define UART_CTL_DCD 0x00001000 // Data Carrier Detect +#define UART_CTL_RTS 0x00000800 // Request to Send +#define UART_CTL_DTR 0x00000400 // Data Terminal Ready +#define UART_CTL_RXE 0x00000200 // UART Receive Enable +#define UART_CTL_TXE 0x00000100 // UART Transmit Enable +#define UART_CTL_LBE 0x00000080 // UART Loop Back Enable +#define UART_CTL_LIN 0x00000040 // LIN Mode Enable +#define UART_CTL_HSE 0x00000020 // High-Speed Enable +#define UART_CTL_EOT 0x00000010 // End of Transmission +#define UART_CTL_SMART 0x00000008 // ISO 7816 Smart Card Support +#define UART_CTL_SIRLP 0x00000004 // UART SIR Low-Power Mode +#define UART_CTL_SIREN 0x00000002 // UART SIR Enable +#define UART_CTL_UARTEN 0x00000001 // UART Enable +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_IFLS register. +// +//****************************************************************************** +#define UART_IFLS_RX_M 0x00000038 // UART Receive Interrupt FIFO + // Level Select +#define UART_IFLS_RX_S 3 +#define UART_IFLS_TX_M 0x00000007 // UART Transmit Interrupt FIFO + // Level Select +#define UART_IFLS_TX_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_IM register. +// +//****************************************************************************** +#define UART_IM_DMATXIM 0x00020000 // Transmit DMA Interrupt Mask +#define UART_IM_DMARXIM 0x00010000 // Receive DMA Interrupt Mask +#define UART_IM_LME5IM 0x00008000 // LIN Mode Edge 5 Interrupt Mask +#define UART_IM_LME1IM 0x00004000 // LIN Mode Edge 1 Interrupt Mask +#define UART_IM_LMSBIM 0x00002000 // LIN Mode Sync Break Interrupt + // Mask +#define UART_IM_9BITIM 0x00001000 // 9-Bit Mode Interrupt Mask +#define UART_IM_EOTIM 0x00000800 // End of Transmission Interrupt + // Mask +#define UART_IM_OEIM 0x00000400 // UART Overrun Error Interrupt + // Mask +#define UART_IM_BEIM 0x00000200 // UART Break Error Interrupt Mask +#define UART_IM_PEIM 0x00000100 // UART Parity Error Interrupt Mask +#define UART_IM_FEIM 0x00000080 // UART Framing Error Interrupt + // Mask +#define UART_IM_RTIM 0x00000040 // UART Receive Time-Out Interrupt + // Mask +#define UART_IM_TXIM 0x00000020 // UART Transmit Interrupt Mask +#define UART_IM_RXIM 0x00000010 // UART Receive Interrupt Mask +#define UART_IM_DSRMIM 0x00000008 // UART Data Set Ready Modem + // Interrupt Mask +#define UART_IM_DCDMIM 0x00000004 // UART Data Carrier Detect Modem + // Interrupt Mask +#define UART_IM_CTSMIM 0x00000002 // UART Clear to Send Modem + // Interrupt Mask +#define UART_IM_RIMIM 0x00000001 // UART Ring Indicator Modem + // Interrupt Mask +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_RIS register. +// +//****************************************************************************** +#define UART_RIS_DMATXRIS 0x00020000 // Transmit DMA Raw Interrupt + // Status +#define UART_RIS_DMARXRIS 0x00010000 // Receive DMA Raw Interrupt Status +#define UART_RIS_LME5RIS 0x00008000 // LIN Mode Edge 5 Raw Interrupt + // Status +#define UART_RIS_LME1RIS 0x00004000 // LIN Mode Edge 1 Raw Interrupt + // Status +#define UART_RIS_LMSBRIS 0x00002000 // LIN Mode Sync Break Raw + // Interrupt Status +#define UART_RIS_9BITRIS 0x00001000 // 9-Bit Mode Raw Interrupt Status +#define UART_RIS_EOTRIS 0x00000800 // End of Transmission Raw + // Interrupt Status +#define UART_RIS_OERIS 0x00000400 // UART Overrun Error Raw Interrupt + // Status +#define UART_RIS_BERIS 0x00000200 // UART Break Error Raw Interrupt + // Status +#define UART_RIS_PERIS 0x00000100 // UART Parity Error Raw Interrupt + // Status +#define UART_RIS_FERIS 0x00000080 // UART Framing Error Raw Interrupt + // Status +#define UART_RIS_RTRIS 0x00000040 // UART Receive Time-Out Raw + // Interrupt Status +#define UART_RIS_TXRIS 0x00000020 // UART Transmit Raw Interrupt + // Status +#define UART_RIS_RXRIS 0x00000010 // UART Receive Raw Interrupt + // Status +#define UART_RIS_DSRRIS 0x00000008 // UART Data Set Ready Modem Raw + // Interrupt Status +#define UART_RIS_DCDRIS 0x00000004 // UART Data Carrier Detect Modem + // Raw Interrupt Status +#define UART_RIS_CTSRIS 0x00000002 // UART Clear to Send Modem Raw + // Interrupt Status +#define UART_RIS_RIRIS 0x00000001 // UART Ring Indicator Modem Raw + // Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_MIS register. +// +//****************************************************************************** +#define UART_MIS_DMATXMIS 0x00020000 // Transmit DMA Masked Interrupt + // Status +#define UART_MIS_DMARXMIS 0x00010000 // Receive DMA Masked Interrupt + // Status +#define UART_MIS_LME5MIS 0x00008000 // LIN Mode Edge 5 Masked Interrupt + // Status +#define UART_MIS_LME1MIS 0x00004000 // LIN Mode Edge 1 Masked Interrupt + // Status +#define UART_MIS_LMSBMIS 0x00002000 // LIN Mode Sync Break Masked + // Interrupt Status +#define UART_MIS_9BITMIS 0x00001000 // 9-Bit Mode Masked Interrupt + // Status +#define UART_MIS_EOTMIS 0x00000800 // End of Transmission Masked + // Interrupt Status +#define UART_MIS_OEMIS 0x00000400 // UART Overrun Error Masked + // Interrupt Status +#define UART_MIS_BEMIS 0x00000200 // UART Break Error Masked + // Interrupt Status +#define UART_MIS_PEMIS 0x00000100 // UART Parity Error Masked + // Interrupt Status +#define UART_MIS_FEMIS 0x00000080 // UART Framing Error Masked + // Interrupt Status +#define UART_MIS_RTMIS 0x00000040 // UART Receive Time-Out Masked + // Interrupt Status +#define UART_MIS_TXMIS 0x00000020 // UART Transmit Masked Interrupt + // Status +#define UART_MIS_RXMIS 0x00000010 // UART Receive Masked Interrupt + // Status +#define UART_MIS_DSRMIS 0x00000008 // UART Data Set Ready Modem Masked + // Interrupt Status +#define UART_MIS_DCDMIS 0x00000004 // UART Data Carrier Detect Modem + // Masked Interrupt Status +#define UART_MIS_CTSMIS 0x00000002 // UART Clear to Send Modem Masked + // Interrupt Status +#define UART_MIS_RIMIS 0x00000001 // UART Ring Indicator Modem Masked + // Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_ICR register. +// +//****************************************************************************** +#define UART_ICR_DMATXIC 0x00020000 // Transmit DMA Interrupt Clear +#define UART_ICR_DMARXIC 0x00010000 // Receive DMA Interrupt Clear +#define UART_ICR_LME5MIC 0x00008000 // LIN Mode Edge 5 Interrupt Clear +#define UART_ICR_LME1MIC 0x00004000 // LIN Mode Edge 1 Interrupt Clear +#define UART_ICR_LMSBMIC 0x00002000 // LIN Mode Sync Break Interrupt + // Clear +#define UART_ICR_9BITIC 0x00001000 // 9-Bit Mode Interrupt Clear +#define UART_ICR_EOTIC 0x00000800 // End of Transmission Interrupt + // Clear +#define UART_ICR_OEIC 0x00000400 // Overrun Error Interrupt Clear +#define UART_ICR_BEIC 0x00000200 // Break Error Interrupt Clear +#define UART_ICR_PEIC 0x00000100 // Parity Error Interrupt Clear +#define UART_ICR_FEIC 0x00000080 // Framing Error Interrupt Clear +#define UART_ICR_RTIC 0x00000040 // Receive Time-Out Interrupt Clear +#define UART_ICR_TXIC 0x00000020 // Transmit Interrupt Clear +#define UART_ICR_RXIC 0x00000010 // Receive Interrupt Clear +#define UART_ICR_DSRMIC 0x00000008 // UART Data Set Ready Modem + // Interrupt Clear +#define UART_ICR_DCDMIC 0x00000004 // UART Data Carrier Detect Modem + // Interrupt Clear +#define UART_ICR_CTSMIC 0x00000002 // UART Clear to Send Modem + // Interrupt Clear +#define UART_ICR_RIMIC 0x00000001 // UART Ring Indicator Modem + // Interrupt Clear +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_DMACTL register. +// +//****************************************************************************** +#define UART_DMACTL_DMAERR 0x00000004 // DMA on Error +#define UART_DMACTL_TXDMAE 0x00000002 // Transmit DMA Enable +#define UART_DMACTL_RXDMAE 0x00000001 // Receive DMA Enable +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_LCTL register. +// +//****************************************************************************** +#define UART_LCTL_BLEN_M 0x00000030 // Sync Break Length 0x00000000 : + // UART_LCTL_BLEN_13T : Sync break + // length is 13T bits (default) + // 0x00000010 : UART_LCTL_BLEN_14T : + // Sync break length is 14T bits + // 0x00000020 : UART_LCTL_BLEN_15T : + // Sync break length is 15T bits + // 0x00000030 : UART_LCTL_BLEN_16T : + // Sync break length is 16T bits +#define UART_LCTL_BLEN_S 4 +#define UART_LCTL_MASTER 0x00000001 // LIN Master Enable +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_LSS register. +// +//****************************************************************************** +#define UART_LSS_TSS_M 0x0000FFFF // Timer Snap Shot +#define UART_LSS_TSS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_LTIM register. +// +//****************************************************************************** +#define UART_LTIM_TIMER_M 0x0000FFFF // Timer Value +#define UART_LTIM_TIMER_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// UART_O_9BITADDR register. +// +//****************************************************************************** +#define UART_9BITADDR_9BITEN \ + 0x00008000 // Enable 9-Bit Mode + +#define UART_9BITADDR_ADDR_M \ + 0x000000FF // Self Address for 9-Bit Mode + +#define UART_9BITADDR_ADDR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// UART_O_9BITAMASK register. +// +//****************************************************************************** +#define UART_9BITAMASK_RANGE_M \ + 0x0000FF00 // Self Address Range for 9-Bit + // Mode + +#define UART_9BITAMASK_RANGE_S 8 +#define UART_9BITAMASK_MASK_M \ + 0x000000FF // Self Address Mask for 9-Bit Mode + +#define UART_9BITAMASK_MASK_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_PP register. +// +//****************************************************************************** +#define UART_PP_MSE 0x00000008 // Modem Support Extended +#define UART_PP_MS 0x00000004 // Modem Support +#define UART_PP_NB 0x00000002 // 9-Bit Support +#define UART_PP_SC 0x00000001 // Smart Card Support +//****************************************************************************** +// +// The following are defines for the bit fields in the UART_O_CC register. +// +//****************************************************************************** +#define UART_CC_CS_M 0x0000000F // UART Baud Clock Source + // 0x00000005 : UART_CC_CS_PIOSC : + // PIOSC 0x00000000 : + // UART_CC_CS_SYSCLK : The system + // clock (default) +#define UART_CC_CS_S 0 + + + +#endif // __HW_UART_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_udma.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_udma.h new file mode 100644 index 00000000..9a495bae --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_udma.h @@ -0,0 +1,336 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_UDMA_H__ +#define __HW_UDMA_H__ + +//***************************************************************************** +// +// The following are defines for the UDMA register offsets. +// +//***************************************************************************** +#define UDMA_O_STAT 0x00000000 +#define UDMA_O_CFG 0x00000004 +#define UDMA_O_CTLBASE 0x00000008 +#define UDMA_O_ALTBASE 0x0000000C +#define UDMA_O_WAITSTAT 0x00000010 +#define UDMA_O_SWREQ 0x00000014 +#define UDMA_O_USEBURSTSET 0x00000018 +#define UDMA_O_USEBURSTCLR 0x0000001C +#define UDMA_O_REQMASKSET 0x00000020 +#define UDMA_O_REQMASKCLR 0x00000024 +#define UDMA_O_ENASET 0x00000028 +#define UDMA_O_ENACLR 0x0000002C +#define UDMA_O_ALTSET 0x00000030 +#define UDMA_O_ALTCLR 0x00000034 +#define UDMA_O_PRIOSET 0x00000038 +#define UDMA_O_PRIOCLR 0x0000003C +#define UDMA_O_ERRCLR 0x0000004C +#define UDMA_O_CHASGN 0x00000500 +#define UDMA_O_CHIS 0x00000504 +#define UDMA_O_CHMAP0 0x00000510 +#define UDMA_O_CHMAP1 0x00000514 +#define UDMA_O_CHMAP2 0x00000518 +#define UDMA_O_CHMAP3 0x0000051C +#define UDMA_O_PV 0x00000FB0 + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_STAT register. +// +//****************************************************************************** +#define UDMA_STAT_DMACHANS_M 0x001F0000 // Available uDMA Channels Minus 1 +#define UDMA_STAT_DMACHANS_S 16 +#define UDMA_STAT_STATE_M 0x000000F0 // Control State Machine Status + // 0x00000090 : UDMA_STAT_STATE_DONE + // : Done 0x00000000 : + // UDMA_STAT_STATE_IDLE : Idle + // 0x00000010 : + // UDMA_STAT_STATE_RD_CTRL : Reading + // channel controller data + // 0x00000030 : + // UDMA_STAT_STATE_RD_DSTENDP : + // Reading destination end pointer + // 0x00000040 : + // UDMA_STAT_STATE_RD_SRCDAT : + // Reading source data 0x00000020 : + // UDMA_STAT_STATE_RD_SRCENDP : + // Reading source end pointer + // 0x00000080 : + // UDMA_STAT_STATE_STALL : Stalled + // 0x000000A0 : + // UDMA_STAT_STATE_UNDEF : Undefined + // 0x00000060 : UDMA_STAT_STATE_WAIT + // : Waiting for uDMA request to + // clear 0x00000070 : + // UDMA_STAT_STATE_WR_CTRL : Writing + // channel controller data + // 0x00000050 : + // UDMA_STAT_STATE_WR_DSTDAT : + // Writing destination data +#define UDMA_STAT_STATE_S 4 +#define UDMA_STAT_MASTEN 0x00000001 // Master Enable Status +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CFG register. +// +//****************************************************************************** +#define UDMA_CFG_MASTEN 0x00000001 // Controller Master Enable +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CTLBASE register. +// +//****************************************************************************** +#define UDMA_CTLBASE_ADDR_M 0xFFFFFC00 // Channel Control Base Address +#define UDMA_CTLBASE_ADDR_S 10 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_ALTBASE register. +// +//****************************************************************************** +#define UDMA_ALTBASE_ADDR_M 0xFFFFFFFF // Alternate Channel Address + // Pointer +#define UDMA_ALTBASE_ADDR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_WAITSTAT register. +// +//****************************************************************************** +#define UDMA_WAITSTAT_WAITREQ_M \ + 0xFFFFFFFF // Channel [n] Wait Status + +#define UDMA_WAITSTAT_WAITREQ_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_SWREQ register. +// +//****************************************************************************** +#define UDMA_SWREQ_M 0xFFFFFFFF // Channel [n] Software Request +#define UDMA_SWREQ_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// UDMA_O_USEBURSTSET register. +// +//****************************************************************************** +#define UDMA_USEBURSTSET_SET_M \ + 0xFFFFFFFF // Channel [n] Useburst Set + +#define UDMA_USEBURSTSET_SET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the +// UDMA_O_USEBURSTCLR register. +// +//****************************************************************************** +#define UDMA_USEBURSTCLR_CLR_M \ + 0xFFFFFFFF // Channel [n] Useburst Clear + +#define UDMA_USEBURSTCLR_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_REQMASKSET register. +// +//****************************************************************************** +#define UDMA_REQMASKSET_SET_M 0xFFFFFFFF // Channel [n] Request Mask Set +#define UDMA_REQMASKSET_SET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_REQMASKCLR register. +// +//****************************************************************************** +#define UDMA_REQMASKCLR_CLR_M 0xFFFFFFFF // Channel [n] Request Mask Clear +#define UDMA_REQMASKCLR_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_ENASET register. +// +//****************************************************************************** +#define UDMA_ENASET_CHENSET_M 0xFFFFFFFF // Channel [n] Enable Set +#define UDMA_ENASET_CHENSET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_ENACLR register. +// +//****************************************************************************** +#define UDMA_ENACLR_CLR_M 0xFFFFFFFF // Clear Channel [n] Enable Clear +#define UDMA_ENACLR_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_ALTSET register. +// +//****************************************************************************** +#define UDMA_ALTSET_SET_M 0xFFFFFFFF // Channel [n] Alternate Set +#define UDMA_ALTSET_SET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_ALTCLR register. +// +//****************************************************************************** +#define UDMA_ALTCLR_CLR_M 0xFFFFFFFF // Channel [n] Alternate Clear +#define UDMA_ALTCLR_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_PRIOSET register. +// +//****************************************************************************** +#define UDMA_PRIOSET_SET_M 0xFFFFFFFF // Channel [n] Priority Set +#define UDMA_PRIOSET_SET_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_PRIOCLR register. +// +//****************************************************************************** +#define UDMA_PRIOCLR_CLR_M 0xFFFFFFFF // Channel [n] Priority Clear +#define UDMA_PRIOCLR_CLR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_ERRCLR register. +// +//****************************************************************************** +#define UDMA_ERRCLR_ERRCLR 0x00000001 // uDMA Bus Error Status +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CHASGN register. +// +//****************************************************************************** +#define UDMA_CHASGN_M 0xFFFFFFFF // Channel [n] Assignment Select +#define UDMA_CHASGN_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CHIS register. +// +//****************************************************************************** +#define UDMA_CHIS_M 0xFFFFFFFF // Channel [n] Interrupt Status +#define UDMA_CHIS_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CHMAP0 register. +// +//****************************************************************************** +#define UDMA_CHMAP0_CH7SEL_M 0xF0000000 // uDMA Channel 7 Source Select +#define UDMA_CHMAP0_CH7SEL_S 28 +#define UDMA_CHMAP0_CH6SEL_M 0x0F000000 // uDMA Channel 6 Source Select +#define UDMA_CHMAP0_CH6SEL_S 24 +#define UDMA_CHMAP0_CH5SEL_M 0x00F00000 // uDMA Channel 5 Source Select +#define UDMA_CHMAP0_CH5SEL_S 20 +#define UDMA_CHMAP0_CH4SEL_M 0x000F0000 // uDMA Channel 4 Source Select +#define UDMA_CHMAP0_CH4SEL_S 16 +#define UDMA_CHMAP0_CH3SEL_M 0x0000F000 // uDMA Channel 3 Source Select +#define UDMA_CHMAP0_CH3SEL_S 12 +#define UDMA_CHMAP0_CH2SEL_M 0x00000F00 // uDMA Channel 2 Source Select +#define UDMA_CHMAP0_CH2SEL_S 8 +#define UDMA_CHMAP0_CH1SEL_M 0x000000F0 // uDMA Channel 1 Source Select +#define UDMA_CHMAP0_CH1SEL_S 4 +#define UDMA_CHMAP0_CH0SEL_M 0x0000000F // uDMA Channel 0 Source Select +#define UDMA_CHMAP0_CH0SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CHMAP1 register. +// +//****************************************************************************** +#define UDMA_CHMAP1_CH15SEL_M 0xF0000000 // uDMA Channel 15 Source Select +#define UDMA_CHMAP1_CH15SEL_S 28 +#define UDMA_CHMAP1_CH14SEL_M 0x0F000000 // uDMA Channel 14 Source Select +#define UDMA_CHMAP1_CH14SEL_S 24 +#define UDMA_CHMAP1_CH13SEL_M 0x00F00000 // uDMA Channel 13 Source Select +#define UDMA_CHMAP1_CH13SEL_S 20 +#define UDMA_CHMAP1_CH12SEL_M 0x000F0000 // uDMA Channel 12 Source Select +#define UDMA_CHMAP1_CH12SEL_S 16 +#define UDMA_CHMAP1_CH11SEL_M 0x0000F000 // uDMA Channel 11 Source Select +#define UDMA_CHMAP1_CH11SEL_S 12 +#define UDMA_CHMAP1_CH10SEL_M 0x00000F00 // uDMA Channel 10 Source Select +#define UDMA_CHMAP1_CH10SEL_S 8 +#define UDMA_CHMAP1_CH9SEL_M 0x000000F0 // uDMA Channel 9 Source Select +#define UDMA_CHMAP1_CH9SEL_S 4 +#define UDMA_CHMAP1_CH8SEL_M 0x0000000F // uDMA Channel 8 Source Select +#define UDMA_CHMAP1_CH8SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CHMAP2 register. +// +//****************************************************************************** +#define UDMA_CHMAP2_CH23SEL_M 0xF0000000 // uDMA Channel 23 Source Select +#define UDMA_CHMAP2_CH23SEL_S 28 +#define UDMA_CHMAP2_CH22SEL_M 0x0F000000 // uDMA Channel 22 Source Select +#define UDMA_CHMAP2_CH22SEL_S 24 +#define UDMA_CHMAP2_CH21SEL_M 0x00F00000 // uDMA Channel 21 Source Select +#define UDMA_CHMAP2_CH21SEL_S 20 +#define UDMA_CHMAP2_CH20SEL_M 0x000F0000 // uDMA Channel 20 Source Select +#define UDMA_CHMAP2_CH20SEL_S 16 +#define UDMA_CHMAP2_CH19SEL_M 0x0000F000 // uDMA Channel 19 Source Select +#define UDMA_CHMAP2_CH19SEL_S 12 +#define UDMA_CHMAP2_CH18SEL_M 0x00000F00 // uDMA Channel 18 Source Select +#define UDMA_CHMAP2_CH18SEL_S 8 +#define UDMA_CHMAP2_CH17SEL_M 0x000000F0 // uDMA Channel 17 Source Select +#define UDMA_CHMAP2_CH17SEL_S 4 +#define UDMA_CHMAP2_CH16SEL_M 0x0000000F // uDMA Channel 16 Source Select +#define UDMA_CHMAP2_CH16SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_CHMAP3 register. +// +//****************************************************************************** +#define UDMA_CHMAP3_CH31SEL_M 0xF0000000 // uDMA Channel 31 Source Select +#define UDMA_CHMAP3_CH31SEL_S 28 +#define UDMA_CHMAP3_CH30SEL_M 0x0F000000 // uDMA Channel 30 Source Select +#define UDMA_CHMAP3_CH30SEL_S 24 +#define UDMA_CHMAP3_CH29SEL_M 0x00F00000 // uDMA Channel 29 Source Select +#define UDMA_CHMAP3_CH29SEL_S 20 +#define UDMA_CHMAP3_CH28SEL_M 0x000F0000 // uDMA Channel 28 Source Select +#define UDMA_CHMAP3_CH28SEL_S 16 +#define UDMA_CHMAP3_CH27SEL_M 0x0000F000 // uDMA Channel 27 Source Select +#define UDMA_CHMAP3_CH27SEL_S 12 +#define UDMA_CHMAP3_CH26SEL_M 0x00000F00 // uDMA Channel 26 Source Select +#define UDMA_CHMAP3_CH26SEL_S 8 +#define UDMA_CHMAP3_CH25SEL_M 0x000000F0 // uDMA Channel 25 Source Select +#define UDMA_CHMAP3_CH25SEL_S 4 +#define UDMA_CHMAP3_CH24SEL_M 0x0000000F // uDMA Channel 24 Source Select +#define UDMA_CHMAP3_CH24SEL_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the UDMA_O_PV register. +// +//****************************************************************************** +#define UDMA_PV_MAJOR_M 0x0000FF00 // Major Revision +#define UDMA_PV_MAJOR_S 8 +#define UDMA_PV_MINOR_M 0x000000FF // Minor Revision +#define UDMA_PV_MINOR_S 0 + + + +#endif // __HW_UDMA_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_wdt.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_wdt.h new file mode 100644 index 00000000..00b14acb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CCWare/inc/hw_wdt.h @@ -0,0 +1,131 @@ +//***************************************************************************** +// +// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef __HW_WDT_H__ +#define __HW_WDT_H__ + +//***************************************************************************** +// +// The following are defines for the WDT register offsets. +// +//***************************************************************************** +#define WDT_O_LOAD 0x00000000 +#define WDT_O_VALUE 0x00000004 +#define WDT_O_CTL 0x00000008 +#define WDT_O_ICR 0x0000000C +#define WDT_O_RIS 0x00000010 +#define WDT_O_MIS 0x00000014 +#define WDT_O_TEST 0x00000418 +#define WDT_O_LOCK 0x00000C00 + + + +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_LOAD register. +// +//****************************************************************************** +#define WDT_LOAD_M 0xFFFFFFFF // Watchdog Load Value +#define WDT_LOAD_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_VALUE register. +// +//****************************************************************************** +#define WDT_VALUE_M 0xFFFFFFFF // Watchdog Value +#define WDT_VALUE_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_CTL register. +// +//****************************************************************************** +#define WDT_CTL_WRC 0x80000000 // Write Complete +#define WDT_CTL_INTTYPE 0x00000004 // Watchdog Interrupt Type +#define WDT_CTL_RESEN 0x00000002 // Watchdog Reset Enable. This bit + // is not used in cc3xx, WDOG shall + // always generate RESET to system + // irrespective of this bit setting. +#define WDT_CTL_INTEN 0x00000001 // Watchdog Interrupt Enable +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_ICR register. +// +//****************************************************************************** +#define WDT_ICR_M 0xFFFFFFFF // Watchdog Interrupt Clear +#define WDT_ICR_S 0 +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_RIS register. +// +//****************************************************************************** +#define WDT_RIS_WDTRIS 0x00000001 // Watchdog Raw Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_MIS register. +// +//****************************************************************************** +#define WDT_MIS_WDTMIS 0x00000001 // Watchdog Masked Interrupt Status +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_TEST register. +// +//****************************************************************************** +#define WDT_TEST_STALL_EN_M 0x00000C00 // Watchdog stall enable +#define WDT_TEST_STALL_EN_S 10 +#define WDT_TEST_STALL 0x00000100 // Watchdog Stall Enable +//****************************************************************************** +// +// The following are defines for the bit fields in the WDT_O_LOCK register. +// +//****************************************************************************** +#define WDT_LOCK_M 0xFFFFFFFF // Watchdog Lock +#define WDT_LOCK_S 0 +#define WDT_LOCK_UNLOCKED 0x00000000 // Unlocked +#define WDT_LOCK_LOCKED 0x00000001 // Locked +#define WDT_LOCK_UNLOCK 0x1ACCE551 // Unlocks the watchdog timer + +//***************************************************************************** +// +// The following are defines for the bit fields in the WDT_ISR, WDT_RIS, and +// WDT_MIS registers. +// +//***************************************************************************** +#define WDT_INT_TIMEOUT 0x00000001 // Watchdog timer expired + + + + + +#endif // __HW_WDT_H__ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CMSIS/TI/TICC3200/cc3200.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CMSIS/TI/TICC3200/cc3200.h new file mode 100644 index 00000000..d9a3c1cc --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/ext/CMSIS/TI/TICC3200/cc3200.h @@ -0,0 +1,118 @@ + + +#ifndef __CC3200_H +#define __CC3200_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +#define __CM4_REV 0x0001U /*!< Core revision r0p1 */ +#define __MPU_PRESENT 1U /*!< STM32F4XX provides an MPU */ +#define __NVIC_PRIO_BITS 4U /*!< STM32F4XX uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0U /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1U /*!< FPU present */ + +typedef enum +{ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1, ADC2 and ADC3 global Interrupts */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break interrupt and TIM9 global interrupt */ + TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global interrupt */ + TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FSMC_IRQn = 48, /*!< FSMC global Interrupt */ + SDIO_IRQn = 49, /*!< SDIO global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ + CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ + CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ + CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ + OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ + OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ + OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ + OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ + DCMI_IRQn = 78, /*!< DCMI global interrupt */ + HASH_RNG_IRQn = 80, /*!< Hash and RNG global interrupt */ + FPU_IRQn = 81 /*!< FPU global interrupt */ + +} IRQn_Type; + + +#include "core_cm4.h" + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __CC3200_H \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/startup/ARMCMx/devices/TICC3200/cmparams.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/startup/ARMCMx/devices/TICC3200/cmparams.h new file mode 100644 index 00000000..a98242b1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/common/startup/ARMCMx/devices/TICC3200/cmparams.h @@ -0,0 +1,119 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file CC3200/cmparams.h + * @brief ARM Cortex-M4 parameters for the CC3200. + * + * @defgroup ARMCMx_CC3200 CC3200 Specific Parameters + * @ingroup ARMCMx_SPECIFIC + * @details This file contains the Cortex-M4 specific parameters for the + * CC3200 platform. + * @{ + */ + +#ifndef CMPARAMS_H +#define CMPARAMS_H + +/* Defines required for correct CMSIS header functioning */ +#define __MPU_PRESENT 1 /**< MPU present */ +#define __NVIC_PRIO_BITS 3 /**< Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 1 /**< Use different SysTick Config */ +#define __FPU_PRESENT 1 /**< FPU present */ + +/* The following two defines are needed by ChibiOS */ +#define SVCall_IRQn -5 +#define PendSV_IRQn -3 + +/** + * @brief Cortex core model. + */ +#define CORTEX_MODEL 4 + +/** + * @brief Floating Point unit presence. + */ +#define CORTEX_HAS_FPU 1 + +/** + * @brief Number of bits in priority masks. + */ +#define CORTEX_PRIORITY_BITS 4 + +/** + * @brief Number of interrupt vectors. + * @note This number does not include the 16 system vectors and must be + * rounded to a multiple of 8. + */ +#define CORTEX_NUM_VECTORS 184 + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +// /* If the device type is not externally defined, for example from the Makefile, +// then a file named board.h is included. This file must contain a device +// definition compatible with the vendor include file.*/ +// #if !defined(STM32F405xx) && !defined(STM32F415xx) && \ +// !defined(STM32F407xx) && !defined(STM32F417xx) && \ +// !defined(STM32F427xx) && !defined(STM32F437xx) && \ +// !defined(STM32F429xx) && !defined(STM32F439xx) && \ +// !defined(STM32F401xC) && !defined(STM32F401xE) && \ +// !defined(STM32F410Cx) && !defined(STM32F410Rx) && \ +// !defined(STM32F411xE) && !defined(STM32F446xx) && \ +// !defined(STM32F469xx) && !defined(STM32F479xx) +#include "board.h" +// #endif + +typedef int IRQn_Type; + +#include "core_cm4.h" + +/* Including the device CMSIS header. Note, we are not using the definitions + from this header because we need this file to be usable also from + assembler source files. We verify that the info matches instead.*/ +//#include "cc3200.h" + + +/* Including the CCWare peripheral headers.*/ +#include "asmdefs.h" +#include "hw_adc.h" +#include "hw_aes.h" +#include "hw_apps_config.h" +#include "hw_apps_rcm.h" +#include "hw_camera.h" +#include "hw_common_reg.h" +#include "hw_des.h" +#include "hw_dthe.h" +#include "hw_flash_ctrl.h" +#include "hw_gpio.h" +#include "hw_gprcm.h" +#include "hw_hib1p2.h" +#include "hw_hib3p3.h" +#include "hw_i2c.h" +#include "hw_ints.h" +#include "hw_mcasp.h" +#include "hw_mcspi.h" +#include "hw_memmap.h" +#include "hw_mmchs.h" +#include "hw_nvic.h" +#include "hw_ocp_shared.h" +#include "hw_shamd5.h" +#include "hw_stack_die_ctrl.h" +#include "hw_timer.h" +#include "hw_types.h" +#include "hw_uart.h" +#include "hw_udma.h" +#include "hw_wdt.h" + +#if CORTEX_NUM_VECTORS != ((((NUM_INTERRUPTS - 16) + 7) / 8) * 8) +#error "CCWare NUM_INTERRUPTS mismatch" +#endif + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* CMPARAMS_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/dummy_includes/hal_community.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/dummy_includes/hal_community.h new file mode 100644 index 00000000..27cb0645 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/dummy_includes/hal_community.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_COMMUNITY_H +#define HAL_COMMUNITY_H + +#ifdef __cplusplus +extern "C" { +#endif + + void halCommunityInit(void); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_COMMUNITY_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_nf_community.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_nf_community.h new file mode 100644 index 00000000..d2ae9bd3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/hal_nf_community.h @@ -0,0 +1,95 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_NF_COMMUNITY_H +#define HAL_NF_COMMUNITY_H + + +// these are for error checks on the configuration header files +#if !defined(HAL_USE_STM32_FLASH) +#define HAL_USE_STM32_FLASH FALSE +#endif + +#if !defined(HAL_USE_STM32_CRC) +// the default for this driver is to be included +#define HAL_USE_STM32_CRC TRUE +#endif + +#if !defined(HAL_USE_STM32_RNG) +// the default for this driver is to be included +#define HAL_USE_STM32_RNG TRUE +#endif + +#if !defined(HAL_USE_FSMC) +#define HAL_USE_FSMC FALSE +#endif + +#if !defined(HAL_USE_STM32_ONEWIRE) +// the default for this driver is NOT to be included +#define HAL_USE_STM32_ONEWIRE FALSE +#endif + +#if !defined(HAL_USE_STM32_USB_MSD) +// the default for this driver is NOT to be included +#define HAL_USE_STM32_USB_MSD FALSE +#endif + +#if !defined(HAL_USE_STM32_QSPI) +// the default for this driver is NOT to be included +#define HAL_USE_STM32_QSPI FALSE +#endif + +// Abstract interfaces + +// Shared headers +// #include "hal_nnnn.h" + +// Normal drivers +#include +#include +#include +#include +#include +#include + +// Complex drivers +// #include "hal_nnnn.h" + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + + void halCommunityInit(void); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_NF_COMMUNITY_H + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_crc/hal_stm32_crc.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_crc/hal_stm32_crc.h new file mode 100644 index 00000000..bfbc7c3d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_crc/hal_stm32_crc.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_STM32_CRC_H +#define HAL_STM32_CRC_H + +#if (HAL_USE_STM32_CRC == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +// Enables the crcAcquireModule() and crcReleaseModule() APIs. +// Disabling this option saves both code and data space. +#if !defined(CRC_USE_MUTUAL_EXCLUSION) +#define CRC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + CRC_UNINIT, // Not initialized + CRC_STOP, // Stopped + CRC_READY, // Ready + CRC_ACTIVE // Calculating CRC +} crcState; + +#include "crc_lld.h" + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + + void crcInit(void); + void crcStart(const crcConfig *config); + void crcStop(); + void crcReset(); + uint32_t crcCompute(const void* buffer, int size, uint32_t initialCrc); + +#if (CRC_USE_MUTUAL_EXCLUSION == TRUE) + void crcAquireModule(); + void crcReleaseModule(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_STM32_CRC + +#endif // HAL_STM32_CRC_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_flash/hal_stm32_flash.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_flash/hal_stm32_flash.h new file mode 100644 index 00000000..a5eafabb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_flash/hal_stm32_flash.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_ST_FLASH_H +#define HAL_ST_FLASH_H + +#if (HAL_USE_STM32_FLASH == TRUE) + +#include "flash_lld.h" + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// +#define FLASH_ERASED_WORD 0x0FFFFFFFFU + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + + void stm32FlashInit(void); + void stm32FlashObjectInit(SMT32FlashDriver* flash); + void stm32FlashReadBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer); + int stm32FlashWrite(uint32_t startAddress, uint32_t length, const uint8_t* buffer); + int stm32FlashIsErased(uint32_t startAddress, uint32_t length); + int stm32FlashErase(uint32_t address); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_STM32_FLASH + +#endif // HAL_ST_FLASH_H + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc/hal_stm32_fsmc.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc/hal_stm32_fsmc.h new file mode 100644 index 00000000..ff94d9cf --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_fsmc/hal_stm32_fsmc.h @@ -0,0 +1,335 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_FSMC_H_ +#define HAL_FSMC_H_ + +#if (HAL_USE_FSMC == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +// (Re)define if needed base address constants supplied in ST's CMSIS +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + #if !defined(FSMC_Bank1_R_BASE) + #define FSMC_Bank1_R_BASE (FMC_R_BASE + 0x0000) + #endif + #if !defined(FSMC_Bank1E_R_BASE) + #define FSMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104) + #endif + #if !defined(FSMC_Bank2_R_BASE) + #define FSMC_Bank2_R_BASE (FMC_R_BASE + 0x0060) + #endif + #if !defined(FSMC_Bank3_R_BASE) + #define FSMC_Bank3_R_BASE (FMC_R_BASE + 0x0080) + #endif + #if !defined(FSMC_Bank4_R_BASE) + #define FSMC_Bank4_R_BASE (FMC_R_BASE + 0x00A0) + #endif + #if !defined(FSMC_Bank5_R_BASE) + #define FSMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140) + #endif +#else + #if !defined(FSMC_Bank1_R_BASE) + #define FSMC_Bank1_R_BASE (FSMC_R_BASE + 0x0000) + #endif + #if !defined(FSMC_Bank1E_R_BASE) + #define FSMC_Bank1E_R_BASE (FSMC_R_BASE + 0x0104) + #endif + #if !defined(FSMC_Bank2_R_BASE) + #define FSMC_Bank2_R_BASE (FSMC_R_BASE + 0x0060) + #endif + #if !defined(FSMC_Bank3_R_BASE) + #define FSMC_Bank3_R_BASE (FSMC_R_BASE + 0x0080) + #endif + #if !defined(FSMC_Bank4_R_BASE) + #define FSMC_Bank4_R_BASE (FSMC_R_BASE + 0x00A0) + #endif +#endif + +/* + * Base bank mappings + */ +#define FSMC_Bank1_MAP_BASE ((uint32_t) 0x60000000) +#define FSMC_Bank2_MAP_BASE ((uint32_t) 0x70000000) +#define FSMC_Bank3_MAP_BASE ((uint32_t) 0x80000000) +#define FSMC_Bank4_MAP_BASE ((uint32_t) 0x90000000) +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F7)) + #define FSMC_Bank5_MAP_BASE ((uint32_t) 0xC0000000) + #define FSMC_Bank6_MAP_BASE ((uint32_t) 0xD0000000) +#endif + +/* + * Subbunks of bank1 + */ +#define FSMC_SUBBUNK_OFFSET (1024 * 1024 * 64) +#define FSMC_Bank1_1_MAP (FSMC_Bank1_MAP_BASE) +#define FSMC_Bank1_2_MAP (FSMC_Bank1_1_MAP + FSMC_SUBBUNK_OFFSET) +#define FSMC_Bank1_3_MAP (FSMC_Bank1_2_MAP + FSMC_SUBBUNK_OFFSET) +#define FSMC_Bank1_4_MAP (FSMC_Bank1_3_MAP + FSMC_SUBBUNK_OFFSET) + +/* + * Bank 2 (NAND) + */ +#define FSMC_Bank2_MAP_COMMON (FSMC_Bank2_MAP_BASE + 0) +#define FSMC_Bank2_MAP_ATTR (FSMC_Bank2_MAP_BASE + 0x8000000) + +#define FSMC_Bank2_MAP_COMMON_DATA (FSMC_Bank2_MAP_COMMON + 0) +#define FSMC_Bank2_MAP_COMMON_CMD (FSMC_Bank2_MAP_COMMON + 0x10000) +#define FSMC_Bank2_MAP_COMMON_ADDR (FSMC_Bank2_MAP_COMMON + 0x20000) + +#define FSMC_Bank2_MAP_ATTR_DATA (FSMC_Bank2_MAP_ATTR + 0) +#define FSMC_Bank2_MAP_ATTR_CMD (FSMC_Bank2_MAP_ATTR + 0x10000) +#define FSMC_Bank2_MAP_ATTR_ADDR (FSMC_Bank2_MAP_ATTR + 0x20000) + +/* + * Bank 3 (NAND) + */ +#define FSMC_Bank3_MAP_COMMON (FSMC_Bank3_MAP_BASE + 0) +#define FSMC_Bank3_MAP_ATTR (FSMC_Bank3_MAP_BASE + 0x8000000) + +#define FSMC_Bank3_MAP_COMMON_DATA (FSMC_Bank3_MAP_COMMON + 0) +#define FSMC_Bank3_MAP_COMMON_CMD (FSMC_Bank3_MAP_COMMON + 0x10000) +#define FSMC_Bank3_MAP_COMMON_ADDR (FSMC_Bank3_MAP_COMMON + 0x20000) + +#define FSMC_Bank3_MAP_ATTR_DATA (FSMC_Bank3_MAP_ATTR + 0) +#define FSMC_Bank3_MAP_ATTR_CMD (FSMC_Bank3_MAP_ATTR + 0x10000) +#define FSMC_Bank3_MAP_ATTR_ADDR (FSMC_Bank3_MAP_ATTR + 0x20000) + +/* + * Bank 4 (PC card) + */ +#define FSMC_Bank4_MAP_COMMON (FSMC_Bank4_MAP_BASE + 0) +#define FSMC_Bank4_MAP_ATTR (FSMC_Bank4_MAP_BASE + 0x8000000) +#define FSMC_Bank4_MAP_IO (FSMC_Bank4_MAP_BASE + 0xC000000) + +/* + * More convenient typedefs than CMSIS has + */ +typedef struct { + __IO uint32_t PCR; /**< NAND Flash control */ + __IO uint32_t SR; /**< NAND Flash FIFO status and interrupt */ + __IO uint32_t PMEM; /**< NAND Flash Common memory space timing */ + __IO uint32_t PATT; /**< NAND Flash Attribute memory space timing */ + uint32_t RESERVED0; /**< Reserved, 0x70 */ + __IO uint32_t ECCR; /**< NAND Flash ECC result registers */ +} FSMC_NAND_TypeDef; + +typedef struct { + __IO uint32_t PCR; /**< PC Card control */ + __IO uint32_t SR; /**< PC Card FIFO status and interrupt */ + __IO uint32_t PMEM; /**< PC Card Common memory space timing */ + __IO uint32_t PATT; /**< PC Card Attribute memory space timing */ + __IO uint32_t PIO; /**< PC Card I/O space timing */ +} FSMC_PCCard_TypeDef; + +typedef struct { + __IO uint32_t BCR; /**< SRAM/NOR chip-select control registers */ + __IO uint32_t BTR; /**< SRAM/NOR chip-select timing registers */ + uint32_t RESERVED[63]; /**< Reserved */ + __IO uint32_t BWTR; /**< SRAM/NOR write timing registers */ +} FSMC_SRAM_NOR_TypeDef; + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F7)) + +typedef struct { + __IO uint32_t SDCR1; /**< SDRAM control register (bank 1) */ + __IO uint32_t SDCR2; /**< SDRAM control register (bank 2) */ + __IO uint32_t SDTR1; /**< SDRAM timing register (bank 1) */ + __IO uint32_t SDTR2; /**< SDRAM timing register (bank 2) */ + __IO uint32_t SDCMR; /**< SDRAM comand mode register */ + __IO uint32_t SDRTR; /**< SDRAM refresh timer register */ + __IO uint32_t SDSR; /**< SDRAM status register */ +} FSMC_SDRAM_TypeDef; + +#endif + +/** + * @brief PCR register + */ +#define FSMC_PCR_PWAITEN ((uint32_t)1 << 1) +#define FSMC_PCR_PBKEN ((uint32_t)1 << 2) +#define FSMC_PCR_PTYP ((uint32_t)1 << 3) +#define FSMC_PCR_PWID_8 ((uint32_t)0 << 4) +#define FSMC_PCR_PWID_16 ((uint32_t)1 << 4) +#define FSMC_PCR_PWID_RESERVED1 ((uint32_t)2 << 4) +#define FSMC_PCR_PWID_RESERVED2 ((uint32_t)3 << 4) +#define FSMC_PCR_PWID_MASK ((uint32_t)3 << 4) +#define FSMC_PCR_ECCEN ((uint32_t)1 << 6) +#define FSMC_PCR_PTYP_PCCARD 0 +#define FSMC_PCR_PTYP_NAND FSMC_PCR_PTYP + +/** + * @brief SR register + */ +#define FSMC_SR_IRS ((uint8_t)0x01) +#define FSMC_SR_ILS ((uint8_t)0x02) +#define FSMC_SR_IFS ((uint8_t)0x04) +#define FSMC_SR_IREN ((uint8_t)0x08) +#define FSMC_SR_ILEN ((uint8_t)0x10) +#define FSMC_SR_IFEN ((uint8_t)0x20) +#define FSMC_SR_FEMPT ((uint8_t)0x40) +#define FSMC_SR_ISR_MASK (FSMC_SR_IRS | FSMC_SR_ILS | FSMC_SR_IFS) + +/** + * @brief BCR register + */ +#define FSMC_BCR_MBKEN ((uint32_t)1 << 0) +#define FSMC_BCR_MUXEN ((uint32_t)1 << 1) +#define FSMC_BCR_MTYP_SRAM ((uint32_t)0 << 2) +#define FSMC_BCR_MTYP_PSRAM ((uint32_t)1 << 2) +#define FSMC_BCR_MTYP_NOR_NAND ((uint32_t)2 << 2) +#define FSMC_BCR_MTYP_RESERVED ((uint32_t)3 << 2) +#define FSMC_BCR_MWID_8 ((uint32_t)0 << 4) +#define FSMC_BCR_MWID_16 ((uint32_t)1 << 4) +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F7)) +#define FSMC_BCR_MWID_32 ((uint32_t)2 << 4) +#else +#define FSMC_BCR_MWID_RESERVED1 ((uint32_t)2 << 4) +#endif +#define FSMC_BCR_MWID_RESERVED2 ((uint32_t)3 << 4) +#define FSMC_BCR_FACCEN ((uint32_t)1 << 6) +#define FSMC_BCR_BURSTEN ((uint32_t)1 << 8) +#define FSMC_BCR_WAITPOL ((uint32_t)1 << 9) +#define FSMC_BCR_WRAPMOD ((uint32_t)1 << 10) +#define FSMC_BCR_WAITCFG ((uint32_t)1 << 11) +#define FSMC_BCR_WREN ((uint32_t)1 << 12) +#define FSMC_BCR_WAITEN ((uint32_t)1 << 13) +#define FSMC_BCR_EXTMOD ((uint32_t)1 << 14) +#define FSMC_BCR_ASYNCWAIT ((uint32_t)1 << 15) +#define FSMC_BCR_CBURSTRW ((uint32_t)1 << 19) +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F7)) +#define FSMC_BCR_CCLKEN ((uint32_t)1 << 20) +#endif +#if (defined(STM32F7)) +#define FSMC_BCR_WFDIS ((uint32_t)1 << 21) +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief FSMC driver enable switch. + * @details If set to @p TRUE the support for FSMC is included. + */ +#if !defined(STM32_FSMC_USE_FSMC1) +#define STM32_FSMC_USE_FSMC1 FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ +#if !STM32_FSMC_USE_FSMC1 +#error "FSMC driver activated but no FSMC peripheral assigned" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an FSMC driver. + */ +typedef struct FSMCDriver FSMCDriver; + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + FSMC_UNINIT = 0, /**< Not initialized. */ + FSMC_STOP = 1, /**< Stopped. */ + FSMC_READY = 2, /**< Ready. */ +} fsmcstate_t; + +/** + * @brief Structure representing an FSMC driver. + */ +struct FSMCDriver { + /** + * @brief Driver state. + */ + fsmcstate_t state; + /* End of the mandatory fields.*/ + +#if STM32_SRAM_USE_FSMC_SRAM1 + FSMC_SRAM_NOR_TypeDef *sram1; +#endif +#if STM32_SRAM_USE_FSMC_SRAM2 + FSMC_SRAM_NOR_TypeDef *sram2; +#endif +#if STM32_SRAM_USE_FSMC_SRAM3 + FSMC_SRAM_NOR_TypeDef *sram3; +#endif +#if STM32_SRAM_USE_FSMC_SRAM4 + FSMC_SRAM_NOR_TypeDef *sram4; +#endif +#if STM32_NAND_USE_FSMC_NAND1 + FSMC_NAND_TypeDef *nand1; +#endif +#if STM32_NAND_USE_FSMC_NAND2 + FSMC_NAND_TypeDef *nand2; +#endif +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F7)) + #if STM32_USE_FSMC_SDRAM + FSMC_SDRAM_TypeDef *sdram; + #endif +#endif +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32_FSMC_USE_FSMC1 && !defined(__DOXYGEN__) +extern FSMCDriver FSMCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void stm32FsmcInit(void); + void fsmc_start(FSMCDriver *fsmcp); + void fsmc_stop(FSMCDriver *fsmcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_FSMC */ + +#endif /* HAL_FSMC_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_onewire/hal_stm32_onewire.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_onewire/hal_stm32_onewire.h new file mode 100644 index 00000000..d56c33c5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_onewire/hal_stm32_onewire.h @@ -0,0 +1,117 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_STM32_ONEWIRE_H +#define HAL_STM32_ONEWIRE_H + +#if (HAL_USE_STM32_ONEWIRE == TRUE) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +// memory commands // +#define WR_SCRPAD 0x0F /* write scratchpad */ +#define RD_SCRPAD 0xAA /* read scratchpad */ +#define COPY_SCRPAD 0x55 /* copy scratchpad */ +#define RD_MEMORY 0xF0 /* read memory */ +#define RD_MEMORY_CRC 0xA5 /* read memory with CRC */ +#define CLEAR_MEMORY 0x3C /* clear memory */ +#define SKIP_ROM 0xCC /* skip ROM */ + +/* ROM commands */ +#define READ_ROM 0x33 /* read ROM */ +#define MATCH_ROM 0x55 /* match ROM */ +#define SEARCH_ROM 0xF0 /* search ROM */ +#define COND_SEARCH_ROM 0xEC /* conditional search ROM */ + +// General command defines +#define READ_MEMORY_PSW_COMMAND 0x69 + +#define MAX_PORTNUM 16 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ + +/** + * @brief Enables the @p oneWireAcquireBus() and @p oneWireReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ONEWIRE_USE_MUTUAL_EXCLUSION) +#define ONEWIRE_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +// forward declarations +typedef struct ONEWIREDriver ONEWIREDriver; + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + ONEWIRE_UNINIT, /* Not initialized. */ + ONEWIRE_STOP, /* Stopped. */ + ONEWIRE_READY, /* Ready. */ + ONEWIRE_ACTIVE /* Generating random number. */ +} oneWireState; + +#include + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void oneWireInit(void); + void oneWireStart(void); + void oneWireStop(void); + uint8_t oneWireTouchReset(void); + bool oneWireTouchBit(bool sendbit); + uint8_t oneWireTouchByte(uint8_t sendbyte); + uint8_t oneWireWriteByte(uint8_t sendbyte); + uint8_t oneWireReadByte(void); + void oneWireSerialNum(uint8_t* serialnum_buf, uint8_t do_read); + uint8_t oneWireAccess(void); + uint8_t oneWireBlock(uint8_t doReset, uint8_t* tran_buf, uint8_t tran_len); + uint8_t oneWireWriteMemory(uint8_t* buf, uint32_t ln, uint32_t adr); + uint8_t oneWireCopyScratchpad(uint32_t ln, uint32_t adr); + uint8_t oneWireWriteScratchpad(uint8_t* buf, uint32_t ln, uint32_t adr); + uint8_t oneWireReadPage(uint32_t start_pg, uint8_t* finalbuf); + uint8_t oneWireReadPageCRCEE77(uint32_t page, uint8_t *buff); + bool oneWireFindFirst (bool doReset, bool alarmOnly); + bool oneWireFindNext (bool doReset, bool alarmOnly); + + +#if ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE + void oneWireAcquireModule(void); + void oneWireReleaseModule(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_STM32_ONEWIRE */ + +#endif /* HAL_STM32_ONEWIRE_H_ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_qspi/hal_stm32_qspi.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_qspi/hal_stm32_qspi.h new file mode 100644 index 00000000..0b9e40cf --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_qspi/hal_stm32_qspi.h @@ -0,0 +1,75 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_STM32_QSPI_H +#define HAL_STM32_QSPI_H + +#if (HAL_USE_STM32_QSPI == TRUE) +#if defined(STM32F0xx_MCUCONF) +#error "CAN'T ENABLE QSPI FOR STM32F0 series" +#endif + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ + +/** + * @brief Enables the @p qspiAcquireBus() and @p qspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +// #if !defined(QSPI_USE_MUTUAL_EXCLUSION) +// #define QSPI_USE_MUTUAL_EXCLUSION TRUE +// #endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +#include "qspi_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* QSPI Error codes */ +#define QSPI_OK ((uint8_t)0x00) +#define QSPI_ERROR ((uint8_t)0x01) +#define QSPI_BUSY ((uint8_t)0x02) +#define QSPI_NOT_SUPPORTED ((uint8_t)0x04) +#define QSPI_SUSPENDED ((uint8_t)0x08) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + void qspiInit(void); + void qspiStart(QSPI_HandleTypeDef* qspip); + void qspiStop(QSPI_HandleTypeDef* qspi); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_STM32_QSPI */ + +#endif /* HAL_STM32_QSPI_H_ */ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_rng/hal_stm32_rng.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_rng/hal_stm32_rng.h new file mode 100644 index 00000000..3c3f01b8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/include/stm32_rng/hal_stm32_rng.h @@ -0,0 +1,87 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_STM32_RNG_H +#define HAL_STM32_RNG_H + +#if (HAL_USE_STM32_RNG == TRUE) + +#if defined(STM32F0xx_MCUCONF) +#error "CAN'T ENABLE RNG FOR STM32F0 series" +#endif + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ + +/** + * @brief Enables the @p rngAcquireBus() and @p rngReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(RNG_USE_MUTUAL_EXCLUSION) +#define RNG_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + RNG_UNINIT, /* Not initialized. */ + RNG_STOP, /* Stopped. */ + RNG_READY, /* Ready. */ + RNG_ACTIVE /* Generating random number. */ +} rngState; + +#include "rng_lld.h" + + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + void rngInit(void); + void rngStart(void); + void rngStop(void); + uint32_t rngGenerateRandomNumber(void); + uint32_t rngGetLastRandomNumber(void); + +#if RNG_USE_MUTUAL_EXCLUSION == TRUE + void rngAcquireModule(void); + void rngReleaseModule(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_STM32_RNG */ + +#endif /* HAL_STM32_RNG_H_ */ + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/README.md new file mode 100644 index 00000000..c5a99c90 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/README.md @@ -0,0 +1,8 @@ +# CRC v1 + +This driver supports all STM32 series. +The low level driver code is taken or heavily inspired in the STCube MX HAL drivers from STMicroelectronics. +The ChibiOS driver follows the 'standard' template driver model. + +**NOTE:** unlike all the other drivers and because all SMT32 chips (until now) have a CRC unit, the default for this driver is to be included. +If for some reason the developer chooses NOT to include support, they have to add `#define HAL_USE_STM32_CRC == FALSE` preferably in the file halconf_nf.h. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c new file mode 100644 index 00000000..816587a1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.c @@ -0,0 +1,331 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////// +// This driver has been tested with the following STM32 series: F0 +/////////////////////////////////////////////////////////////////////////////// + + +// The reversed CRC32 calculation is an extra step required for F1, L1, F2 and F4 units series. +// Others have different configurations and polynomial coefficients. + + +#include +#include + +#if (HAL_USE_STM32_CRC == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +#if (STM32_CRC_PROGRAMMABLE == TRUE) || \ + defined(STM32F7XX) || defined(STM32L0XX) || defined(STM32H7XX) + +// CRC default configuration. +static const crcConfig defaultConfig = { + + .CRCLength = CRC_POLYLENGTH_32B, + .GeneratingPolynomial = DEFAULT_CRC32_POLY, + .InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES, + .InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE, + .OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE +}; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +CRCDriver CRCD1; + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +void crc_lld_init(void) { + + CRCD1.State = CRC_STOP; + CRCD1.Config = NULL; + + #if (CRC_USE_MUTUAL_EXCLUSION == TRUE) + osalMutexObjectInit(&CRCD1.Lock); + #endif + + CRCD1.Instance = CRC; +} + +void crc_lld_start(const crcConfig *config) { + + // enable peripheral + rccEnableCRC(FALSE); + +#if (STM32_CRC_PROGRAMMABLE == TRUE) || \ + defined(STM32F7XX) || defined(STM32L0XX) || defined(STM32H7XX) + + // set configuration, if supplied + if (config == NULL) + { + CRCD1.Config = &defaultConfig; + } + else + { + CRCD1.Config = config; + } + +#else + osalDbgAssert(config == NULL, "CRC peripheral doesn't support configuration"); +#endif + +#if (STM32_CRC_PROGRAMMABLE == TRUE) || \ + defined(STM32F7XX) || defined(STM32L0XX) || defined(STM32H7XX) + + WRITE_REG(CRCD1.Instance->INIT, DEFAULT_CRC_INITVALUE); + + // set generating polynomial + WRITE_REG(CRCD1.Instance->POL, CRCD1.Config->GeneratingPolynomial); + + CRCD1.Instance->CR = 0; + + // set generating polynomial size + MODIFY_REG(CRCD1.Instance->CR, CRC_CR_POLYSIZE, CRCD1.Config->CRCLength); + + // set input data inversion mode + MODIFY_REG(CRCD1.Instance->CR, CRC_CR_REV_IN, CRCD1.Config->OutputDataInversionMode); + + // set output data inversion mode + MODIFY_REG(CRCD1.Instance->CR, CRC_CR_REV_OUT, CRCD1.Config->OutputDataInversionMode); + +#endif + + // driver is ready + CRCD1.State = CRC_READY; +} + +void crc_lld_stop() { + + // disable peripheral + rccDisableCRC(); + + // driver is stopped + CRCD1.State = CRC_STOP; +} + +void crc_lld_reset() { + + CRCD1.Instance->CR |= CRC_CR_RESET; +} + +uint32_t crc_lld_compute(const void* buffer, int size, uint32_t initialCrc) { + + int32_t index = 0U; + uint32_t arg1; + uint32_t crc = 0; + + // anything to do here? + if(size == 0) + { + return initialCrc; + } + + // get pointer to buffer + uint8_t* ptr = (uint8_t*)buffer; + +#if defined(STM32F1XX) || defined(STM32L1XX) || defined(STM32F2XX) || defined(STM32F4XX) + uint32_t size_remainder = 0; + + // need to reset CRC peripheral if: + // - CRC initial value is 0 + // - the initial CRC is NOT already loaded in the calculation register + if(initialCrc == 0 || (CRCD1.Instance->DR != initialCrc)) + { + // Reset CRC Calculation Unit + crc_lld_reset(); + + // CRC calculation unit is initiated with 0xFFFFFFFF which is not a initial value for our CRC calculation + // feeding 0xFFFFFFFF to the calculation unit will set the register to 0x00000000 + while(CRCD1.Instance->DR != 0x0) + { + CRCD1.Instance->DR = CRCD1.Instance->DR; + } + } + + if(initialCrc != 0 && CRCD1.Instance->DR != initialCrc) + { + // we have an initial value for CRC calculation and that is not loaded in the CRC calculation register + // load calculation register with REVERSE initial CRC32 value (because of STM32F4 shift order) + CRCD1.Instance->DR = crc_lld_reverseCRC32(initialCrc); + } + + // set variable to hold how many bytes remain after processing the buffer in steps of 4 bytes + size_remainder = size & 3; + + // we'll be reading the buffer in steps of 4 bytes, so the size must be recalculated accordingly + size = size >> 2; + + // feed data into the CRC calculator + for(index = 0U; index < size; index++) + { + // take the next 4 bytes as if they were a UINT32 + // because the CRC calculation unit expects the bytes in reverse order, reverse the byte order first + arg1 = __REV(*(uint32_t*)(ptr)); + + // feed the bytes to the CRC + CRCD1.Instance->DR = arg1; + + // copy to return value + crc = (uint32_t)CRCD1.Instance->DR; + + // increase pointer by 4 to the next position + // !! we are reading UINT32 from a UINT8 pointer!! + ptr +=4; + } + + // compute CRC for remaining bytes, if any + while(size_remainder--) + { + crc = crc_lld_fastCRC32(crc, *(uint8_t*)(ptr++)); + } + +#else + uint16_t* ptr16 = (uint16_t*)buffer; + + // need to reset CRC peripheral if: + // - CRC initial value is 0 + // - the initial CRC is NOT already loaded in the calculation register + if(initialCrc != DEFAULT_CRC_INITVALUE || (CRCD1.Instance->DR != initialCrc)) + { + // Reset CRC Calculation Unit + crc_lld_reset(); + + #if (STM32_CRC_PROGRAMMABLE == TRUE) || \ + defined(STM32F7XX) || defined(STM32L0XX) || defined(STM32H7XX) + // set initial CRC value + WRITE_REG(CRCD1.Instance->INIT, initialCrc); + #endif + } + + switch (CRCD1.Config->InputDataFormat) + { + case CRC_INPUTDATA_FORMAT_WORDS: + // Enter 32-bit input data to the CRC calculator + for(index = 0; index < size; index++) + { + arg1 = ((uint32_t*)buffer)[index]; + CRCD1.Instance->DR = arg1; + } + break; + + case CRC_INPUTDATA_FORMAT_BYTES: + // Specific 8-bit input data handling + + /* Processing time optimization: 4 bytes are entered in a row with a single word write, + * last bytes must be carefully fed to the CRC calculator to ensure a correct type + * handling by the IP */ + for(index = 0; index < (size / 4); index++) + { + CRCD1.Instance->DR = (uint32_t)(((uint32_t)(ptr[4*index])<<24) | ((uint32_t)(ptr[4*index + 1])<<16) | ((uint32_t)(ptr[4*index + 2])<<8) | (uint32_t)(ptr[4*index + 3])); + } + + // last bytes specific handling + if((size % 4) != 0) + { + if(size % 4 == 1) + { + CRCD1.Instance->DR = ptr[4*index]; + } + if(size % 4 == 2) + { + CRCD1.Instance->DR = (uint16_t)((uint16_t)((uint16_t)(ptr[4*index])<<8) | (uint16_t)(ptr[4*index + 1])); + } + if(size % 4 == 3) + { + CRCD1.Instance->DR = (uint16_t)((uint16_t)((uint16_t)(ptr[4*index])<<8) | (uint16_t)(ptr[4*index + 1])); + CRCD1.Instance->DR = ptr[4*index + 2]; + } + } + break; + + case CRC_INPUTDATA_FORMAT_HALFWORDS: + // Specific 16-bit input data handling + + /* Processing time optimization: 2 HalfWords are entered in a row with a single word write, + * in case of odd length, last HalfWord must be carefully fed to the CRC calculator to ensure + * a correct type handling by the IP */ + for(index = 0; index < (size / 2); index++) + { + CRCD1.Instance->DR = (((uint32_t)(ptr16[2*index])<<16) | (uint32_t)(ptr16[2*index + 1])); + } + if((size % 2) != 0) + { + CRCD1.Instance->DR = ptr16[2*index]; + } + break; + } + + crc = CRCD1.Instance->DR; + +#endif + + // Return the CRC computed value + return crc; +} + +#if (CRC_USE_MUTUAL_EXCLUSION == TRUE) + +void crc_lld_aquire() { + osalMutexLock(&CRCD1.Lock); +} + +void crc_lld_release() { + osalMutexUnlock(&CRCD1.Lock); +} + +#endif + +uint32_t crc_lld_reverseCRC32(uint32_t targetCRC) +{ + // nibble lookup table for _REVERSE_ CRC32 polynomial 0x4C11DB7 + static const uint32_t crc32NibbleTable[16] = + { + 0x00000000, 0xB2B4BCB6, 0x61A864DB, 0xD31CD86D, 0xC350C9B6, 0x71E47500, 0xA2F8AD6D, 0x104C11DB, + 0x82608EDB, 0x30D4326D, 0xE3C8EA00, 0x517C56B6, 0x4130476D, 0xF384FBDB, 0x209823B6, 0x922C9F00 + }; + + uint8_t counter = 8; + + while(counter--) + { + targetCRC = (targetCRC >> 4) ^ crc32NibbleTable[targetCRC & 0x0F]; + } + + return targetCRC; +} + +uint32_t crc_lld_fastCRC32(uint32_t initialCrc, uint8_t data) +{ + // nibble lookup table for CRC32 polynomial 0x4C11DB7 + static const uint32_t crc32NibbleTable[16] = + { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD + }; + + initialCrc = crc32NibbleTable[(initialCrc >> 28) ^ (data >> 4)] ^ (initialCrc << 4) ; + initialCrc = crc32NibbleTable[(initialCrc >> 28) ^ (data & 0xF)] ^ (initialCrc << 4) ; + + return initialCrc; +} + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.h new file mode 100644 index 00000000..e7449b53 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/CRCv1/crc_lld.h @@ -0,0 +1,182 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef CRC_LLD_H +#define CRC_LLD_H + +#include "stm32_registry.h" +#include +#include + +#if (HAL_USE_STM32_CRC == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// Driver configuration structure. +typedef struct crcConfig { + + // indicates CRC length + uint32_t CRCLength; + + // 7, 8, 16 or 32-bit long value for a polynomial degree + uint32_t GeneratingPolynomial; + + // Input data format + uint32_t InputDataFormat; + + // The final XOR value + uint32_t FinalValue; + + // Specifies input data inversion mode + bool InputDataInversionMode; + + // Specifies output data (i.e. CRC) inversion mode + bool OutputDataInversionMode; + +} crcConfig; + +typedef struct CRCDriver { + + CRC_TypeDef *Instance; //Register base address + + // Driver state. + crcState State; + + // Current configuration data. + const crcConfig *Config; + +#if CRC_USE_MUTUAL_EXCLUSION + // Mutex protecting the peripheral + mutex_t Lock; +#endif // CRC_USE_MUTUAL_EXCLUSION + +} CRCDriver; + + +// From STMicroelectronics Cube HAL +/////////////////////////////////////////// + +#if defined(STM32L0XX) +// this series uses different names for the buses + +#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp) +#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN) +#define rccResetCRC() rccResetAHB(RCC_AHB1RSTR_CRCRST) + +#endif + +/** @defgroup CRC_Default_Polynomial_Value Default CRC generating polynomial + * @{ + */ +#define DEFAULT_CRC32_POLY 0x04C11DB7U + +/** @defgroup CRC_Default_InitValue Default CRC computation initialization value + * @{ + */ +#define DEFAULT_CRC_INITVALUE 0xFFFFFFFFU + +/** @defgroup CRC_Default_Polynomial Indicates whether or not default polynomial is used + * @{ + */ +#define DEFAULT_POLYNOMIAL_ENABLE ((uint8_t)0x00U) +#define DEFAULT_POLYNOMIAL_DISABLE ((uint8_t)0x01U) + +/** @defgroup CRC_Default_InitValue_Use Indicates whether or not default init value is used + * @{ + */ +#define DEFAULT_INIT_VALUE_ENABLE ((uint8_t)0x00U) +#define DEFAULT_INIT_VALUE_DISABLE ((uint8_t)0x01U) + +/** @defgroup CRC_Polynomial_Sizes Polynomial sizes to configure the IP + * @{ + */ +#define CRC_POLYLENGTH_32B ((uint32_t)0x00000000U) +#define CRC_POLYLENGTH_16B ((uint32_t)CRC_CR_POLYSIZE_0) +#define CRC_POLYLENGTH_8B ((uint32_t)CRC_CR_POLYSIZE_1) +#define CRC_POLYLENGTH_7B ((uint32_t)CRC_CR_POLYSIZE) + +/** @defgroup CRC_Polynomial_Size_Definitions CRC polynomial possible sizes actual definitions + * @{ + */ +#define HAL_CRC_LENGTH_32B 32U +#define HAL_CRC_LENGTH_16B 16U +#define HAL_CRC_LENGTH_8B 8U +#define HAL_CRC_LENGTH_7B 7U + +/* WARNING: CRC_INPUT_FORMAT_UNDEFINED is created for reference purposes but + * an error is triggered in HAL_CRC_Init() if InputDataFormat field is set + * to CRC_INPUT_FORMAT_UNDEFINED: the format MUST be defined by the user for + * the CRC APIs to provide a correct result */ +#define CRC_INPUTDATA_FORMAT_UNDEFINED ((uint32_t)0x00000000U) +#define CRC_INPUTDATA_FORMAT_BYTES ((uint32_t)0x00000001U) +#define CRC_INPUTDATA_FORMAT_HALFWORDS ((uint32_t)0x00000002U) +#define CRC_INPUTDATA_FORMAT_WORDS ((uint32_t)0x00000003U) + +/** @defgroup CRCEx_Input_Data_Inversion CRC Extended input data inversion modes + * @{ + */ +#define CRC_INPUTDATA_INVERSION_NONE ((uint32_t)0x00000000U) +#define CRC_INPUTDATA_INVERSION_BYTE ((uint32_t)CRC_CR_REV_IN_0) +#define CRC_INPUTDATA_INVERSION_HALFWORD ((uint32_t)CRC_CR_REV_IN_1) +#define CRC_INPUTDATA_INVERSION_WORD ((uint32_t)CRC_CR_REV_IN) + +/** @defgroup CRCEx_Output_Data_Inversion CRC Extended output data inversion modes + * @{ + */ +#define CRC_OUTPUTDATA_INVERSION_DISABLE ((uint32_t)0x00000000U) +#define CRC_OUTPUTDATA_INVERSION_ENABLE ((uint32_t)CRC_CR_REV_OUT) + +/////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +// From STMicroelectronics Cube HAL + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + + void crc_lld_init(void); + void crc_lld_start(const crcConfig *config); + void crc_lld_stop(); + void crc_lld_reset(); + uint32_t crc_lld_compute(const void* buffer, int size, uint32_t initialCrc); + +#if (CRC_USE_MUTUAL_EXCLUSION == TRUE) + void crc_lld_aquire(); + void crc_lld_release(); +#endif + +uint32_t crc_lld_reverseCRC32(uint32_t targetCRC); +uint32_t crc_lld_fastCRC32(uint32_t initialCrc, uint8_t data); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_STM32_CRC + +#endif // CRC_LLD_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/README.md new file mode 100644 index 00000000..e15983aa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/README.md @@ -0,0 +1,4 @@ +# Flash driver V1 + +This driver supports F0 series. +The low level driver code is taken or heavily inspired in the STCube MX HAL drivers from STMicroelectronics. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c new file mode 100644 index 00000000..08196953 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c @@ -0,0 +1,227 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////// +// This driver has been tested with the following STM32 series: F0 +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#if (HAL_USE_STM32_FLASH == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +SMT32FlashDriver STM32FLASH; + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Unlock the FLASH control register access +bool HAL_FLASH_Unlock(void) +{ + bool status = true; + + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) + { + // Authorize the FLASH Registers access + WRITE_REG(FLASH->KEYR, FLASH_KEY1); + WRITE_REG(FLASH->KEYR, FLASH_KEY2); + + // Verify Flash is unlocked + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) + { + status = false; + } + } + + return status; +} + +// Locks the FLASH control register access +bool HAL_FLASH_Lock(void) +{ + // Set the LOCK Bit to lock the FLASH Registers access + SET_BIT(FLASH->CR, FLASH_CR_LOCK); + + return true; +} + +bool FLASH_WaitForLastOperation(uint32_t timeout) +{ + (void)timeout; + + bool success = true; + + // Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + // Even if the FLASH operation fails, the BUSY flag will be reset and an error flag will be set + // no need to overload this with a timeout workflow as the watchdog will quick-in if execution gets stuck + + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)); + + // Check FLASH End of Operation flag + if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) ) + { + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR)) + { + // at this point we don't care about the details of the programming error + success = false; + } + + return success; +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +void flash_lld_init() +{ + stm32FlashObjectInit(&STM32FLASH); +} + +void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer) +{ + + __IO uint8_t* cursor = (__IO uint8_t*)startAddress; + __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); + + // copy contents from flash to buffer starting from the start address + while(cursor < endAddress) + { + *buffer++ = *cursor++; + } +} + +int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer) +{ + bool success = true; + + __IO uint8_t* cursor = (__IO uint8_t*)startAddress; + __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); + + // unlock the FLASH + if(HAL_FLASH_Unlock()) + { + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + + while(cursor < endAddress) + { + // proceed to program the flash by setting the PG Bit + SET_BIT(FLASH->CR, FLASH_CR_PG); + + // if buffer has enough data, program half-words (16 bits) in a single operation to speed up things + // NOTE: assuming that the supply voltage is able to cope with half-word programming + if((endAddress - cursor) >= 2) + { + *(__IO uint16_t*)cursor = *((uint16_t*)buffer); + + // update flash and buffer pointers by the 'extra' byte that was programmed + cursor += 2; + buffer += 2; + } + else + { + // program single byte + *(__IO uint8_t*)cursor = *buffer; + + // update flash pointer by the 'extra' byte that was programmed + cursor += 2; + } + + // wait for any flash operation to be completed + // timeout set to 0 on purpose + // watchdog will quick-in if execution gets stuck + success = FLASH_WaitForLastOperation(0); + + if(!success) + { + // quit on failure + break; + } + } + + // after the program operation is completed disable the PG Bit + CLEAR_BIT(FLASH->CR, FLASH_CR_PG); + + // lock the FLASH + HAL_FLASH_Lock(); + } + + return success; +} + +int flash_lld_isErased(uint32_t startAddress, uint32_t length) +{ + __IO uint32_t* cursor = (__IO uint32_t*)startAddress; + __IO uint32_t* endAddress = (__IO uint32_t*)(startAddress + length); + + // an erased flash address has to read FLASH_ERASED_WORD + // OK to check by word (32 bits) because the erase is performed by 'page' whose size is word multiple + while(cursor < endAddress) + { + if(*cursor++ != FLASH_ERASED_WORD) + { + // found an address with something other than FLASH_ERASED_WORD!! + return false; + } + } + + // reached here so the segment must be erased + return true; +} + +uint8_t flash_lld_getSector(uint32_t address) +{ + return (address - FLASH_BASE) / F0_SERIES_SECTOR_SIZE; +} + +int flash_lld_erase(uint32_t address) +{ + bool success = true; + + //unlock the FLASH + if(HAL_FLASH_Unlock()) + { + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + + // erase the page + SET_BIT(FLASH->CR, FLASH_CR_PER); + WRITE_REG(FLASH->AR, address); + SET_BIT(FLASH->CR, FLASH_CR_STRT); + + // wait for any flash operation to be completed + // watchdog will quick-in if execution gets stuck + success = FLASH_WaitForLastOperation(0); + + // after erase operation completed disable the PER Bit + CLEAR_BIT(FLASH->CR, FLASH_CR_PER); + + // lock the FLASH + HAL_FLASH_Lock(); + } + + return success; +} + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h new file mode 100644 index 00000000..8bcce8b4 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef FLASH_LLD_H +#define FLASH_LLD_H + +#include "stm32_registry.h" +#include + +#if (HAL_USE_STM32_FLASH == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// From STMicroelectronics Cube HAL +// HAL Status structures definition +typedef struct SMT32FlashDriver { + + // pointer to the FLASH Registers + FLASH_TypeDef *flash; + +}SMT32FlashDriver; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +// From STMicroelectronics Cube HAL +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET) + +#define FLASH_FLAG_BSY FLASH_SR_BSY //!< FLASH Busy flag +#define FLASH_FLAG_PGERR FLASH_SR_PGERR //!< FLASH Programming error flag +#define FLASH_FLAG_WRPERR FLASH_SR_WRPERR //!< FLASH Write protected error flag +#define FLASH_FLAG_EOP FLASH_SR_EOP //!< FLASH End of Operation flag + +#define FLASH_FLAG_ALL_ERRORS ( FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR ) + +// FLASH_Program_Parallelism FLASH Program Parallelism +#define FLASH_PSIZE_BYTE ((uint32_t)0x00000000U) +#define FLASH_PSIZE_HALF_WORD ((uint32_t)0x00000100U) +#define FLASH_PSIZE_WORD ((uint32_t)0x00000200U) +#define FLASH_PSIZE_DOUBLE_WORD ((uint32_t)0x00000300U) +#define CR_PSIZE_MASK ((uint32_t)0xFFFFFCFFU) + +#define __HAL_FLASH_GET_FLAG(__FLAG__) ((FLASH->SR & (__FLAG__))) +#define __HAL_FLASH_CLEAR_FLAG(__FLAG__) (FLASH->SR = (__FLAG__)) + +#define F0_SERIES_SECTOR_SIZE ((uint32_t)0x00001000U) + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32FLASH_USE_FLASH +SMT32FlashDriver STM32FLASH; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + void flash_lld_init(); + void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer); + int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer); + int flash_lld_isErased(uint32_t startAddress, uint32_t length); + int flash_lld_erase(uint32_t address); + uint8_t flash_lld_getSector(uint32_t address); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_STM32_FLASH + +#endif // FLASH_LLD_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/README.md new file mode 100644 index 00000000..e450e52d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/README.md @@ -0,0 +1,4 @@ +# Flash driver V2 + +This driver supports F4 and F7 series. +The low level driver code is taken or heavily inspired in the STCube MX HAL drivers from STMicroelectronics. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.c new file mode 100644 index 00000000..1163a36a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.c @@ -0,0 +1,396 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////// +// This driver has been tested with the following STM32 series: F4 +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#if (HAL_USE_STM32_FLASH == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +SMT32FlashDriver STM32FLASH; + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Unlock the FLASH control register access +bool HAL_FLASH_Unlock(void) +{ + if((FLASH->CR & FLASH_CR_LOCK) != RESET) + { + // Authorize the FLASH Registers access + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } + else + { + return false; + } + + return true; +} + +// Locks the FLASH control register access +void HAL_FLASH_Lock(void) +{ + // Set the LOCK Bit to lock the FLASH Registers access + FLASH->CR |= FLASH_CR_LOCK; +} + +bool FLASH_WaitForLastOperation(uint32_t timeout) +{ + // Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + // Even if the FLASH operation fails, the BUSY flag will be reset and an error + // flag will be set + + systime_t start = chVTGetSystemTime(); + systime_t end = start + TIME_MS2I(timeout); + + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET) + { + // do nothing until the timeout expires + if(chVTIsSystemTimeWithin(start, end)) + { + __NOP(); + } + else + { + return false; + } + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_ALL_ERRORS) != RESET) + { + return false; + } + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) != RESET) + { + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + // If there is no error flag set + return true; +} + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) ||\ + defined(STM32F469xx) || defined(STM32F479xx) ||\ + defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F412Zx) ||\ + defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) ||\ + defined(STM32F401xC) ||\ + defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) ||\ + defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) + +void FLASH_FlushCaches(void) +{ + // Flush instruction cache + if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN)!= RESET) + { + // Disable instruction cache + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + // Reset instruction cache + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + // Enable instruction cache + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + } + + // Flush data cache + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + // Disable data cache + __HAL_FLASH_DATA_CACHE_DISABLE(); + // Reset data cache + __HAL_FLASH_DATA_CACHE_RESET(); + // Enable data cache + __HAL_FLASH_DATA_CACHE_ENABLE(); + } +} +#endif // define STM32F4xxxx + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +void flash_lld_init() { + stm32FlashObjectInit(&STM32FLASH); +} + +void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer) { + + __IO uint8_t* cursor = (__IO uint8_t*)startAddress; + __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); + + // copy contents from flash to buffer starting from the start address + while(cursor < endAddress) + { + *buffer++ = *cursor++; + } +} + +int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer) { + + __IO uint8_t* cursor = (__IO uint8_t*)startAddress; + __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); + + // default to false + bool success = false; + + // unlock the FLASH + if(HAL_FLASH_Unlock()) + { + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + + while(cursor < endAddress) + { + // if buffer has enough data, program half-words (16 bits) in a single operation to speed up things + // NOTE: assuming that the supply voltage is able to cope with half-word programming + if((endAddress - cursor) >= 2) + { + // clear the program size mask + FLASH->CR &= CR_PSIZE_MASK; + // set the size of of the programming word to HALF WORD + FLASH->CR |= FLASH_PSIZE_HALF_WORD; + // proceed to program the flash by setting the PG Bit + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint16_t*)cursor = *((uint16_t*)buffer); + +#if defined(STM32F756xx) || defined(STM32F746xx) || defined(STM32F745xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F722xx) || \ + defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) + + // Data synchronous Barrier, forcing the CPU to respect the sequence of instruction without optimization + __DSB(); +#endif + // update flash and buffer pointers by the 'extra' byte that was programmed + cursor += 2; + buffer += 2; + } + else + { + // program single byte + + // clear the program size mask + FLASH->CR &= CR_PSIZE_MASK; + // set the size of of the programming word to BYTE + FLASH->CR |= FLASH_PSIZE_BYTE; + // proceed to program the flash by setting the PG Bit + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint8_t*)cursor = *buffer; + +#if defined(STM32F756xx) || defined(STM32F746xx) || defined(STM32F745xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F722xx) || \ + defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) + + // Data synchronous Barrier, forcing the CPU to respect the sequence of instruction without optimization + __DSB(); +#endif + + // update flash pointer by the 'extra' byte that was programmed + cursor += 2; + } + + // wait 500ms for any flash operation to be completed + success = FLASH_WaitForLastOperation(500); + + if(!success) + { + // quit on failure + break; + } + } + + // after the program operation is completed disable the PG Bit + FLASH->CR &= (~FLASH_CR_PG); + + // lock the FLASH + HAL_FLASH_Lock(); + } + + return success; +} + +int flash_lld_isErased(uint32_t startAddress, uint32_t length) { + + __IO uint32_t* cursor = (__IO uint32_t*)startAddress; + __IO uint32_t* endAddress = (__IO uint32_t*)(startAddress + length); + + // an erased flash address has to read FLASH_ERASED_WORD + // OK to check by word (32 bits) because the erase is performed by 'page' whose size is word multiple + while(cursor < endAddress) + { + if(*cursor++ != FLASH_ERASED_WORD) + { + // found an address with something other than FLASH_ERASED_WORD!! + return false; + } + } + + // reached here so the segment must be erased + return true; +} + +uint8_t flash_lld_getSector(uint32_t address) +{ + uint8_t sector = 0; + + if((address < ADDR_FLASH_SECTOR_1) && (address >= ADDR_FLASH_SECTOR_0)) + { + sector = FLASH_SECTOR_0; + } + else if((address < ADDR_FLASH_SECTOR_2) && (address >= ADDR_FLASH_SECTOR_1)) + { + sector = FLASH_SECTOR_1; + } + else if((address < ADDR_FLASH_SECTOR_3) && (address >= ADDR_FLASH_SECTOR_2)) + { + sector = FLASH_SECTOR_2; + } + else if((address < ADDR_FLASH_SECTOR_4) && (address >= ADDR_FLASH_SECTOR_3)) + { + sector = FLASH_SECTOR_3; + } + +// need to wrap the else ifs below because not all target devices have all the sectors defined +#if defined(FLASH_SECTOR_4) + else if((address < ADDR_FLASH_SECTOR_5) && (address >= ADDR_FLASH_SECTOR_4)) + { + sector = FLASH_SECTOR_4; + } +#endif +#if defined(FLASH_SECTOR_5) + else if((address < ADDR_FLASH_SECTOR_6) && (address >= ADDR_FLASH_SECTOR_5)) + { + sector = FLASH_SECTOR_5; + } +#endif +#if defined(FLASH_SECTOR_6) + else if((address < ADDR_FLASH_SECTOR_7) && (address >= ADDR_FLASH_SECTOR_6)) + { + sector = FLASH_SECTOR_6; + } +#endif +// the next one is for devices that have FLASH sector 8 defined (see next one for devices WITHOUT sector 8) +#if defined(FLASH_SECTOR_7) && defined(FLASH_SECTOR_8) + else if((address < ADDR_FLASH_SECTOR_8) && (address >= ADDR_FLASH_SECTOR_7)) + { + sector = FLASH_SECTOR_7; + } +#endif +// this next one needs to be here for devices that don't have FLASH sector 8 +#if defined(FLASH_SECTOR_7) && !defined(FLASH_SECTOR_8) + else if(address >= ADDR_FLASH_SECTOR_7) + { + sector = FLASH_SECTOR_7; + } +#endif +#if defined(FLASH_SECTOR_8) + else if((address < ADDR_FLASH_SECTOR_9) && (address >= ADDR_FLASH_SECTOR_8)) + { + sector = FLASH_SECTOR_8; + } +#endif +#if defined(FLASH_SECTOR_9) + else if((address < ADDR_FLASH_SECTOR_10) && (address >= ADDR_FLASH_SECTOR_9)) + { + sector = FLASH_SECTOR_9; + } +#endif +#if defined(FLASH_SECTOR_10) + else if((address < ADDR_FLASH_SECTOR_11) && (address >= ADDR_FLASH_SECTOR_10)) + { + sector = FLASH_SECTOR_10; + } +#endif + else /* (address < FLASH_END_ADDR) && (address >= ADDR_FLASH_SECTOR_11) */ + { + sector = FLASH_SECTOR_11; + } + + return sector; +} + +int flash_lld_erase(uint32_t address) { + + // default to false + bool success = false; + + // unlock the FLASH + if(HAL_FLASH_Unlock()) + { + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + + // get the sector number to erase + uint8_t sectorNumber = flash_lld_getSector(address); + + // Need to add offset of 4 when sector higher than FLASH_SECTOR_11 + if(sectorNumber > FLASH_SECTOR_11) + { + sectorNumber += 4U; + } + + // If the previous operation is completed, proceed to erase the sector + CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); + SET_BIT(FLASH->CR, FLASH_PSIZE_HALF_WORD); + CLEAR_BIT(FLASH->CR, FLASH_CR_SNB); + FLASH->CR |= FLASH_CR_SER | (sectorNumber << POSITION_VAL(FLASH_CR_SNB)); + + // start erase operation + FLASH->CR |= FLASH_CR_STRT; + +#if defined(STM32F756xx) || defined(STM32F746xx) || defined(STM32F745xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F722xx) || \ + defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) + + // Data synchronous Barrier, forcing the CPU to respect the sequence of instruction without optimization + __DSB(); +#endif + + // wait 500ms for any flash operation to be completed + success = FLASH_WaitForLastOperation(2000); + + // after erase operation completed disable the SER and SNB Bits + CLEAR_BIT(FLASH->CR, (FLASH_CR_SER | FLASH_CR_SNB)); + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) ||\ + defined(STM32F469xx) || defined(STM32F479xx) ||\ + defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F412Zx) ||\ + defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) ||\ + defined(STM32F401xC) ||\ + defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) ||\ + defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) + + // Flush the caches to be sure of the data consistency + FLASH_FlushCaches(); +#endif + + // lock the FLASH + HAL_FLASH_Lock(); + } + + return success; +} + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h new file mode 100644 index 00000000..06c27d18 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv2/flash_lld.h @@ -0,0 +1,451 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef FLASH_LLD_H +#define FLASH_LLD_H + +#include "stm32_registry.h" +#include + +#if (HAL_USE_STM32_FLASH == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// From STMicroelectronics Cube HAL +// HAL Status structures definition + +typedef struct SMT32FlashDriver { + + // pointer to the FLASH Registers + FLASH_TypeDef *flash; + +}SMT32FlashDriver; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +// From STMicroelectronics Cube HAL +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#ifndef HAL_IS_BIT_SET +#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET) +#endif +#define FLASH_KEY1 ((uint32_t)0x45670123U) +#define FLASH_KEY2 ((uint32_t)0xCDEF89ABU) +#define FLASH_OPT_KEY1 ((uint32_t)0x08192A3BU) +#define FLASH_OPT_KEY2 ((uint32_t)0x4C5D6E7FU) +#define SECTOR_MASK ((uint32_t)0xFFFFFF07) + +// FLASH_Error_Code FLASH Error Code +#define HAL_FLASH_ERROR_NONE ((uint32_t)0x00000000U) /*!< No error */ +#define HAL_FLASH_ERROR_ERS ((uint32_t)0x00000002U) /*!< Programming Sequence error */ +#define HAL_FLASH_ERROR_PGP ((uint32_t)0x00000004U) /*!< Programming Parallelism error */ +#define HAL_FLASH_ERROR_PGA ((uint32_t)0x00000008U) /*!< Programming Alignment error */ +#define HAL_FLASH_ERROR_WRP ((uint32_t)0x00000010U) /*!< Write protection error */ +#define HAL_FLASH_ERROR_OPERATION ((uint32_t)0x00000020U) /*!< Operation Error */ +#define HAL_FLASH_ERROR_RD ((uint32_t)0x00000040U) /*!< Read Protection Error */ + +// FLASH_Program_Parallelism FLASH Program Parallelism +#define FLASH_PSIZE_BYTE ((uint32_t)0x00000000U) +#define FLASH_PSIZE_HALF_WORD ((uint32_t)0x00000100U) +#define FLASH_PSIZE_WORD ((uint32_t)0x00000200U) +#define FLASH_PSIZE_DOUBLE_WORD ((uint32_t)0x00000300U) +#define CR_PSIZE_MASK ((uint32_t)0xFFFFFCFFU) + +//---------------------------------- STM32F4xx ------------------------------// +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) ||\ + defined(STM32F469xx) || defined(STM32F479xx) ||\ + defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F412Zx) ||\ + defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) ||\ + defined(STM32F401xC) ||\ + defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) ||\ + defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) + +#define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */ +#define FLASH_FLAG_OPERR FLASH_SR_SOP /*!< FLASH operation Error flag */ +#define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_PGAERR FLASH_SR_PGAERR /*!< FLASH Programming Alignment error flag */ +#define FLASH_FLAG_PGPERR FLASH_SR_PGPERR /*!< FLASH Programming Parallelism error flag */ +#define FLASH_FLAG_PGSERR FLASH_SR_PGSERR /*!< FLASH Programming Sequence error flag */ +#if defined(FLASH_SR_RDERR) +#define FLASH_FLAG_RDERR FLASH_SR_RDERR /*!< Read Protection error flag (PCROP) */ +#endif /* FLASH_SR_RDERR */ +#define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */ + +#if defined(FLASH_SR_RDERR) +#define FLASH_FLAG_ALL_ERRORS (FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \ + FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR | FLASH_FLAG_RDERR) + +#else +#define FLASH_FLAG_ALL_ERRORS (FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \ + FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR ) + +#endif // FLASH_SR_RDERR + + +//---------------------------------- STM32F7xx ------------------------------// +#elif defined(STM32F756xx) || defined(STM32F746xx) || defined(STM32F745xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F722xx) || \ + defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) + +#define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */ +#define FLASH_FLAG_OPERR FLASH_SR_OPERR /*!< FLASH operation Error flag */ +#define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_PGAERR FLASH_SR_PGAERR /*!< FLASH Programming Alignment error flag */ +#define FLASH_FLAG_PGPERR FLASH_SR_PGPERR /*!< FLASH Programming Parallelism error flag */ +#define FLASH_FLAG_ERSERR FLASH_SR_ERSERR /*!< FLASH Erasing Sequence error flag */ +#define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */ + +#if defined (FLASH_OPTCR2_PCROP) +#define FLASH_FLAG_RDERR FLASH_SR_RDERR /*!< FLASH Read protection error flag */ +#define FLASH_FLAG_ALL_ERRORS (FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \ + FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR | FLASH_FLAG_RDERR) +#else +#define FLASH_FLAG_ALL_ERRORS (FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \ + FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR) +#endif /* FLASH_OPTCR2_PCROP */ + +#endif + +#define __HAL_FLASH_GET_FLAG(__FLAG__) ((FLASH->SR & (__FLAG__))) +#define __HAL_FLASH_CLEAR_FLAG(__FLAG__) (FLASH->SR = (__FLAG__)) + +// FLASHEx_Sectors FLASH Sectors +/*-------------------------------------- STM32F42xxx/STM32F43xxx/STM32F469xx ------------------------------------*/ +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) ||\ + defined(STM32F469xx) || defined(STM32F479xx) + +#define FLASH_SECTOR_0 ((uint32_t)0U) /*!< Sector Number 0 */ +#define FLASH_SECTOR_1 ((uint32_t)1U) /*!< Sector Number 1 */ +#define FLASH_SECTOR_2 ((uint32_t)2U) /*!< Sector Number 2 */ +#define FLASH_SECTOR_3 ((uint32_t)3U) /*!< Sector Number 3 */ +#define FLASH_SECTOR_4 ((uint32_t)4U) /*!< Sector Number 4 */ +#define FLASH_SECTOR_5 ((uint32_t)5U) /*!< Sector Number 5 */ +#define FLASH_SECTOR_6 ((uint32_t)6U) /*!< Sector Number 6 */ +#define FLASH_SECTOR_7 ((uint32_t)7U) /*!< Sector Number 7 */ +#define FLASH_SECTOR_8 ((uint32_t)8U) /*!< Sector Number 8 */ +#define FLASH_SECTOR_9 ((uint32_t)9U) /*!< Sector Number 9 */ +#define FLASH_SECTOR_10 ((uint32_t)10U) /*!< Sector Number 10 */ +#define FLASH_SECTOR_11 ((uint32_t)11U) /*!< Sector Number 11 */ +#define FLASH_SECTOR_12 ((uint32_t)12U) /*!< Sector Number 12 */ +#define FLASH_SECTOR_13 ((uint32_t)13U) /*!< Sector Number 13 */ +#define FLASH_SECTOR_14 ((uint32_t)14U) /*!< Sector Number 14 */ +#define FLASH_SECTOR_15 ((uint32_t)15U) /*!< Sector Number 15 */ +#define FLASH_SECTOR_16 ((uint32_t)16U) /*!< Sector Number 16 */ +#define FLASH_SECTOR_17 ((uint32_t)17U) /*!< Sector Number 17 */ +#define FLASH_SECTOR_18 ((uint32_t)18U) /*!< Sector Number 18 */ +#define FLASH_SECTOR_19 ((uint32_t)19U) /*!< Sector Number 19 */ +#define FLASH_SECTOR_20 ((uint32_t)20U) /*!< Sector Number 20 */ +#define FLASH_SECTOR_21 ((uint32_t)21U) /*!< Sector Number 21 */ +#define FLASH_SECTOR_22 ((uint32_t)22U) /*!< Sector Number 22 */ +#define FLASH_SECTOR_23 ((uint32_t)23U) /*!< Sector Number 23 */ + +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbyte */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base @ of Sector 12, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base @ of Sector 13, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base @ of Sector 14, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base @ of Sector 15, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base @ of Sector 16, 64 Kbyte */ +#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base @ of Sector 17, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base @ of Sector 18, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base @ of Sector 19, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base @ of Sector 20, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base @ of Sector 21, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base @ of Sector 22, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base @ of Sector 23, 128 Kbyte */ + +#endif /* STM32F427xx || STM32F437xx || STM32F429xx|| STM32F439xx || STM32F469xx || STM32F479xx */ +/*-----------------------------------------------------------------------------------------------------*/ + +/*--------------------------------------- STM32F40xxx/STM32F41xxx -------------------------------------*/ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F412Zx) ||\ + defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) +#define FLASH_SECTOR_0 ((uint32_t)0U) /*!< Sector Number 0 */ +#define FLASH_SECTOR_1 ((uint32_t)1U) /*!< Sector Number 1 */ +#define FLASH_SECTOR_2 ((uint32_t)2U) /*!< Sector Number 2 */ +#define FLASH_SECTOR_3 ((uint32_t)3U) /*!< Sector Number 3 */ +#define FLASH_SECTOR_4 ((uint32_t)4U) /*!< Sector Number 4 */ +#define FLASH_SECTOR_5 ((uint32_t)5U) /*!< Sector Number 5 */ +#define FLASH_SECTOR_6 ((uint32_t)6U) /*!< Sector Number 6 */ +#define FLASH_SECTOR_7 ((uint32_t)7U) /*!< Sector Number 7 */ +#define FLASH_SECTOR_8 ((uint32_t)8U) /*!< Sector Number 8 */ +#define FLASH_SECTOR_9 ((uint32_t)9U) /*!< Sector Number 9 */ +#define FLASH_SECTOR_10 ((uint32_t)10U) /*!< Sector Number 10 */ +#define FLASH_SECTOR_11 ((uint32_t)11U) /*!< Sector Number 11 */ + +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */ + +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */ +/*-----------------------------------------------------------------------------------------------------*/ + +/*--------------------------------------------- STM32F401xC -------------------------------------------*/ +#if defined(STM32F401xC) + +#define FLASH_SECTOR_0 ((uint32_t)0U) /*!< Sector Number 0 */ +#define FLASH_SECTOR_1 ((uint32_t)1U) /*!< Sector Number 1 */ +#define FLASH_SECTOR_2 ((uint32_t)2U) /*!< Sector Number 2 */ +#define FLASH_SECTOR_3 ((uint32_t)3U) /*!< Sector Number 3 */ +#define FLASH_SECTOR_4 ((uint32_t)4U) /*!< Sector Number 4 */ +#define FLASH_SECTOR_5 ((uint32_t)5U) /*!< Sector Number 5 */ + +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */ + +#endif /* STM32F401xC */ +/*-----------------------------------------------------------------------------------------------------*/ + +/*--------------------------------------------- STM32F410xx -------------------------------------------*/ +#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) +#define FLASH_SECTOR_0 ((uint32_t)0U) /*!< Sector Number 0 */ +#define FLASH_SECTOR_1 ((uint32_t)1U) /*!< Sector Number 1 */ +#define FLASH_SECTOR_2 ((uint32_t)2U) /*!< Sector Number 2 */ +#define FLASH_SECTOR_3 ((uint32_t)3U) /*!< Sector Number 3 */ +#define FLASH_SECTOR_4 ((uint32_t)4U) /*!< Sector Number 4 */ +#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ +/*-----------------------------------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F401xE/STM32F411xE/STM32F446xx ------------------------------*/ +#if defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) + +#define FLASH_SECTOR_0 ((uint32_t)0U) /*!< Sector Number 0 */ +#define FLASH_SECTOR_1 ((uint32_t)1U) /*!< Sector Number 1 */ +#define FLASH_SECTOR_2 ((uint32_t)2U) /*!< Sector Number 2 */ +#define FLASH_SECTOR_3 ((uint32_t)3U) /*!< Sector Number 3 */ +#define FLASH_SECTOR_4 ((uint32_t)4U) /*!< Sector Number 4 */ +#define FLASH_SECTOR_5 ((uint32_t)5U) /*!< Sector Number 5 */ +#define FLASH_SECTOR_6 ((uint32_t)6U) /*!< Sector Number 6 */ +#define FLASH_SECTOR_7 ((uint32_t)7U) /*!< Sector Number 7 */ + +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbyte */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbyte */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbyte */ + +#endif /* STM32F401xE || STM32F411xE || STM32F446xx */ +/*-----------------------------------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F7xx ------------------------------*/ +#if defined(STM32F756xx) || defined(STM32F746xx) || defined(STM32F745xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) || defined(STM32F722xx) || \ + defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) + +#define FLASH_SECTOR_0 ((uint32_t)0U) /*!< Sector Number 0 */ +#define FLASH_SECTOR_1 ((uint32_t)1U) /*!< Sector Number 1 */ +#define FLASH_SECTOR_2 ((uint32_t)2U) /*!< Sector Number 2 */ +#define FLASH_SECTOR_3 ((uint32_t)3U) /*!< Sector Number 3 */ +#define FLASH_SECTOR_4 ((uint32_t)4U) /*!< Sector Number 4 */ +#define FLASH_SECTOR_5 ((uint32_t)5U) /*!< Sector Number 5 */ +#define FLASH_SECTOR_6 ((uint32_t)6U) /*!< Sector Number 6 */ +#define FLASH_SECTOR_7 ((uint32_t)7U) /*!< Sector Number 7 */ + +#if (FLASH_SECTOR_TOTAL == 24) +#define FLASH_SECTOR_8 ((uint32_t)8U) /*!< Sector Number 8 */ +#define FLASH_SECTOR_9 ((uint32_t)9U) /*!< Sector Number 9 */ +#define FLASH_SECTOR_10 ((uint32_t)10U) /*!< Sector Number 10 */ +#define FLASH_SECTOR_11 ((uint32_t)11U) /*!< Sector Number 11 */ +#define FLASH_SECTOR_12 ((uint32_t)12U) /*!< Sector Number 12 */ +#define FLASH_SECTOR_13 ((uint32_t)13U) /*!< Sector Number 13 */ +#define FLASH_SECTOR_14 ((uint32_t)14U) /*!< Sector Number 14 */ +#define FLASH_SECTOR_15 ((uint32_t)15U) /*!< Sector Number 15 */ +#define FLASH_SECTOR_16 ((uint32_t)16U) /*!< Sector Number 16 */ +#define FLASH_SECTOR_17 ((uint32_t)17U) /*!< Sector Number 17 */ +#define FLASH_SECTOR_18 ((uint32_t)18U) /*!< Sector Number 18 */ +#define FLASH_SECTOR_19 ((uint32_t)19U) /*!< Sector Number 19 */ +#define FLASH_SECTOR_20 ((uint32_t)20U) /*!< Sector Number 20 */ +#define FLASH_SECTOR_21 ((uint32_t)21U) /*!< Sector Number 21 */ +#define FLASH_SECTOR_22 ((uint32_t)22U) /*!< Sector Number 22 */ +#define FLASH_SECTOR_23 ((uint32_t)23U) /*!< Sector Number 23 */ +#else +// need to define here a 'dummy'' SECTOR_11, for F7 series this required when FLASH_SECTOR_TOTAL is 8 +#define FLASH_SECTOR_11 ((uint32_t)11U) /*!< Sector Number 11 */ +#endif /* FLASH_SECTOR_TOTAL == 24 */ + +// the following is assuming DUAL BANK is not used +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) /* Base address of Sector 1, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) /* Base address of Sector 2, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) /* Base address of Sector 3, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) /* Base address of Sector 4, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) /* Base address of Sector 5, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) /* Base address of Sector 6, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) /* Base address of Sector 7, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08100000) /* Base address of Sector 8, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x08140000) /* Base address of Sector 9, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x08180000) /* Base address of Sector 10, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x081C0000) /* Base address of Sector 11, 256 Kbytes */ + +#endif // efined(STM32F756xx) || defined(STM32F746xx) || defined(STM32F745xx) || defined(STM32F767xx) || .... etc + + +///////////////// +// sector address +///////////////// + +#if defined(STM32F746xx) || defined(STM32F745xx) + +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) /* Base address of Sector 1, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) /* Base address of Sector 2, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) /* Base address of Sector 3, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) /* Base address of Sector 4, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) /* Base address of Sector 5, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) /* Base address of Sector 6, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) /* Base address of Sector 7, 256 Kbytes */ + +#elif defined(STM32F767xx) + +// this is assuming that we DO NOT work with dual bank +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) /* Base address of Sector 1, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) /* Base address of Sector 2, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) /* Base address of Sector 3, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) /* Base address of Sector 4, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) /* Base address of Sector 5, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) /* Base address of Sector 6, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) /* Base address of Sector 7, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08100000) /* Base address of Sector 8, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x08140000) /* Base address of Sector 9, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x08180000) /* Base address of Sector 10, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x081C0000) /* Base address of Sector 11, 256 Kbytes */ + +#elif defined(STM32F769xx) + +// this is assuming that we DO NOT work with dual bank +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 32 Kbyte */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) /* Base @ of Sector 1, 32 Kbyte */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) /* Base @ of Sector 2, 32 Kbyte */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) /* Base @ of Sector 3, 32 Kbyte */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) /* Base @ of Sector 4, 128 Kbyte */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) /* Base @ of Sector 5, 256 Kbyte */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) /* Base @ of Sector 6, 256 Kbyte */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) /* Base @ of Sector 7, 256 Kbyte */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08100000) /* Base @ of Sector 8, 256 Kbyte */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x08140000) /* Base @ of Sector 9, 256 Kbyte */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x08180000) /* Base @ of Sector 10, 256 Kbyte */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x081C0000) /* Base @ of Sector 11, 256 Kbyte */ + +#elif defined(STM32F722xx) + +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) /* Base address of Sector 1, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) /* Base address of Sector 2, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) /* Base address of Sector 3, 32 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) /* Base address of Sector 4, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) /* Base address of Sector 5, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) /* Base address of Sector 6, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) /* Base address of Sector 7, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08100000) /* Base address of Sector 8, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x08140000) /* Base address of Sector 9, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x08180000) /* Base address of Sector 10, 256 Kbytes */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x081C0000) /* Base address of Sector 11, 256 Kbytes */ + +#elif defined(STM32F723xx) + +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */ + +#endif + +// sanity check for definition of flash sector, sector0 exists on any target, so we are good checking for its definition +#ifndef ADDR_FLASH_SECTOR_0 +#error >>THE SECTORS ADDRESSES FOR THE TARGET BOARD HAVE NOT BEEN DEFINED, PLEASE ADD THOSE ABOVE AT THE APPROPRIATE LOCATION AND SUBMIT A PR<< +#endif + + +// END of sector address + + +#define __HAL_FLASH_INSTRUCTION_CACHE_ENABLE() (FLASH->ACR |= FLASH_ACR_ICEN) +#define __HAL_FLASH_INSTRUCTION_CACHE_DISABLE() (FLASH->ACR &= (~FLASH_ACR_ICEN)) + +#define __HAL_FLASH_DATA_CACHE_DISABLE() (FLASH->ACR &= (~FLASH_ACR_DCEN)) +#define __HAL_FLASH_DATA_CACHE_ENABLE() (FLASH->ACR |= FLASH_ACR_DCEN) +#define __HAL_FLASH_INSTRUCTION_CACHE_RESET() do {FLASH->ACR |= FLASH_ACR_ICRST; \ + FLASH->ACR &= ~FLASH_ACR_ICRST; \ + }while(0U) +#define __HAL_FLASH_DATA_CACHE_RESET() do {FLASH->ACR |= FLASH_ACR_DCRST; \ + FLASH->ACR &= ~FLASH_ACR_DCRST; \ + }while(0U) + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32FLASH_USE_FLASH +SMT32FlashDriver STM32FLASH; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + bool HAL_FLASH_Unlock(void); + void HAL_FLASH_Lock(void); + bool FLASH_WaitForLastOperation(uint32_t timeout); + + void flash_lld_init(); + void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer); + int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer); + int flash_lld_isErased(uint32_t startAddress, uint32_t length); + int flash_lld_erase(uint32_t address); + uint8_t flash_lld_getSector(uint32_t address); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_STM32_FLASH + +#endif // FLASH_LLD_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/README.md new file mode 100644 index 00000000..a5d81d13 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/README.md @@ -0,0 +1,4 @@ +# Flash driver V3 + +This driver supports L0 series. +The low level driver code is taken or heavily inspired in the STCube MX HAL drivers from STMicroelectronics. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.c new file mode 100644 index 00000000..199df17b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.c @@ -0,0 +1,236 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////// +// This driver has been tested with the following STM32 series: F0 +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#if (HAL_USE_STM32_FLASH == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +SMT32FlashDriver STM32FLASH; + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Unlock the FLASH control register access +bool HAL_FLASH_Unlock(void) +{ + // Unlocking FLASH_PECR register access + if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK)) + { + WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY1); + WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY2); + } + + if (HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PRGLOCK)) + { + // Unlocking the program memory access + WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY1); + WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY2); + } + + return true; +} + +// Locks the FLASH control register access +bool HAL_FLASH_Lock(void) +{ + // Set the PRGLOCK Bit to lock the FLASH Registers access + SET_BIT(FLASH->PECR, FLASH_PECR_PRGLOCK); + + // Set the PELOCK Bit to lock the PECR Register access + SET_BIT(FLASH->PECR, FLASH_PECR_PELOCK); + + return true; +} + +// Wait for a FLASH operation to complete. +bool FLASH_WaitForLastOperation(uint32_t timeout) +{ + (void)timeout; + + // Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + // Even if the FLASH operation fails, the BUSY flag will be reset and an error flag will be set + // no need to overload this with a timeout workflow as the watchdog will quick-in if execution gets stuck + + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)); + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) + { + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_FWWERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_NOTZEROERR) ) + { + return false; + } + + // There is no error flag set + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +void flash_lld_init() +{ + stm32FlashObjectInit(&STM32FLASH); +} + +void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer) +{ + + __IO uint8_t* cursor = (__IO uint8_t*)startAddress; + __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); + + // copy contents from flash to buffer starting from the start address + while(cursor < endAddress) + { + *buffer++ = *cursor++; + } +} + +int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer) +{ + bool success = true; + + __IO uint8_t* cursor = (__IO uint8_t*)startAddress; + __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); + + // unlock the FLASH + if(HAL_FLASH_Unlock()) + { + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + + while(cursor < endAddress) + { + // if buffer has enough data, program words (32 bits) in a single operation to speed up things + // NOTE: assuming that the supply voltage is able to cope with half-word programming + if((endAddress - cursor) >= 4) + { + *(__IO uint32_t*)cursor = *((uint32_t*)buffer); + + //*(__IO uint32_t*)cursor = 0xBEEFBEEF; + + // update flash and buffer pointers by the 'extra' byte that was programmed + cursor += 4; + buffer += 4; + } + else + { + // can only program words + // TODO add error code? + success = false; + break; + } + + // wait for any flash operation to be completed + // timeout set to 0 on purpose + // watchdog will quick-in if execution gets stuck + success = FLASH_WaitForLastOperation(0); + + if(!success) + { + // quit on failure + break; + } + } + + // lock the FLASH + HAL_FLASH_Lock(); + } + + // done here + return success; +} + +int flash_lld_isErased(uint32_t startAddress, uint32_t length) +{ + __IO uint32_t* cursor = (__IO uint32_t*)startAddress; + __IO uint32_t* endAddress = (__IO uint32_t*)(startAddress + length); + + // an erased flash address has to read FLASH_ERASED_WORD + // OK to check by word (32 bits) because the erase is performed by 'page' whose size is word multiple + while(cursor < endAddress) + { + if(*cursor++ != FLASH_ERASED_WORD) + { + // found an address with something other than FLASH_ERASED_WORD!! + return false; + } + } + + // reached here so the segment must be erased + return true; +} + +uint8_t flash_lld_getSector(uint32_t address) +{ + return (address - FLASH_BASE) / FLASH_PAGE_SIZE; +} + +int flash_lld_erase(uint32_t address) +{ + bool success = true; + + // unlock the FLASH + if(HAL_FLASH_Unlock()) + { + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + + // erase the page + + // Set the ERASE bit + SET_BIT(FLASH->PECR, FLASH_PECR_ERASE); + + // Set PROG bit + SET_BIT(FLASH->PECR, FLASH_PECR_PROG); + + // Write 00000000h to the first word of the program page to erase + *(__IO uint32_t *)(uint32_t)(address & ~(FLASH_PAGE_SIZE - 1)) = 0x00000000; + + // wait for any flash operation to be completed + // watchdog will quick-in if execution gets stuck + success = FLASH_WaitForLastOperation(0); + + // If the erase operation is completed, disable the ERASE Bit + CLEAR_BIT(FLASH->PECR, FLASH_PECR_PROG); + CLEAR_BIT(FLASH->PECR, FLASH_PECR_ERASE); + + // lock the FLASH + HAL_FLASH_Lock(); + } + + return success; +} + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.h new file mode 100644 index 00000000..475aae08 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv3/flash_lld.h @@ -0,0 +1,152 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef FLASH_LLD_H +#define FLASH_LLD_H + +#include "stm32_registry.h" +#include + +#if (HAL_USE_STM32_FLASH == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// From STMicroelectronics Cube HAL +// HAL Status structures definition +typedef struct SMT32FlashDriver { + + // pointer to the FLASH Registers + FLASH_TypeDef *flash; + +}SMT32FlashDriver; + +/** + * @brief HAL Status structures definition + */ +typedef enum +{ + HAL_OK = 0x00U, + HAL_ERROR = 0x01U, + HAL_BUSY = 0x02U, + HAL_TIMEOUT = 0x03U +} HAL_StatusTypeDef; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +// From STMicroelectronics Cube HAL +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET) + +#define FLASH_PEKEY1 ((uint32_t)0x89ABCDEFU) /*!< Flash program erase key1 */ +#define FLASH_PEKEY2 ((uint32_t)0x02030405U) /*!< Flash program erase key: used with FLASH_PEKEY2 + to unlock the write access to the FLASH_PECR register and + data EEPROM */ + +#define FLASH_PRGKEY1 ((uint32_t)0x8C9DAEBFU) /*!< Flash program memory key1 */ +#define FLASH_PRGKEY2 ((uint32_t)0x13141516U) /*!< Flash program memory key2: used with FLASH_PRGKEY2 + to unlock the program memory */ +#define FLASH_TIMEOUT_VALUE (50000U) /* 50 s */ +#define FLASH_SIZE_DATA_REGISTER FLASHSIZE_BASE + +#define FLASH_SIZE (uint32_t)((*((uint32_t *)FLASHSIZE_BASE)&0xFFFF) * 1024U) +#define FLASH_PAGE_SIZE ((uint32_t)128U) /*!< FLASH Page Size in bytes */ + +#define FLASH_FLAG_ALL_ERRORS ( FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_SIZERR | \ + FLASH_FLAG_OPTVERR | FLASH_FLAG_RDERR | FLASH_FLAG_FWWERR | \ + FLASH_FLAG_NOTZEROERR ) + +/** + * @brief Get the specified FLASH flag status. + * @param __FLAG__ specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg @ref FLASH_FLAG_BSY FLASH Busy flag + * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag + * @arg @ref FLASH_FLAG_ENDHV FLASH End of High Voltage flag + * @arg @ref FLASH_FLAG_READY FLASH Ready flag after low power mode + * @arg @ref FLASH_FLAG_PGAERR FLASH Programming Alignment error flag + * @arg @ref FLASH_FLAG_SIZERR FLASH Size error flag + * @arg @ref FLASH_FLAG_OPTVERR FLASH Option validity error flag (not valid with STM32L031xx/STM32L041xx) + * @arg @ref FLASH_FLAG_RDERR FLASH Read protected error flag + * @arg @ref FLASH_FLAG_WRPERR FLASH Write protected error flag + * @arg @ref FLASH_FLAG_FWWERR FLASH Fetch While Write Error flag + * @arg @ref FLASH_FLAG_NOTZEROERR Not Zero area error flag + * @retval The new state of __FLAG__ (SET or RESET). + */ +#define __HAL_FLASH_GET_FLAG(__FLAG__) (((FLASH->SR) & (__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear the specified FLASH flag. + * @param __FLAG__ specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag + * @arg @ref FLASH_FLAG_PGAERR FLASH Programming Alignment error flag + * @arg @ref FLASH_FLAG_SIZERR FLASH Size error flag + * @arg @ref FLASH_FLAG_OPTVERR FLASH Option validity error flag (not valid with STM32L031xx/STM32L041xx) + * @arg @ref FLASH_FLAG_RDERR FLASH Read protected error flag + * @arg @ref FLASH_FLAG_WRPERR FLASH Write protected error flag + * @arg @ref FLASH_FLAG_FWWERR FLASH Fetch While Write Error flag + * @arg @ref FLASH_FLAG_NOTZEROERR Not Zero area error flag + * @retval none + */ +#define __HAL_FLASH_CLEAR_FLAG(__FLAG__) ((FLASH->SR) = (__FLAG__)) + +/** @defgroup FLASH_Flags FLASH Flags + * @{ + */ + +#define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */ +#define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Programming flag */ +#define FLASH_FLAG_ENDHV FLASH_SR_HVOFF /*!< FLASH End of High Voltage flag */ +#define FLASH_FLAG_READY FLASH_SR_READY /*!< FLASH Ready flag after low power mode */ +#define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_PGAERR FLASH_SR_PGAERR /*!< FLASH Programming Alignment error flag */ +#define FLASH_FLAG_SIZERR FLASH_SR_SIZERR /*!< FLASH Size error flag */ +#define FLASH_FLAG_OPTVERR FLASH_SR_OPTVERR /*!< FLASH Option Validity error flag */ +#define FLASH_FLAG_RDERR FLASH_SR_RDERR /*!< FLASH Read protected error flag */ +#define FLASH_FLAG_FWWERR FLASH_SR_FWWERR /*!< FLASH Write or Errase operation aborted */ +#define FLASH_FLAG_NOTZEROERR FLASH_SR_NOTZEROERR /*!< FLASH Read protected error flag */ + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32FLASH_USE_FLASH +SMT32FlashDriver STM32FLASH; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + void flash_lld_init(); + void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer); + int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer); + int flash_lld_isErased(uint32_t startAddress, uint32_t length); + int flash_lld_erase(uint32_t address); + uint8_t flash_lld_getSector(uint32_t address); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_STM32_FLASH + +#endif // FLASH_LLD_H diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/README.md new file mode 100644 index 00000000..2324fcee --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/README.md @@ -0,0 +1,4 @@ +# External flexible memory controller (FSMC) driver V1 + +This driver supports F4 and F7 series. +The low level driver code is taken from or heavily inspired in the ChibiOS community contribution repository. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c new file mode 100644 index 00000000..ac2ac802 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.c @@ -0,0 +1,475 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#include +#include + +#if (HAL_USE_NAND == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// +#define NAND_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_NAND_DMA_STREAM, \ + STM32_FSMC_DMA_CHN) + +// Bus width of NAND IC. +// Must be 8 or 16 +#if ! defined(STM32_NAND_BUS_WIDTH) +#define STM32_NAND_BUS_WIDTH 8 +#endif + +// DMA transaction width on AHB bus in bytes +#define AHB_TRANSACTION_WIDTH 2 + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// + +// NAND1 driver identifier. +#if STM32_NAND_USE_FSMC_NAND1 +NANDDriver NANDD1; +#endif + +// NAND2 driver identifier. +#if STM32_NAND_USE_FSMC_NAND2 +NANDDriver NANDD2; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Helper function. +static void align_check(const void *ptr, uint32_t len) { + osalDbgCheck((((uint32_t)ptr % AHB_TRANSACTION_WIDTH) == 0) && + ((len % AHB_TRANSACTION_WIDTH) == 0) && + (len >= AHB_TRANSACTION_WIDTH)); + (void)ptr; + (void)len; +} + +// Work around errata in STM32's FSMC core. +// Constant output clock (if enabled) disappears when CLKDIV value +// sets to 1 (FMC_CLK period = 2 × HCLK periods) AND 8-bit async +// transaction generated on AHB. This workaround eliminates 8-bit +// transactions on bus when you use 8-bit memory. It suitable only +// for 8-bit memory (i.e. PWID bits in PCR register must be set +// to 8-bit mode). +static void set_16bit_bus(NANDDriver *nandp) { +#if STM32_NAND_BUS_WIDTH + nandp->nand->PCR |= FSMC_PCR_PWID_16; +#else + (void)nandp; +#endif +} + +static void set_8bit_bus(NANDDriver *nandp) { +#if STM32_NAND_BUS_WIDTH + nandp->nand->PCR &= ~FSMC_PCR_PWID_16; +#else + (void)nandp; +#endif +} + +// Wakes up the waiting thread. +// nandp pointer to the @p NANDDriver object +// msg wakeup message +static void wakeup_isr(NANDDriver *nandp) { + + osalDbgCheck(nandp->thread != NULL); + osalThreadResumeI(&nandp->thread, MSG_OK); +} + +// Put calling thread in suspend and switch driver state +// nandp pointer to the @p NANDDriver object +static void nand_lld_suspend_thread(NANDDriver *nandp) { + + osalThreadSuspendS(&nandp->thread); +} + +// Caclulate ECCPS register value +// nandp pointer to the @p NANDDriver object +static uint32_t calc_eccps(NANDDriver *nandp) { + + uint32_t i = 0; + uint32_t eccps = nandp->config->page_data_size; + + eccps = eccps >> 9; + while (eccps > 0){ + i++; + eccps >>= 1; + } + + return i << 17; +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver interrupt handlers. // +/////////////////////////////////////////////////////////////////////////////// + +// Enable interrupts from NAND +// nandp pointer to the @p NANDDriver object +static void nand_ready_isr_enable(NANDDriver *nandp) { + + nandp->nand->SR &= ~(FSMC_SR_IRS | FSMC_SR_ILS | FSMC_SR_IFS | + FSMC_SR_ILEN | FSMC_SR_IFEN); + nandp->nand->SR |= FSMC_SR_IREN; +} + +// Disable interrupts from NAND +// nandp pointer to the @p NANDDriver object +static void nand_ready_isr_disable(NANDDriver *nandp) { + + nandp->nand->SR &= ~FSMC_SR_IREN; +} + +// Ready interrupt handler +// nandp pointer to the @p NANDDriver object +static void nand_isr_handler(NANDDriver *nandp) { + + osalSysLockFromISR(); + + osalDbgCheck(nandp->nand->SR & FSMC_SR_IRS); // spurious interrupt happened + nandp->nand->SR &= ~FSMC_SR_IRS; + + switch (nandp->state){ + case NAND_READ: + nandp->state = NAND_DMA_RX; + dmaStartMemCopy(nandp->dma, nandp->dmamode, nandp->map_data, nandp->rxdata, + nandp->datalen/AHB_TRANSACTION_WIDTH); + // thread will be waked up from DMA ISR + break; + + case NAND_ERASE: // NAND reports about erase finish + case NAND_PROGRAM: // NAND reports about page programming finish + case NAND_RESET: // NAND reports about finished reset recover + nandp->state = NAND_READY; + wakeup_isr(nandp); + break; + + default: + osalSysHalt("Unhandled case"); + break; + } + osalSysUnlockFromISR(); +} + +// DMA RX end IRQ handler. +// nandp pointer to the @p NANDDriver object +// flags pre-shifted content of the ISR register +static void nand_lld_serve_transfer_end_irq(NANDDriver *nandp, uint32_t flags) { + // DMA errors handling. +#if defined(STM32_NAND_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_NAND_DMA_ERROR_HOOK(nandp); + } +#else + (void)flags; +#endif + + osalSysLockFromISR(); + + dmaStreamDisable(nandp->dma); + + switch (nandp->state){ + case NAND_DMA_TX: + nandp->state = NAND_PROGRAM; + nandp->map_cmd[0] = NAND_CMD_PAGEPROG; + // thread will be woken up from ready_isr() + break; + + case NAND_DMA_RX: + nandp->state = NAND_READY; + nandp->rxdata = NULL; + nandp->datalen = 0; + wakeup_isr(nandp); + break; + + default: + osalSysHalt("Unhandled case"); + break; + } + + osalSysUnlockFromISR(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level NAND driver initialization. +void fsmcNandInit(void) { + + stm32FsmcInit(); + +#if STM32_NAND_USE_FSMC_NAND1 + // Driver initialization. + nandObjectInit(&NANDD1); + NANDD1.rxdata = NULL; + NANDD1.datalen = 0; + NANDD1.thread = NULL; + NANDD1.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM); + NANDD1.nand = FSMCD1.nand1; + NANDD1.map_data = (void *)FSMC_Bank2_MAP_COMMON_DATA; + NANDD1.map_cmd = (uint16_t *)FSMC_Bank2_MAP_COMMON_CMD; + NANDD1.map_addr = (uint16_t *)FSMC_Bank2_MAP_COMMON_ADDR; + NANDD1.bb_map = NULL; +#endif // STM32_NAND_USE_FSMC_NAND1 + +#if STM32_NAND_USE_FSMC_NAND2 + // Driver initialization. + nandObjectInit(&NANDD2); + NANDD2.rxdata = NULL; + NANDD2.datalen = 0; + NANDD2.thread = NULL; + NANDD2.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM); + NANDD2.nand = FSMCD1.nand2; + NANDD2.map_data = (void *)FSMC_Bank3_MAP_COMMON_DATA; + NANDD2.map_cmd = (uint16_t *)FSMC_Bank3_MAP_COMMON_CMD; + NANDD2.map_addr = (uint16_t *)FSMC_Bank3_MAP_COMMON_ADDR; + NANDD2.bb_map = NULL; +#endif // STM32_NAND_USE_FSMC_NAND2 +} + +// Configures and activates the NAND peripheral. +// nandp pointer to the @p NANDDriver object +void fsmcNandStart(NANDDriver *nandp) { + + bool b; + uint32_t dmasize; + uint32_t pcr_bus_width; + + if (FSMCD1.state == FSMC_STOP) + fsmc_start(&FSMCD1); + + if (nandp->state == NAND_STOP) { + b = dmaStreamAllocate(nandp->dma, + STM32_EMC_FSMC1_IRQ_PRIORITY, + (stm32_dmaisr_t)nand_lld_serve_transfer_end_irq, + (void *)nandp); + osalDbgAssert(!b, "stream already allocated"); + +#if AHB_TRANSACTION_WIDTH == 4 + dmasize = STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; +#elif AHB_TRANSACTION_WIDTH == 2 + dmasize = STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD; +#elif AHB_TRANSACTION_WIDTH == 1 + dmasize = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; +#else +#error "Incorrect AHB_TRANSACTION_WIDTH" +#endif + + nandp->dmamode = STM32_DMA_CR_CHSEL(NAND_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_NAND_NAND1_DMA_PRIORITY) | + dmasize | + STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | + STM32_DMA_CR_TCIE; + +#if STM32_NAND_BUS_WIDTH == 8 + pcr_bus_width = FSMC_PCR_PWID_8; +#elif STM32_NAND_BUS_WIDTH == 16 + pcr_bus_width = FSMC_PCR_PWID_16; +#else +#error "Bus width must be 8 or 16 bits" +#endif + nandp->nand->PCR = pcr_bus_width | calc_eccps(nandp) | + FSMC_PCR_PTYP_NAND | FSMC_PCR_PBKEN; + nandp->nand->PMEM = nandp->config->pmem; + nandp->nand->PATT = nandp->config->pmem; + nandp->isr_handler = nand_isr_handler; + nand_ready_isr_enable(nandp); + } +} + +// Deactivates the NAND peripheral. +// nandp pointer to the @p NANDDriver object +void fsmcNandStop(NANDDriver *nandp) { + + if (nandp->state == NAND_READY) { + dmaStreamRelease(nandp->dma); + nandp->nand->PCR &= ~FSMC_PCR_PBKEN; + nand_ready_isr_disable(nandp); + nandp->isr_handler = NULL; + } +} + +// Read data from NAND. +// nandp pointer to the @p NANDDriver object +// data pointer to data buffer +// datalen size of data buffer in bytes +// addr pointer to address buffer +// addrlen length of address +// ecc pointer to store computed ECC. Ignored when NULL. +void nand_lld_read_data(NANDDriver *nandp, uint16_t *data, size_t datalen, + uint8_t *addr, size_t addrlen, uint32_t *ecc){ + + align_check(data, datalen); + + nandp->state = NAND_READ; + nandp->rxdata = data; + nandp->datalen = datalen; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_READ0); + nand_lld_write_addr(nandp, addr, addrlen); + osalSysLock(); + nand_lld_write_cmd(nandp, NAND_CMD_READ0_CONFIRM); + set_8bit_bus(nandp); + + // Here NAND asserts busy signal and starts transferring from memory + // array to page buffer. After the end of transmission ready_isr functions + // starts DMA transfer from page buffer to MCU's RAM. + osalDbgAssert((nandp->nand->PCR & FSMC_PCR_ECCEN) == 0, + "State machine broken. ECCEN must be previously disabled."); + + if (NULL != ecc){ + nandp->nand->PCR |= FSMC_PCR_ECCEN; + } + + nand_lld_suspend_thread(nandp); + osalSysUnlock(); + + // thread was woken up from DMA ISR + if (NULL != ecc){ + while (! (nandp->nand->SR & FSMC_SR_FEMPT)) + ; + *ecc = nandp->nand->ECCR; + nandp->nand->PCR &= ~FSMC_PCR_ECCEN; + } +} + +// Write data to NAND. +// nandp pointer to the @p NANDDriver object +// data buffer with data to be written +// datalen size of data buffer in bytes +// addr pointer to address buffer +// addrlen length of address +// ecc pointer to store computed ECC. Ignored when NULL. +// The operation status reported by NAND IC (0x70 command). +uint8_t nand_lld_write_data(NANDDriver *nandp, const uint16_t *data, + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc) { + + align_check(data, datalen); + + nandp->state = NAND_WRITE; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_WRITE); + osalSysLock(); + nand_lld_write_addr(nandp, addr, addrlen); + set_8bit_bus(nandp); + + // Now start DMA transfer to NAND buffer and put thread in sleep state. + // Tread will be woken up from ready ISR. + nandp->state = NAND_DMA_TX; + osalDbgAssert((nandp->nand->PCR & FSMC_PCR_ECCEN) == 0, + "State machine broken. ECCEN must be previously disabled."); + + if (NULL != ecc){ + nandp->nand->PCR |= FSMC_PCR_ECCEN; + } + + dmaStartMemCopy(nandp->dma, nandp->dmamode, data, nandp->map_data, + datalen/AHB_TRANSACTION_WIDTH); + + nand_lld_suspend_thread(nandp); + osalSysUnlock(); + + if (NULL != ecc){ + while (! (nandp->nand->SR & FSMC_SR_FEMPT)) + ; + *ecc = nandp->nand->ECCR; + nandp->nand->PCR &= ~FSMC_PCR_ECCEN; + } + + return nand_lld_read_status(nandp); +} + +// Soft reset NAND device. +// nandp pointer to the @p NANDDriver object +void nand_lld_reset(NANDDriver *nandp) { + + nandp->state = NAND_RESET; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_RESET); + set_8bit_bus(nandp); + + osalSysLock(); + nand_lld_suspend_thread(nandp); + osalSysUnlock(); +} + +// Erase block. +// nandp pointer to the @p NANDDriver object +// addr pointer to address buffer +// addrlen length of address +// return The operation status reported by NAND IC (0x70 command). +uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen) { + + nandp->state = NAND_ERASE; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_ERASE); + nand_lld_write_addr(nandp, addr, addrlen); + osalSysLock(); + nand_lld_write_cmd(nandp, NAND_CMD_ERASE_CONFIRM); + set_8bit_bus(nandp); + + nand_lld_suspend_thread(nandp); + osalSysUnlock(); + + return nand_lld_read_status(nandp); +} + +// Send addres to NAND. +// nandp pointer to the @p NANDDriver object +// len length of address array +// addr pointer to address array +void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len) { + size_t i = 0; + + for (i=0; imap_addr[i] = addr[i]; +} + +// Send command to NAND. +// nandp pointer to the @p NANDDriver object +// cmd command value +void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd) { + nandp->map_cmd[0] = cmd; +} + +// Read status byte from NAND. +// nandp pointer to the @p NANDDriver object +// return Status byte. +uint8_t nand_lld_read_status(NANDDriver *nandp) { + + uint16_t status; + + set_16bit_bus(nandp); + nand_lld_write_cmd(nandp, NAND_CMD_STATUS); + set_8bit_bus(nandp); + status = nandp->map_data[0]; + + return status & 0xFF; +} + +#endif // HAL_USE_NAND diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h new file mode 100644 index 00000000..74f5a52b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_nand_lld.h @@ -0,0 +1,219 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_NAND_LLD_H_ +#define HAL_NAND_LLD_H_ + +#include "hal_stm32_fsmc" +#include + +#if (HAL_USE_NAND == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// +#define NAND_MIN_PAGE_SIZE 256 +#define NAND_MAX_PAGE_SIZE 8192 + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +// Configuration options + +// FSMC1 interrupt priority level setting. +#if !defined(STM32_EMC_FSMC1_IRQ_PRIORITY) +#define STM32_EMC_FSMC1_IRQ_PRIORITY 10 +#endif + +// NAND driver enable switch. +// If set to @p TRUE the support for NAND1 is included. + +#if !defined(STM32_NAND_USE_NAND1) +#define STM32_NAND_USE_NAND1 FALSE +#endif + +// NAND driver enable switch. +// If set to @p TRUE the support for NAND2 is included. +#if !defined(STM32_NAND_USE_NAND2) +#define STM32_NAND_USE_NAND2 FALSE +#endif + +// NAND DMA error hook. +// The default action for DMA errors is a system halt because DMA +// error can only happen because programming errors. +#if !defined(STM32_NAND_DMA_ERROR_HOOK) +#define STM32_NAND_DMA_ERROR_HOOK(nandp) osalSysHalt("DMA failure") +#endif + +// NAND interrupt enable switch. +// If set to @p TRUE the support for internal FSMC interrupt included. +#if !defined(STM32_NAND_USE_INT) +#define STM32_NAND_USE_INT FALSE +#endif + +// NAND1 DMA priority (0..3|lowest..highest). +#if !defined(STM32_NAND_NAND1_DMA_PRIORITY) +#define STM32_NAND_NAND1_DMA_PRIORITY 0 +#endif + +// NAND2 DMA priority (0..3|lowest..highest). +#if !defined(STM32_NAND_NAND2_DMA_PRIORITY) +#define STM32_NAND_NAND2_DMA_PRIORITY 0 +#endif + +// DMA stream used for NAND operations. +// This option is only available on platforms with enhanced DMA. +#if !defined(STM32_NAND_DMA_STREAM) +#define STM32_NAND_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +#if !STM32_NAND_USE_FSMC_NAND1 && !STM32_NAND_USE_FSMC_NAND2 +#error "NAND driver activated but no NAND peripheral assigned" +#endif + +#if (STM32_NAND_USE_FSMC_NAND2 || STM32_NAND_USE_FSMC_NAND1) && !STM32_HAS_FSMC +#error "FSMC not present in the selected device" +#endif + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// Type of a structure representing an NAND driver. +typedef struct NANDDriver NANDDriver; + +// Type of interrupt handler function. +typedef void (*nandisrhandler_t)(NANDDriver *nandp); + +// Driver configuration structure. +// It could be empty on some architectures. +typedef struct { + // Number of erase blocks in NAND device. + uint32_t blocks; + + // Number of data bytes in page. + uint32_t page_data_size; + + // Number of spare bytes in page. + uint32_t page_spare_size; + + // Number of pages in block. + uint32_t pages_per_block; + + // Number of write cycles for row addressing. + uint8_t rowcycles; + + // Number of write cycles for column addressing. + uint8_t colcycles; + + // End of the mandatory fields. + // Number of wait cycles. This value will be used both for + // PMEM and PATTR registers + // For proper calculation procedure please look at AN2784 document from STMicroelectronics + uint32_t pmem; + +} NANDConfig; + +// Structure representing an NAND driver. +struct NANDDriver { + // Driver state. + nandstate_t state; + + // Current configuration data. + const NANDConfig *config; + + // Array to store bad block map. +#if NAND_USE_MUTUAL_EXCLUSION +#if CH_CFG_USE_MUTEXES + // Mutex protecting the bus. + mutex_t mutex; +#elif CH_CFG_USE_SEMAPHORES + semaphore_t semaphore; +#endif +#endif // NAND_USE_MUTUAL_EXCLUSION + // End of the mandatory fields. + + // Function enabling interrupts from FSMC. + nandisrhandler_t isr_handler; + + // Pointer to current transaction buffer. + void *rxdata; + + // Current transaction length in bytes. + size_t datalen; + + // DMA mode bit mask. + uint32_t dmamode; + + // DMA channel. + const stm32_dma_stream_t *dma; + + // Thread waiting for I/O completion. + thread_t *thread; + + // Pointer to the FSMC NAND registers block. + FSMC_NAND_TypeDef *nand; + + // Memory mapping for data. + uint16_t *map_data; + + // Memory mapping for commands. + uint16_t *map_cmd; + + // Memory mapping for addresses. + uint16_t *map_addr; + +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32_NAND_USE_FSMC_NAND1 +extern NANDDriver NANDD1; +#endif + +#if STM32_NAND_USE_FSMC_NAND2 +extern NANDDriver NANDD2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + void fsmcNandInit(void); + void fsmcNandStart(NANDDriver *nandp); + void fsmcNandStop(NANDDriver *nandp); + uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen); + void nand_lld_read_data(NANDDriver *nandp, uint16_t *data, + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); + void nand_lld_write_addr(NANDDriver *nandp, const uint8_t *addr, size_t len); + void nand_lld_write_cmd(NANDDriver *nandp, uint8_t cmd); + uint8_t nand_lld_write_data(NANDDriver *nandp, const uint16_t *data, + size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc); + uint8_t nand_lld_read_status(NANDDriver *nandp); + void nand_lld_reset(NANDDriver *nandp); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_USE_NAND + +#endif // HAL_NAND_LLD_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c new file mode 100644 index 00000000..8efa372e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.c @@ -0,0 +1,168 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess and Nick Klimov aka progfin +// See LICENSE file in the project root for full license information. +// + +#include +#include + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + +#if (STM32_USE_FSMC_SDRAM == TRUE) + +#include "fsmc_sdram_lld.h" + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +// FMC_Command_Mode +#define FMCCM_NORMAL ((uint32_t)0x00000000) +#define FMCCM_CLK_ENABLED ((uint32_t)0x00000001) +#define FMCCM_PALL ((uint32_t)0x00000002) +#define FMCCM_AUTO_REFRESH ((uint32_t)0x00000003) +#define FMCCM_LOAD_MODE ((uint32_t)0x00000004) +#define FMCCM_SELFREFRESH ((uint32_t)0x00000005) +#define FMCCM_POWER_DOWN ((uint32_t)0x00000006) + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +// SDRAM driver identifier. +SDRAMDriver SDRAMD; + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Wait until the SDRAM controller is ready. +static void _sdram_wait_ready(void) { + // Wait until the SDRAM controller is ready + while (SDRAMD.sdram->SDSR & FMC_SDSR_BUSY); +} + +// Executes the SDRAM memory initialization sequence. +// cfgp pointer to the @p SDRAMConfig object +static void _sdram_init_sequence(const SDRAMConfig *cfgp) { + + uint32_t command_target = 0; + +#if STM32_SDRAM_USE_FSMC_SDRAM1 + command_target |= FMC_SDCMR_CTB1; +#endif +#if STM32_SDRAM_USE_FSMC_SDRAM2 + command_target |= FMC_SDCMR_CTB2; +#endif + + // Step 3: Configure a clock configuration enable command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_CLK_ENABLED | command_target; + + // Step 4: Insert delay (tipically 100uS). + osalThreadSleepMilliseconds(1); + + // Step 5: Configure a PALL (precharge all) command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_PALL | command_target; + + // Step 6.1: Configure a Auto-Refresh command: send the first command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_AUTO_REFRESH | command_target | + (cfgp->sdcmr & FMC_SDCMR_NRFS); + + // Step 6.2: Send the second command. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_AUTO_REFRESH | command_target | + (cfgp->sdcmr & FMC_SDCMR_NRFS); + + // Step 7: Program the external memory mode register. + _sdram_wait_ready(); + SDRAMD.sdram->SDCMR = FMCCM_LOAD_MODE | command_target | + (cfgp->sdcmr & FMC_SDCMR_MRD); + + // Step 8: Set clock. + _sdram_wait_ready(); + SDRAMD.sdram->SDRTR = cfgp->sdrtr & FMC_SDRTR_COUNT; + + _sdram_wait_ready(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Driver interrupt handlers. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level SDRAM driver initialization. + +void fsmcSdramInit(void) { + + stm32FsmcInit(); + + SDRAMD.sdram = FSMCD1.sdram; + SDRAMD.state = SDRAM_STOP; +} + +// Configures and activates the SDRAM peripheral. +// sdramp pointer to the @p SDRAMDriver object +// cfgp pointer to the @p SDRAMConfig object +void fsmcSdramStart(SDRAMDriver *sdramp, const SDRAMConfig *cfgp) { + + if (FSMCD1.state == FSMC_STOP) + fsmc_start(&FSMCD1); + + osalDbgAssert((sdramp->state == SDRAM_STOP) || (sdramp->state == SDRAM_READY), + "SDRAM. Invalid state."); + + if (sdramp->state == SDRAM_STOP) { + + // Even if you need only bank2 you must properly set up SDCR and SDTR + // regitsters for bank1 too. Both banks will be tuned equally assuming + // connected memory ICs are equal. + sdramp->sdram->SDCR1 = cfgp->sdcr; + sdramp->sdram->SDTR1 = cfgp->sdtr; + sdramp->sdram->SDCR2 = cfgp->sdcr; + sdramp->sdram->SDTR2 = cfgp->sdtr; + + _sdram_init_sequence(cfgp); + + sdramp->state = SDRAM_READY; + } +} + +// Deactivates the SDRAM peripheral. +// sdramp pointer to the @p SDRAMDriver object +void fsmcSdramStop(SDRAMDriver *sdramp) { + + uint32_t command_target = 0; + +#if STM32_SDRAM_USE_FSMC_SDRAM1 + command_target |= FMC_SDCMR_CTB1; +#endif +#if STM32_SDRAM_USE_FSMC_SDRAM2 + command_target |= FMC_SDCMR_CTB2; +#endif + + if (sdramp->state == SDRAM_READY) { + SDRAMD.sdram->SDCMR = FMCCM_POWER_DOWN | command_target; + sdramp->state = SDRAM_STOP; + } +} + +#endif // STM32_USE_FSMC_SDRAM + +#endif //STM32F427xx / STM32F429xx / STM32F437xx / STM32F439xx / STM32F469xx / STM32F479xx / STM32F745xx / STM32F746xx + // STM32F756xx / STM32F767xx / STM32F769xx / STM32F777xx / STM32F779xx diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h new file mode 100644 index 00000000..20fe8587 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sdram_lld.h @@ -0,0 +1,133 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess and Nick Klimov aka progfin +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_FMC_SDRAM_H_ +#define HAL_FMC_SDRAM_H_ + +#include + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + +#include "hal_stm32_fsmc.h" + +#if (STM32_USE_FSMC_SDRAM == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// +// Configuration options + +// SDRAM driver enable switch. +// If set to @p TRUE the support for SDRAM1 is included. +#if !defined(STM32_SDRAM_USE_FSMC_SDRAM1) +#define STM32_SDRAM_USE_FSMC_SDRAM1 FALSE +#else +#define STM32_SDRAM1_MAP_BASE FSMC_Bank5_MAP_BASE +#endif + +// SDRAM driver enable switch. +// If set to @p TRUE the support for SDRAM2 is included. +#if !defined(STM32_SDRAM_USE_FSMC_SDRAM2) +#define STM32_SDRAM_USE_FSMC_SDRAM2 FALSE +#else +#define STM32_SDRAM2_MAP_BASE FSMC_Bank6_MAP_BASE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +#if !STM32_SDRAM_USE_FSMC_SDRAM1 && !STM32_SDRAM_USE_FSMC_SDRAM2 +#error "SDRAM driver activated but no SDRAM peripheral assigned" +#endif + +#if (STM32_SDRAM_USE_FSMC_SDRAM1 || STM32_SDRAM_USE_FSMC_SDRAM2) && !STM32_HAS_FSMC +#error "FMC not present in the selected device" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// Driver state machine possible states. +typedef enum +{ + SDRAM_UNINIT = 0, //*< Not initialized. + SDRAM_STOP = 1, //*< Stopped. + SDRAM_READY = 2, //*< Ready. +} sdramstate_t; + +// Type of a structure representing an SDRAM driver. +typedef struct SDRAMDriver SDRAMDriver; + +// Driver configuration structure. +// It could be empty on some architectures. +typedef struct { + // SDRAM control register. + // Its value will be used for both banks. + uint32_t sdcr; + + // SDRAM timing register. + // Its value will be used for both banks. + uint32_t sdtr; + + // SDRAM command mode register. + // Only its MRD and NRFS bits will be used. + uint32_t sdcmr; + + // SDRAM refresh timer register. + // Only its COUNT bits will be used. + uint32_t sdrtr; + +} SDRAMConfig; + +// Structure representing an SDRAM driver. +struct SDRAMDriver { + // Driver state. + sdramstate_t state; + + // Pointer to the FMC SDRAM registers block. + FSMC_SDRAM_TypeDef *sdram; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +extern SDRAMDriver SDRAMD; + +#ifdef __cplusplus +extern "C" { +#endif + + void fsmcSdramInit(void); + void fsmcSdramStart(SDRAMDriver *sdramp, const SDRAMConfig *cfgp); + void fsmcSdramStop(SDRAMDriver *sdramp); + +#ifdef __cplusplus +} +#endif + +#endif // STM32_USE_FSMC_SDRAM + +#endif //STM32F427xx / STM32F429xx / STM32F437xx / STM32F439xx / STM32F469xx / STM32F479xx / STM32F745xx / STM32F746xx + // STM32F756xx / STM32F767xx / STM32F769xx / STM32F777xx / STM32F779xx + +#endif // HAL_FMC_SDRAM_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c new file mode 100644 index 00000000..436759c7 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.c @@ -0,0 +1,123 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include "fsmc_sram_lld.h" + +#if (STM32_USE_FSMC_SRAM == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// +// SRAM1 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM1 +SRAMDriver SRAMD1; +#endif + +// SRAM2 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM2 +SRAMDriver SRAMD2; +#endif + +// SRAM3 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM3 +SRAMDriver SRAMD3; +#endif + +// SRAM4 driver identifier. +#if STM32_SRAM_USE_FSMC_SRAM4 +SRAMDriver SRAMD4; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver interrupt handlers. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level SRAM driver initialization. +void fsmcSramInit(void) { + + stm32FsmcInit(); + +#if STM32_SRAM_USE_FSMC_SRAM1 + SRAMD1.sram = FSMCD1.sram1; + SRAMD1.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM1 */ + +#if STM32_SRAM_USE_FSMC_SRAM2 + SRAMD2.sram = FSMCD1.sram2; + SRAMD2.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM2 */ + +#if STM32_SRAM_USE_FSMC_SRAM3 + SRAMD3.sram = FSMCD1.sram3; + SRAMD3.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM3 */ + +#if STM32_SRAM_USE_FSMC_SRAM4 + SRAMD4.sram = FSMCD1.sram4; + SRAMD4.state = SRAM_STOP; +#endif /* STM32_SRAM_USE_FSMC_SRAM4 */ +} + +// Configures and activates the SRAM peripheral. +// sramp pointer to the @p SRAMDriver object +// cfgp pointer to the @p SRAMConfig object +void fsmcSramStart(SRAMDriver *sramp, const SRAMConfig *cfgp) { + + if (FSMCD1.state == FSMC_STOP) + fsmc_start(&FSMCD1); + + osalDbgAssert((sramp->state == SRAM_STOP) || (sramp->state == SRAM_READY), + "invalid state"); + + if (sramp->state == SRAM_STOP) { + sramp->sram->BTR = cfgp->btr; + sramp->sram->BWTR = cfgp->bwtr; + sramp->sram->BCR = cfgp->bcr | FSMC_BCR_MBKEN; + sramp->state = SRAM_READY; + } +} + +// Deactivates the SRAM peripheral. +// sramp pointer to the @p SRAMDriver object +void fsmcSramStop(SRAMDriver *sramp) { + + if (sramp->state == SRAM_READY) { + uint32_t mask = FSMC_BCR_MBKEN; + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + mask |= FSMC_BCR_CCLKEN; +#endif + + sramp->sram->BCR &= ~mask; + sramp->state = SRAM_STOP; + } +} + +#endif // STM32_USE_FSMC_SRAM */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h new file mode 100644 index 00000000..1d10d377 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FSMCv1/fsmc_sram_lld.h @@ -0,0 +1,131 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_FSMC_SRAM_H_ +#define HAL_FSMC_SRAM_H_ + +#include "hal_stm32_fsmc.h" +#include + +#if (STM32_USE_FSMC_SRAM == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver constants. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver pre-compile time settings. // +/////////////////////////////////////////////////////////////////////////////// + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM1 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM1) +#define STM32_SRAM_USE_FSMC_SRAM1 FALSE +#endif + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM2 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM2) +#define STM32_SRAM_USE_FSMC_SRAM2 FALSE +#endif + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM3 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM3) +#define STM32_SRAM_USE_FSMC_SRAM3 FALSE +#endif + +// SRAM driver enable switch. +// If set to @p TRUE the support for SRAM4 is included. +#if !defined(STM32_SRAM_USE_FSMC_SRAM4) +#define STM32_SRAM_USE_FSMC_SRAM4 FALSE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Derived constants and error checks. // +/////////////////////////////////////////////////////////////////////////////// + +#if !STM32_SRAM_USE_FSMC_SRAM1 && !STM32_SRAM_USE_FSMC_SRAM2 && \ + !STM32_SRAM_USE_FSMC_SRAM3 && !STM32_SRAM_USE_FSMC_SRAM4 +#error "SRAM driver activated but no SRAM peripheral assigned" +#endif + +#if (STM32_SRAM_USE_FSMC_SRAM1 || STM32_SRAM_USE_FSMC_SRAM2 || \ + STM32_SRAM_USE_FSMC_SRAM3 || STM32_SRAM_USE_FSMC_SRAM4) && !STM32_HAS_FSMC +#error "FSMC not present in the selected device" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver data structures and types. // +/////////////////////////////////////////////////////////////////////////////// + +// Driver state machine possible states. +typedef enum { + SRAM_UNINIT = 0, // Not initialized + SRAM_STOP = 1, // Stopped + SRAM_READY = 2, // Ready +} sramstate_t; + +// Type of a structure representing an NAND driver. +typedef struct SRAMDriver SRAMDriver; + +// Driver configuration structure. +// It could be empty on some architectures. +// Some bits in BCR register will be forced by driver. +typedef struct { + uint32_t bcr; + uint32_t btr; + uint32_t bwtr; +} SRAMConfig; + +// Structure representing an NAND driver. +struct SRAMDriver { + // Driver state + sramstate_t state; + + // Pointer to the FSMC SRAM registers block. + FSMC_SRAM_NOR_TypeDef *sram; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Driver macros. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// External declarations. // +/////////////////////////////////////////////////////////////////////////////// + +#if STM32_SRAM_USE_FSMC_SRAM1 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD1; +#endif + +#if STM32_SRAM_USE_FSMC_SRAM2 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD2; +#endif + +#if STM32_SRAM_USE_FSMC_SRAM3 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD3; +#endif + +#if STM32_SRAM_USE_FSMC_SRAM4 && !defined(__DOXYGEN__) +extern SRAMDriver SRAMD4; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + void fsmcSramInit(void); + void fsmcSramStart(SRAMDriver *sramp, const SRAMConfig *cfgp); + void fsmcSramStop(SRAMDriver *sramp); + +#ifdef __cplusplus +} +#endif + +#endif // STM32_USE_FSMC_SRAM + +#endif // HAL_FSMC_SRAM_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/README.md new file mode 100644 index 00000000..103714ee --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/README.md @@ -0,0 +1,4 @@ +# 1-Wire v1 + +This driver supports all STM32 series. +The low level driver code is taken or heavily inspired in the 1-Wire SDK from MAXIM Semiconductors. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c new file mode 100644 index 00000000..8def10f5 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.c @@ -0,0 +1,320 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include +#include + +#if (HAL_USE_STM32_ONEWIRE == TRUE) + +#include +#include + +#if !NF_ONEWIRE_STM32_UART_USE_USART1 && !NF_ONEWIRE_STM32_UART_USE_USART2 && \ + !NF_ONEWIRE_STM32_UART_USE_USART3 && !NF_ONEWIRE_STM32_UART_USE_USART4 && \ + !NF_ONEWIRE_STM32_UART_USE_USART5 && !NF_ONEWIRE_STM32_UART_USE_USART6 && \ + !NF_ONEWIRE_STM32_UART_USE_USART7 && !NF_ONEWIRE_STM32_UART_USE_USART8 + +#error "1-Wire driver activated but no USART/UART peripheral assigned. Make sure to assign it @ target_nf_devices_onewire_config.h" +#endif + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ONEWIRED1 driver identifier.*/ +ONEWIREDriver ONEWIRED1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +void uartSetSpeed(uint32_t speed) +{ + // stop UART, better do this before changing configuration + uartStop(ONEWIRED1.UartDriver); + + // default UART config + ONEWIRED1.UartConfig.speed = speed; + + uartStart(ONEWIRED1.UartDriver, &ONEWIRED1.UartConfig); +} + + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +static void TxEnd(UARTDriver *uartp) +{ + (void) uartp; + + //NATIVE_INTERRUPT_START + + //chSysLockFromISR(); + chBSemSignalI(&ONEWIRED1.TxCompleted); + // chSysUnlockFromISR(); + + //NATIVE_INTERRUPT_END +} + +static void RxEnd(UARTDriver *uartp) +{ + (void) uartp; + + //NATIVE_INTERRUPT_START + + // chSysLockFromISR(); + chBSemSignalI(&ONEWIRED1.RxCompleted); + // chSysUnlockFromISR(); + + // NATIVE_INTERRUPT_END +} + +static void RxErr(UARTDriver *uartp, uartflags_t e) +{ + (void) uartp; + (void) e; +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ONEWIRE driver initialization. + * + * @notapi + */ +void oneWire_lld_init(void) { + + ONEWIRED1.State = ONEWIRE_STOP; + + // reset UART config + memset(&ONEWIRED1.UartConfig, 0, sizeof(ONEWIRED1.UartConfig)); + + // set callbacks + ONEWIRED1.UartConfig.txend1_cb = TxEnd; + ONEWIRED1.UartConfig.rxend_cb = RxEnd; + ONEWIRED1.UartConfig.rxerr_cb = RxErr; + + // UART config + // half duplex mode + ONEWIRED1.UartConfig.cr3 = USART_CR3_HDSEL; + + #if (ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE) + osalMutexObjectInit(&ONEWIRED1.Lock); + #endif + +} + +void oneWire_lld_start() { + + // set UART according to target config + // configure UART pins + // set buffers +#if NF_ONEWIRE_STM32_UART_USE_USART1 + ConfigPins_UART1(); + ONEWIRED1.UartDriver = &UARTD1; + ONEWIRED1.TxBuffer = Uart1_TxBuffer; + ONEWIRED1.RxBuffer = Uart1_RxBuffer; +#endif +#if NF_ONEWIRE_STM32_UART_USE_USART2 + ConfigPins_UART2(); + ONEWIRED1.UartDriver = &UARTD2; + ONEWIRED1.TxBuffer = Uart2_TxBuffer; + ONEWIRED1.RxBuffer = Uart2_RxBuffer; +#endif +#if NF_ONEWIRE_STM32_UART_USE_USART3 + ConfigPins_UART3(); + ONEWIRED1.UartDriver = &UARTD3; + ONEWIRED1.TxBuffer = Uart3_TxBuffer; + ONEWIRED1.RxBuffer = Uart3_RxBuffer; +#endif +#if NF_ONEWIRE_STM32_UART_USE_USART4 + ConfigPins_UART4(); + ONEWIRED1.UartDriver = &UARTD4; + ONEWIRED1.TxBuffer = Uart4_TxBuffer; + ONEWIRED1.RxBuffer = Uart4_RxBuffer; +#endif +#if NF_ONEWIRE_STM32_UART_USE_USART5 + ConfigPins_UART5(); + ONEWIRED1.UartDriver = &UARTD5; + ONEWIRED1.TxBuffer = Uart5_TxBuffer; + ONEWIRED1.RxBuffer = Uart5_RxBuffer; +#endif +#if NF_ONEWIRE_STM32_UART_USE_USART6 + ConfigPins_UART6(); + ONEWIRED1.UartDriver = &UARTD6; + ONEWIRED1.TxBuffer = Uart6_TxBuffer; + ONEWIRED1.RxBuffer = Uart6_RxBuffer; +#endif +#if NF_ONEWIRE_STM32_UART_USE_USART7 + ConfigPins_UART7(); + ONEWIRED1.UartDriver = &UARTD7; + ONEWIRED1.TxBuffer = Uart7_TxBuffer; + ONEWIRED1.RxBuffer = Uart7_RxBuffer; +#endif +#if NF_ONEWIRE_STM32_UART_USE_USART8 + ConfigPins_UART8(); + ONEWIRED1.UartDriver = &UARTD8; + ONEWIRED1.TxBuffer = Uart8_TxBuffer; + ONEWIRED1.RxBuffer = Uart8_RxBuffer; +#endif + + uartSetSpeed(9600); + + // driver is ready + ONEWIRED1.State = ONEWIRE_READY; +} + +void oneWire_lld_stop() { + + // stop UART + uartStop(ONEWIRED1.UartDriver); + + // driver is stopped + ONEWIRED1.State = ONEWIRE_STOP; +} + +uint8_t oneWire_lld_TouchReset(void) +{ + ONEWIRED1.TxBuffer[0] = 0xf0; + ONEWIRED1.RxBuffer[0] = 0; + + // flush DMA buffer to ensure cache coherency + // (only required for Cortex-M7) + cacheBufferFlush(&ONEWIRED1.TxBuffer[0], 1); + + // set UART baud rate to 9600bps (required to send the RESET condition to the 1-Wire bus) + uartSetSpeed(9600); + + chBSemReset(&ONEWIRED1.TxCompleted, TRUE); + chBSemReset(&ONEWIRED1.RxCompleted, TRUE); + uartStartReceive (ONEWIRED1.UartDriver, 1 , &ONEWIRED1.RxBuffer[0]); + uartStartSend (ONEWIRED1.UartDriver, 1, &ONEWIRED1.TxBuffer[0]); + chThdSleepMilliseconds(10); + chBSemWait (&ONEWIRED1.TxCompleted); + chBSemWait (&ONEWIRED1.RxCompleted); + + // invalidate cache over read buffer to ensure that content from DMA is read + // (only required for Cortex-M7) + cacheBufferInvalidate(&ONEWIRED1.RxBuffer[0], 1); + + // set UART baud rate to 115200bps (normal comm is performed at this baud rate) + uartSetSpeed(115200); + + // check for presence pulse + return (ONEWIRED1.TxBuffer[0] != ONEWIRED1.RxBuffer[0]); +} + +bool oneWire_lld_TouchBit(bool sendbit) +{ + // need to send 1-Wire write 1 or 0 according to sendbit + ONEWIRED1.TxBuffer[0] = sendbit ? IWIRE_WR1 : IWIRE_WR0; + + // flush DMA buffer to ensure cache coherency + // (only required for Cortex-M7) + cacheBufferFlush(&ONEWIRED1.TxBuffer[0], 1); + + chBSemReset(&ONEWIRED1.RxCompleted, TRUE); + chBSemReset(&ONEWIRED1.TxCompleted, TRUE); + uartStartReceive (ONEWIRED1.UartDriver, 1 , &ONEWIRED1.RxBuffer[0]); + uartStartSend(ONEWIRED1.UartDriver, 1, &ONEWIRED1.TxBuffer[0]); + chThdSleepMilliseconds(0.1); + chBSemWait (&ONEWIRED1.TxCompleted); + chBSemWait (&ONEWIRED1.RxCompleted); + + // invalidate cache over read buffer to ensure that content from DMA is read + // (only required for Cortex-M7) + cacheBufferInvalidate(&ONEWIRED1.RxBuffer[0], 1); + + // interpret 1-Wire reply + return (ONEWIRED1.RxBuffer[0] == 0xff); +} + +uint8_t oneWire_lld_TouchByte(uint8_t sendbyte) +{ + uint8_t send_mask = 0x01, result = 0; + uint8_t i = 0; + + // send byte + while (send_mask) + { + if (sendbyte & send_mask) + { + // if transmit bit is 1 + ONEWIRED1.TxBuffer[i] = IWIRE_WR1; + } + else + { + // if transmit bit is 0 + ONEWIRED1.TxBuffer[i] = IWIRE_WR0; + } + + i++; + + // rotates the position mask transmit bit + send_mask<<=1; + }; + + + // flush DMA buffer to ensure cache coherency + // (only required for Cortex-M7) + cacheBufferFlush(&ONEWIRED1.TxBuffer[0], 8); + + chBSemReset(&ONEWIRED1.RxCompleted, TRUE); + chBSemReset(&ONEWIRED1.TxCompleted, TRUE); + uartStartReceive (ONEWIRED1.UartDriver, 8 , &ONEWIRED1.RxBuffer[0]); + uartStartSend (ONEWIRED1.UartDriver, 8, &ONEWIRED1.TxBuffer[0]); + chThdSleepMilliseconds(0.1); + chBSemWait (&ONEWIRED1.TxCompleted); + chBSemWait (&ONEWIRED1.RxCompleted); + + // invalidate cache over read buffer to ensure that content from DMA is read + // (only required for Cortex-M7) + cacheBufferInvalidate(&ONEWIRED1.RxBuffer[0], 8); + + // reset send mask to interpret the reply + send_mask = 0x01; + + for (uint32_t i = 0; i < 8; i++) + { + if (ONEWIRED1.RxBuffer[i] == 0xff) + { + result |= send_mask; + } + + send_mask<<=1; + } + + return result; +} + +#if (ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE) + +void oneWire_lld_aquire() +{ + osalMutexLock(&ONEWIRED1.Lock); +} + +void oneWire_lld_release() +{ + osalMutexUnlock(&ONEWIRED1.Lock); +} + +#endif + +#endif /* HAL_USE_STM32_ONEWIRE */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.h new file mode 100644 index 00000000..270c3d32 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/ONEWIREv1/onewire_lld.h @@ -0,0 +1,138 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef ONEWIRE_LLD_H +#define ONEWIRE_LLD_H + +#if (HAL_USE_STM32_ONEWIRE == TRUE) + +#include "hal_uart_lld.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +//character to send on the UART to mimic 1-Wire bus signals +#define IWIRE_WR0 0x00 // 1-Wire write 0 time slot +#define IWIRE_WR1 0xFF // 1-Wire write 1 time slot +#define IWIRE_RD 0xFF // 1-Wire read time slot + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Structure representing an ONEWIRE driver. + */ +typedef struct ONEWIREDriver { + // UART to use for 1-Wire comm + UARTDriver* UartDriver; + + // UART config struct + UARTConfig UartConfig; + + // Driver state. + oneWireState State; + + // TX buffer + uint8_t* TxBuffer; + + // RX buffer + uint8_t* RxBuffer; + + // semaphore for Tx operation completed + binary_semaphore_t TxCompleted; + + // semaphore for Rx operation completed + binary_semaphore_t RxCompleted; + + +#if ONEWIRE_USE_MUTUAL_EXCLUSION + // Mutex protecting the peripheral + mutex_t Lock; +#endif // ONEWIRE_USE_MUTUAL_EXCLUSION + +} ONEWIREDriver; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void oneWire_lld_init(void); + void oneWire_lld_start(void); + void oneWire_lld_stop(void); + void oneWire_lld_UART9600(void); + void oneWire_lld_UART115200(void); + uint8_t oneWire_lld_TouchReset(void); + bool oneWire_lld_TouchBit(bool sendbit); + uint8_t oneWire_lld_TouchByte(uint8_t sendbyte); + +#if (ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE) + + void oneWire_lld_aquire(); + void oneWire_lld_release(); + +#endif + + void ConfigPins_UART1(void); + void ConfigPins_UART2(void); + void ConfigPins_UART3(void); + void ConfigPins_UART4(void); + void ConfigPins_UART5(void); + void ConfigPins_UART6(void); + void ConfigPins_UART7(void); + void ConfigPins_UART8(void); + + ///////////////////////////////////// + // UART Tx buffers // + // these live in the target folder // + ///////////////////////////////////// + extern uint8_t Uart1_TxBuffer[]; + extern uint8_t Uart2_TxBuffer[]; + extern uint8_t Uart3_TxBuffer[]; + extern uint8_t Uart4_TxBuffer[]; + extern uint8_t Uart5_TxBuffer[]; + extern uint8_t Uart6_TxBuffer[]; + extern uint8_t Uart7_TxBuffer[]; + extern uint8_t Uart8_TxBuffer[]; + + ///////////////////////////////////// + // UART Rx buffers // + // these live in the target folder // + ///////////////////////////////////// + extern uint8_t Uart1_RxBuffer[]; + extern uint8_t Uart2_RxBuffer[]; + extern uint8_t Uart3_RxBuffer[]; + extern uint8_t Uart4_RxBuffer[]; + extern uint8_t Uart5_RxBuffer[]; + extern uint8_t Uart6_RxBuffer[]; + extern uint8_t Uart7_RxBuffer[]; + extern uint8_t Uart8_RxBuffer[]; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_STM32_ONEWIRE */ + +#endif /* ONEWIRE_LLD_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/README.md new file mode 100644 index 00000000..29f0f78b --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/README.md @@ -0,0 +1,5 @@ +# QSPI v1 + +This driver supports all STM32 series. +The low level driver code is taken or heavily inspired in the STCube MX HAL drivers from STMicroelectronics. +The ChibiOS driver follows the 'standard' template driver model. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.c new file mode 100644 index 00000000..58d1e908 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.c @@ -0,0 +1,98 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +//possible help: +// https://github.com/xpacks/stm32f7-hal/blob/xpack/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_qspi.c + +#include +#include + +#if (HAL_USE_STM32_QSPI == TRUE) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief QSPID1 driver identifier.*/ +QSPI_HandleTypeDef QSPID1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level QSPI driver initialization. + * + * @notapi + */ +void qspi_lld_init() +{ + +} + +void qspi_lld_start(QSPI_HandleTypeDef* qspi) +{ + QSPI_CLK_ENABLE(); + QSPI_FORCE_RESET(); + QSPI_RELEASE_RESET(); + + nvicEnableVector(STM32_QUADSPI1_NUMBER, STM32_QSPI_QUADSPI1_IRQ_PRIORITY); + + qspi->Instance = QUADSPI; + + qspi->State = HAL_QSPI_STATE_RESET; + + // driver is ready + qspi->State = HAL_QSPI_STATE_READY; +} + +void qspi_lld_stop(QSPI_HandleTypeDef* qspi) +{ + /* If in ready state then disables the QUADSPI clock.*/ + if (qspi->State == HAL_QSPI_STATE_READY) + { + /* WSPI disable.*/ + qspi->Instance->CR = 0U; + + // /* Releasing the DMA.*/ + // dmaStreamFreeI(wspip->dma); + // wspip->dma = NULL; + + /* Stopping involved clocks.*/ + rccDisableQUADSPI1(); + } + + // driver is stopped + qspi->State = HAL_QSPI_STATE_RESET; +} + +// QSPI interrupt handler, following ChibiOS style +OSAL_IRQ_HANDLER(STM32_QUADSPI1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + HAL_QSPI_IRQHandler(&QSPID1); + + OSAL_IRQ_EPILOGUE(); +} + +#endif /* HAL_USE_STM32_QSPI */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.h new file mode 100644 index 00000000..cb4ab3bd --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/QSPIv1/qspi_lld.h @@ -0,0 +1,72 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +//Help: https://github.com/xpacks/stm32f7-hal/blob/xpack/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_qspi.h + +#ifndef QSPI_LLD_H +#define QSPI_LLD_H + +#include + +#if defined(STM32F4XX) +#include +#endif +#if defined(STM32F7XX) +#include +#endif + +#if (HAL_USE_STM32_QSPI == TRUE) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief QUADSPI1 interrupt priority level setting. + */ +#if !defined(STM32_QSPI_QUADSPI1_IRQ_PRIORITY) +#define STM32_QSPI_QUADSPI1_IRQ_PRIORITY 10 +#endif + +#define QSPI_CLK_ENABLE() __HAL_RCC_QSPI_CLK_ENABLE() +#define QSPI_CLK_DISABLE() __HAL_RCC_QSPI_CLK_DISABLE() +#define QSPI_FORCE_RESET() __HAL_RCC_QSPI_FORCE_RESET() +#define QSPI_RELEASE_RESET() __HAL_RCC_QSPI_RELEASE_RESET() + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +extern QSPI_HandleTypeDef QSPID1; + +#ifdef __cplusplus +extern "C" { +#endif + + void qspi_lld_init(void); + void qspi_lld_start(QSPI_HandleTypeDef* qspip); + void qspi_lld_stop(QSPI_HandleTypeDef* qspi); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_STM32_QSPI */ + +#endif /* QSPI_LLD_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/README.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/README.md new file mode 100644 index 00000000..fe86a3e1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/README.md @@ -0,0 +1,8 @@ +# RNG v1 + +This driver supports all STM32 series except for the STM32F0 series. +The low level driver code is taken or heavily inspired in the STCube MX HAL drivers from STMicroelectronics. +The ChibiOS driver follows the 'standard' template driver model. + +**NOTE:** unlike all the other drivers and because most SMT32 chips (**Except the STM32F0 series**) have a RNG unit, the default for this driver is to be included. +If for some reason the developer chooses NOT to include support, they have to add `#define HAL_USE_STM32_RNG == FALSE` preferably in the file halconf_nf.h. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c new file mode 100644 index 00000000..33a3b532 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.c @@ -0,0 +1,128 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +//possible help: +// https://github.com/xpacks/stm32f7-hal/blob/xpack/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rng.c +// https://github.com/ChibiOS/ChibiOS-Contrib/blob/master/os/hal/src/hal_rng.c + +#include +#include + +#if (HAL_USE_STM32_RNG == TRUE) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief RNGD1 driver identifier.*/ +RNGDriver RNGD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +#define RNG_TIMEOUT_VALUE 200 + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level RNG driver initialization. + * + * @notapi + */ +void rng_lld_init(void) { + RNGD1.State = RNG_STOP; + + #if (RNG_USE_MUTUAL_EXCLUSION == TRUE) + osalMutexObjectInit(&RNGD1.Lock); + #endif + + RNGD1.Instance = RNG; +} + + +void rng_lld_start() { + + rccEnableRNG(FALSE) + + // Enables the RNG peripheral. + __RNG_ENABLE(RNGD1); + + // driver is ready + RNGD1.State = RNG_READY; +} + + +void rng_lld_stop() { + + /* Disable the RNG Peripheral */ + CLEAR_BIT(RNGD1.Instance->CR, RNG_CR_IE | RNG_CR_RNGEN); + + /* Clear RNG interrupt status flags */ + CLEAR_BIT(RNGD1.Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS); + + rccDisableRNG(); + + // driver is stopped + RNGD1.State = RNG_STOP; +} + + +uint32_t rng_lld_GenerateRandomNumber() { + systime_t start = chVTGetSystemTime(); + systime_t end = start + TIME_MS2I(RNG_TIMEOUT_VALUE); + + + /* Check if data register contains valid random data */ + while(__RNG_GET_FLAG(RNGD1, RNG_FLAG_DRDY) == RESET) + { + if(!chVTIsSystemTimeWithin(start, end)) + { + return 0; + } + + } + + /* Get a 32bit Random number */ + RNGD1.RandomNumber = RNGD1.Instance->DR; + + return RNGD1.RandomNumber; +} + + +uint32_t rng_lld_GetLastRandomNumber() { + return RNGD1.RandomNumber; +} + + +#if (RNG_USE_MUTUAL_EXCLUSION == TRUE) + +void rng_lld_aquire() { + osalMutexLock(&RNGD1.Lock); +} + +void rng_lld_release() { + osalMutexUnlock(&RNGD1.Lock); +} + +#endif + +#endif /* HAL_USE_STM32_RNG */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.h new file mode 100644 index 00000000..a7b9d892 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/RNGv1/rng_lld.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2016 STMicroelectronics. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +//Help: https://github.com/xpacks/stm32f7-hal/blob/xpack/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rng.h + +#ifndef RNG_LLD_H +#define RNG_LLD_H + +#include "stm32_registry.h" +#include +#include + +#if (HAL_USE_STM32_RNG == TRUE) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +// RNG Flag definitions +#define RNG_FLAG_DRDY RNG_SR_DRDY /*!< Data ready */ +#define RNG_FLAG_CECS RNG_SR_CECS /*!< Clock error current status */ +#define RNG_FLAG_SECS RNG_SR_SECS /*!< Seed error current status */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Structure representing an RNG driver. + */ +typedef struct RNGDriver { + //Register base address + RNG_TypeDef *Instance; + + // Driver state. + rngState State; + + // Last Generated random number. + uint32_t RandomNumber; + +#if RNG_USE_MUTUAL_EXCLUSION + // Mutex protecting the peripheral + mutex_t Lock; +#endif // RNG_USE_MUTUAL_EXCLUSION + +} RNGDriver; + +// From STMicroelectronics Cube HAL +///////////////////////////////////////////////////////////// + +#if defined(STM32L0XX) +// this series uses different names for the buses + +#define rccEnableRNG(lp) rccEnableAPB2(RCC_AHBENR_RNGEN, lp) +#define rccDisableRNG() rccDisableAPB2(RCC_AHBENR_RNGEN) + +#else + +#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp) +#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN) + +#endif + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +// Enables the RNG peripheral. +#define __RNG_ENABLE(__HANDLE__) ((__HANDLE__).Instance->CR |= RNG_CR_RNGEN) + +// Disables the RNG peripheral. +#define __RNG_DISABLE(__HANDLE__) ((__HANDLE__).Instance->CR &= ~RNG_CR_RNGEN) + +// Check the selected RNG flag status. +// This parameter can be one of the following values: +// @arg RNG_FLAG_DRDY: Data ready +// @arg RNG_FLAG_CECS: Clock error current status +// @arg RNG_FLAG_SECS: Seed error current status +#define __RNG_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__).Instance->SR & (__FLAG__)) == (__FLAG__)) + + + // Clears the selected RNG flag status. + // WARNING: This is a dummy macro for HAL code alignment, + // flags RNG_FLAG_DRDY, RNG_FLAG_CECS and RNG_FLAG_SECS are read-only. +#define __RNG_CLEAR_FLAG(__HANDLE__, __FLAG__) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rng_lld_init(void); + void rng_lld_start(void); + void rng_lld_stop(void); + uint32_t rng_lld_GenerateRandomNumber(void); + uint32_t rng_lld_GetLastRandomNumber(void); + +#if (RNG_USE_MUTUAL_EXCLUSION == TRUE) + + void rng_lld_aquire(); + void rng_lld_release(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_STM32_RNG */ + +#endif /* RNG_LLD_H */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.c new file mode 100644 index 00000000..6349b509 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.c @@ -0,0 +1,432 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file GPIO/hal_pal_lld.c + * @brief TICC3200 PAL subsystem low level driver. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if TICC3200_HAS_GPIOA || defined(__DOXYGEN__) +#define GPIOA_BIT (1 << 0) +#if TICC3200_GPIO_GPIOA_USE_AHB && defined(TM4C123x) +#define GPIOA_AHB_BIT (1 << 0) +#else +#define GPIOA_AHB_BIT 0 +#endif +#else +#define GPIOA_BIT 0 +#define GPIOA_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOB || defined(__DOXYGEN__) +#define GPIOB_BIT (1 << 1) +#if TICC3200_GPIO_GPIOB_USE_AHB && defined(TM4C123x) +#define GPIOB_AHB_BIT (1 << 1) +#else +#define GPIOB_AHB_BIT 0 +#endif +#else +#define GPIOB_BIT 0 +#define GPIOB_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOC || defined(__DOXYGEN__) +#define GPIOC_BIT (1 << 2) +#if TICC3200_GPIO_GPIOC_USE_AHB && defined(TM4C123x) +#define GPIOC_AHB_BIT (1 << 2) +#else +#define GPIOC_AHB_BIT 0 +#endif +#else +#define GPIOC_BIT 0 +#define GPIOC_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOD || defined(__DOXYGEN__) +#define GPIOD_BIT (1 << 3) +#if TICC3200_GPIO_GPIOD_USE_AHB && defined(TM4C123x) +#define GPIOD_AHB_BIT (1 << 3) +#else +#define GPIOD_AHB_BIT 0 +#endif +#else +#define GPIOD_BIT 0 +#define GPIOD_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOE || defined(__DOXYGEN__) +#define GPIOE_BIT (1 << 4) +#if TICC3200_GPIO_GPIOE_USE_AHB && defined(TM4C123x) +#define GPIOE_AHB_BIT (1 << 4) +#else +#define GPIOE_AHB_BIT 0 +#endif +#else +#define GPIOE_BIT 0 +#define GPIOE_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOF || defined(__DOXYGEN__) +#define GPIOF_BIT (1 << 5) +#if TICC3200_GPIO_GPIOF_USE_AHB && defined(TM4C123x) +#define GPIOF_AHB_BIT (1 << 5) +#else +#define GPIOF_AHB_BIT 0 +#endif +#else +#define GPIOF_BIT 0 +#define GPIOF_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOG || defined(__DOXYGEN__) +#define GPIOG_BIT (1 << 6) +#if TICC3200_GPIO_GPIOG_USE_AHB && defined(TM4C123x) +#define GPIOG_AHB_BIT (1 << 6) +#else +#define GPIOG_AHB_BIT 0 +#endif +#else +#define GPIOG_BIT 0 +#define GPIOG_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOH || defined(__DOXYGEN__) +#define GPIOH_BIT (1 << 7) +#if TICC3200_GPIO_GPIOH_USE_AHB && defined(TM4C123x) +#define GPIOH_AHB_BIT (1 << 7) +#else +#define GPIOH_AHB_BIT 0 +#endif +#else +#define GPIOH_BIT 0 +#define GPIOH_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOJ || defined(__DOXYGEN__) +#define GPIOJ_BIT (1 << 8) +#if TICC3200_GPIO_GPIOJ_USE_AHB && defined(TM4C123x) +#define GPIOJ_AHB_BIT (1 << 8) +#else +#define GPIOJ_AHB_BIT 0 +#endif +#else +#define GPIOJ_BIT 0 +#define GPIOJ_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOK || defined(__DOXYGEN__) +#define GPIOK_BIT (1 << 9) +#define GPIOK_AHB_BIT (1 << 9) +#else +#define GPIOK_BIT 0 +#define GPIOK_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOL || defined(__DOXYGEN__) +#define GPIOL_BIT (1 << 10) +#define GPIOL_AHB_BIT (1 << 10) +#else +#define GPIOL_BIT 0 +#define GPIOL_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOM || defined(__DOXYGEN__) +#define GPIOM_BIT (1 << 11) +#define GPIOM_AHB_BIT (1 << 11) +#else +#define GPIOM_BIT 0 +#define GPIOM_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPION || defined(__DOXYGEN__) +#define GPION_BIT (1 << 12) +#define GPION_AHB_BIT (1 << 12) +#else +#define GPION_BIT 0 +#define GPION_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOP || defined(__DOXYGEN__) +#define GPIOP_BIT (1 << 13) +#define GPIOP_AHB_BIT (1 << 13) +#else +#define GPIOP_BIT 0 +#define GPIOP_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOQ || defined(__DOXYGEN__) +#define GPIOQ_BIT (1 << 14) +#define GPIOQ_AHB_BIT (1 << 14) +#else +#define GPIOQ_BIT 0 +#define GPIOQ_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOR || defined(__DOXYGEN__) +#define GPIOR_BIT (1 << 15) +#define GPIOR_AHB_BIT (1 << 15) +#else +#define GPIOR_BIT 0 +#define GPIOR_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOS || defined(__DOXYGEN__) +#define GPIOS_BIT (1 << 16) +#define GPIOS_AHB_BIT (1 << 16) +#else +#define GPIOS_BIT 0 +#define GPIOS_AHB_BIT 0 +#endif + +#if TICC3200_HAS_GPIOT || defined(__DOXYGEN__) +#define GPIOT_BIT (1 << 17) +#define GPIOT_AHB_BIT (1 << 17) +#else +#define GPIOT_BIT 0 +#define GPIOT_AHB_BIT 0 +#endif + +#define RCGCGPIO_MASK (GPIOA_BIT | GPIOB_BIT | GPIOC_BIT | GPIOD_BIT | \ + GPIOE_BIT | GPIOF_BIT | GPIOG_BIT | GPIOH_BIT | \ + GPIOJ_BIT | GPIOK_BIT | GPIOL_BIT | GPIOM_BIT | \ + GPION_BIT | GPIOP_BIT | GPIOQ_BIT | GPIOR_BIT | \ + GPIOS_BIT | GPIOR_BIT) + +#define GPIOHBCTL_MASK (GPIOA_AHB_BIT | GPIOB_AHB_BIT | GPIOC_AHB_BIT | \ + GPIOD_AHB_BIT | GPIOE_AHB_BIT | GPIOF_AHB_BIT | \ + GPIOG_AHB_BIT | GPIOH_AHB_BIT | GPIOJ_AHB_BIT | \ + GPIOK_AHB_BIT | GPIOL_AHB_BIT | GPIOM_AHB_BIT | \ + GPION_AHB_BIT | GPIOP_AHB_BIT | GPIOQ_AHB_BIT | \ + GPIOR_AHB_BIT | GPIOS_AHB_BIT | GPIOT_AHB_BIT) + +#define GPIOC_JTAG_MASK (0x0F) +#define GPIOD_NMI_MASK (0x80) +#define GPIOF_NMI_MASK (0x01) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the port with the port configuration. + * + * @param[in] port the port identifier + * @param[in] config the port configuration + */ +static void gpio_init(ioportid_t port, const tiva_gpio_setup_t *config) +{ + HWREG(port + GPIO_O_DATA) = config->data; + HWREG(port + GPIO_O_DIR) = config->dir; + HWREG(port + GPIO_O_AFSEL) = config->afsel; + HWREG(port + GPIO_O_DR2R) = config->dr2r; + HWREG(port + GPIO_O_DR4R) = config->dr4r; + HWREG(port + GPIO_O_DR8R) = config->dr8r; + HWREG(port + GPIO_O_ODR) = config->odr; + HWREG(port + GPIO_O_PUR) = config->pur; + HWREG(port + GPIO_O_PDR) = config->pdr; + HWREG(port + GPIO_O_SLR) = config->slr; + HWREG(port + GPIO_O_DEN) = config->den; + HWREG(port + GPIO_O_AMSEL) = config->amsel; + HWREG(port + GPIO_O_PCTL) = config->pctl; +} + +/** + * @brief Unlocks the masked pins of the GPIO peripheral. + * @note This function is only useful for PORTC0-3, PORTD7 and PORTF0. + * + * @param[in] port the port identifier + * @param[in] mask the pin mask + */ +static void gpio_unlock(ioportid_t port, ioportmask_t mask) +{ + + HWREG(port + GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(port + GPIO_O_CR) = mask; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Tiva I/O ports configuration. + * @details Ports A-F (G, H, J, K, L, M, N, P, Q, R, S, T) clocks enabled. + * + * @param[in] config the Tiva ports configuration + * + * @notapi + */ +void _pal_lld_init(const PALConfig *config) +{ + /* + * Enables all GPIO clocks. + */ + HWREG(SYSCTL_RCGCGPIO) = RCGCGPIO_MASK; +#if defined(TM4C123x) + HWREG(SYSCTL_GPIOHBCTL) = GPIOHBCTL_MASK; +#endif + + /* Wait until all GPIO modules are ready */ + while (!((HWREG(SYSCTL_PRGPIO) & RCGCGPIO_MASK) == RCGCGPIO_MASK)) + ; + +#if TICC3200_HAS_GPIOA + gpio_init(GPIOA, &config->PAData); +#endif +#if TICC3200_HAS_GPIOB + gpio_init(GPIOB, &config->PBData); +#endif +#if TICC3200_HAS_GPIOC + /* Unlock JTAG pins.*/ + gpio_unlock(GPIOC, GPIOC_JTAG_MASK); + gpio_init(GPIOC, &config->PCData); +#endif +#if TICC3200_HAS_GPIOD + /* Unlock NMI pin.*/ + gpio_unlock(GPIOD, GPIOD_NMI_MASK); + gpio_init(GPIOD, &config->PDData); +#endif +#if TICC3200_HAS_GPIOE + gpio_init(GPIOE, &config->PEData); +#endif +#if TICC3200_HAS_GPIOF + /* Unlock NMI pin.*/ + gpio_unlock(GPIOF, GPIOF_NMI_MASK); + gpio_init(GPIOF, &config->PFData); +#endif +#if TICC3200_HAS_GPIOG || defined(__DOXYGEN__) + gpio_init(GPIOG, &config->PGData); +#endif +#if TICC3200_HAS_GPIOH || defined(__DOXYGEN__) + gpio_init(GPIOH, &config->PHData); +#endif +#if TICC3200_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_init(GPIOJ, &config->PJData); +#endif +#if TICC3200_HAS_GPIOK || defined(__DOXYGEN__) + gpio_init(GPIOK, &config->PKData); +#endif +#if TICC3200_HAS_GPIOL || defined(__DOXYGEN__) + gpio_init(GPIOL, &config->PLData); +#endif +#if TICC3200_HAS_GPIOM || defined(__DOXYGEN__) + gpio_init(GPIOM, &config->PMData); +#endif +#if TICC3200_HAS_GPION || defined(__DOXYGEN__) + gpio_init(GPION, &config->PNData); +#endif +#if TICC3200_HAS_GPIOP || defined(__DOXYGEN__) + gpio_init(GPIOP, &config->PPData); +#endif +#if TICC3200_HAS_GPIOQ || defined(__DOXYGEN__) + gpio_init(GPIOQ, &config->PQData); +#endif +#if TICC3200_HAS_GPIOR || defined(__DOXYGEN__) + gpio_init(GPIOR, &config->PRData); +#endif +#if TICC3200_HAS_GPIOS || defined(__DOXYGEN__) + gpio_init(GPIOS, &config->PSData); +#endif +#if TICC3200_HAS_GPIOT || defined(__DOXYGEN__) + gpio_init(GPIOT, &config->PTData); +#endif +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, ioportmask_t mask, iomode_t mode) +{ + uint32_t dir = (mode & PAL_TICC3200_DIR_MASK) >> 0; + uint32_t afsel = (mode & PAL_TICC3200_AFSEL_MASK) >> 1; + uint32_t dr2r = (mode & PAL_TICC3200_DR2R_MASK) >> 2; + uint32_t dr4r = (mode & PAL_TICC3200_DR4R_MASK) >> 3; + uint32_t dr8r = (mode & PAL_TICC3200_DR8R_MASK) >> 4; + uint32_t odr = (mode & PAL_TICC3200_ODR_MASK) >> 5; + uint32_t pur = (mode & PAL_TICC3200_PUR_MASK) >> 6; + uint32_t pdr = (mode & PAL_TICC3200_PDR_MASK) >> 7; + uint32_t slr = (mode & PAL_TICC3200_SLR_MASK) >> 8; + uint32_t den = (mode & PAL_TICC3200_DEN_MASK) >> 9; + uint32_t amsel = (mode & PAL_TICC3200_AMSEL_MASK) >> 10; + uint32_t pctl = (mode & PAL_TICC3200_PCTL_MASK) >> 11; + uint32_t bit = 0; + + while(TRUE) { + uint32_t pctl_mask = (7 << (4 * bit)); + uint32_t bit_mask = (1 << bit); + + if ((mask & 1) != 0) { + HWREG(port + GPIO_O_DIR) = (HWREG(port + GPIO_O_DIR) & ~bit_mask) | dir; + HWREG(port + GPIO_O_AFSEL) = (HWREG(port + GPIO_O_AFSEL) & ~bit_mask) | afsel; + HWREG(port + GPIO_O_DR2R) = (HWREG(port + GPIO_O_DR2R) & ~bit_mask) | dr2r; + HWREG(port + GPIO_O_DR4R) = (HWREG(port + GPIO_O_DR4R) & ~bit_mask) | dr4r; + HWREG(port + GPIO_O_DR8R) = (HWREG(port + GPIO_O_DR8R) & ~bit_mask) | dr8r; + HWREG(port + GPIO_O_ODR) = (HWREG(port + GPIO_O_ODR) & ~bit_mask) | odr; + HWREG(port + GPIO_O_PUR) = (HWREG(port + GPIO_O_PUR) & ~bit_mask) | pur; + HWREG(port + GPIO_O_PDR) = (HWREG(port + GPIO_O_PDR) & ~bit_mask) | pdr; + HWREG(port + GPIO_O_SLR) = (HWREG(port + GPIO_O_SLR) & ~bit_mask) | slr; + HWREG(port + GPIO_O_DEN) = (HWREG(port + GPIO_O_DEN) & ~bit_mask) | den; + HWREG(port + GPIO_O_AMSEL) = (HWREG(port + GPIO_O_AMSEL) & ~bit_mask) | amsel; + HWREG(port + GPIO_O_PCTL) = (HWREG(port + GPIO_O_PCTL) & ~pctl_mask) | pctl; + } + + mask >>= 1; + if (!mask) { + return; + } + + dir <<= 1; + afsel <<= 1; + dr2r <<= 1; + dr4r <<= 1; + dr8r <<= 1; + odr <<= 1; + pur <<= 1; + pdr <<= 1; + slr <<= 1; + den <<= 1; + amsel <<= 1; + pctl <<= 4; + + bit++; + } +} + +#endif /* HAL_USE_PAL */ + +/** + * @} + */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.h new file mode 100644 index 00000000..f73d22fb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPIO/hal_pal_lld.h @@ -0,0 +1,806 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file GPIO/hal_pal_lld.h + * @brief TICC3200 PAL subsystem low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef HAL_PAL_LLD_H +#define HAL_PAL_LLD_H + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +#undef PAL_MODE_RESET +#undef PAL_MODE_UNCONNECTED +#undef PAL_MODE_INPUT +#undef PAL_MODE_INPUT_PULLUP +#undef PAL_MODE_INPUT_PULLDOWN +#undef PAL_MODE_INPUT_ANALOG +#undef PAL_MODE_OUTPUT_PUSHPULL +#undef PAL_MODE_OUTPUT_OPENDRAIN + +/** + * @name TICC3200 specific I/O mode flags + * @{ + */ +#define PAL_TICC3200_DIR_MASK (1 << 0) +#define PAL_TICC3200_DIR_INPUT (0 << 0) +#define PAL_TICC3200_DIR_OUTPUT (1 << 0) + +#define PAL_TICC3200_AFSEL_MASK (1 << 1) +#define PAL_TICC3200_AFSEL_GPIO (0 << 1) +#define PAL_TICC3200_AFSEL_ALTERNATE (1 << 1) + +#define PAL_TICC3200_DR2R_MASK (1 << 2) +#define PAL_TICC3200_DR2R_DISABLE (0 << 2) +#define PAL_TICC3200_DR2R_ENABLE (1 << 2) + +#define PAL_TICC3200_DR4R_MASK (1 << 3) +#define PAL_TICC3200_DR4R_DISABLE (0 << 3) +#define PAL_TICC3200_DR4R_ENABLE (1 << 3) + +#define PAL_TICC3200_DR8R_MASK (1 << 4) +#define PAL_TICC3200_DR8R_DISABLE (0 << 4) +#define PAL_TICC3200_DR8R_ENABLE (1 << 4) + +#define PAL_TICC3200_ODR_MASK (1 << 5) +#define PAL_TICC3200_ODR_PUSHPULL (0 << 5) +#define PAL_TICC3200_ODR_OPENDRAIN (1 << 5) + +#define PAL_TICC3200_PUR_MASK (1 << 6) +#define PAL_TICC3200_PUR_DISABLE (0 << 6) +#define PAL_TICC3200_PUR_ENABLE (1 << 6) + +#define PAL_TICC3200_PDR_MASK (1 << 7) +#define PAL_TICC3200_PDR_DISABLE (0 << 7) +#define PAL_TICC3200_PDR_ENABLE (1 << 7) + +#define PAL_TICC3200_SLR_MASK (1 << 8) +#define PAL_TICC3200_SLR_DISABLE (0 << 8) +#define PAL_TICC3200_SLR_ENABLE (1 << 8) + +#define PAL_TICC3200_DEN_MASK (1 << 9) +#define PAL_TICC3200_DEN_DISABLE (0 << 9) +#define PAL_TICC3200_DEN_ENABLE (1 << 9) + +#define PAL_TICC3200_AMSEL_MASK (1 << 10) +#define PAL_TICC3200_AMSEL_DISABLE (0 << 10) +#define PAL_TICC3200_AMSEL_ENABLE (1 << 10) + +#define PAL_TICC3200_PCTL_MASK (7 << 11) +#define PAL_TICC3200_PCTL(n) ((n) << 11) + +/** + * @brief Alternate function. + * + * @param[in] n alternate function selector + */ +#define PAL_MODE_ALTERNATE(n) (PAL_TICC3200_AFSEL_ALTERNATE | \ + PAL_TICC3200_PCTL(n)) +/** @} */ + +/** + * @name Standard I/O mode flags + * @{ + */ +/** + * @brief This mode is implemented as input. + */ +#define PAL_MODE_RESET PAL_MODE_INPUT + +/** + * @brief This mode is implemented as input with pull-up. + */ +#define PAL_MODE_UNCONNECTED PAL_MODE_INPUT_PULLUP + +/** + * @brief Regular input high-Z pad. + */ +#define PAL_MODE_INPUT (PAL_TICC3200_DEN_ENABLE | \ + PAL_TICC3200_DIR_INPUT) + +/** + * @brief Input pad with weak pull up resistor. + */ +#define PAL_MODE_INPUT_PULLUP (PAL_TICC3200_DIR_INPUT | \ + PAL_TICC3200_PUR_ENABLE | \ + PAL_TICC3200_DEN_ENABLE) + +/** + * @brief Input pad with weak pull down resistor. + */ +#define PAL_MODE_INPUT_PULLDOWN (PAL_TICC3200_DIR_INPUT | \ + PAL_TICC3200_PDR_ENABLE | \ + PAL_TICC3200_DEN_ENABLE) + +/** + * @brief Analog input mode. + */ +#define PAL_MODE_INPUT_ANALOG (PAL_TICC3200_DEN_DISABLE | \ + PAL_TICC3200_AMSEL_ENABLE) + +/** + * @brief Push-pull output pad. + */ +#define PAL_MODE_OUTPUT_PUSHPULL (PAL_TICC3200_DIR_OUTPUT | \ + PAL_TICC3200_DR2R_ENABLE | \ + PAL_TICC3200_ODR_PUSHPULL | \ + PAL_TICC3200_DEN_ENABLE) + +/** + * @brief Open-drain output pad. + */ +#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_TICC3200_DIR_OUTPUT | \ + PAL_TICC3200_DR2R_ENABLE | \ + PAL_TICC3200_ODR_OPENDRAIN | \ + PAL_TICC3200_DEN_ENABLE) +/** @} */ + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @name Port related definitions + * @{ + */ +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 8 + +/** + * @brief Whole port mask. + * @brief This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFF) +/** @} */ + +/** + * @name Line handling macros + * @{ + */ +/** + * @brief Forms a line identifier. + * @details A port/pad pair are encoded into an @p ioline_t type. The encoding + * of this type is platform-dependent. + * @note In this driver the pad number is encoded in the lower 4 bits of + * the GPIO address which are guaranteed to be zero. + */ +#define PAL_LINE(port, pad) \ + ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad))) + +/** + * @brief Decodes a port identifier from a line identifier. + */ +#define PAL_PORT(line) \ + ((ioportid_t)(((uint32_t)(line)) & 0xFFFFFFF0U)) + +/** + * @brief Decodes a pad identifier from a line identifier. + */ +#define PAL_PAD(line) \ + ((uint32_t)((uint32_t)(line) & 0x0000000FU)) + +/** + * @brief Value identifying an invalid line. + */ +#define PAL_NOLINE 0U +/** @} */ + +/** + * @brief GPIO port setup info. + */ +typedef struct +{ + /** @brief Initial value for DATA register.*/ + uint32_t data; + /** @brief Initial value for DIR register.*/ + uint32_t dir; + /** @brief Initial value for AFSEL register.*/ + uint32_t afsel; + /** @brief Initial value for DR2R register.*/ + uint32_t dr2r; + /** @brief Initial value for DR4R register.*/ + uint32_t dr4r; + /** @brief Initial value for DR8R register.*/ + uint32_t dr8r; + /** @brief Initial value for ODR register.*/ + uint32_t odr; + /** @brief Initial value for PUR register.*/ + uint32_t pur; + /** @brief Initial value for PDR register.*/ + uint32_t pdr; + /** @brief Initial value for SLR register.*/ + uint32_t slr; + /** @brief Initial value for DEN register.*/ + uint32_t den; + /** @brief Initial value for AMSEL register.*/ + uint32_t amsel; + /** @brief Initial value for PCTL register.*/ + uint32_t pctl; +} tiva_gpio_setup_t; + +/** + * @brief Tiva GPIO static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialized the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + */ +typedef struct +{ + /** @brief GPIO port A setup data.*/ + tiva_gpio_setup_t PAData; + /** @brief GPIO port B setup data.*/ + tiva_gpio_setup_t PBData; + /** @brief GPIO port C setup data.*/ + tiva_gpio_setup_t PCData; + /** @brief GPIO port D setup data.*/ + tiva_gpio_setup_t PDData; + /** @brief GPIO port E setup data.*/ + tiva_gpio_setup_t PEData; + /** @brief GPIO port F setup data.*/ + tiva_gpio_setup_t PFData; +#if TICC3200_HAS_GPIOG || defined(__DOXYGEN__) + /** @brief GPIO port G setup data.*/ + tiva_gpio_setup_t PGData; +#endif +#if TICC3200_HAS_GPIOH || defined(__DOXYGEN__) + /** @brief GPIO port H setup data.*/ + tiva_gpio_setup_t PHData; +#endif +#if TICC3200_HAS_GPIOJ || defined(__DOXYGEN__) + /** @brief GPIO port J setup data.*/ + tiva_gpio_setup_t PJData; +#endif +#if TICC3200_HAS_GPIOK || defined(__DOXYGEN__) + /** @brief GPIO port K setup data.*/ + tiva_gpio_setup_t PKData; +#endif +#if TICC3200_HAS_GPIOL || defined(__DOXYGEN__) + /** @brief GPIO port L setup data.*/ + tiva_gpio_setup_t PLData; +#endif +#if TICC3200_HAS_GPIOM || defined(__DOXYGEN__) + /** @brief GPIO port M setup data.*/ + tiva_gpio_setup_t PMData; +#endif +#if TICC3200_HAS_GPION || defined(__DOXYGEN__) + /** @brief GPIO port N setup data.*/ + tiva_gpio_setup_t PNData; +#endif +#if TICC3200_HAS_GPIOP || defined(__DOXYGEN__) + /** @brief GPIO port P setup data.*/ + tiva_gpio_setup_t PPData; +#endif +#if TICC3200_HAS_GPIOQ || defined(__DOXYGEN__) + /** @brief GPIO port Q setup data.*/ + tiva_gpio_setup_t PQData; +#endif +#if TICC3200_HAS_GPIOR || defined(__DOXYGEN__) + /** @brief GPIO port R setup data.*/ + tiva_gpio_setup_t PRData; +#endif +#if TICC3200_HAS_GPIOS || defined(__DOXYGEN__) + /** @brief GPIO port S setup data.*/ + tiva_gpio_setup_t PSData; +#endif +#if TICC3200_HAS_GPIOT || defined(__DOXYGEN__) + /** @brief GPIO port T setup data.*/ + tiva_gpio_setup_t PTData; +#endif +} PALConfig; + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Digital I/O modes. + */ +typedef uint32_t iomode_t; + +/** + * @brief Type of an I/O line. + */ +typedef uint32_t ioline_t; + +/** + * @brief Port Identifier. + */ +typedef uint32_t ioportid_t; + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +#if defined(TM4C123x) + +/** + * @brief GPIOA AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOA. When set + * to @p FALSE the APB bus is used to access GPIOA. + */ +#if !defined(TICC3200_GPIO_GPIOA_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOA_USE_AHB TRUE +#endif + +/** + * @brief GPIOB AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOB. When set + * to @p FALSE the APB bus is used to access GPIOB. + */ +#if !defined(TICC3200_GPIO_GPIOB_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOB_USE_AHB TRUE +#endif + +/** + * @brief GPIOC AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOC. When set + * to @p FALSE the APB bus is used to access GPIOC. + */ +#if !defined(TICC3200_GPIO_GPIOC_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOC_USE_AHB TRUE +#endif + +/** + * @brief GPIOD AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOD. When set + * to @p FALSE the APB bus is used to access GPIOD. + */ +#if !defined(TICC3200_GPIO_GPIOD_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOD_USE_AHB TRUE +#endif + +/** + * @brief GPIOE AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOE. When set + * to @p FALSE the APB bus is used to access GPIOE. + */ +#if !defined(TICC3200_GPIO_GPIOE_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOE_USE_AHB TRUE +#endif + +/** + * @brief GPIOF AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOF. When set + * to @p FALSE the APB bus is used to access GPIOF. + */ +#if !defined(TICC3200_GPIO_GPIOF_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOF_USE_AHB TRUE +#endif + +/** + * @brief GPIOG AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOG. When set + * to @p FALSE the APB bus is used to access GPIOG. + */ +#if !defined(TICC3200_GPIO_GPIOG_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOG_USE_AHB TRUE +#endif + +/** + * @brief GPIOH AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOH. When set + * to @p FALSE the APB bus is used to access GPIOH. + */ +#if !defined(TICC3200_GPIO_GPIOH_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOH_USE_AHB TRUE +#endif + +/** + * @brief GPIOJ AHB enable switch. + * @details When set to @p TRUE the AHB bus is used to access GPIOJ. When set + * to @p FALSE the APB bus is used to access GPIOJ. + */ +#if !defined(TICC3200_GPIO_GPIOJ_USE_AHB) || defined(__DOXYGEN__) +#define TICC3200_GPIO_GPIOJ_USE_AHB TRUE +#endif + +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if TICC3200_GPIO_GPIOA_USE_AHB && defined(TM4C123x) +#define GPIOA GPIO_PORTA_AHB_BASE +#else +#define GPIOA GPIO_PORTA_BASE +#endif + +#if TICC3200_GPIO_GPIOB_USE_AHB && defined(TM4C123x) +#define GPIOB GPIO_PORTB_AHB_BASE +#else +#define GPIOB GPIO_PORTB_BASE +#endif + +#if TICC3200_GPIO_GPIOC_USE_AHB && defined(TM4C123x) +#define GPIOC GPIO_PORTC_AHB_BASE +#else +#define GPIOC GPIO_PORTC_BASE +#endif + +#if TICC3200_GPIO_GPIOD_USE_AHB && defined(TM4C123x) +#define GPIOD GPIO_PORTD_AHB_BASE +#else +#define GPIOD GPIO_PORTD_BASE +#endif + +#if TICC3200_GPIO_GPIOE_USE_AHB && defined(TM4C123x) +#define GPIOE GPIO_PORTE_AHB_BASE +#else +#define GPIOE GPIO_PORTE_BASE +#endif + +#if TICC3200_GPIO_GPIOF_USE_AHB && defined(TM4C123x) +#define GPIOF GPIO_PORTF_AHB_BASE +#else +#define GPIOF GPIO_PORTF_BASE +#endif + +#if TICC3200_GPIO_GPIOG_USE_AHB && defined(TM4C123x) +#define GPIOG GPIO_PORTG_AHB_BASE +#else +#define GPIOG GPIO_PORTG_BASE +#endif + +#if TICC3200_GPIO_GPIOH_USE_AHB && defined(TM4C123x) +#define GPIOH GPIO_PORTH_AHB_BASE +#else +#define GPIOH GPIO_PORTH_BASE +#endif + +#if TICC3200_GPIO_GPIOJ_USE_AHB && defined(TM4C123x) +#define GPIOJ GPIO_PORTJ_AHB_BASE +#else +#define GPIOJ GPIO_PORTJ_BASE +#endif + +#define GPIOK GPIO_PORTK_BASE +#define GPIOL GPIO_PORTL_BASE +#define GPIOM GPIO_PORTM_BASE +#define GPION GPIO_PORTN_BASE +#define GPIOP GPIO_PORTP_BASE +#define GPIOQ GPIO_PORTQ_BASE +#define GPIOR GPIO_PORTR_BASE +#define GPIOS GPIO_PORTS_BASE +#define GPIOT GPIO_PORTT_BASE + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#define IOPORT1 GPIOA + +/** + * @brief GPIO port B identifier. + */ +#define IOPORT2 GPIOB + +/** + * @brief GPIO port C identifier. + */ +#define IOPORT3 GPIOC + +/** + * @brief GPIO port D identifier. + */ +#define IOPORT4 GPIOD + +/** + * @brief GPIO port E identifier. + */ +#define IOPORT5 GPIOE + +/** + * @brief GPIO port F identifier. + */ +#define IOPORT6 GPIOF + +/** + * @brief GPIO port G identifier. + */ +#if TICC3200_HAS_GPIOG || defined(__DOXYGEN__) +#define IOPORT7 GPIOG +#endif + +/** + * @brief GPIO port H identifier. + */ +#if TICC3200_HAS_GPIOH || defined(__DOXYGEN__) +#define IOPORT8 GPIOH +#endif + +/** + * @brief GPIO port J identifier. + */ +#if TICC3200_HAS_GPIOJ || defined(__DOXYGEN__) +#define IOPORT9 GPIOJ +#endif + +/** + * @brief GPIO port K identifier. + */ +#if TICC3200_HAS_GPIOK || defined(__DOXYGEN__) +#define IOPORT10 GPIOK +#endif + +/** + * @brief GPIO port L identifier. + */ +#if TICC3200_HAS_GPIOL || defined(__DOXYGEN__) +#define IOPORT11 GPIOL +#endif + +/** + * @brief GPIO port M identifier. + */ +#if TICC3200_HAS_GPIOM || defined(__DOXYGEN__) +#define IOPORT12 GPIOM +#endif + +/** + * @brief GPIO port N identifier. + */ +#if TICC3200_HAS_GPION || defined(__DOXYGEN__) +#define IOPORT13 GPION +#endif + +/** + * @brief GPIO port P identifier. + */ +#if TICC3200_HAS_GPIOP || defined(__DOXYGEN__) +#define IOPORT14 GPIOP +#endif + +/** + * @brief GPIO port Q identifier. + */ +#if TICC3200_HAS_GPIOQ || defined(__DOXYGEN__) +#define IOPORT15 GPIOQ +#endif + +/** + * @brief GPIO port R identifier. + */ +#if TICC3200_HAS_GPIOR || defined(__DOXYGEN__) +#define IOPORT16 GPIOR +#endif + +/** + * @brief GPIO port S identifier. + */ +#if TICC3200_HAS_GPIOS || defined(__DOXYGEN__) +#define IOPORT17 GPIOS +#endif + +/** + * @brief GPIO port T identifier. + */ +#if TICC3200_HAS_GPIOT || defined(__DOXYGEN__) +#define IOPORT18 GPIOT +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief Low level PAL subsystem initialization. + * + * @param[in] config architecture-dependent ports configuration + * + * @notapi + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads the physical I/O port states. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) (HWREG((port) + GPIO_O_GPIO_DATA + (0xff << 2))) + +/** + * @brief Reads the output latch. + * @details The purpose of this function is to read back the latched output + * value. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) pal_lld_readport(port) + +/** + * @brief Writes a bits mask on a I/O port. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) (HWREG((port) + GPIO_O_GPIO_DATA + (0xff << 2)) = (bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @notapi + */ +#define pal_lld_setport(port, bits) (HWREG((port) + (GPIO_O_GPIO_DATA + (bits << 2))) = 0xFF) + +/** + * @brief Clears a bits mask on a I/O port. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @notapi + */ +#define pal_lld_clearport(port, bits) (HWREG((port) + (GPIO_O_GPIO_DATA + (bits << 2))) = 0) + +/** + * @brief Reads a group of bits. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @return The group logical states. + * + * @notapi + */ +#define pal_lld_readgroup(port, mask, offset) \ + (HWREG((port) + (GPIO_O_GPIO_DATA + (((mask) << (offset)) << 2)))) + +/** + * @brief Writes a group of bits. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] bits bits to be written. Values exceeding the group width + * are masked. + * + * @notapi + */ +#define pal_lld_writegroup(port, mask, offset, bits) \ + (HWREG((port) + (GPIO_O_GPIO_DATA + (((mask) << (offset)) << 2))) = (bits)) + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +/** + * @brief Reads a logical state from an I/O pad. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @return The logical state. + * @retval PAL_LOW low logical state. + * @retval PAL_HIGH high logical state. + * + * @notapi + */ +#define pal_lld_readpad(port, pad) (HWREG((port) + (GPIO_O_GPIO_DATA + ((1 << (pad)) << 2)))) + +/** + * @brief Writes a logical state on an output pad. + * @note This function is not meant to be invoked directly by the + * application code. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +#define pal_lld_writepad(port, pad, bit) \ + (HWREG((port) + (GPIO_O_GPIO_DATA + ((1 << (pad)) << 2))) = (bit)) + +/** + * @brief Sets a pad logical state to @p PAL_HIGH. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_setpad(port, pad) \ + (HWREG((port) + (GPIO_O_GPIO_DATA + ((1 << (pad)) << 2))) = 1 << (pad)) + +/** + * @brief Clears a pad logical state to @p PAL_LOW. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_clearpad(port, pad) \ + (HWREG((port) + (GPIO_O_GPIO_DATA + ((1 << (pad)) << 2))) = 0) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const PALConfig pal_default_config; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const PALConfig *config); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL */ + +#endif /* HAL_PAL_LLD_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.c new file mode 100644 index 00000000..06b2f946 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.c @@ -0,0 +1,244 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file GPTM/hal_st_lld.c + * @brief ST Driver subsystem low level driver code. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + +#if (TICC3200_ST_USE_WIDE_TIMER == TRUE) + +#if TICC3200_ST_TIMER_NUMBER == 0 +#define ST_HANDLER TICC3200_WGPT0A_HANDLER +#define ST_NUMBER TICC3200_WGPT0A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCWTIMER |= (1 << 0)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRWTIMER & (1 << 0))) + +#elif TICC3200_ST_TIMER_NUMBER == 1 +#define ST_HANDLER TICC3200_WGPT1A_HANDLER +#define ST_NUMBER TICC3200_WGPT1A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCWTIMER |= (1 << 1)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRWTIMER & (1 << 1))) + +#elif TICC3200_ST_TIMER_NUMBER == 2 +#define ST_HANDLER TICC3200_WGPT2A_HANDLER +#define ST_NUMBER TICC3200_WGPT2A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCWTIMER |= (1 << 2)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRWTIMER & (1 << 2))) + +#elif TICC3200_ST_TIMER_NUMBER == 3 +#define ST_HANDLER TICC3200_WGPT3A_HANDLER +#define ST_NUMBER TICC3200_WGPT3A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCWTIMER |= (1 << 3)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRWTIMER & (1 << 3))) + +#elif TICC3200_ST_TIMER_NUMBER == 4 +#define ST_HANDLER TICC3200_WGPT4A_HANDLER +#define ST_NUMBER TICC3200_WGPT4A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCWTIMER |= (1 << 4)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRWTIMER & (1 << 4))) + +#elif TICC3200_ST_TIMER_NUMBER == 5 +#define ST_HANDLER TICC3200_WGPT5A_HANDLER +#define ST_NUMBER TICC3200_WGPT5A_NUMBER +#define ST_ENABLE_CLOCK() (HWREG(SYSCTL_RCGCWTIMER) |= (1 << 5)) +#define ST_WAIT_CLOCK() while (!(HWREG(SYSCTL_PRWTIMER) & (1 << 5))) + +#else +#error "TICC3200_ST_USE_TIMER specifies an unsupported timer" +#endif + +#if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF +#error "the selected ST frequency is not obtainable because TIM timer prescaler limits" +#endif + +#elif (TICC3200_ST_USE_WIDE_TIMER == FALSE) + +#if TICC3200_ST_TIMER_NUMBER == 0 +#define ST_HANDLER TICC3200_GPT0A_HANDLER +#define ST_NUMBER TICC3200_GPT0A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCTIMER |= (1 << 0)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRTIMER & (1 << 0))) + +#elif TICC3200_ST_TIMER_NUMBER == 1 +#define ST_HANDLER TICC3200_GPT1A_HANDLER +#define ST_NUMBER TICC3200_GPT1A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCTIMER |= (1 << 1)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRTIMER & (1 << 1))) + +#elif TICC3200_ST_TIMER_NUMBER == 2 +#define ST_HANDLER TICC3200_GPT2A_HANDLER +#define ST_NUMBER TICC3200_GPT2A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCTIMER |= (1 << 2)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRTIMER & (1 << 2))) + +#elif TICC3200_ST_TIMER_NUMBER == 3 +#define ST_HANDLER TICC3200_GPT3A_HANDLER +#define ST_NUMBER TICC3200_GPT3A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCTIMER |= (1 << 3)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRTIMER & (1 << 3))) + +#elif TICC3200_ST_TIMER_NUMBER == 4 +#define ST_HANDLER TICC3200_GPT4A_HANDLER +#define ST_NUMBER TICC3200_GPT4A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCTIMER |= (1 << 4)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRTIMER & (1 << 4))) + +#elif TICC3200_ST_TIMER_NUMBER == 5 +#define ST_HANDLER TICC3200_GPT5A_HANDLER +#define ST_NUMBER TICC3200_GPT5A_NUMBER +#define ST_ENABLE_CLOCK() (SYSCTL->RCGCTIMER |= (1 << 5)) +#define ST_WAIT_CLOCK() while (!(SYSCTL->PRTIMER & (1 << 5))) + +#else +#error "TICC3200_ST_USE_TIMER specifies an unsupported timer" +#endif + +#if (TICC3200_SYSCLK / OSAL_ST_FREQUENCY) - 1 > 0xFF +#error "the selected ST frequency is not obtainable because TIM timer prescaler limits" +#endif + +#endif + +#if TICC3200_SYSCLK % OSAL_ST_FREQUENCY != 0 +#error "the selected ST frequency is not obtainable because integer rounding" +#endif + +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) +/** + * @brief System Timer vector. + * @details This interrupt is used for system tick in periodic mode. + * + * @isr + */ +OSAL_IRQ_HANDLER(SysTick_Handler) +{ + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) +/** + * @brief GPT interrupt handler. + * @details This interrupt is used for system tick in free running mode. + * + * @isr + */ +OSAL_IRQ_HANDLER(ST_HANDLER) +{ + uint32_t mis; + + OSAL_IRQ_PROLOGUE(); + + mis = HWREG(TICC3200_ST_TIM + TIMER_O_MIS); + HWREG(TICC3200_ST_TIM + TIMER_O_ICR) = mis; + + if (mis & TIMER_IMR_TAMIM) { + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + } + + OSAL_IRQ_EPILOGUE(); +} +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ST driver initialization. + * + * @notapi + */ +void st_lld_init(void) +{ +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + /* Free running counter mode.*/ + + /* Enabling timer clock.*/ + ST_ENABLE_CLOCK(); + + /* Wait until timer peripheral is ready */ + ST_WAIT_CLOCK(); + + /* Initializing the counter in free running down mode.*/ + HWREG(TICC3200_ST_TIM + TIMER_O_CTL) = 0; + HWREG(TICC3200_ST_TIM + TIMER_O_CFG) = TIMER_CFG_16_BIT; /* Timer split mode */ + HWREG(TICC3200_ST_TIM + TIMER_O_TAMR) = ( + TIMER_TAMR_TAMR_PERIOD | /* Periodic mode */ + TIMER_TAMR_TAMIE | /* Match interrupt enable */ + TIMER_TAMR_TASNAPS); /* Snapshot mode */ + + HWREG(TICC3200_ST_TIM + TIMER_O_TAPR) = (TICC3200_SYSCLK / OSAL_ST_FREQUENCY) - 1; + HWREG(TICC3200_ST_TIM + TIMER_O_CTL) = ( + TIMER_CTL_TAEN | /* Timer A enable */ + TIMER_CTL_TASTALL); /* Timer A stall when paused */ + + /* IRQ enabled.*/ + nvicEnableVector(ST_NUMBER, TICC3200_ST_IRQ_PRIORITY); +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + /* Periodic systick mode, the Cortex-Mx internal systick timer is used + in this mode.*/ + SysTick->LOAD = (TICC3200_SYSCLK / OSAL_ST_FREQUENCY) - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_ENABLE_Msk | + SysTick_CTRL_TICKINT_Msk; + + /* IRQ enabled.*/ + nvicSetSystemHandlerPriority(HANDLER_SYSTICK, TICC3200_ST_IRQ_PRIORITY); +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** + * @} + */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.h new file mode 100644 index 00000000..013211d1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/GPTM/hal_st_lld.h @@ -0,0 +1,199 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file GPTM/hal_st_lld.h + * @brief ST Driver subsystem low level driver header. + * @details This header is designed to be include-able without having to + * include other files from the HAL. + * + * @addtogroup ST + * @{ + */ + +#ifndef HAL_ST_LLD_H +#define HAL_ST_LLD_H + +#include "mcuconf.h" +#include "ticc3200_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ + +/** + * @brief SysTick timer IRQ priority. + */ +#if !defined(TICC3200_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_ST_IRQ_PRIORITY 2 +#endif + +/** + * @brief GPTx unit (by number) to be used for free running operations. + * @note You must select a 32 bits timer if a 32 bits @p systick_t type + * is required. + */ +#if !defined(TICC3200_ST_TIMER_NUMBER) || defined(__DOXYGEN__) +#define TICC3200_ST_TIMER_NUMBER 0 +#endif + +/** + * @brief When set to @p TRUE a wide timer is used. When set to @p FALSE a + * normal timer is used. + */ +#if !defined(TICC3200_ST_USE_WIDE_TIMER) || defined(__DOXYGEN__) +#define TICC3200_ST_USE_WIDE_TIMER TRUE +#endif + +/** + * @} + */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if TICC3200_ST_TIMER_NUMBER == 0 +#if !TICC3200_HAS_GPT0 +#error "GPT0 not present" +#endif +#define TICC3200_ST_TIM TIMERA0_BASE + +#elif TICC3200_ST_TIMER_NUMBER == 1 +#if !TICC3200_HAS_GPT1 +#error "GPT1 not present" +#endif +#define TICC3200_ST_TIM TIMERA1_BASE + +#elif TICC3200_ST_TIMER_NUMBER == 2 +#if !TICC3200_HAS_GPT2 +#error "GPT2 not present" +#endif +#define TICC3200_ST_TIM TIMERA2_BASE + +#elif TICC3200_ST_TIMER_NUMBER == 3 +#if !TICC3200_HAS_GPT3 +#error "GPT3 not present" +#endif +#define TICC3200_ST_TIM TIMERA3_BASE + +#else +#error "TICC3200_ST_TIMER_NUMBER specifies an unsupported timer" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void st_lld_init(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the time counter value. + * + * @return The counter value. + * + * @notapi + */ +static inline systime_t st_lld_get_counter(void) +{ + return (systime_t) (((systime_t) 0xffffffff) - HWREG(TICC3200_ST_TIM + TIMER_O_TAV)); +} + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +static inline void st_lld_start_alarm(systime_t time) +{ + HWREG(TICC3200_ST_TIM + TIMER_O_TAMATCHR) = (systime_t) (((systime_t) 0xffffffff) - time); + HWREG(TICC3200_ST_TIM + TIMER_O_ICR) = HWREG(TICC3200_ST_TIM + TIMER_O_MIS); + HWREG(TICC3200_ST_TIM + TIMER_O_IMR) = TIMER_IMR_TAMIM; +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void st_lld_stop_alarm(void) +{ + HWREG(TICC3200_ST_TIM + TIMER_O_IMR) = 0; +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +static inline void st_lld_set_alarm(systime_t time) +{ + HWREG(TICC3200_ST_TIM + TIMER_O_TAMATCHR) = (systime_t) (((systime_t) 0xffffffff) - time); +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t st_lld_get_alarm(void) +{ + return (systime_t) (((systime_t)0xffffffff) - HWREG(TICC3200_ST_TIM + TIMER_O_TAMATCHR)); +} + +/** + * @brief Determines if the alarm is active. + * + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @notapi + */ +static inline bool st_lld_is_alarm_active(void) +{ + return (bool) ((HWREG(TICC3200_ST_TIM + TIMER_O_IMR) & TIMER_IMR_TAMIM) !=0); +} + +#endif /* HAL_ST_LLD_H */ + +/** + * @} + */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/RTC/hal_rtc_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/RTC/hal_rtc_lld.h new file mode 100644 index 00000000..8ead7b02 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/RTC/hal_rtc_lld.h @@ -0,0 +1,188 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file RTCv1/hal_rtc_lld.h + * @brief TCC3200 RTC subsystem low level driver header. + * + * @addtogroup RTC + * @{ + */ + +#ifndef HAL_RTC_LLD_H +#define HAL_RTC_LLD_H + +#if HAL_USE_RTC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Implementation capabilities + */ +/** + * @brief This RTC implementation supports callbacks. + */ +#define RTC_SUPPORTS_CALLBACKS TRUE + +/** + * @brief One alarm comparator available. + */ +#define RTC_ALARMS 1 + +/** + * @brief Presence of a local persistent storage. + */ +#define RTC_HAS_STORAGE FALSE +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/* + * RTC driver system settings. + */ +#define TICC3200_RTC_IRQ_PRIORITY 15 +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_RTC && !TICC3200_HAS_RTC +#error "RTC not present in the selected device" +#endif + +#if TICC3200_RTCCLK == 0 +#error "RTC clock not enabled" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief FileStream specific methods. + */ +#define _rtc_driver_methods \ + _file_stream_methods + +/** + * @brief Type of a structure representing an RTC alarm time stamp. + */ +typedef struct RTCAlarm RTCAlarm; + +/** + * @brief Type of an RTC alarm. + * @details Meaningful on platforms with more than 1 alarm comparator. + */ +typedef uint32_t rtcalarm_t; + +/** + * @brief Type of an RTC event. + */ +typedef enum { + RTC_EVENT_SECOND = 0, /** Triggered every second. */ + RTC_EVENT_ALARM = 1, /** Triggered on alarm. */ + RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */ +} rtcevent_t; + +/** + * @brief Type of a generic RTC callback. + */ +typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event); + +/** + * @brief Structure representing an RTC alarm time stamp. + */ +struct RTCAlarm { + /** + * @brief Seconds since UNIX epoch. + */ + uint32_t tv_sec; +}; + +#if RTC_HAS_STORAGE || defined(__DOXYGEN__) +/** + * @extends FileStream + * + * @brief @p RTCDriver virtual methods table. + */ +struct RTCDriverVMT { + _rtc_driver_methods +}; +#endif + +/** + * @brief Structure representing an RTC driver. + */ +struct RTCDriver{ +#if RTC_HAS_STORAGE || defined(__DOXYGEN__) + /** + * @brief Virtual Methods Table. + */ + const struct RTCDriverVMT *vmt; +#endif + /** + * @brief Pointer to the RTC registers block. + */ + RTC_TypeDef *rtc; + /** + * @brief Callback pointer. + */ + rtccb_t callback; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern RTCDriver RTCD1; +#if RTC_HAS_STORAGE +extern struct RTCDriverVMT _rtc_lld_vmt; +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void rtc_lld_set_prescaler(void); + void rtc_lld_init(void); + void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); + void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); + void rtc_lld_set_alarm(RTCDriver *rtcp, + rtcalarm_t alarm_number, + const RTCAlarm *alarmspec); + void rtc_lld_get_alarm(RTCDriver *rtcp, + rtcalarm_t alarm_number, + RTCAlarm *alarmspec); + void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); + void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec); + void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC */ + +#endif /* HAL_RTC_LLD_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/UART/hal_serial_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/UART/hal_serial_lld.h new file mode 100644 index 00000000..5c976131 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/LLD/UART/hal_serial_lld.h @@ -0,0 +1,437 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file UART/hal_serial_lld.h + * @brief TICC3200 low level serial driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef HAL_SERIAL_LLD_H +#define HAL_SERIAL_LLD_H + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Advanced buffering support switch. + * @details This constants enables the advanced buffering support in the + * low level driver, the queue buffer is no more part of the + * @p SerialDriver structure, each driver can have a different + * queue size. + */ +#define SERIAL_ADVANCED_BUFFERING_SUPPORT TRUE + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief UART0 driver enable switch. + * @details If set to @p TRUE the support for UART0 is included. + * @note The default is @p TRUE. + */ +#if !defined(TICC3200_SERIAL_USE_UART0) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART0 FALSE +#endif + +/** + * @brief UART1 driver enable switch. + * @details If set to @p TRUE the support for UART1 is included. + * @note The default is @p FALSE . + */ +#if !defined(TICC3200_SERIAL_USE_UART1) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART1 FALSE +#endif + +/** + * @brief UART2 driver enable switch. + * @details If set to @p TRUE the support for UART2 is included. + * @note The default is @p FALSE . + */ +#if !defined(TICC3200_SERIAL_USE_UART2) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART2 FALSE +#endif + +/** + * @brief UART3 driver enable switch. + * @details If set to @p TRUE the support for UART3 is included. + * @note The default is @p FALSE . + */ +#if !defined(TICC3200_SERIAL_USE_UART3) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART3 FALSE +#endif + +/** + * @brief UART4 driver enable switch. + * @details If set to @p TRUE the support for UART4 is included. + * @note The default is @p FALSE . + */ +#if !defined(TICC3200_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART4 FALSE +#endif + +/** + * @brief UART5 driver enable switch. + * @details If set to @p TRUE the support for UART5 is included. + * @note The default is @p FALSE . + */ +#if !defined(TICC3200_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART5 FALSE +#endif + +/** + * @brief UART6 driver enable switch. + * @details If set to @p TRUE the support for UART6 is included. + * @note The default is @p FALSE . + */ +#if !defined(TICC3200_SERIAL_USE_UART6) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART6 FALSE +#endif + +/** + * @brief UART7 driver enable switch. + * @details If set to @p TRUE the support for UART7 is included. + * @note The default is @p FALSE . + */ +#if !defined(TICC3200_SERIAL_USE_UART7) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_USE_UART7 FALSE +#endif + +/** + * @brief UART0 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART0_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART0_PRIORITY 5 +#endif + +/** + * @brief UART1 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART1_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART1_PRIORITY 5 +#endif + +/** + * @brief UART2 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART2_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART2_PRIORITY 5 +#endif + +/** + * @brief UART3 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART3_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART3_PRIORITY 5 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART4_PRIORITY 5 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART5_PRIORITY 5 +#endif + +/** + * @brief UART6 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART6_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART6_PRIORITY 5 +#endif + +/** + * @brief UART7 interrupt priority level setting. + */ +#if !defined(TICC3200_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART7_PRIORITY 5 +#endif + +/** + * @brief Input buffer size for UART0. + */ +#if !defined(TICC3200_SERIAL_UART0_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART0_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART0. + */ +#if !defined(TICC3200_SERIAL_UART0_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART0_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART1. + */ +#if !defined(TICC3200_SERIAL_UART1_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART1. + */ +#if !defined(TICC3200_SERIAL_UART1_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART2. + */ +#if !defined(TICC3200_SERIAL_UART2_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART2_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART2. + */ +#if !defined(TICC3200_SERIAL_UART2_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART2_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART3. + */ +#if !defined(TICC3200_SERIAL_UART3_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART3_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART3. + */ +#if !defined(TICC3200_SERIAL_UART3_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART3_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART4. + */ +#if !defined(TICC3200_SERIAL_UART4_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART4_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART4. + */ +#if !defined(TICC3200_SERIAL_UART4_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART4_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART5. + */ +#if !defined(TICC3200_SERIAL_UART5_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART5_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART5. + */ +#if !defined(TICC3200_SERIAL_UART5_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART5_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART6. + */ +#if !defined(TICC3200_SERIAL_UART6_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART6_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART6. + */ +#if !defined(TICC3200_SERIAL_UART6_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART6_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Input buffer size for UART7. + */ +#if !defined(TICC3200_SERIAL_UART7_IN_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART7_IN_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif + +/** + * @brief Output buffer size for UART7. + */ +#if !defined(TICC3200_SERIAL_UART7_OUT_BUF_SIZE) || defined(__DOXYGEN__) +#define TICC3200_SERIAL_UART7_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !TICC3200_SERIAL_USE_UART0 && !TICC3200_SERIAL_USE_UART1 && \ + !TICC3200_SERIAL_USE_UART2 && !TICC3200_SERIAL_USE_UART3 && \ + !TICC3200_SERIAL_USE_UART4 && !TICC3200_SERIAL_USE_UART5 && \ + !TICC3200_SERIAL_USE_UART6 && !TICC3200_SERIAL_USE_UART7 +#error "SERIAL driver activated but no UART peripheral assigned" +#endif + +#if TICC3200_SERIAL_USE_UART0 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART0_PRIORITY) +#error "Invalid IRQ priority assigned to UART0" +#endif + +#if TICC3200_SERIAL_USE_UART1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART1_PRIORITY) +#error "Invalid IRQ priority assigned to UART1" +#endif + +#if TICC3200_SERIAL_USE_UART2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART2_PRIORITY) +#error "Invalid IRQ priority assigned to UART2" +#endif + +#if TICC3200_SERIAL_USE_UART3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART3_PRIORITY) +#error "Invalid IRQ priority assigned to UART3" +#endif + +#if TICC3200_SERIAL_USE_UART4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART4_PRIORITY) +#error "Invalid IRQ priority assigned to UART4" +#endif + +#if TICC3200_SERIAL_USE_UART5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART5_PRIORITY) +#error "Invalid IRQ priority assigned to UART5" +#endif + +#if TICC3200_SERIAL_USE_UART6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART6_PRIORITY) +#error "Invalid IRQ priority assigned to UART6" +#endif + +#if TICC3200_SERIAL_USE_UART7 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(TICC3200_SERIAL_UART7_PRIORITY) +#error "Invalid IRQ priority assigned to UART7" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Tiva Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t speed; + /* End of the mandatory fields. */ + /** + * @brief Initialization value for the CTL register. + */ + uint16_t ctl; + /** + * @brief Initialization value for the LCRH register. + */ + uint8_t lcrh; + /** + * @brief Initialization value for the IFLS register. + */ + uint8_t ifls; + /** + * @brief Initialization value for the CC register. + */ + uint8_t cc; +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the USART registers block.*/ \ + uint32_t uart; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if TICC3200_SERIAL_USE_UART0 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif + +#if TICC3200_SERIAL_USE_UART1 && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif + +#if TICC3200_SERIAL_USE_UART2 && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif + +#if TICC3200_SERIAL_USE_UART3 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif + +#if TICC3200_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif + +#if TICC3200_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif + +#if TICC3200_SERIAL_USE_UART6 && !defined(__DOXYGEN__) +extern SerialDriver SD7; +#endif + +#if TICC3200_SERIAL_USE_UART7 && !defined(__DOXYGEN__) +extern SerialDriver SD8; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* HAL_SERIAL_LLD_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.c new file mode 100644 index 00000000..c9633519 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.c @@ -0,0 +1,131 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file TI/TICC3200/hal_lld.c + * @brief TI CC3200 HAL Driver subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) +{ +} + +/** + * @brief CC3200 clocks and PLL initialization. + * @note All the involved constants come from the file @p board.h and + * @p mcuconf.h. + * @note This function should be invoked just after the system reset. + * + * @special + */ +void ti3200_clock_init(void) +{ + uint32_t rcc, rcc2, i; + + /* 1. Bypass the PLL and system clock divider by setting the BYPASS bit and + * clearing the USESYSDIV bit in the RCC register, thereby configuring the + * microcontroller to run off a "raw" clock source and allowing for the new + * PLL configuration to be validated before switching the system clock to the + * PLL. */ + /* read */ + + rcc = HWREG(SYSCTL_RCC); + rcc2 = HWREG(SYSCTL_RCC2); + + /* modify */ + rcc |= SYSCTL_RCC_BYPASS; + rcc &= ~SYSCTL_RCC_USESYSDIV; + rcc2 |= SYSCTL_RCC2_BYPASS2 | SYSCTL_RCC2_USERCC2; + + /* write */ + HWREG(SYSCTL_RCC) = rcc; + HWREG(SYSCTL_RCC2) = rcc2; + + /* 2 Select the crystal value (XTAL) and oscillator source (OSCSRC), and + * clear the PWRDN bit in RCC and RCC2. Setting the XTAL field automatically + * pulls valid PLL configuration data for the appropriate crystal, and + * clearing the PWRDN bit powers and enables the PLL and its output. */ + /* modify */ + rcc &= ~(SYSCTL_RCC_OSCSRC_M | SYSCTL_RCC_XTAL_M | SYSCTL_RCC_PWRDN | SYSCTL_RCC_MOSCDIS); + rcc |= ((TIVA_XTAL | TIVA_OSCSRC | TIVA_MOSCDIS) & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M | SYSCTL_RCC_MOSCDIS)); + rcc2 &= ~(SYSCTL_RCC2_OSCSRC2_M | SYSCTL_RCC2_PWRDN2); + rcc2 |= ((TIVA_OSCSRC | TIVA_DIV400) & (SYSCTL_RCC2_OSCSRC2_M | SYSCTL_RCC2_DIV400)); + + /* write */ + HWREG(SYSCTL_RCC) = rcc; + HWREG(SYSCTL_RCC2) = rcc2; + for(i = 100000; i; i--); + + /* 3. Select the desired system divider (SYSDIV) in RCC and RCC2 and set the + * USESYSDIV bit in RCC. The SYSDIV field determines the system frequency for + * the microcontroller. */ + /* modify */ + rcc &= ~SYSCTL_RCC_SYSDIV_M; + rcc |= (TIVA_SYSDIV & SYSCTL_RCC_SYSDIV_M) | SYSCTL_RCC_USESYSDIV; + rcc2 &= ~(SYSCTL_RCC2_SYSDIV2_M | SYSCTL_RCC2_SYSDIV2LSB); + rcc2 |= ((TIVA_SYSDIV2 | TIVA_SYSDIV2LSB) & (SYSCTL_RCC2_SYSDIV2_M | SYSCTL_RCC2_SYSDIV2LSB)); + + /* write */ + HWREG(SYSCTL_RCC) = rcc; + HWREG(SYSCTL_RCC2) = rcc2; + + /* 4. Wait for the PLL to lock by polling the PLLLRIS bit in the Raw + * Interrupt Status (RIS) register. */ + while ((HWREG(SYSCTL_RIS) & SYSCTL_RIS_PLLLRIS) == 0); + + /* 5. Enable use of the PLL by clearing the BYPASS bit in RCC and RCC2. */ + rcc &= ~SYSCTL_RCC_BYPASS; + rcc2 &= ~SYSCTL_RCC2_BYPASS2; + rcc |= (TIVA_BYPASS_VALUE << 11); + rcc2 |= (TIVA_BYPASS_VALUE << 11); + HWREG(SYSCTL_RCC) = rcc; + HWREG(SYSCTL_RCC2) = rcc2; + +#if HAL_USE_PWM + HWREG(SYSCTL_RCC) |= TIVA_PWM_FIELDS; +#endif + +#if defined(TICC3200_UDMA_REQUIRED) + udmaInit(); +#endif +} + +/** + * @} + */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.h new file mode 100644 index 00000000..d2122366 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/hal_lld.h @@ -0,0 +1,234 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file TI/TICC3200/hal_lld.h + * @brief TI CC3200 HAL subsystem low level driver header. + * @pre This module requires the following macros to be defined in the + * @p board.h file: + * - TODO: add required macros + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +#include "ticc3200_registry.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification + * @{ + */ + +#define PLATFORM_NAME "TI CC3200" + +/** + * @} + */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ + +#if !defined(TICC3200_OSCSRC) +#define TICC3200_OSCSRC SYSCTL_RCC2_OSCSRC2_MO +#endif + +#if !defined(TICC3200_MOSC_ENABLE) +#define TICC3200_MOSC_ENABLE TRUE +#endif + +#if !defined(TICC3200_DIV400_VALUE) +#define TICC3200_DIV400_VALUE 1 +#endif + +#if !defined(TICC3200_SYSDIV_VALUE) +#define TICC3200_SYSDIV_VALUE 2 +#endif + +#if !defined(TICC3200_USESYSDIV_ENABLE) +#define TICC3200_USESYSDIV_ENABLE FALSE +#endif + +#if !defined(TICC3200_SYSDIV2LSB_ENABLE) +#define TICC3200_SYSDIV2LSB_ENABLE FALSE +#endif + +#if !defined(TICC3200_BYPASS_VALUE) +#define TICC3200_BYPASS_VALUE 0 +#endif + +/** + * @} + */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(TICC3200_MCUCONF) +#error "Using a wrong mcuconf.h file, TICC3200_MCUCONF not defined" +#endif + +/* + * Oscillator-related checks. + */ +#if !(TICC3200_OSCSRC == SYSCTL_RCC2_OSCSRC2_MO) && \ + !(TICC3200_OSCSRC == SYSCTL_RCC2_OSCSRC2_IO) && \ + !(TICC3200_OSCSRC == SYSCTL_RCC2_OSCSRC2_IO4) && \ + !(TICC3200_OSCSRC == SYSCTL_RCC2_OSCSRC2_30) && \ + !(TICC3200_OSCSRC == SYSCTL_RCC2_OSCSRC2_32) +#error "Invalid value for TICC3200_OSCSRC defined" +#endif + +// #if TICC3200_XTAL_VALUE == 4000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_4MHZ +// #elif TICC3200_XTAL_VALUE == 4096000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_4_09MHZ +// #elif TICC3200_XTAL_VALUE == 4915200 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_4_91MHZ +// #elif TICC3200_XTAL_VALUE == 5000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_5MHZ +// #elif TICC3200_XTAL_VALUE == 5120000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_5_12MHZ +// #elif TICC3200_XTAL_VALUE == 6000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_6MHZ +// #elif TICC3200_XTAL_VALUE == 6144000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_6_14MHZ +// #elif TICC3200_XTAL_VALUE == 7372800 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_7_37MHZ +// #elif TICC3200_XTAL_VALUE == 8000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_8MHZ +// #elif TICC3200_XTAL_VALUE == 8192000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_8_19MHZ +// #elif TICC3200_XTAL_VALUE == 10000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_10MHZ +// #elif TICC3200_XTAL_VALUE == 12000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_12MHZ +// #elif TICC3200_XTAL_VALUE == 12288000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_12_2MHZ +// #elif TICC3200_XTAL_VALUE == 13560000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_13_5MHZ +// #elif TICC3200_XTAL_VALUE == 14318180 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_14_3MHZ +// #elif TICC3200_XTAL_VALUE == 16000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_16MHZ +// #elif TICC3200_XTAL_VALUE == 16384000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_16_3MHZ +// #elif TICC3200_XTAL_VALUE == 18000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_18MHZ +// #elif TICC3200_XTAL_VALUE == 20000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_20MHZ +// #elif TICC3200_XTAL_VALUE == 24000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_24MHZ +// #elif TICC3200_XTAL_VALUE == 25000000 +// #define TICC3200_XTAL_ SYSCTL_RCC_XTAL_25MHZ +// #else +// #error "Invalid value for TICC3200_XTAL_VALUE defined" +// #endif + +// #if TICC3200_MOSC_ENABLE == TRUE +// #define TICC3200_MOSCDIS (0 << 0) +// #define TICC3200_XTAL TICC3200_XTAL_ +// #elif TICC3200_MOSC_ENABLE == FALSE +// #define TICC3200_MOSCDIS (1 << 0) +// #define TICC3200_XTAL 0 +// #else +// #error "Invalid value for TICC3200_MOSC_ENABLE defined" +// #endif + +// #if TICC3200_DIV400_VALUE == 1 +// #define TICC3200_DIV400 (1 << 30) +// #elif TICC3200_DIV400_VALUE == 0 +// #define TICC3200_DIV400 (0 << 30) +// #else +// #error "Invalid value for TICC3200_DIV400_VALUE defined" +// #endif + +// #if (TICC3200_SYSDIV_VALUE >= 0x02) && (TICC3200_SYSDIV_VALUE <= 0x3f) +// #define TICC3200_SYSDIV (TICC3200_SYSDIV_VALUE << 23) +// #define TICC3200_SYSDIV2 (TICC3200_SYSDIV_VALUE << 23) +// #else +// #error "Invalid value for TICC3200_SYSDIV_VALUE defined" +// #endif + +// #if TICC3200_USESYSDIV_ENABLE == TRUE +// #define TICC3200_USESYSDIV (1 << 22) +// #elif TICC3200_USESYSDIV_ENABLE == FALSE +// #define TICC3200_USESYSDIV (0 << 22) +// #else +// #error "Invalid value for TICC3200_USESYSDIV_ENABLE defined" +// #endif + +// #if TICC3200_SYSDIV2LSB_ENABLE == TRUE +// #define TICC3200_SYSDIV2LSB (1 << 22) +// #elif TICC3200_SYSDIV2LSB_ENABLE == FALSE +// #define TICC3200_SYSDIV2LSB (0 << 22) +// #else +// #error "Invalid value for TICC3200_SYSDIV2LSB_ENABLE defined" +// #endif + +// #if TICC3200_BYPASS_VALUE == 1 +// #define TICC3200_SRC 16000000 +// #elif TICC3200_BYPASS_VALUE == 0 +// #define TICC3200_SRC (200000000 + (TICC3200_DIV400_VALUE * 200000000)) +// #else +// #error "Invalid value for TICC3200_BYPASS_VALUE defined" +// #endif + +// #if (TICC3200_OSCSRC == TICC3200_RCC_OSCSRC_MOSC) && (TICC3200_MOSC_ENABLE == FALSE) +// #error "Main Oscillator selected but not enabled" +// #endif + +/* + * System Clock calculation + */ +#define TICC3200_SYSCLK (TICC3200_SRC / (((TICC3200_SYSDIV_VALUE << TICC3200_DIV400_VALUE /*& TICC3200_BYPASS_VALUE*/) | (TICC3200_SYSDIV2LSB >> 22)) + 1)) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "ticc3200_isr.h" +// #include "TICC3200_udma.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); + void ti3200_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H */ + +/** + * @} + */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_isr.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_isr.h new file mode 100644 index 00000000..889551d8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_isr.h @@ -0,0 +1,40 @@ + +/** + * @file TICC3200/ticc3200_isr.h + * @brief TICC3200 ISR remapper driver header. + * + * @addtogroup TICC3200_ISR + * @{ + */ + +#ifndef _TICC3200_ISR_H_ +#define _TICC3200_ISR_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers remapping + * @{ + */ + +// /* UDMA units.*/ +// #define TICC3200_UDMA_SW_HANDLER VectorF8 +// #define TICC3200_UDMA_ERR_HANDLER VectorFC + +// #define TICC3200_UDMA_SW_NUMBER 46 +// #define TICC3200_UDMA_ERR_NUMBER 47 + +/* GPIO units.*/ +#define TICC3200_GPIOA_HANDLER INT_GPIOA0 +#define TICC3200_GPIOB_HANDLER INT_GPIOA1 +#define TICC3200_GPIOC_HANDLER INT_GPIOA2 +#define TICC3200_GPIOD_HANDLER INT_GPIOA3 + +#define TICC3200_GPIOA_NUMBER 0 +#define TICC3200_GPIOB_NUMBER 1 +#define TICC3200_GPIOC_NUMBER 2 +#define TICC3200_GPIOD_NUMBER 3 + +#endif // _TICC3200_ISR_H_ \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_registry.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_registry.h new file mode 100644 index 00000000..0f974458 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/TI/TICC3200/ticc3200_registry.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/** + * @file TICC3200/TICC3200_registry.h + * @brief TICC3200 capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef _TICC3200_REGISTRY_H_ +#define _TICC3200_REGISTRY_H_ + +#define TICC3200_HAS_GPIOA TRUE +#define TICC3200_HAS_GPIOB TRUE +#define TICC3200_HAS_GPIOC TRUE + +#define TICC3200_HAS_GPT0 TRUE +#define TICC3200_HAS_GPT1 TRUE +#define TICC3200_HAS_GPT2 TRUE +#define TICC3200_HAS_GPT3 TRUE + +#define TICC3200_HAS_UART0 TRUE +#define TICC3200_HAS_UART1 TRUE + +#define TICC3200_HAS_RTC TRUE + +#endif // _TICC3200_REGISTRY_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c new file mode 100644 index 00000000..20bed282 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/hal_community.c @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// HAL initialization (community part). +void halCommunityInit(void) { + +/////////////////////////////// +// from ChibiOS-Contrib repo // +/////////////////////////////// + +#if (HAL_USE_USBH == TRUE) + usbhInit(); +#endif + +/////////////////////////// +// nanoFramework overlay // +/////////////////////////// + +#if (HAL_USE_STM32_FLASH == TRUE) + stm32FlashInit(); +#endif + +#if (HAL_USE_STM32_CRC == TRUE) + crcInit(); +#endif + +#if (HAL_USE_STM32_RNG == TRUE) + rngInit(); +#endif + +#if HAL_USE_FSMC + stm32FsmcInit(); +#endif + +#if (HAL_USE_STM32_ONEWIRE == TRUE) + oneWireInit(); +#endif + +#if (HAL_USE_STM32_QSPI == TRUE) + qspiInit(); +#endif + +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc/hal_stm32_crc.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc/hal_stm32_crc.c new file mode 100644 index 00000000..0ba165f3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_crc/hal_stm32_crc.c @@ -0,0 +1,85 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// This driver is slightly different from the usual ChibiOS drivers because the calls don't require an instance of the driver. +// The reason for this is that the hardware only has a single instance of the peripheral +// so there is no point on wasting memory with calling functions with dummy arguments. + + +#include +#include + +#if (HAL_USE_STM32_CRC == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Initializes the CRC Driver +void crcInit(void) { + crc_lld_init(); +} + +// Configures and activates the CRC peripheral +void crcStart(const crcConfig *config) { + + // better lock this to setup the driver and start the peripheral + osalSysLock(); + + crc_lld_start(config); + + osalSysUnlock(); +} + +// Deactivates the CRC peripheral +void crcStop() { + + // better lock this to stop the peripheral + osalSysLock(); + + crc_lld_stop(); + + osalSysUnlock(); +} + +// Resets the current CRC calculation +void crcReset() { + osalSysLock(); + crc_lld_reset(); + osalSysUnlock(); +} + +uint32_t crcCompute(const void* buffer, int size, uint32_t initialCrc) { + + return crc_lld_compute(buffer, size, initialCrc); +} + +void crcAquireModule() { + + crc_lld_aquire(); +} + +void crcReleaseModule() { + + crc_lld_release(); +} + +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_flash/hal_stm32_flash.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_flash/hal_stm32_flash.c new file mode 100644 index 00000000..b4ccb743 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_flash/hal_stm32_flash.c @@ -0,0 +1,70 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" +#include + +#if (HAL_USE_STM32_FLASH == TRUE) + +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +void stm32FlashInit(void) { + flash_lld_init(); +} + +void stm32FlashObjectInit(SMT32FlashDriver* flash) { + (void)flash; +} + + +void stm32FlashReadBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer) { + osalDbgCheck((startAddress > FLASH_BASE) && (length > 0U) && (buffer != NULL)); + + flash_lld_readBytes(startAddress, length, buffer); +} + +int stm32FlashWrite(uint32_t startAddress, uint32_t length, const uint8_t* buffer) { + osalDbgCheck((startAddress > FLASH_BASE) && (length > 0U) && (buffer != NULL)); + + return flash_lld_write(startAddress, length, buffer); +} + +int stm32FlashIsErased(uint32_t startAddress, uint32_t length) { + osalDbgCheck((startAddress > FLASH_BASE) && (length > 0U)); + + return flash_lld_isErased(startAddress, length); +} + +int stm32FlashErase(uint32_t address) { + osalDbgCheck(address > FLASH_BASE); + + return flash_lld_erase(address); +} + +uint8_t stm32FlashGetSector(uint32_t address) { + return flash_lld_getSector(address); +} + + +#endif + diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c new file mode 100644 index 00000000..82b85d86 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_fsmc/hal_stm32_fsmc.c @@ -0,0 +1,149 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2014 Uladzimir Pylinsky aka barthess +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include "hal_stm32_fsmc.h" + +#if (HAL_USE_FSMC == TRUE) +/////////////////////////////////////////////////////////////////////////////// +// Driver local definitions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported variables. // +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief FSMC1 driver identifier. + */ +#if STM32_FSMC_USE_FSMC1 +FSMCDriver FSMCD1; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Driver local variables and types. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver local functions. // +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Driver exported functions. // +/////////////////////////////////////////////////////////////////////////////// + +// Low level FSMC driver initialization. +void stm32FsmcInit(void) { + + if (FSMCD1.state == FSMC_UNINIT) { + FSMCD1.state = FSMC_STOP; + +#if STM32_SRAM_USE_FSMC_SRAM1 + FSMCD1.sram1 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE); +#endif + +#if STM32_SRAM_USE_FSMC_SRAM2 + FSMCD1.sram2 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE + 8); +#endif + +#if STM32_SRAM_USE_FSMC_SRAM3 + FSMCD1.sram3 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE + 8 * 2); +#endif + +#if STM32_SRAM_USE_FSMC_SRAM4 + FSMCD1.sram4 = (FSMC_SRAM_NOR_TypeDef *)(FSMC_Bank1_R_BASE + 8 * 3); +#endif + +#if STM32_NAND_USE_FSMC_NAND1 + FSMCD1.nand1 = (FSMC_NAND_TypeDef *)FSMC_Bank2_R_BASE; +#endif + +#if STM32_NAND_USE_FSMC_NAND2 + FSMCD1.nand2 = (FSMC_NAND_TypeDef *)FSMC_Bank3_R_BASE; +#endif + +#if (defined(STM32F427xx) || defined(STM32F437xx) || \ + defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || \ + defined(STM32F745xx) || defined(STM32F746xx) || \ + defined(STM32F756xx) || defined(STM32F767xx) || \ + defined(STM32F769xx) || defined(STM32F777xx) || \ + defined(STM32F779xx)) + #if STM32_USE_FSMC_SDRAM + FSMCD1.sdram = (FSMC_SDRAM_TypeDef *)FSMC_Bank5_6_R_BASE; + #endif +#endif + } +} + +// Configures and activates the FSMC peripheral. +// fsmcp pointer to the @p FSMCDriver object +void fsmc_start(FSMCDriver *fsmcp) { + + osalDbgAssert((fsmcp->state == FSMC_STOP) || (fsmcp->state == FSMC_READY), + "invalid state"); + + if (fsmcp->state == FSMC_STOP) { + /* Enables the peripheral.*/ +#if STM32_FSMC_USE_FSMC1 + if (&FSMCD1 == fsmcp) { +#ifdef rccResetFSMC + rccResetFSMC(); +#endif + rccEnableFSMC(FALSE); +#if HAL_USE_NAND + nvicEnableVector(STM32_FSMC_NUMBER, STM32_FSMC_FSMC1_IRQ_PRIORITY); +#endif + } +#endif /* STM32_FSMC_USE_FSMC1 */ + + fsmcp->state = FSMC_READY; + } +} + +// Deactivates the FSMC peripheral. +// emcp pointer to the @p FSMCDriver object +void fsmc_stop(FSMCDriver *fsmcp) { + + if (fsmcp->state == FSMC_READY) { + /* Resets the peripheral.*/ +#ifdef rccResetFSMC + rccResetFSMC(); +#endif + + /* Disables the peripheral.*/ +#if STM32_FSMC_USE_FSMC1 + if (&FSMCD1 == fsmcp) { +#if HAL_USE_NAND + nvicDisableVector(STM32_FSMC_NUMBER); +#endif + rccDisableFSMC(); + } +#endif /* STM32_FSMC_USE_FSMC1 */ + + fsmcp->state = FSMC_STOP; + } +} + +// FSMC shared interrupt handler. +CH_IRQ_HANDLER(STM32_FSMC_HANDLER) { + + CH_IRQ_PROLOGUE(); +#if STM32_NAND_USE_FSMC_NAND1 + if (FSMCD1.nand1->SR & FSMC_SR_ISR_MASK) { + NANDD1.isr_handler(&NANDD1); + } +#endif +#if STM32_NAND_USE_FSMC_NAND2 + if (FSMCD1.nand2->SR & FSMC_SR_ISR_MASK) { + NANDD2.isr_handler(&NANDD2); + } +#endif + CH_IRQ_EPILOGUE(); +} + +#endif /* HAL_USE_FSMC */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_onewire/hal_stm32_onewire.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_onewire/hal_stm32_onewire.c new file mode 100644 index 00000000..6df9df43 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_onewire/hal_stm32_onewire.c @@ -0,0 +1,1033 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/* + * Hardware Abstraction Layer for ONEWIRE Unit + */ +#include +#include + +#if (HAL_USE_STM32_ONEWIRE == TRUE) + +#include + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define PAGE_LENGTH 64 +#define PAGE_LENGTH_HYGRO 32 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +uint32_t utilcrc16 = 0; +uint8_t utilcrc8; + +// local variables for this module to hold search state information + +uint8_t LastDiscrepancy; +uint8_t LastFamilyDiscrepancy; +uint8_t LastDevice; + +uint8_t SerialNum[8]; + +#if ONEWIRE_CRC8_TABLE + +static const uint8_t dscrc_table[] = { + 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, + 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, + 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, + 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, + 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, + 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, + 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, + 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, + 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, + 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, + 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, + 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, + 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, + 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, + 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, + 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; + +#endif // ONEWIRE_CRC8_TABLE + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + + +// Initializes the ONEWIRE Driver +void oneWireInit(void) { + oneWire_lld_init(); +} + +// Configures and activates the CRC peripheral +void oneWireStart() { + + // better lock this to setup the driver and start the peripheral + osalSysLock(); + + oneWire_lld_start(); + + osalSysUnlock(); +} + +// Deactivates the ONEWIRE peripheral +void oneWireStop() { + + // better lock this to stop the peripheral + osalSysLock(); + + oneWire_lld_stop(); + + osalSysUnlock(); +} + + +#if (ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE) + +void oneWireAcquireModule() { + + oneWire_lld_aquire(); +} + +void oneWireReleaseModule() { + + oneWire_lld_release(); +} + +#endif /* ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE */ + +// Calculate a new CRC16 from the input data short. Return the current +// CRC16 and also update the global variable CRC16. +uint32_t docrc16(uint32_t cdata) +{ + uint8_t oddparity[] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; + + cdata = (cdata ^ (utilcrc16 & 0xff)) & 0xff; + utilcrc16 >>= 8; + + if ((oddparity[(cdata & 0xf)] ^ oddparity[(cdata >> 4)]) == 1) + { + utilcrc16 ^= 0xC001; + } + + cdata <<= 6; + utilcrc16 ^= cdata; + cdata <<= 1; + utilcrc16 ^= cdata; + + return utilcrc16; +} + +// Reset CRC16 to the value passed in +void setcrc16(uint32_t reset) +{ + utilcrc16 = reset; +} + +#if ONEWIRE_CRC8_TABLE + +// compute CRC8 using lookup table (FLASH expensive) + +uint8_t doCrc8(uint8_t oldCrc, uint8_t x) +{ + return dscrc_table[oldCrc ^ x]; +} + +#else + +// compute CRC8 using running algorith (slower but saves FLASH) + +uint8_t doCrc8(uint8_t oldCrc, uint8_t x) +{ + uint8_t crc = oldCrc; + + for (uint8_t i = 8; i; i--) + { + uint8_t mix = (crc ^ x) & 0x01; + crc >>= 1; + if (mix) crc ^= 0x8C; + x >>= 1; + } + + return crc; +} + +#endif // ONEWIRE_CRC8_TABLE + + +/******************************************************************************* +** NAME: oneWireTouchReset ************************************************* +******************************************************************************** + +DESCRIPTION: +Reset all of the devices on the 1-Wire Net and return the result. + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: +-------------------------------------------------------------------------- + + Returns: TRUE(1): presense pulse(s) detected, device(s) reset + FALSE(0): no presense pulses detected + +*******************************************************************************/ +uint8_t oneWireTouchReset(void) +{ + return oneWire_lld_TouchReset(); +} + +/******************************************************************************* +** NAME: oneWireTouchBit *************************************************** +******************************************************************************** + +DESCRIPTION: + * Send 1 bit of communication to the 1-Wire Net and return the + * result 1 bit read from the 1-Wire Net. The parameter 'sendbit' + * least significant bit is used and the least significant bit + * of the result is the return bit. + * @return a SMALLINT with 0 bit read from sendbit or 1 bit read fromsendbit + * @param sendbit the least significant bit is the bit to send + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +bool oneWireTouchBit(bool sendbit) +{ + return oneWire_lld_TouchBit(sendbit); +} + +/******************************************************************************* +** NAME: oneWireTouchByte ************************************************** +******************************************************************************** + +DESCRIPTION: + // Send 8 bits of communication to the 1-Wire Net and return the + // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' + // least significant 8 bits are used and the least significant 8 bits + // of the result is the return byte. + // + // 'sendbyte' - 8 bits to send (least significant byte) + // + // Returns: 8 bits read from sendbyte + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +uint8_t oneWireTouchByte(uint8_t sendbyte) +{ + return oneWire_lld_TouchByte(sendbyte); +} + +/******************************************************************************* +** NAME: oneWireWriteByte ************************************************** +******************************************************************************** + +DESCRIPTION: + // Send 8 bits of communication to the 1-Wire Net and verify that the + // 8 bits read from the 1-Wire Net is the same (write operation). + // The parameter 'sendbyte' least significant 8 bits are used. + // + // 'sendbyte' - 8 bits to send (least significant byte) + // + // Returns: TRUE: bytes written and echo was the same + // FALSE: echo was not the same + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +uint8_t oneWireWriteByte(uint8_t sendbyte) +{ + return (oneWireTouchByte(sendbyte) == sendbyte) ? TRUE : FALSE; +} + +/******************************************************************************* +** NAME: oneWireReadByte *************************************************** +******************************************************************************** + +DESCRIPTION: + // Send 8 bits of read communication to the 1-Wire Net and and return the + // result 8 bits read from the 1-Wire Net. + // + // Returns: 8 bytes read from 1-Wire Net + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +uint8_t oneWireReadByte(void) +{ + return oneWireTouchByte(0xFF); +} + +/******************************************************************************* +** NAME: oneWireSerialNum ************************************************** +******************************************************************************** + +DESCRIPTION: + // The 'oneWireSerialNum' function either reads or sets the SerialNum buffer + // that is used in the search functions 'owFirst' and 'owNext'. + // This function contains two parameters, 'serialnum_buf' is a pointer + // to a buffer provided by the caller. 'serialnum_buf' should point to + // an array of 8 unsigned chars. The second parameter is a flag called + // 'do_read' that is TRUE (1) if the operation is to read and FALSE + // (0) if the operation is to set the internal SerialNum buffer from + // the data in the provided buffer. + // + // 'serialnum_buf' - buffer to that contains the serial number to set + // when do_read = FALSE (0) and buffer to get the serial + // number when do_read = TRUE (1). + // 'do_read' - flag to indicate reading (1) or setting (0) the current + // serial number. + // + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +void oneWireSerialNum(uint8_t* serialnum_buf, uint8_t do_read) +{ + uint8_t i; + + //-------------------------------------------------// + // read the internal buffer and place in 'serialnum_buf' + if (do_read) + { + for (i = 0; i < 8; i++) + { + serialnum_buf[i] = SerialNum[i]; + } + } + // set the internal buffer from the data in 'serialnum_buf' + else + { + for (i = 0; i < 8; i++) + { + SerialNum[i] = serialnum_buf[i]; + } + } +} + +/******************************************************************************* +** NAME: oneWireAccess ***************************************************** +******************************************************************************** + +DESCRIPTION: + //-------------------------------------------------------------------------- + // The 'owAccess' function resets the 1-Wire and sends a MATCH Serial + // Number command followed by the current SerialNum code. After this + // function is complete the 1-Wire device is ready to accept device-specific + // commands. + // + // Returns: TRUE (1) : reset indicates present and device is ready + // for commands. + // FALSE (0): reset does not indicate presence or echos 'writes' + // are not correct. + // + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +uint8_t oneWireAccess(void) +{ + uint8_t sendpacket[9]; + uint8_t i; + + // + //-------------------------------------------------// + // reset the 1-wire + if (oneWireTouchReset()) + { + // create a buffer to use with block function + // match Serial Number command 0x55 + sendpacket[0] = MATCH_ROM; + // Serial Number + for (i = 1; i < 9; i++) + { + sendpacket[i] = SerialNum[i-1]; + } + + // send/recieve the transfer buffer + if (oneWireBlock(FALSE, sendpacket, 9)) + { + // verify that the echo of the writes was correct + for (i = 1; i < 9; i++) + { + if (sendpacket[i] != SerialNum[i-1]) + { + return FALSE; + } + } + + if (sendpacket[0] != MATCH_ROM) + { + //OWERROR(//OWERROR_WRITE_VERIFY_FAILED); + return FALSE; + } + else + { + return TRUE; + } + } + } + + // reset or match echo failed + return FALSE; +} + +/******************************************************************************* +** NAME: oneWireBlock ****************************************************** +******************************************************************************** + +DESCRIPTION: + // The 'oneWireBlock' transfers a block of data to and from the + // 1-Wire Net with an optional reset at the begining of communication. + // The result is returned in the same buffer. + // + // 'doReset' - cause a oneWireTouchReset to occure at the begining of + // communication TRUE(1) or not FALSE(0) + // 'tran_buf' - pointer to a block of unsigned + // chars of length 'TranferLength' that will be sent + // to the 1-Wire Net + // 'tran_len' - length in bytes to transfer + // Supported devices: all + // + // Returns: TRUE (1) : The optional reset returned a valid + // presence (doReset == TRUE) or there + // was no reset required. + // FALSE (0): The reset did not return a valid prsence + // (doReset == TRUE). + // + // The maximum tran_len is 160 + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +uint8_t oneWireBlock(uint8_t doReset, uint8_t* tran_buf, uint8_t tran_len) +{ + uint8_t i; + // + //-------------------------------------------------// + // check for a block too big + if (tran_len > 160) + { + // error: BLOCK TOO BIG + return FALSE; + } + + // check if need to do a owTouchReset first + if (doReset) + { + if (!oneWireTouchReset()) + { + // error: NO DEVICES ON NET + return FALSE; + } + } + + // send and receive the buffer + for (i = 0; i < tran_len; i++) + { + tran_buf[i] = oneWireTouchByte(tran_buf[i]); + } + + return TRUE; +} + +/******************************************************************************* +** NAME: oneWireWriteMemory ************************************************** +******************************************************************************** + +DESCRIPTION: +write block of memory to iButton memory + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +uint8_t oneWireWriteMemory(uint8_t* buf, uint32_t ln, uint32_t adr) +{ + //-------------------------------------------------// + // write to scratch and then copy + if (oneWireWriteScratchpad(buf, ln, adr)) + return oneWireCopyScratchpad(ln, adr); + + // end function + return FALSE; +} + +/******************************************************************************* +** NAME: oneWireCopyScratchpad *********************************************** +******************************************************************************** + +DESCRIPTION: +copy scratchpad contempts + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: +Only valid for DS1921G,H,Z + +*******************************************************************************/ +uint8_t oneWireCopyScratchpad(uint32_t ln, uint32_t adr) +{ + // local variables + uint8_t i; + uint8_t pbuf[15]; + + //-------------------------------------------------// + // check for presence indicator + if (oneWireAccess()) + { + // construct a packet to send + pbuf[0] = COPY_SCRPAD; // copy scratch command + pbuf[1] = (adr & 0xFF); // address 1 + pbuf[2] = ((adr >> 8) & 0xFF); // address 2 + pbuf[3] = (adr + ln - 1) & 0x1F; // offset + for (i = 0; i <= 9; i++) + pbuf[4 + i] = 0xFF; // result of copy + // perform the block + if (oneWireBlock(FALSE, pbuf, 14)) { + if ((pbuf[13] == 0x55) || (pbuf[13] == 0xAA)) + return TRUE; + } + } + + // end function + return FALSE; +} + +/******************************************************************************* +** NAME: oneWireWriteScratchpad ********************************************** +******************************************************************************** + +DESCRIPTION: +copy scratchpad contempts + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: +Only valid for DS1921G,H,Z + +*******************************************************************************/ +uint8_t oneWireWriteScratchpad(uint8_t* buf, uint32_t ln, uint32_t adr) +{ + uint8_t i; + uint8_t pbuf[40]; + + //-------------------------------------------------// + // check for presence indicator + if (oneWireAccess()) + { + // construct a packet to send + pbuf[0] = WR_SCRPAD; // write scratch command + pbuf[1] = (adr & 0xFF); // address 1 + pbuf[2] = ((adr >> 8) & 0xFF); // address 2 + + // the write bytes + for (i = 0; i < ln; i++) + pbuf[3 + i] = (uint8_t)(buf[i]); // data + + // perform the block + if (!oneWireBlock(FALSE, pbuf, ln+3)) + return FALSE; + + // Now read back the scratch + if (oneWireAccess()) { + // construct a packet to send + pbuf[0] = RD_SCRPAD; // read scratch command + pbuf[1] = 0xFF; // address 1 + pbuf[2] = 0xFF; // address 2 + pbuf[3] = 0xFF; // offset + + // the write bytes + for (i = 0; i < ln; i++) + pbuf[4 + i] = 0xFF; // data + + // perform the block + if (!oneWireBlock(FALSE, pbuf, ln+4)) + return FALSE; + + // read address 1 + if (pbuf[1] != (adr & 0xFF)) + return FALSE; + // read address 2 + if (pbuf[2] != ((adr >> 8) & 0xFF)) + return FALSE; + // read the offset + if (pbuf[3] != ((adr + ln - 1) & 0x1F)) + return FALSE; + // read and compare the contents + for (i = 0; i < ln; i++) { + if (pbuf[4 + i] != buf[i]) + return FALSE; + } + // success + return TRUE; + } + } + + // end function + return FALSE; + +} + +/******************************************************************************* +** NAME: oneWireReadPage ***************************************************** +******************************************************************************** + +DESCRIPTION +read memory page + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: +Only valid for DS1921G,H,Z +Simplification of addressing using SKIP ROM + +*******************************************************************************/ +uint8_t oneWireReadPage(uint32_t start_pg, uint8_t* finalbuf) +{ + uint32_t lastcrc16; + uint32_t len,i; + + // create a packet to read a page + len = 0; + setcrc16(0x0); + // skip ROM + finalbuf[len++] = SKIP_ROM; + // read memory with crc command + finalbuf[len] = RD_MEMORY_CRC; + docrc16(finalbuf[len++]); + + // address + finalbuf[len] = (uint8_t)((start_pg << 5) & 0xFF); + docrc16(finalbuf[len++]); + finalbuf[len] = (uint8_t)(start_pg >> 3); + docrc16(finalbuf[len++]); + + // set 32 reads for data and 2 for crc + for (i = 0; i < 34; i++) + { + finalbuf[len++] = 0xFF; + } + // send the bytes + if (oneWireBlock(TRUE , finalbuf, len)) + { + // calculate the CRC over the last 34 bytes + for (i = 0; i < 34; i++) + { + lastcrc16 = docrc16(finalbuf[len - 34 + i]); + } + // check crc + if (lastcrc16 == 0xB001) + { + // copy the data into the buffer without the command and parameters + for (i = 0; i < 32; i++) + { + finalbuf[i] = finalbuf[i + 4]; + } + } + else + { + return FALSE; + } + } + else + { + return FALSE; + } + + // end function + return TRUE; +} + +/******************************************************************************* +** NAME: oneWireReadPageCRCEE77 ********************************************** +******************************************************************************** + +DESCRIPTION + Read a complete memory page with CRC verification provided by the + device. Not supported by all devices. See the method + 'hasPageAutoCRCEE()'. + + bank to tell what memory bank of the ibutton to use. + portnum the port number of the port being used for the + 1-Wire Network. + SNum the serial number for the part. + psw 8 byte password + page the page to read + rd_cont if 'true' then device read is continued without + re-selecting. This can only be used if the new + read() continious where the last one led off + and it is inside a 'beginExclusive/endExclusive' + block. + buff byte array containing data that was read + + @return - returns '0' if the read page wasn't completed. + '1' if the operation is complete. + + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +uint8_t oneWireReadPageCRCEE77(uint32_t page, uint8_t *buff) +{ + uint8_t i, send_len=0, lsCRC16; + uint8_t raw_buf[15]; + uint32_t str_add; + uint32_t lastcrc16; + + // select the device + if (!oneWireAccess()) + { + return FALSE; + } + + // command, address, offset, password (except last byte) + raw_buf[send_len++] = READ_MEMORY_PSW_COMMAND; + if(SerialNum[0] == 0x37) + { + str_add = page * PAGE_LENGTH; + } + else + { + str_add = page * PAGE_LENGTH_HYGRO; + } + raw_buf[send_len++] = str_add & 0xFF; + raw_buf[send_len++] = ((str_add & 0xFFFF) >> 8) & 0xFF; + + // calculate the CRC16 + setcrc16(0); + for(i = 0; i < send_len; i++) + lastcrc16 = docrc16(raw_buf[i]); + + for (i = 0; i < 8; i++) + raw_buf[send_len++] = 0xFF; + + + if(SerialNum[0] == 0x37) + { + // send block (check copy indication complete) + if(!oneWireBlock(FALSE,(uint8_t*)raw_buf,(send_len-1))) + { + return FALSE; + } + + } + else + { + if(!oneWireBlock(FALSE,(uint8_t*)raw_buf,send_len)) + { + return FALSE; + } + } + + // set the read bytes + if(SerialNum[0] == 0x37) + { + + for (i = 0; i < PAGE_LENGTH; i++) + buff[i] = 0xFF; + } + else + { + for(i=0; i 0) + { + // all connected devices reply with 0 or 1 + // write bit to perform search + outBit = attempt >> 1; + } + else + { + if (romBitIndex < LastDiscrepancy) + { + outBit = ((SerialNum[romByteIndex] & bitMask) > 0); + } + else + { + // set to 1 if it's the same, otherwise 0 + outBit = (romBitIndex == LastDiscrepancy); + } + + // on 0 record position on bitMask + if (outBit == 0) + { + discrepMarker = romBitIndex; + } + } + + // isolate bit in ROM[n] with bitMask + if (outBit == 1) + { + SerialNum[romByteIndex] |= bitMask; + } + else + { + SerialNum[romByteIndex] &= ~bitMask; + } + + // ROM search write + oneWireTouchBit(outBit); + + romBitIndex++; + + bitMask = bitMask << 1; + + // if the mask has reached 0 then go for a new ROM + if (bitMask == 0) + { + // reset mask and perform CRC8 + lastcrc8 = doCrc8(lastcrc8, SerialNum[romByteIndex]); + + romByteIndex++; + bitMask++; + } + } + + } + while (romByteIndex < 8); // loop until we have all ROM bytes + + if ((romBitIndex < 65) || (lastcrc8 != 0)) + { + // search was unsuccessful reset the last discrepancy + LastDiscrepancy = 0; + } + else + { + // search was successful: set last discrepancy, device and result + LastDiscrepancy = discrepMarker; + LastDevice = (LastDiscrepancy == 0); + + // search isn't completed there are more devices present in the bus + result = TRUE; + } + + return result; +} + +#endif /* HAL_USE_STM32_ONEWIRE */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_qspi/hal_stm32_qspi.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_qspi/hal_stm32_qspi.c new file mode 100644 index 00000000..232e3278 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_qspi/hal_stm32_qspi.c @@ -0,0 +1,63 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/* + * Hardware Abstraction Layer for QSPI + */ +#include +#include + +#if (HAL_USE_STM32_QSPI == TRUE) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + + +// Initializes the QSPI Driver +void qspiInit() +{ + qspi_lld_init(); +} + +// Configures and activates the QSPI peripheral +void qspiStart(QSPI_HandleTypeDef* qspi) +{ + // better lock this to setup the driver and start the peripheral + osalSysLock(); + + qspi_lld_start(qspi); + + osalSysUnlock(); +} + +// Deactivates the QSPI peripheral +void qspiStop(QSPI_HandleTypeDef* qspi) +{ + // better lock this to stop the peripheral + osalSysLock(); + + qspi_lld_stop(qspi); + + osalSysUnlock(); +} + +#endif /* HAL_USE_STM32_QSPI */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng/hal_stm32_rng.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng/hal_stm32_rng.c new file mode 100644 index 00000000..6a4ed5b8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/src/stm32_rng/hal_stm32_rng.c @@ -0,0 +1,94 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/* + * Hardware Abstraction Layer for RNG Unit + */ +#include +#include + +#if (HAL_USE_STM32_RNG == TRUE) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + + +// Initializes the RNG Driver +void rngInit(void) { + rng_lld_init(); +} + +// Configures and activates the CRC peripheral +void rngStart() { + + // better lock this to setup the driver and start the peripheral + osalSysLock(); + + rng_lld_start(); + + osalSysUnlock(); +} + +// Deactivates the RNG peripheral +void rngStop() { + + // better lock this to stop the peripheral + osalSysLock(); + + rng_lld_stop(); + + osalSysUnlock(); +} + + +#if (RNG_USE_MUTUAL_EXCLUSION == TRUE) + +void rngAquireModule() { + + rng_lld_aquire(); +} + +void rngReleaseModule() { + + rng_lld_release(); +} + +#endif /* RNG_USE_MUTUAL_EXCLUSION == TRUE */ + + +uint32_t rngGenerateRandomNumber() { + uint32_t randomNumber; + osalSysLock(); + randomNumber = rng_lld_GenerateRandomNumber(); + osalSysUnlock(); + return randomNumber; +} + +uint32_t rngGetLastRandomNumber() { + uint32_t randomNumber; + osalSysLock(); + randomNumber = rng_lld_GetLastRandomNumber(); + osalSysUnlock(); + return randomNumber; +} + +#endif /* HAL_USE_STM32_RNG */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/stm32-internal-flash-driver.md b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/stm32-internal-flash-driver.md new file mode 100644 index 00000000..39500086 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/nf-overlay/stm32-internal-flash-driver.md @@ -0,0 +1,31 @@ +# Driver for SMT32 internal flash + +This driver enables **nanoFramework** to access the internal flash for STM32 parts taking care of the low level details and implementation specifics. + +In order to enable/use it the developer has to set HAL_USE_STM32_FLASH to TRUE on the halconf_nf.h provided in the reference implementations. +_Note: to enable the driver the developer has to also enable the HAL_USE_COMMUNITY 'master switch' on that same file._ + +There are currently two versions of the driver: +- FLASHv1: suitable for F0 series +- FLASHv2: suitable for F4 series + + +The functions provided by driver are: +- ```void stm32FlashReadBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer)``` + - startAddress: the flash start address from where to read data + - length: how many bytes to be read from the flash + - buffer: pointer to the buffer where to read the flash data + +- ```int stm32FlashWrite(uint32_t startAddress, uint32_t length, const uint8_t* buffer)``` + - startAddress: the flash start address where to write data to + - length: how many bytes to be written to the flash + - buffer: pointer to the buffer whit the data to be written to the flash + +- ```int stm32FlashIsErased(uint32_t startAddress, uint32_t length)``` + - startAddress: the flash start address to check if it's erased + - length: length of the flash segment to check if it's erased + +- ```int stm32FlashErase(uint32_t address)``` + - address: the flash address belonging to the segment to be erased (this can be a block or a page depending on the flash organization of the target series) + +The driver performs basic and trivial checks on the arguments passed. diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/CMakeLists.txt new file mode 100644 index 00000000..f868eac1 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# include SPIFFS sources, if feature is enabled +if(NF_FEATURE_USE_SPIFFS) + list(APPEND TARGET_CHIBIOS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/hal_spiffs.c") + list(APPEND TARGET_CHIBIOS_COMMON_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") +endif() + +# make var global +set(TARGET_CHIBIOS_COMMON_SOURCES ${TARGET_CHIBIOS_COMMON_SOURCES} CACHE INTERNAL "make global") +set(TARGET_CHIBIOS_COMMON_INCLUDE_DIRS ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.c b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.c new file mode 100644 index 00000000..e6108a7e --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.c @@ -0,0 +1,141 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +extern s32_t hal_spiffs_erase(u32_t addr, u32_t size); +extern s32_t hal_spiffs_read(u32_t addr, u32_t size, u8_t *dst); +extern s32_t hal_spiffs_write(u32_t addr, u32_t size, u8_t *src); + +extern uint8_t target_spiffs_init(); + +mutex_t spiffs_mutex; + +spiffs fs; +spiffs_config spiffs_cfg; +bool spiffsFileSystemReady; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t spiffs_work_buffer[SPIFFS_WORK_BUFFER_SIZE]; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t spiffs_fd_space[SPIFFS_FILE_DESCRIPTORS_SPACE]; + +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t spiffs_cache[SPIFFS_CACHE_SIZE]; + +// initialization of SPIFFS: configurations, data structures, drivers and lock +uint8_t hal_spiffs_config() +{ + uint8_t mountResult; + + // low level hardware and drivers initializations + target_spiffs_init(); + + osalMutexObjectInit(&spiffs_mutex); + + // setup SPIFFS configurations + spiffs_cfg.phys_size = SPIFFS_TOTAL_SIZE; + spiffs_cfg.phys_addr = 0; + spiffs_cfg.phys_erase_block = SPIFFS_ERASE_BLOCK_SIZE; + spiffs_cfg.log_block_size = SPIFFS_LOGICAL_BLOCK_SIZE; + spiffs_cfg.log_page_size = SPIFFS_LOGICAL_PAGE_SIZE; + + // setup pointers to HAL functions + spiffs_cfg.hal_erase_f = hal_spiffs_erase; + spiffs_cfg.hal_read_f = hal_spiffs_read; + spiffs_cfg.hal_write_f = hal_spiffs_write; + + mountResult = SPIFFS_mount(&fs, + &spiffs_cfg, + spiffs_work_buffer, + spiffs_fd_space, + SPIFFS_FILE_DESCRIPTORS_SPACE, + spiffs_cache, + SPIFFS_CACHE_SIZE, + 0); + + if( mountResult != SPIFFS_OK && + SPIFFS_errno(&fs) == SPIFFS_ERR_NOT_A_FS) + { + // looks like SPIFFS is not formated + + // need to unmount 1st + SPIFFS_unmount(&fs); + + // now format + if (SPIFFS_format(&fs) != SPIFFS_OK) + { + return -1; + } + + // finally try mounting it again + mountResult = SPIFFS_mount(&fs, + &spiffs_cfg, + spiffs_work_buffer, + spiffs_fd_space, + SPIFFS_FILE_DESCRIPTORS_SPACE, + spiffs_cache, + SPIFFS_CACHE_SIZE, + 0); + } + + #if !defined(BUILD_RTM) + + ASSERT(mountResult == SPIFFS_OK) + + #endif + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // // code block to assist testing SPIFFS + // char writeBuf[] = {"Hello! if you get this message, congratulations, that's because SPIFFS is working on your device!!"}; + // char readBuf[sizeof(writeBuf)]; + + // spiffs_file fd = SPIFFS_open(&fs, "file1.txt", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); + // if (SPIFFS_write(&fs, fd, writeBuf, sizeof(writeBuf)) < 0) + // { + // return -1; + // } + + // SPIFFS_close(&fs, fd); + // fd = SPIFFS_open(&fs, "file1.txt", SPIFFS_RDWR, 0); + // if (SPIFFS_read(&fs, fd, readBuf, sizeof(readBuf)) < 0) + // { + // return -1; + // } + + // SPIFFS_close(&fs, fd); + + // uint32_t total = 0; + // uint32_t used_space = 0; + // SPIFFS_info(&fs, &total, &used_space); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + // mirror SPIFFS mount result into global flag + spiffsFileSystemReady = (mountResult == SPIFFS_OK); + + return mountResult; +} + +void hal_spiffs_lock() +{ + osalMutexLock(&spiffs_mutex); +} + +void hal_spiffs_unlock() +{ + osalMutexUnlock(&spiffs_mutex); +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.h b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.h new file mode 100644 index 00000000..1b8d23cb --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/ChibiOS/spiffs/hal_spiffs.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef HAL_SPIFFS_H_ +#define HAL_SPIFFS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPIFFS_SUCCESS (0) +#define SPIFFS_ERROR (-1) + +extern spiffs fs; +extern spiffs_config spiffs_cfg; +extern bool spiffsFileSystemReady; + +uint8_t hal_spiffs_config(); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_SPIFFS_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/cc.h b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/cc.h new file mode 100644 index 00000000..e03ee9e8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/cc.h @@ -0,0 +1,93 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + * **** This file incorporates work covered by the following copyright and **** + * **** permission notice: **** + * + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __CC_H__ +#define __CC_H__ + +// need to declare this here instead of adding an include because debug_printf is declared in nanoHAL.h which is a C++ header +extern void debug_printf(const char* format, ...); + +/* Use errno provided by system. */ +#define LWIP_ERRNO_INCLUDE + +typedef int sys_prot_t; + +/** + * @brief Use system provided struct timeval by default. + */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 0 +#include +#endif + +/** + * @brief Use a no-op diagnostic output macro by default. + */ +#if !defined(LWIP_PLATFORM_DIAG) +#define LWIP_PLATFORM_DIAG(x) do {debug_printf x;} while(0) + +#endif + +/** + * @brief Halt the system on lwIP assert failure by default. + */ +#if !defined(LWIP_PLATFORM_ASSERT) +#define LWIP_PLATFORM_ASSERT(x) __asm volatile("BKPT #0\n"); +#endif + +/** + * @brief The NETIF API is required by lwipthread. + */ +#ifdef LWIP_NETIF_API +#undef LWIP_NETIF_API +#endif +#define LWIP_NETIF_API 1 + +#endif /* __CC_H__ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/perf.h b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/perf.h new file mode 100644 index 00000000..dc786cad --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/perf.h @@ -0,0 +1,57 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + * **** This file incorporates work covered by the following copyright and **** + * **** permission notice: **** + * + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START +#define PERF_STOP(x) + +#endif /* __PERF_H__ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/sys_arch.h b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/sys_arch.h new file mode 100644 index 00000000..c79c5b5d --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/arch/sys_arch.h @@ -0,0 +1,85 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + * **** This file incorporates work covered by the following copyright and **** + * **** permission notice: **** + * + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include + +#ifndef __SYS_ARCH_H__ +#define __SYS_ARCH_H__ + +#define SYS_MBOX_NULL (osMessageQId)0 +#define SYS_SEM_NULL (osSemaphoreId)0 +#define SYS_THREAD_NULL (thread_t *)0 + +typedef osSemaphoreId sys_sem_t; +typedef osSemaphoreId sys_mutex_t; +typedef osMessageQId sys_mbox_t; +typedef osThreadId sys_thread_t; + +// typedef struct _sys_arch_state_t +// { +// // Task creation data. +// char cTaskName[configMAX_TASK_NAME_LEN]; +// unsigned short nStackDepth; +// unsigned short nTaskCount; +// } sys_arch_state_t; + +/* let sys.h use binary semaphores for mutexes */ +#define LWIP_COMPAT_MUTEX 1 + +#if LWIP_NETCONN_SEM_PER_THREAD +sys_sem_t* sys_arch_netconn_sem_get(void); +void sys_arch_netconn_sem_alloc(void); +void sys_arch_netconn_sem_free(void); +#define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get() +#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc() +#define LWIP_NETCONN_THREAD_SEM_FREE() sys_arch_netconn_sem_free() +#endif // LWIP_NETCONN_SEM_PER_THREAD + +#endif /* __SYS_ARCH_H__ */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_api_msg.c b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_api_msg.c new file mode 100644 index 00000000..b9ac0cfd --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_api_msg.c @@ -0,0 +1,1954 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// from the original source code file +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGE. +// +// This file is part of the lwIP TCP/IP stack. +// +// Author: Adam Dunkels + + +#include +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +/* netconns are polled once per second (e.g. continue write on memory error) */ +#define NETCONN_TCP_POLL_INTERVAL 2 + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +#if LWIP_TCPIP_CORE_LOCKING +#define WRITE_DELAYED , 1 +#define WRITE_DELAYED_PARAM , u8_t delayed +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define WRITE_DELAYED +#define WRITE_DELAYED_PARAM +#endif /* LWIP_TCPIP_CORE_LOCKING */ +static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM); +static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM); +#endif + +#if LWIP_TCPIP_CORE_LOCKING +#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_TCP +u8_t netconn_aborted; +#endif /* LWIP_TCP */ + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only copies it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + pbuf_free(p); + return; + } + + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if (!sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if (!sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ip_addr_set(&buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr(); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ip_addr_set(&buf->toaddr, ip_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + if (err != ERR_OK) { + NETCONN_SET_SAFE_ERR(conn, err); + } + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { +#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER + if (conn->current_msg && conn->current_msg->msg.sd.polls_left) { + conn->current_msg->msg.sd.polls_left--; + } +#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */ + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn) { + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + if (old_state == NETCONN_CLOSE) { + /* RST during close: let close return success & dealloc the netconn */ + err = ERR_OK; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } else { + /* no check since this is always fatal! */ + SYS_ARCH_SET(conn->last_err, err); + } + + /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ + + /* Notify the user layer about a connection error. Used to signal select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ + sys_mbox_trypost(&conn->recvmbox, NULL); + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ + sys_mbox_trypost(&conn->acceptmbox, NULL); + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + sys_sem_t* op_completed_sem; + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem)); + conn->current_msg = NULL; + /* wake up the waiting task */ + NETCONN_SET_SAFE_ERR(conn, err); + sys_sem_signal(op_completed_sem); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + if (newpcb == NULL) { + /* out-of-pcbs during connect: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_VAL; + } + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + /* We have to set the callback here even though + * the new socket is unknown. newconn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + /* outof netconns: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + /* handle backlog counter */ + tcp_backlog_delayed(newpcb); + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from lwip_netconn_do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + */ +static void +pcb_new(struct api_msg *msg) +{ + enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4; + + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + +#if LWIP_IPV6 && LWIP_IPV4 + /* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */ + if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) { + iptype = IPADDR_TYPE_ANY; + } +#endif + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); + if (msg->conn->pcb.raw != NULL) { +#if LWIP_IPV6 + /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ + if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { + msg->conn->pcb.raw->chksum_reqd = 1; + msg->conn->pcb.raw->chksum_offset = 2; + } +#endif /* LWIP_IPV6 */ + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new_ip_type(iptype); + if (msg->conn->pcb.udp != NULL) { +#if LWIP_UDPLITE + if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new_ip_type(iptype); + if (msg->conn->pcb.tcp != NULL) { + setup_tcp(msg->conn); + } + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + return; + } + if (msg->conn->pcb.ip == NULL) { + msg->err = ERR_MEM; + } +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param m the api_msg_msg describing the connection type + */ +void +lwip_netconn_do_newconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } + + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + goto free_and_return; + } +#if !LWIP_NETCONN_SEM_PER_THREAD + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + sys_mbox_free(&conn->recvmbox); + goto free_and_return; + } +#endif + +#if LWIP_TCP + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + conn->linger = -1; +#endif /* LWIP_SO_LINGER */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); +#endif + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { + if (mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + if (mem != &netconn_aborted) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static err_t +lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + u8_t close_finished = 0; + struct tcp_pcb* tpcb; +#if LWIP_SO_LINGER + u8_t linger_wait_required = 0; +#endif /* LWIP_SO_LINGER */ + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + tpcb = conn->pcb.tcp; + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing + (also if RD or WR side was shut down before already) */ + if (shut == NETCONN_SHUT_RDWR) { + close = 1; + } else if (shut_rx && + ((tpcb->state == FIN_WAIT_1) || + (tpcb->state == FIN_WAIT_2) || + (tpcb->state == CLOSING))) { + close = 1; + } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { + close = 1; + } else { + close = 0; + } + + /* Set back some callback pointers */ + if (close) { + tcp_arg(tpcb, NULL); + } + if (tpcb->state == LISTEN) { + tcp_accept(tpcb, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(tpcb, NULL); + tcp_accept(tpcb, NULL); + } + if (shut_tx) { + tcp_sent(tpcb, NULL); + } + if (close) { + tcp_poll(tpcb, NULL, 0); + tcp_err(tpcb, NULL); + } + } + /* Try to close the connection */ + if (close) { +#if LWIP_SO_LINGER + /* check linger possibilites before calling tcp_close */ + err = ERR_OK; + /* linger enabled/required at all? (i.e. is there untransmitted data left?) */ + if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) { + if ((conn->linger == 0)) { + /* data left but linger prevents waiting */ + tcp_abort(tpcb); + tpcb = NULL; + } else if (conn->linger > 0) { + /* data left and linger says we should wait */ + if (netconn_is_nonblocking(conn)) { + /* data left on a nonblocking netconn -> cannot linger */ + err = ERR_WOULDBLOCK; + } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= + (conn->linger * 1000)) { + /* data left but linger timeout has expired (this happens on further + calls to this function through poll_tcp */ + tcp_abort(tpcb); + tpcb = NULL; + } else { + /* data left -> need to wait for ACK after successful close */ + linger_wait_required = 1; + } + } + } + if ((err == ERR_OK) && (tpcb != NULL)) +#endif /* LWIP_SO_LINGER */ + { + err = tcp_close(tpcb); + } + } else { + err = tcp_shutdown(tpcb, shut_rx, shut_tx); + } + if (err == ERR_OK) { + close_finished = 1; +#if LWIP_SO_LINGER + if (linger_wait_required) { + /* wait for ACK of all unsent/unacked data by just getting called again */ + close_finished = 0; + err = ERR_INPROGRESS; + } +#endif /* LWIP_SO_LINGER */ + } else { + if (err == ERR_MEM) { + /* Closing failed because of memory shortage, try again later. Even for + nonblocking netconns, we have to wait since no standard socket application + is prepared for close failing because of resource shortage. + Check the timeout: this is kind of an lwip addition to the standard sockets: + we wait for some time when failing to allocate a segment for the FIN */ +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout > 0) { + close_timeout = conn->send_timeout; + } +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_LINGER + if (conn->linger >= 0) { + /* use linger timeout (seconds) */ + close_timeout = conn->linger * 1000U; + } +#endif + if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + if (conn->current_msg->msg.sd.polls_left == 0) { +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + close_finished = 1; + if (close) { + /* in this case, we want to RST the connection */ + tcp_abort(tpcb); + err = ERR_OK; + } + } + } else { + /* Closing failed for a non-memory error: give up */ + close_finished = 1; + } + } + if (close_finished) { + /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (err == ERR_OK) { + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + /* wake up the application task */ + sys_sem_signal(op_completed_sem); + } + return ERR_OK; + } + if (!close_finished) { + /* Closing failed and we want to wait: restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN)); + if (shut_tx) { + tcp_sent(tpcb, sent_tcp); + } + /* when waiting for close, set up poll interval to 500ms */ + tcp_poll(tpcb, poll_tcp, 1); + tcp_err(tpcb, err_tcp); + tcp_arg(tpcb, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ + LWIP_ASSERT("err != ERR_OK", err != ERR_OK); + return err; +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_delconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + enum netconn_state state = msg->conn->state; + LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ + (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); +#if LWIP_NETCONN_FULLDUPLEX + /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ + if (state != NETCONN_NONE) { + if ((state == NETCONN_WRITE) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* close requested, abort running write/connect */ + sys_sem_t* op_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(op_completed_sem); + } + } +#else /* LWIP_NETCONN_FULLDUPLEX */ + if (((state != NETCONN_NONE) && + (state != NETCONN_LISTEN) && + (state != NETCONN_CONNECT)) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* This means either a blocking write or blocking connect is running + (nonblocking write returns and sets state to NONE) */ + msg->err = ERR_INPROGRESS; + } else +#endif /* LWIP_NETCONN_FULLDUPLEX */ + { + LWIP_ASSERT("blocking connect in progress", + (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + msg->err = ERR_OK; + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { + TCPIP_APIMSG_ACK(msg); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +lwip_netconn_do_bind(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + sys_sem_t* op_completed_sem = NULL; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + } + if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + LWIP_ASSERT("blocking connect state error", + (was_blocking && op_completed_sem != NULL) || + (!was_blocking && op_completed_sem == NULL)); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(op_completed_sem); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +lwip_netconn_do_connect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state == NETCONN_CONNECT) { + msg->err = ERR_ALREADY; + } else if (msg->conn->state != NETCONN_NONE) { + msg->err = ERR_ISCONN; + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), + msg->msg.bc.port, lwip_netconn_do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), + when the connection is established! */ +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + return; + } + } + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Disconnect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param m the api_msg_msg pointing to the connection to disconnect + */ +void +lwip_netconn_do_disconnect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_listen(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { + struct tcp_pcb* lpcb; + if (msg->conn->pcb.tcp->state != CLOSED) { + /* connection is not closed, cannot listen */ + msg->err = ERR_VAL; + } else { + err_t err; + u8_t backlog; +#if TCP_LISTEN_BACKLOG + backlog = msg->msg.lb.backlog; +#else /* TCP_LISTEN_BACKLOG */ + backlog = TCP_DEFAULT_LISTEN_BACKLOG; +#endif /* TCP_LISTEN_BACKLOG */ +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen + */ + if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) && + (netconn_get_ipv6only(msg->conn) == 0)) { + /* change PCB type to IPADDR_TYPE_ANY */ + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY); + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err); + + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = err; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } else if (msg->conn->state == NETCONN_LISTEN) { + /* already listening, allow updating of the backlog */ + msg->err = ERR_OK; + tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog); + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_send(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + &msg->msg.b->addr, msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_recv(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + } while (remaining != 0); + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if TCP_LISTEN_BACKLOG +/** Indicate that a TCP pcb has been accepted + * Called from netconn_accept + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_accepted(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + tcp_backlog_accepted(msg->conn->pcb.tcp); + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* TCP_LISTEN_BACKLOG */ + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from lwip_netconn_do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + const void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock; + u8_t apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + + apiflags = conn->current_msg->msg.w.apiflags; + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + conn->write_offset = 0; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock) { + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + err_t out_err; + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + } + out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else if (err == ERR_MEM) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called. + For blocking sockets, we do NOT return to the application + thread, since ERR_MEM is only a temporary error! Non-blocking + will remain non-writable until sent_tcp/poll_tcp is called */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + err_t out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } else if (dontblock) { + /* non-blocking write is done on ERR_MEM */ + err = ERR_WOULDBLOCK; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->write_offset = 0; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + sys_sem_signal(op_completed_sem); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else { + return ERR_MEM; + } +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_write(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by lwip_netconn_do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG + since lwip_netconn_do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_getaddr(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->local_ip); + } else { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->remote_ip); + } + + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + if ((msg->msg.ad.local == 0) && + ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { + /* pcb is not connected and remote name is requested */ + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close or half-shutdown a TCP pcb contained in a netconn + * Called from netconn_close + * In contrast to closing sockets, the netconn is not deallocated. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_close(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_TCP + enum netconn_state state = msg->conn->state; + /* First check if this is a TCP netconn and if it is in a correct state + (LISTEN doesn't support half shutdown) */ + if ((msg->conn->pcb.tcp != NULL) && + (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) && + ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) { + /* Check if we are in a connected state */ + if (state == NETCONN_CONNECT) { + /* TCP connect in progress: cannot shutdown */ + msg->err = ERR_CONN; + } else if (state == NETCONN_WRITE) { +#if LWIP_NETCONN_FULLDUPLEX + if (msg->msg.sd.shut & NETCONN_SHUT_WR) { + /* close requested, abort running write */ + sys_sem_t* write_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(write_completed_sem); + } else { + LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); + /* In this case, let the write continue and do not interfere with + conn->current_msg or conn->state! */ + msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); + } + } + if (state == NETCONN_NONE) { +#else /* LWIP_NETCONN_FULLDUPLEX */ + msg->err = ERR_INPROGRESS; + } else { +#endif /* LWIP_NETCONN_FULLDUPLEX */ + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_join_leave_group(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP +#if LWIP_IPV6 && LWIP_IPV6_MLD + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } + } + else +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + { +#if LWIP_IGMP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + /* we trust the internal implementation to be correct :-) */ + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + API_EXPR_DEREF(msg->err) = ERR_VAL; + } else { + /* address was resolved */ + API_EXPR_DEREF(msg->err) = ERR_OK; + API_EXPR_DEREF(msg->addr) = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); + + // [NF_CHANGE] + sys_signal_sock_event(); + // [END_NF_CHANGE] +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +lwip_netconn_do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + u8_t addrtype = +#if LWIP_IPV4 && LWIP_IPV6 + msg->dns_addrtype; +#else + LWIP_DNS_ADDRTYPE_DEFAULT; +#endif + + API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name, + API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype); + if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sockets.c b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sockets.c new file mode 100644 index 00000000..4dc0c28a --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sockets.c @@ -0,0 +1,2868 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// from the original source code file +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGE. +// +// This file is part of the lwIP TCP/IP stack. +// +// Author: Adam Dunkels +// Improved by Marc Boucher and David Haas + + +#include +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/priv/tcpip_priv.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +/* If the netconn API is not required publicly, then we include the necessary + files here to get the implementation */ +#if !LWIP_NETCONN +#undef LWIP_NETCONN +#define LWIP_NETCONN 1 +#include "api_msg.c" +#include "api_lib.c" +#include "netbuf.c" +#undef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +#if LWIP_IPV4 +#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ + (sin)->sin_len = sizeof(struct sockaddr_in); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = lwip_htons((port)); \ + inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ + memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) +#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ + inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ + (port) = lwip_ntohs((sin)->sin_port); }while(0) +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ + (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = lwip_htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ + inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ + (sin6)->sin6_scope_id = 0; }while(0) +#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ + inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ + (port) = lwip_ntohs((sin6)->sin6_port); }while(0) +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 && LWIP_IPV6 +static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port); + +#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ + ((namelen) == sizeof(struct sockaddr_in6))) +#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ + ((name)->sa_family == AF_INET6)) +#define SOCK_ADDR_TYPE_MATCH(name, sock) \ + ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ + (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ + if (IP_IS_V6(ipaddr)) { \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ + } else { \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ + } } while(0) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) +#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ + (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#endif /* LWIP_IPV6 */ + +#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ + IS_SOCK_ADDR_TYPE_VALID(name)) +#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ + SOCK_ADDR_TYPE_MATCH(name, sock)) +#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) + + +#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if ((sock)->conn == NULL) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ + if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) + + +#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) +#if LWIP_MPU_COMPATIBLE +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ + name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ + if (name == NULL) { \ + sock_set_errno(sock, ENOMEM); \ + return -1; \ + } }while(0) +#else /* LWIP_MPU_COMPATIBLE */ +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) +#endif /* LWIP_MPU_COMPATIBLE */ + +#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) +#else +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ + s32_t loc = (val); \ + ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ + ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) +#endif + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** This is overridable for the rare case where more than 255 threads + * select on the same socket... + */ +#ifndef SELWAIT_T +#define SELWAIT_T u8_t +#endif + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ + u8_t err; + /** counter of how many threads are waiting for this socket using select */ + SELWAIT_T select_waiting; +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define SELECT_SEM_T sys_sem_t* +#define SELECT_SEM_PTR(sem) (sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define SELECT_SEM_T sys_sem_t +#define SELECT_SEM_PTR(sem) (&(sem)) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + SELECT_SEM_T sem; +}; + +/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ + * sockaddr_in6 if instantiated. + */ +union sockaddr_aligned { + struct sockaddr sa; +#if LWIP_IPV6 + struct sockaddr_in6 sin6; +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + struct sockaddr_in sin; +#endif /* LWIP_IPV4 */ +}; + +#if LWIP_IGMP +/* Define the number of IPv4 multicast memberships, default is one per socket */ +#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS +#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS +#endif + +/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when + a socket is closed */ +struct lwip_socket_multicast_pair { + /** the socket */ + struct lwip_sock* sock; + /** the interface address */ + ip4_addr_t if_addr; + /** the group address */ + ip4_addr_t multi_addr; +}; + +struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; + +static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_drop_registered_memberships(int s); +#endif /* LWIP_IGMP */ + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is changed + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +#if LWIP_SOCKET_SET_ERRNO +#ifndef set_errno +#define set_errno(err) do { if (err) { errno = (err); } } while(0) +#endif +#else /* LWIP_SOCKET_SET_ERRNO */ +#define set_errno(err) +#endif /* LWIP_SOCKET_SET_ERRNO */ + +#define sock_set_errno(sk, e) do { \ + const int sockerr = (e); \ + sk->err = (u8_t)sockerr; \ + set_errno(sockerr); \ +} while (0) + +/* Forward declaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +#if !LWIP_TCPIP_CORE_LOCKING +static void lwip_getsockopt_callback(void *arg); +static void lwip_setsockopt_callback(void *arg); +#endif +static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); +static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); + +#if LWIP_IPV4 && LWIP_IPV6 +static void +sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port) +{ + if ((sockaddr->sa_family) == AF_INET6) { + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V6; + } else { + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V4; + } +} +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void +lwip_socket_thread_init(void) +{ + netconn_thread_init(); +} + +/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ +void +lwip_socket_thread_cleanup(void) +{ + netconn_thread_cleanup(); +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +get_socket(int s) +{ + struct lwip_sock *sock; + + s -= LWIP_SOCKET_OFFSET; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + s -= LWIP_SOCKET_OFFSET; + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn && (sockets[i].select_waiting == 0)) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; + return i + LWIP_SOCKET_OFFSET; + } + SYS_ARCH_UNPROTECT(lev); + } + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; + + /* Protect socket array */ + SYS_ARCH_SET(sock->conn, NULL); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + pbuf_free((struct pbuf *)lastdata); + } else { + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ip_addr_t naddr; + u16_t port = 0; + int newsock; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + set_errno(EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + } else if (err == ERR_CLSD) { + sock_set_errno(sock, EINVAL); + } else { + sock_set_errno(sock, err_to_errno(err)); + } + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (addr != NULL) { + union sockaddr_aligned tempaddr; + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + free_socket(nsock, 1); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); + if (*addrlen > tempaddr.sa.sa_len) { + *addrlen = tempaddr.sa.sa_len; + } + MEMCPY(addr, &tempaddr, *addrlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + } else { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); + } + + // [NF_CHANGE] - Signal the CLR that a socket event has occured + // TODO: We may want to investigate other ways to signal + // the CLR (maybe based on which socket received the + // event). + if(nsock->rcvevent > 0 ) { + sys_signal_sock_event(); + } + //[END_NF_CHANGE] + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ip_addr_t local_addr; + u16_t local_port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(namelen); + + SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr)); + IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_bind(sock->conn, &local_addr, local_port); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; + } else { + LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); + } + +#if LWIP_IGMP + /* drop all possibly joined IGMP memberships */ + lwip_socket_drop_registered_memberships(s); +#endif /* LWIP_IGMP */ + + err = netconn_delete(sock->conn); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + free_socket(sock, is_tcp); + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + LWIP_UNUSED_ARG(namelen); + if (name->sa_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ip_addr_t remote_addr; + u16_t remote_port; + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr)); + IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_connect(sock->conn, &remote_addr, remote_port); + } + + if (err == ERR_INPROGRESS) + { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) operation in progress\n", s)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + set_errno(EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { + if (err == ERR_CLSD) { + /* closed but already received data, ensure select gets the FIN, too */ + event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0); + } + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ((len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK) != 0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { +#if !SOCKETS_DEBUG + if (from && fromlen) +#endif /* !SOCKETS_DEBUG */ + { + u16_t port; + ip_addr_t tmpaddr; + ip_addr_t *fromaddr; + union sockaddr_aligned saddr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + fromaddr = &tmpaddr; + netconn_getaddr(sock->conn, fromaddr, &port, 0); + } else { + port = netbuf_fromport((struct netbuf *)buf); + fromaddr = netbuf_fromaddr((struct netbuf *)buf); + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr)); + IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); + ip_addr_debug_print(SOCKETS_DEBUG, fromaddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); +#if SOCKETS_DEBUG + if (from && fromlen) +#endif /* SOCKETS_DEBUG */ + { + if (*fromlen > saddr.sa.sa_len) { + *fromlen = saddr.sa.sa_len; + } + MEMCPY(from, &saddr, *fromlen); + } + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + buf = NULL; + } + } + } while (!done); + + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)written : -1); +} + +int +lwip_sendmsg(int s, const struct msghdr *msg, int flags) +{ + struct lwip_sock *sock; + int i; +#if LWIP_TCP + u8_t write_flags; + size_t written; +#endif + int size = 0; + err_t err = ERR_OK; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + LWIP_UNUSED_ARG(msg->msg_control); + LWIP_UNUSED_ARG(msg->msg_controllen); + LWIP_UNUSED_ARG(msg->msg_flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + + for (i = 0; i < msg->msg_iovlen; i++) { + u8_t apiflags = write_flags; + if (i + 1 < msg->msg_iovlen) { + apiflags |= NETCONN_MORE; + } + written = 0; + err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); + if (err == ERR_OK) { + size += written; + /* check that the entire IO vector was accepected, if not return a partial write */ + if (written != msg->msg_iov[i].iov_len) + break; + } + /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */ + else if (err == ERR_WOULDBLOCK && size > 0) { + err = ERR_OK; + /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */ + break; + } else { + size = -1; + break; + } + } + sock_set_errno(sock, err_to_errno(err)); + return size; +#else /* LWIP_TCP */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + /* else, UDP and RAW NETCONNs */ +#if LWIP_UDP || LWIP_RAW + { + struct netbuf *chain_buf; + + LWIP_UNUSED_ARG(flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || + IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + /* initialize chain buffer with destination */ + chain_buf = netbuf_new(); + if (!chain_buf) { + sock_set_errno(sock, err_to_errno(ERR_MEM)); + return -1; + } + if (msg->msg_name) { + u16_t remote_port; + SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); + netbuf_fromport(chain_buf) = remote_port; + } +#if LWIP_NETIF_TX_SINGLE_PBUF + for (i = 0; i < msg->msg_iovlen; i++) { + size += msg->msg_iov[i].iov_len; + } + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { + err = ERR_MEM; + } else { + /* flatten the IO vectors */ + size_t offset = 0; + for (i = 0; i < msg->msg_iovlen; i++) { + MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); + offset += msg->msg_iov[i].iov_len; + } +#if LWIP_CHECKSUM_ON_COPY + { + /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ + u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); + netbuf_set_chksum(chain_buf, chksum); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain + manually to avoid having to allocate, chain, and delete a netbuf for each iov */ + for (i = 0; i < msg->msg_iovlen; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (p == NULL) { + err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ + break; + } + p->payload = msg->msg_iov[i].iov_base; + LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); + p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; + /* netbuf empty, add new pbuf */ + if (chain_buf->p == NULL) { + chain_buf->p = chain_buf->ptr = p; + /* add pbuf to existing pbuf chain */ + } else { + pbuf_cat(chain_buf->p, p); + } + } + /* save size of total chain */ + if (err == ERR_OK) { + size = netbuf_len(chain_buf); + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr)); + IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, chain_buf); + } + + /* deallocated the buffer */ + netbuf_delete(chain_buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? size : -1); + } +#else /* LWIP_UDP || LWIP_RAW */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_UDP || LWIP_RAW */ +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + u16_t remote_port; + struct netbuf buf; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + (IS_SOCK_ADDR_LEN_VALID(tolen) && + IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(tolen); + + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { + remote_port = 0; + ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); + } + netbuf_fromport(&buf) = remote_port; + + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + MEMCPY(buf.p->payload, data, short_size); + } + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr)); + IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + + LWIP_UNUSED_ARG(domain); /* @todo: check this */ + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), + (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, + ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , + event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +int +lwip_writev(int s, const struct iovec *iov, int iovcnt) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + /* Hack: we have to cast via number to cast from 'const' pointer to non-const. + Blame the opengroup standard for this inconsistency. */ + msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return lwip_sendmsg(s, &msg, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in set of sockets to check for read events + * @param writeset_in set of sockets to check for write events + * @param exceptset_in set of sockets to check for error events + * @param readset_out set of sockets that had read events + * @param writeset_out set of sockets that had write events + * @param exceptset_out set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + /* if this FD is not in the set, continue */ + if (!(readset_in && FD_ISSET(i, readset_in)) && + !(writeset_in && FD_ISSET(i, writeset_in)) && + !(exceptset_in && FD_ISSET(i, exceptset_in))) { + continue; + } + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + void* lastdata = sock->lastdata; + s16_t rcvevent = sock->rcvevent; + u16_t sendevent = sock->sendevent; + u16_t errevent = sock->errevent; + SYS_ARCH_UNPROTECT(lev); + + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } else { + SYS_ARCH_UNPROTECT(lev); + /* continue on to next FD in list */ + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + int i; + int maxfdp2; +#if LWIP_NETCONN_SEM_PER_THREAD + int waited = 0; +#endif + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + maxfdp2 = maxfdp1; + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + } else { + /* Not a valid socket */ + nready = -1; + maxfdp2 = i; + SYS_ARCH_UNPROTECT(lev); + break; + } + SYS_ARCH_UNPROTECT(lev); + } + } + + if (nready >= 0) { + /* Call lwip_selscan again: there could have been events between + the last scan (without us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); +#if LWIP_NETCONN_SEM_PER_THREAD + waited = 1; +#endif + } + } + + /* Decrease select_waiting for each socket we are interested in */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + /* for now, handle select_waiting==0... */ + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + if (sock->select_waiting > 0) { + sock->select_waiting--; + } + } else { + /* Not a valid socket */ + nready = -1; + } + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + +#if LWIP_NETCONN_SEM_PER_THREAD + if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { + /* don't leave the thread-local semaphore signalled */ + sys_arch_sem_wait(select_cb.sem, 1); + } +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_sem_free(&select_cb.sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + if (nready < 0) { + /* This happens when a socket got closed while waiting */ + set_errno(EBADF); + return -1; + } + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + + // [NF_CHANGE] - Signal the CLR that a socket event has occured + // TODO: We may want to investigate other ways to signal + // the CLR (maybe based on which socket received the + // event). + sys_signal_sock_event(); + //[END_NF_CHANGE] + + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + /* remember the state of select_cb_list to detect changes */ + last_select_cb_ctr = select_cb_ctr; + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidating the semaphore. */ + /* CHIBIOS FIX: specific variant of this call to be called from within + a lock.*/ +#if !SYS_LIGHTWEIGHT_PROT + sys_sem_signal(&scb->sem); +#else + #if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_signal_S(scb->sem); + #else + sys_sem_signal_S(&scb->sem); + #endif + +#endif + } + } + /* unlock interrupts with each step */ + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); + + // [NF_CHANGE] - Signal the CLR that a socket event has occurred + // TODO: We may want to investigate other ways to signal + // the CLR (maybe based on which socket received the + // event). + sys_signal_sock_event(); + //[END_NF_CHANGE] +} + +/** + * Close one end of a full-duplex connection. + */ +int +lwip_shutdown(int s, int how) +{ + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + } else { + sock_set_errno(sock, ENOTCONN); + return -1; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if (how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return -1; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + union sockaddr_aligned saddr; + ip_addr_t naddr; + u16_t port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* get the IP address and port */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && + IP_IS_V4_VAL(naddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr)); + IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); + + if (*namelen > saddr.sa.sa_len) { + *namelen = saddr.sa.sa_len; + } + MEMCPY(name, &saddr, *namelen); + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_getsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; +#if !LWIP_MPU_COMPATIBLE + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; +#endif /* !LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* write back optlen and optval */ + *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); +#endif /* LWIP_MPU_COMPATIBLE */ + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_getsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_getsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.p, +#endif /* LWIP_MPU_COMPATIBLE */ + &data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_getsockopt_impl: the actual implementation of getsockopt: + * same argument as lwip_getsockopt, either called directly or through callback + */ +static u8_t +lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + +#if LWIP_TCP + case SO_ACCEPTCONN: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { + return ENOPROTOOPT; + } + if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { + *(int*)optval = 1; + } else { + *(int*)optval = 0; + } + break; +#endif /* LWIP_TCP */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = netconn_type(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); + /* only overwrite ERR_OK or temporary errors */ + if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err); + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + s16_t conn_linger; + struct linger* linger = (struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger); + conn_linger = sock->conn->linger; + if (conn_linger >= 0) { + linger->l_onoff = 1; + linger->l_linger = (int)conn_linger; + } else { + linger->l_onoff = 0; + linger->l_linger = 0; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", + s, *(int *)optval)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); + if (sock->conn->pcb.raw->chksum_reqd == 0) { + *(int *)optval = -1; + } else { + *(int *)optval = sock->conn->pcb.raw->chksum_offset; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", + s, (*(int*)optval)) ); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_setsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); +#else /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; +#endif /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_setsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_setsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.pc, +#endif /* LWIP_MPU_COMPATIBLE */ + data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_setsockopt_impl: the actual implementation of setsockopt: + * same argument as lwip_setsockopt, either called directly or through callback + */ +static u8_t +lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* SO_ACCEPTCONN is get-only */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + if (*(const int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(const int*)optval?"on":"off"))); + break; + + /* SO_TYPE is get-only */ + /* SO_ERROR is get-only */ + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); + netconn_set_recvbufsize(sock->conn, *(const int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + const struct linger* linger = (const struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger); + if (linger->l_onoff) { + int lingersec = linger->l_linger; + if (lingersec < 0) { + return EINVAL; + } + if (lingersec > 0xFFFF) { + lingersec = 0xFFFF; + } + sock->conn->linger = (s16_t)lingersec; + } else { + sock->conn->linger = -1; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + if (*(const int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); + break; + case IP_MULTICAST_IF: + { + ip4_addr_t if_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); + inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval); + udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr); + } + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(const u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#if LWIP_IGMP + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + /* @todo: assign membership to this socket so that it is dropped when closing the socket */ + err_t igmp_err; + const struct ip_mreq *imr = (const struct ip_mreq *)optval; + ip4_addr_t if_addr; + ip4_addr_t multi_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); + inet_addr_to_ip4addr(&if_addr, &imr->imr_interface); + inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr); + if (optname == IP_ADD_MEMBERSHIP) { + if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { + /* cannot track membership (out of memory) */ + err = ENOMEM; + igmp_err = ERR_OK; + } else { + igmp_err = igmp_joingroup(&if_addr, &multi_addr); + } + } else { + igmp_err = igmp_leavegroup(&if_addr, &multi_addr); + lwip_socket_unregister_membership(s, &if_addr, &multi_addr); + } + if (igmp_err != ERR_OK) { + err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + if (*(const int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(const int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (*(const int*)optval) { + netconn_set_ipv6only(sock->conn, 1); + } else { + netconn_set_ipv6only(sock->conn, 0); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", + s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + /* It should not be possible to disable the checksum generation with ICMPv6 + * as per RFC 3542 chapter 3.1 */ + if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { + return EINVAL; + } + + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); + if (*(const int *)optval < 0) { + sock->conn->pcb.raw->chksum_reqd = 0; + } else if (*(const int *)optval & 1) { + /* Per RFC3542, odd offsets are not allowed */ + return EINVAL; + } else { + sock->conn->pcb.raw->chksum_reqd = 1; + sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", + s, sock->conn->pcb.raw->chksum_reqd)); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } +#if LWIP_FIONREAD_LINUXMODE + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + struct pbuf *p; + if (sock->lastdata) { + p = ((struct netbuf *)sock->lastdata)->p; + *((int*)argp) = p->tot_len - sock->lastoffset; + } else { + struct netbuf *rxbuf; + err_t err; + if (sock->rcvevent <= 0) { + *((int*)argp) = 0; + } else { + err = netconn_recv(sock->conn, &rxbuf); + if (err != ERR_OK) { + *((int*)argp) = 0; + } else { + sock->lastdata = rxbuf; + sock->lastoffset = 0; + *((int*)argp) = rxbuf->p->tot_len; + } + } + } + return 0; + } +#endif /* LWIP_FIONREAD_LINUXMODE */ + +#if LWIP_SO_RCVBUF + /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((int*)argp) = recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((int*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#else /* LWIP_SO_RCVBUF */ + break; +#endif /* LWIP_SO_RCVBUF */ +#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + + case (long)FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + break; + } /* switch (cmd) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + sock_set_errno(sock, 0); + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + sock_set_errno(sock, 0); + } else { + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + break; + } + return ret; +} + +#if LWIP_IGMP +/** Register a new IGMP membership. On socket close, the membership is dropped automatically. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + * + * @return 1 on success, 0 on failure + */ +static int +lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return 0; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == NULL) { + socket_ipv4_multicast_memberships[i].sock = sock; + ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); + ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); + return 1; + } + } + return 0; +} + +/** Unregister a previously registered membership. This prevents dropping the membership + * on socket close. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if ((socket_ipv4_multicast_memberships[i].sock == sock) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + return; + } + } +} + +/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. + * + * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_drop_registered_memberships(int s) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == sock) { + ip_addr_t multi_addr, if_addr; + ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); + ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + + netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE); + } + } +} +#endif /* LWIP_IGMP */ + +// get last socket error +// lwIP is clearly missing an API to get the last error from a socket +uint32_t lwip_socket_get_err(int s) +{ + struct lwip_sock *sock = get_socket(s); + return sock->err; +} + +#endif /* LWIP_SOCKET */ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sys_arch.c b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sys_arch.c new file mode 100644 index 00000000..86169cb8 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/LwIP/nf_sys_arch.c @@ -0,0 +1,368 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// from the original source code file +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +// OF SUCH DAMAGE. +// +// This file is part of the lwIP TCP/IP stack. +// +// Author: Adam Dunkels + +// see http://lwip.wikia.com/wiki/Porting_for_an_OS for instructions + +#include +#include + +#include "lwip/opt.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/api.h" + +#include "arch/cc.h" +#include "arch/sys_arch.h" + +osMutexId lwip_sys_mutex; +osMutexDef(lwip_sys_mutex); + +void sys_init(void) +{ + lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex)); +} + +// Creates a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + osSemaphoreDef(SEM); + + *sem = osSemaphoreCreate (osSemaphore(SEM), 1); + + if(*sem == NULL) + { + #if SYS_STATS + ++lwip_stats.sys.sem.err; + #endif /* SYS_STATS */ + return ERR_MEM; + } + + if(count == 0) // Means it can't be taken + { + osSemaphoreWait(*sem,0); + } + + #if SYS_STATS + ++lwip_stats.sys.sem.used; + + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) + { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } + #endif /* SYS_STATS */ + + return ERR_OK; +} + +// Deallocates a semaphore +void sys_sem_free(sys_sem_t *sem) +{ + #if SYS_STATS + --lwip_stats.sys.sem.used; + #endif /* SYS_STATS */ + + osSemaphoreDelete(*sem); +} + +// Signals a semaphore +void sys_sem_signal(sys_sem_t *sem) +{ + osSemaphoreRelease(*sem); +} + +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + uint32_t starttime = osKernelSysTick(); + + if(timeout != 0) + { + if(osSemaphoreWait (*sem, timeout) == osOK) + { + return (osKernelSysTick() - starttime); + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else + { + while(osSemaphoreWait (*sem, osWaitForever) != osOK); + return (osKernelSysTick() - starttime); + } +} + +int sys_sem_valid(sys_sem_t *sem) +{ + if (*sem == SYS_SEM_NULL) + return 0; + else + return 1; +} + +void sys_sem_set_invalid(sys_sem_t *sem) +{ + *sem = SYS_SEM_NULL; +} + +// Creates an empty mailbox. +///////////////////////////////////////////////////////// +// NEEDS strong implementation at platform level +///////////////////////////////////////////////////////// +__nfweak err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + (void)mbox; + (void)size; + + // breaks execution to ensure developer is aware that this function needs a strong implementation at platform level + __asm volatile("BKPT #0\n"); + + return ERR_OK; +} + +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +///////////////////////////////////////////////////////// +// NEEDS strong implementation at platform level +///////////////////////////////////////////////////////// +__nfweak void sys_mbox_free(sys_mbox_t *mbox) +{ + (void)mbox; + + // breaks execution to ensure developer is aware that this function needs a strong implementation at platform level + __asm volatile("BKPT #0\n"); +} + +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t *mbox, void *data) +{ + while(osMessagePut(*mbox, (uint32_t)data, osWaitForever) != osOK); +} + +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + err_t result; + + if ( osMessagePut(*mbox, (uint32_t)msg, 0) == osOK) + { + result = ERR_OK; + } + else + { + // could not post, queue must be full + result = ERR_MEM; + + #if SYS_STATS + lwip_stats.sys.mbox.err++; + #endif /* SYS_STATS */ + + } + + return result; +} + +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ + osEvent event; + uint32_t starttime = osKernelSysTick();; + + if(timeout != 0) + { + event = osMessageGet (*mbox, timeout); + + if(event.status == osEventMessage) + { + *msg = (void *)event.value.v; + return (osKernelSysTick() - starttime); + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else + { + event = osMessageGet (*mbox, osWaitForever); + *msg = (void *)event.value.v; + return (osKernelSysTick() - starttime); + } +} + +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ + osEvent event; + + event = osMessageGet (*mbox, 0); + + if(event.status == osEventMessage) + { + *msg = (void *)event.value.v; + return ERR_OK; + } + else + { + return SYS_MBOX_EMPTY; + } +} + +int sys_mbox_valid(sys_mbox_t *mbox) +{ + if (*mbox == SYS_MBOX_NULL) + { + return 0; + } + else + { + return 1; + } +} + +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ + *mbox = SYS_MBOX_NULL; +} + +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) +{ + const osThreadDef_t os_thread_def = { (os_pthread)thread, (osPriority)prio, stacksize, (char *)name }; + sys_thread_t newThread = osThreadCreate(&os_thread_def, arg); + + netconn_thread_init(); + + return newThread; +} + +sys_prot_t sys_arch_protect(void) +{ + osMutexWait(lwip_sys_mutex, osWaitForever); + return (sys_prot_t)1; +} + +void sys_arch_unprotect(sys_prot_t pval) +{ + (void) pval; + osMutexRelease(lwip_sys_mutex); +} + +#if LWIP_NETCONN_SEM_PER_THREAD + +///////////////////////////////////////////////////////// +// NEEDS to be implementated at platform level +// CMSIS RTOS API doesn't have a decent API to tackle +///////////////////////////////////////////////////////// + +// sys_sem_t* sys_arch_netconn_sem_get(void) +// { +// return 0; +// } + +// void sys_arch_netconn_sem_alloc(void) +// { +// } + +// void sys_arch_netconn_sem_free(void) +// { +// } + +#endif // LWIP_NETCONN_SEM_PER_THREAD + + +//////////////////////////////////////////////////// +// nanoFramework "hack" extending LwIP original code +// with this callback here we don't need any reference to CLR nor need to include any nanoFramework headers here +void (*signal_sock_functionPtr)() = 0; + +void set_signal_sock_function( void (*funcPtr)() ) +{ + signal_sock_functionPtr = funcPtr; +} + +void sys_signal_sock_event() +{ + if ( signal_sock_functionPtr != 0 ) + signal_sock_functionPtr(); +} + +//////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// NEEDS strong implementation at platform level +///////////////////////////////////////////////////////// +__nfweak u32_t sys_now(void) +{ + + // breaks execution to ensure developer is aware that this function needs a strong implementation at platform level + __asm volatile("BKPT #0\n"); + + return 0; +} diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/common/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/common/CMakeLists.txt new file mode 100644 index 00000000..b0df1bf2 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/common/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append target CMSIS-OS common source files + +# if SWO opting add source file +if(SWO_OUTPUT_OPTION) + list(APPEND TARGET_CMSIS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/swo.cpp") +endif() + +list(APPEND TARGET_CMSIS_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/syscalls.c") + +# make var global +set(TARGET_CMSIS_COMMON_SOURCES ${TARGET_CMSIS_COMMON_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/common/Include/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/common/Include/CMakeLists.txt new file mode 100644 index 00000000..c6747eaa --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/common/Include/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/swo.h.in" +"${CMAKE_CURRENT_BINARY_DIR}/swo.h" @ONLY) + +# append include directory for target CMSIS, need this to be the binary dir because the header is a config file +list(APPEND TARGET_CMSIS_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) + +# make var global +set(TARGET_CMSIS_COMMON_INCLUDE_DIRS ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/common/Include/swo.h.in b/source/native/nf-interpreter/targets/CMSIS-OS/common/Include/swo.h.in new file mode 100644 index 00000000..5629a8d3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/common/Include/swo.h.in @@ -0,0 +1,35 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef SWO_H_ +#define SWO_H_ + + +#define SWO_OUTPUT @SWO_OUTPUT_OPTION@ + + +#if (SWO_OUTPUT == TRUE) + +#ifdef __cplusplus +extern "C" { +#endif + + void SwoInit(); + void SwoPrintChar(char c); + void SwoPrintString(const char *s); + +#ifdef __cplusplus +} +#endif + +#endif //(SWO_OUTPUT == TRUE) + + +#endif // SWO_H_ diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/common/swo.cpp b/source/native/nf-interpreter/targets/CMSIS-OS/common/swo.cpp new file mode 100644 index 00000000..b0b62004 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/common/swo.cpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +#include "nanoCLR_Types.h" + +#if (__CORTEX_M == 0) + #error "ITM port is not available on Cortex-M0(+) cores. Need to set CMake option SWO_OUTPUT to OFF." +#else + +extern "C" void SwoInit() +{ + // set SWO pin (PB3) to alternate mode (0 == the status after RESET) + // in case it's being set to a different function in board config + palSetPadMode(GPIOB, 0x03, PAL_MODE_ALTERNATE(0) ); + + // enable trace in core debug register + CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk; + + // enable trace pins with async trace + DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN | ~DBGMCU_CR_TRACE_MODE; + + // default speed for ST-Link is 2000kHz + uint32_t swoSpeed = 2000000; + uint32_t swoPrescaler = (STM32_SYSCLK / swoSpeed) + 1; + + // Write the TPIU Current Port Size Register to the desired value (default is 0x1 for a 1-bit port size) + TPI->CSPSR = 1; + // Write TPIU Formatter and Flush Control Register + TPI->FFCR = 0x100; + // Write the TPIU Select Pin Protocol to select the sync or async mode. Example: 0x2 for async NRZ mode (UART like) + TPI->SPPR = 2; + + // Write clock prescaler + TPI->ACPR = swoPrescaler; + + // unlock Write Access to the ITM registers + ITM->LAR = 0xC5ACCE55; + + // core debug: + // Trace bus ID for TPIU + // enable events + // enable sync packets + // time stamp enable + // trace main enable + ITM->TCR = ITM_TCR_TraceBusID_Msk | ITM_TCR_SWOENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_ITMENA_Msk; /* ITM Trace Control Register */ + + // enable stimulus port 0 + // we are not using any other port right now + ITM->TER |= 1; + ITM->TPR = ITM_TPR_PRIVMASK_Msk; +} + +extern "C" void SwoPrintChar(char c) +{ + ITM_SendChar(c); +} + +extern "C" void SwoPrintString(const char *s) +{ + // print char until terminator is found + while(*s) + { + SwoPrintChar(*s++); + } +} + +// this function is heavily based in the CMSIS ITM_SendChar +// but with small performance improvements as we are sending a string not individual chars +__STATIC_INLINE uint32_t GenericPort_Write_CMSIS(int portNum, const char* data, size_t size) +{ + (void)portNum; + + char* p = (char*)data; + uint32_t counter = 0; + + // check if ITM port is enabled before start sending + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while(*p != '\0' || counter < size) + { + // wait until TX buffer is available + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + + ITM->PORT[0U].u8 = (uint8_t)*p++; + + counter++; + } + } + + return counter; +} + +uint32_t GenericPort_Write(int portNum, const char* data, size_t size) +{ + return GenericPort_Write_CMSIS(portNum, data, size); +} + +#endif // (__CORTEX_M == 0) diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/common/syscalls.c b/source/native/nf-interpreter/targets/CMSIS-OS/common/syscalls.c new file mode 100644 index 00000000..d53b7517 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/common/syscalls.c @@ -0,0 +1,64 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// these are stubs to keep the linker happy when these are pulled in + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * _gettimeofday primitive (Stub function) + * */ + +/* + * Structure used in select() call, taken from the BSD file sys/time.h. + */ +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int _gettimeofday (struct timeval * tp, struct timezone * tzp) +{ + (void)tp; + + /* Return fixed data for the timezone. */ + if (tzp) + { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + + return 0; +} + +extern void _exit(int status) +{ + (void)status; + + for (;;); +} + +extern void _kill(int pid, int sig) +{ + (void) pid; + (void) sig; + return; +} + +extern int _getpid(void) +{ + return -1; +} + +#ifdef __cplusplus +} +#endif diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/nanoBooter/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/nanoBooter/CMakeLists.txt new file mode 100644 index 00000000..0753c7f3 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/nanoBooter/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append target CMSIS-OS nanoBooter source files +# list(APPEND TARGET_CMSIS_NANOBOOTER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_ReceiverThread.c") + +# PAL source files +list(APPEND TARGET_CMSIS_NANOBOOTER_SOURCES "${PROJECT_SOURCE_DIR}/src/PAL/BlockStorage/nanoPAL_BlockStorage.c") + +# make var global +set(TARGET_CMSIS_NANOBOOTER_SOURCES ${TARGET_CMSIS_NANOBOOTER_SOURCES} CACHE INTERNAL "make global") + +# appendtarget CMSIS-OS nanoBooter include directory +list(APPEND TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") +# make var global +set(TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/CMSIS-OS/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/CMSIS-OS/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..4bbd6432 --- /dev/null +++ b/source/native/nf-interpreter/targets/CMSIS-OS/nanoCLR/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append target CMSIS-OS nanoCLR source files +# list(APPEND TARGET_CMSIS_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR_dat.s) + +# make var global +set(TARGET_CMSIS_NANOCLR_SOURCES ${TARGET_CMSIS_NANOCLR_SOURCES} CACHE INTERNAL "make global") + + +# append target CMSIS-OS nanoCLR include directory +list(APPEND TARGET_CMSIS_NANOCLR_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") +# make var global +set(TARGET_CMSIS_NANOCLR_INCLUDE_DIRS ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/CMakeLists.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/CMakeLists.txt new file mode 100644 index 00000000..ca780615 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/CMakeLists.txt @@ -0,0 +1,107 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# if mbed TLS is enabled add it to the build +if(USE_SECURITY_MBEDTLS_OPTION) + + # check if MBEDTLS_SOURCE was specified or if it's empty (default is empty) + set(NO_MBEDTLS_SOURCE TRUE) + + if(MBEDTLS_SOURCE) + if(NOT "${MBEDTLS_SOURCE}" STREQUAL "") + set(NO_MBEDTLS_SOURCE FALSE) + endif() + endif() + + # set options for mbed TLS + option(ENABLE_TESTING "no testing when building mbed TLS." OFF) + + if(NO_MBEDTLS_SOURCE) + # no mbed TLS source specified, download it from it's repo + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + # set tag for currently supported version + set(MBEDTLS_GIT_TAG "mbedtls-2.16.3") + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/mbedTLS.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/mbedTLS_Download/CMakeLists.txt") + + # setup CMake project for mbedTLS download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/mbedTLS_Download") + + # run build on mbedTLS download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/mbedTLS_Download") + + # add mbedTLS as external project + ExternalProject_Add( + mbedTLS + PREFIX mbedTLS + SOURCE_DIR ${CMAKE_BINARY_DIR}/mbedTLS_Source + GIT_REPOSITORY https://github.com/nanoframework/mbedtls + GIT_TAG ${MBEDTLS_GIT_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + else() + # mbedTLS source was specified + + # sanity check is source path exists + if(EXISTS "${MBEDTLS_SOURCE}/") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/mbedTLS_Source") + message(STATUS "mbedTLS source from: ${MBEDTLS_SOURCE}") + file(COPY "${MBEDTLS_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/mbedTLS_Source") + else() + message(STATUS "Using local cache of mbedTLS source from ${MBEDTLS_SOURCE}") + endif() + + set(MBEDTLS_INCLUDE_DIR ${CMAKE_BINARY_DIR}/mbedTLS_Source/include) + else() + message(FATAL_ERROR "Couldn't find mbedTLS source at ${MBEDTLS_SOURCE}/") + endif() + + # add mbedTLS as external project + ExternalProject_Add( + mbedTLS + PREFIX mbedTLS + SOURCE_DIR ${CMAKE_BINARY_DIR}/mbedTLS_Source + + # Disable all other steps + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + endif() + + # get source dir for mbedTLS CMake project + ExternalProject_Get_Property(mbedTLS SOURCE_DIR) + + set(mbedTLS_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/3rdparty/humblelogging/include") + set(mbedTLS_LIBRARIES "${CMAKE_SHARED_LIBRARY_PREFIX}mbedTLS${CMAKE_SHARED_LIBRARY_SUFFIX}") + include_directories(${mbedTLS_INCLUDE_DIRS}) + +endif() diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CMakeLists.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CMakeLists.txt new file mode 100644 index 00000000..85b526f2 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CMakeLists.txt @@ -0,0 +1,301 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +ENABLE_LANGUAGE(ASM) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +configure_file("${CMAKE_SOURCE_DIR}/CMake/ESP32_target_os.h.in" + "${CMAKE_BINARY_DIR}/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_os.h" @ONLY) + +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: Networking Stack, LWIP included in IDF libs +if(USE_NETWORKING_OPTION) + find_package(NF_NETWORKING REQUIRED) +endif() + +# RTC (real time clock) (default is OFF so RTC is NOT included) +option(NF_FEATURE_RTC "option to use hardware RTC") +if(NF_FEATURE_RTC) + set(HAL_USE_RTC_OPTION TRUE CACHE INTERNAL "NF feature RTC") +else() + set(HAL_USE_RTC_OPTION FALSE CACHE INTERNAL "NF feature RTC") +endif() + +# security provider is mbedTLS +if(USE_SECURITY_MBEDTLS_OPTION) + find_package(mbedTLS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("Lwip") # lwip must be before IDF +add_subdirectory("IDF") +add_subdirectory("Network") +add_subdirectory("nanoCLR") + +# mbed TLS requires a config file +if(USE_SECURITY_MBEDTLS_OPTION) + # this seems to be only option to properly set a compiler define through the command line that needs to be a string literal + file(TO_CMAKE_PATH "${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl/mbedTLS/nf_mbedtls_config.h" MBED_CONFILE) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${MBED_CONFILE}>\"") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBEDTLS_CONFIG_FILE=\"<${MBED_CONFILE}>\"") +endif() + +# Build the networking components as a separate library +# This is done this way to stop "Createprocess: file no found" errors in linker when object input file is greater than 32k +if(USE_NETWORKING_OPTION) + add_library(NetworkLib STATIC ${NF_Networking_SOURCES} ${TARGET_ESP32_NETWORK_SOURCES} ${TARGET_LWIP_SOURCES} ${mbedTLS_SOURCES} ) +endif() + +# add dependency for security provider mbedTLS +if(USE_SECURITY_MBEDTLS_OPTION) + add_dependencies(NetworkLib mbedTLS) +endif() + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + ${COMMON_PROJECT_SOURCES} + ${TARGET_ESP32_COMMON_SOURCES} + + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_ESP32_NANOCLR_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# Add link flags +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--start-group ") + +if(USE_SECURITY_MBEDTLS_OPTION) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf NetworkLib) +endif() + +#message( "project libs:${PROJECT_LINK_LIBS} " ) +set(LIBPATHSAVE "") +foreach( IDF_libraries ${PROJECT_LINK_LIBS} ) + + get_filename_component( LIBNAME ${IDF_libraries} NAME_WE ) + get_filename_component( LIBPATH ${IDF_libraries} DIRECTORY ) + + string( SUBSTRING ${LIBNAME} 3 -1 LIBSHORT ) + + if( NOT "${LIBPATHSAVE}" STREQUAL ${LIBPATH} ) + set(LIBPATHSAVE ${LIBPATH}) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -L${LIBPATH} " ) + endif() + + # Add psram workarounds for newlib + if( "${LIBSHORT}" STREQUAL "newlib" ) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " ${ESP32_IDF_PATH}/components/newlib/lib/libc-psram-workaround.a " ) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " ${ESP32_IDF_PATH}/components/newlib/lib/libm-psram-workaround.a " ) + endif() + + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -l${LIBSHORT} " ) + + if( "${LIBSHORT}" STREQUAL "app_update" ) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -u esp_app_desc " ) + endif() + + if( "${LIBSHORT}" STREQUAL "bt" ) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -L${ESP32_IDF_PATH}/components/bt/lib -lbtdm_app " ) + endif() + + # Add options into LINK_FLAGS in same position as IDF link + if( "${LIBSHORT}" STREQUAL "cxx" ) + # Cxx Library needs an undefine + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -u __cxa_guard_dummy -u __cxx_fatal_exception " ) + endif() + + if( "${LIBSHORT}" STREQUAL "esp32" ) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " ${ESP32_IDF_PATH}/components/esp32/libhal.a " ) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -L ${ESP32_IDF_PATH}/components/esp32/lib -lcore -lrtc -lnet80211 -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 -lespnow -lphy -lmesh") + + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -L ${CMAKE_CURRENT_SOURCE_DIR} -T esp32_out.ld ") + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -L ${ESP32_IDF_PATH}/components/esp32/ld -u ld_include_panic_highint_hdl -T esp32.project.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.libgcc.ld ") + endif() + + + if( "${LIBSHORT}" STREQUAL "freertos" ) + # Cxx Library needs an undefine + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--undefined=uxTopUsedPriority " ) + endif() + +endforeach( IDF_libraries ) + + +if(USE_NETWORKING_OPTION) + set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -L${CMAKE_CURRENT_BINARY_DIR} -lNetworkLib " ) +endif() + +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -lgcc -lstdc++ -lgcov -Wl,--end-group -Wl,-EL ") + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/CLR/Debugger + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + ${PROJECT_SOURCE_DIR}/src/CLR/Runtime.Native + + ${PROJECT_SOURCE_DIR}/src/PAL/COM/sockets/ssl + + ${WireProtocol_INCLUDE_DIRS} + + ${TARGET_ESP32_IDF_INCLUDES} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Networking_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} +) + +# Set Includes & compile definition for Network library +if(USE_NETWORKING_OPTION) + target_include_directories(NetworkLib PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Networking_INCLUDE_DIRS} + ${mbedTLS_INCLUDE_DIRS} + ) + + target_compile_definitions(NetworkLib PUBLIC "-DPLATFORM_ESP32 " ) + set (EXTRA_LIBS ${EXTRA_LIBS} NetworkLib) + target_link_libraries(${NANOCLR_PROJECT_NAME}.elf ${EXTRA_LIBS}) + SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) + + # Inhibit warnings so we can compile 3rd party code (Lwip) + set_target_properties(NetworkLib PROPERTIES COMPILE_FLAGS " -w " ) +endif() + +# set platform for NanoClr +target_compile_definitions(${NANOCLR_PROJECT_NAME}.elf PUBLIC "-DPLATFORM_ESP32 " ) + +# build types that have debugging capabilities AND are NOT RTM have to have the define 'NANOCLR_ENABLE_SOURCELEVELDEBUGGING' +if((NOT NF_BUILD_RTM) OR NF_FEATURE_DEBUGGER) + target_compile_definitions(${NANOCLR_PROJECT_NAME}.elf PUBLIC "-DNANOCLR_ENABLE_SOURCELEVELDEBUGGING ") +endif() + +# set compiler definition for using Application Domains feature +if(NF_FEATURE_USE_APPDOMAINS) + target_compile_definitions(${NANOCLR_PROJECT_NAME}.elf PUBLIC -DNANOCLR_USE_APPDOMAINS) +endif() + +# set compiler definition for implementing (or not) CRC32 in Wire Protocol +if(NF_WP_IMPLEMENTS_CRC32) + target_compile_definitions(${NANOCLR_PROJECT_NAME}.elf PUBLIC -DWP_IMPLEMENTS_CRC32) +endif() + +# set compiler definition regarding inclusion of trace messages and checks on CLR +if(NF_PLATFORM_NO_CLR_TRACE) + target_compile_definitions(${TARGET} PUBLIC -DPLATFORM_NO_CLR_TRACE=1) +endif() + +# set compiler definition regarding CLR IL inlining +if(NF_CLR_NO_IL_INLINE) + target_compile_definitions(${TARGET} PUBLIC -DNANOCLR_NO_IL_INLINE=1) +endif() + +# set extra linker flags for DEBUG +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS_DEBUG "") + +# set extra linker flags for RELEASE +#set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " -flto ") + +# add linker flags set with traditional CMAKE_EXE_LINKER_FLAGS +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + +# add linker flags to generate map file +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-Map=${PROJECT_BINARY_DIR}/${NANOCLR_PROJECT_NAME}.map") +# Verbose linking, uncomment to enable +#set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--verbose ") + +# add dependency for networking +if(USE_SECURITY_MBEDTLS_OPTION) + add_dependencies(${NANOCLR_PROJECT_NAME}.elf NetworkLib) +endif() + +# Create bin file from elf +set(GEN_ESP32_BIN_PATH ${EXECUTABLE_OUTPUT_PATH} ) +set(NANOCLR_BIN_FILE ${GEN_ESP32_BIN_PATH}/${NANOCLR_PROJECT_NAME}.bin) +set(ESPTOOL_PY_FILE ${ESP32_IDF_PATH}/components/esptool_py/esptool/esptool.py ) +set(ESPTOOL_PY_FLAGS "--chip esp32 elf2image --flash_mode \"dio\" --flash_freq \"40m\" --flash_size \"4MB\" " ) +set(GEN_ESP32PART_PY_FILE ${ESP32_IDF_PATH}/components/partition_table/gen_esp32part.py ) + +add_custom_command( TARGET ${NANOCLR_PROJECT_NAME}.elf POST_BUILD + COMMAND ${ESPTOOL_PY_FILE} ${ESPTOOL_PY_FLAGS} -o ${NANOCLR_BIN_FILE} ${EXECUTABLE_OUTPUT_PATH}/${NANOCLR_PROJECT_NAME}.elf + COMMENT "Generate nanoClr BIN file for deployment" ) + +# # Create partition table +add_custom_command( TARGET ${NANOCLR_PROJECT_NAME}.elf POST_BUILD + COMMAND ${GEN_ESP32PART_PY_FILE} --verify ${PROJECT_SOURCE_DIR}/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_16mb.csv ${GEN_ESP32_BIN_PATH}/partitions_16mb.bin + COMMAND ${GEN_ESP32PART_PY_FILE} --verify ${PROJECT_SOURCE_DIR}/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_8mb.csv ${GEN_ESP32_BIN_PATH}/partitions_8mb.bin + COMMAND ${GEN_ESP32PART_PY_FILE} --verify ${PROJECT_SOURCE_DIR}/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_4mb.csv ${GEN_ESP32_BIN_PATH}/partitions_4mb.bin + COMMAND ${GEN_ESP32PART_PY_FILE} --verify ${PROJECT_SOURCE_DIR}/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_2mb.csv ${GEN_ESP32_BIN_PATH}/partitions_2mb.bin + COMMENT "Generate Esp32 Partition tables for 2MB, 4MB, 8MB and 16MB flash" ) + +# list partition table +add_custom_command( TARGET ${NANOCLR_PROJECT_NAME}.elf POST_BUILD + COMMAND ${GEN_ESP32PART_PY_FILE} ${GEN_ESP32_BIN_PATH}/partitions_4mb.bin + COMMENT "List flash 4Mb Esp32 Partition tables" ) + +#message("CMAKE_CXX_FLAGS:${CMAKE_CXX_FLAGS}" ) +#message("CMAKE_EXE_LINKER_FLAGS:${CMAKE_EXE_LINKER_FLAGS}" ) +#message("CMAKE_EXE_LINKER_FLAGS_DEBUG:${CMAKE_EXE_LINKER_FLAGS_DEBUG}" ) +#message("CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT:${CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT}" ) +#message("CMAKE_CXX_LINK_EXECUTABLE:${CMAKE_CXX_LINK_EXECUTABLE}" ) +#message("CMAKE_C_LINK_EXECUTABLE:${CMAKE_C_LINK_EXECUTABLE}" ) +#message("FLAGS:${FLAGS}" ) diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CopyLibs.cmd b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CopyLibs.cmd new file mode 100644 index 00000000..c262f6e3 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/CopyLibs.cmd @@ -0,0 +1,89 @@ +echo off + +SET idfVer=3.3 +SET targetDir=c:\Esp32_tools\libs-v%idfVer% + +echo Copy IDF libraries to %targetDir% + +rmdir /S /Q %targetDir% +mkdir %targetDir% + + +copy /Y build\bootloader\bootloader.bin %targetDir% + +copy /Y build\app_trace\libapp_trace.a %targetDir% +copy /Y build\app_update\libapp_update.a %targetDir% +copy /Y build\asio\libasio.a %targetDir% +copy /Y build\aws_iot\libaws_iot.a %targetDir% +copy /Y build\bootloader\bootloader_support\libbootloader_support.a %targetDir% + +copy /Y build\bt\libbt.a %targetDir% + +copy /Y build\coap\libcoap.a %targetDir% +copy /Y build\console\libconsole.a %targetDir% + +copy /Y build\cxx\libcxx.a %targetDir% +copy /Y build\driver\libdriver.a %targetDir% +copy /Y build\efuse\libefuse.a %targetDir% +copy /Y build\esp-tls\libesp-tls.a %targetDir% +copy /Y build\esp32\libesp32.a %targetDir% + +copy /Y build\esp_adc_cal\libesp_adc_cal.a %targetDir% +copy /Y build\esp_event\libesp_event.a %targetDir% + +copy /Y build\esp_http_client\libesp_http_client.a %targetDir% +copy /Y build\esp_http_server\libesp_http_server.a %targetDir% + +copy /Y build\esp_https_ota\libesp_https_ota.a %targetDir% +copy /Y build\esp_https_server\libesp_https_server.a %targetDir% +copy /Y build\esp_ringbuf\libesp_ringbuf.a %targetDir% +copy /Y build\espcoredump\libespcoredump.a %targetDir% +copy /Y build\ethernet\libethernet.a %targetDir% +copy /Y build\expat\libexpat.a %targetDir% +copy /Y build\fatfs\libfatfs.a %targetDir% +copy /Y build\freemodbus\libfreemodbus.a %targetDir% +copy /Y build\freertos\libfreertos.a %targetDir% +copy /Y build\heap\libheap.a %targetDir% +copy /Y build\idf_test\libidf_test.a %targetDir% +copy /Y build\jsmn\libjsmn.a %targetDir% +copy /Y build\json\libjson.a %targetDir% +copy /Y build\libsodium\liblibsodium.a %targetDir% +copy /Y build\log\liblog.a %targetDir% + +copy /Y build\main\libmain.a %targetDir% +copy /Y build\lwip\liblwip.a %targetDir% +copy /Y build\mbedtls\libmbedtls.a %targetDir% +copy /Y build\mdns\libmdns.a %targetDir% +copy /Y build\micro-ecc\libmicro-ecc.a %targetDir% +copy /Y build\mqtt\libmqtt.a %targetDir% + +copy /Y build\newlib\libnewlib.a %targetDir% + +copy /Y build\nghttp\libnghttp.a %targetDir% +copy /Y build\nvs_flash\libnvs_flash.a %targetDir% +copy /Y build\openssl\libopenssl.a %targetDir% + +copy /Y build\protobuf-c\libprotobuf-c.a %targetDir% +copy /Y build\protocomm\libprotocomm.a %targetDir% +copy /Y build\pthread\libpthread.a %targetDir% +copy /Y build\sdmmc\libsdmmc.a %targetDir% +copy /Y build\smartconfig_ack\libsmartconfig_ack.a %targetDir% +copy /Y build\soc\libsoc.a %targetDir% +copy /Y build\spi_flash\libspi_flash.a %targetDir% +copy /Y build\spiffs\libspiffs.a %targetDir% + +copy /Y build\tcp_transport\libtcp_transport.a %targetDir% +copy /Y build\tcpip_adapter\libtcpip_adapter.a %targetDir% +copy /Y build\ulp\libulp.a %targetDir% +copy /Y build\unity\libunity.a %targetDir% +copy /Y build\vfs\libvfs.a %targetDir% +copy /Y build\wear_levelling\libwear_levelling.a %targetDir% +copy /Y build\wifi_provisioning\libwifi_provisioning.a %targetDir% +copy /Y build\wpa_supplicant\libwpa_supplicant.a %targetDir% +copy /Y build\xtensa-debug-module\libxtensa-debug-module.a %targetDir% + + + + + + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/CMakeLists.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/CMakeLists.txt new file mode 100644 index 00000000..957e1e68 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/CMakeLists.txt @@ -0,0 +1,380 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + + +list(APPEND COMPONENT_PATH "${ESP32_IDF_PATH}/components") +#append ESP32 IDF include paths + +list(APPEND IDF_SDKCONFIG "${ESP32_IDF_PATH}/examples/get-started/blink/build/include") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/tcpip_adapter/include") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/lwip/lwip/src/include/lwip") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/lwip/include/lwip/port") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/lwip/lwip/src") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/lwip/lwip/src/include/posix") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/lwip/include/apps") + + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/newlib/platform_include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/driver/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/driver/include/driver") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/esp32/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/esp32/include/rom") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/esp_event/include") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/spi_flash/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/nvs_flash/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/Log/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/Ethernet/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/wpa_supplicant/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/wpa_supplicant/port/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/freertos/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/freertos/include/freertos") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/soc/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/soc/esp32/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/heap/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/app_trace/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/bt/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/wear_levelling/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/esp_ringbuf/include") + +# list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/mbedtls/port/include" "${COMPONENT_PATH}/mbedtls/mbedtls/include" ) + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/nghttp/port/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/nghttp/nghttp2/lib/includes") + +# list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/openssl/include") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/app_update/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/vfs/include") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/micro-ecc/micro-ecc") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/xtensa-debug-module/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/ulp/include") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/ulp/include") + +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/spiffs/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/fatfs/src") + +#sdkconfig reference +list(APPEND TARGET_ESP32_IDF_INCLUDES "${ESP32_IDF_PATH}/examples/get-started/blink/build/include") + + +list( APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/bootloader_support/include" ) +list( APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/bootloader_support/include" ) + +set( IDF_EXAMPLE_BASE "${ESP32_IDF_PATH}/examples/get-started/blink/build" CACHE INTERNAL "make global") +set( IDF_NANOFRAMEWORK_BASE "${ESP32_IDF_PATH}/examples/get-started/blink/build" CACHE INTERNAL "make global") + +# library paths for Example project +set( PROJECT_LINK_LIBS "" ) + +# find_library( LIB_APPTRACE_PATH +# NAMES libapp_trace.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/app_trace" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_APPTRACE_PATH}) + +# find_library( LIB_APPUPDATE_PATH +# NAMES libapp_update.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/app_update" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_APPUPDATE_PATH}) + +# find_library( LIB_AWS_IOT_PATH +# NAMES libaws_iot.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/aws_iot" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_AWS_IOT_PATH}) + +# find_library( LIB_BOOTLOADER_SUPPORT_PATH +# NAMES libbootloader_support.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/bootloader_support" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_BOOTLOADER_SUPPORT_PATH}) + +# find_library( LIB_BT_PATH +# NAMES libbt.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/bt" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_BT_PATH}) + +# find_library( LIB_COAP_PATH +# NAMES libcoap.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/coap" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_COAP_PATH}) + +# find_library( LIB_CONSOLE_PATH +# NAMES libconsole.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/console" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_CONSOLE_PATH}) + +# find_library( LIB_CXX_PATH +# NAMES libcxx.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/cxx" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_CXX_PATH}) + +# find_library( LIB_DRIVER_PATH +# NAMES libdriver.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/driver" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_DRIVER_PATH}) + +# find_library( LIB_ESP32_PATH +# NAMES libesp32.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/esp32" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_ESP32_PATH}) + +# find_library( LIB_ETHERNET_PATH +# NAMES libethernet.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/ethernet" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_ETHERNET_PATH}) + +# find_library( LIB_EXPAT_PATH +# NAMES libexpat.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/expat" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_EXPAT_PATH}) + +# find_library( LIB_FATFS_PATH +# NAMES libfatfs.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/fatfs" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_FATFS_PATH}) + +# find_library( LIB_FREERTOS_PATH +# NAMES libfreertos.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/freertos" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_FREERTOS_PATH}) + +# find_library( LIB_HEAP_PATH +# NAMES libheap.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/heap" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_HEAP_PATH}) + +# find_library( LIB_JSMN_PATH +# NAMES libjsmn.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/jsmn" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_JSMN_PATH}) + +# find_library( LIB_JSON_PATH +# NAMES libjson.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/json" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_JSON_PATH}) + +# find_library( LIB_SODIUM_PATH +# NAMES liblibsodium.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/libsodium" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_SODIUM_PATH}) + +# find_library( LIB_LOG_PATH +# NAMES liblog.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/log" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_LOG_PATH}) + +# find_library( LIB_LWIP_PATH +# NAMES liblwip.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/lwip" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_LWIP_PATH}) + +# find_library( LIB_MBEDTLS_PATH +# NAMES libmbedtls.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/mbedtls" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_MBEDTLS_PATH}) + +# find_library( LIB_MDNS_PATH +# NAMES libmdns.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/mdns" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_MDNS_PATH}) + +# find_library( LIB_MICROECC_PATH +# NAMES libmicro-ecc.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/micro-ecc" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_MICROECC_PATH}) + +# find_library( LIB_NEWLIB_PATH +# NAMES libnewlib.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/newlib" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_NEWLIB_PATH}) + +# find_library( LIB_NGHTTP_PATH +# NAMES libnghttp.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/nghttp" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_NGHTTP_PATH}) + +# find_library( LIB_NVSFLASH_PATH +# NAMES libnvs_flash.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/nvs_flash" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_NVSFLASH_PATH}) + +# find_library( LIB_OPENSSL_PATH +# NAMES libopenssl.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/openssl" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_OPENSSL_PATH}) + +# find_library( LIB_SDMMC_PATH +# NAMES libsdmmc.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/sdmmc" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_SDMMC_PATH}) + +# find_library( LIB_SOC_PATH +# NAMES libsoc.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/soc" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_SOC_PATH}) + +# find_library( LIB_SPIFLASH_PATH +# NAMES libspi_flash.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/spi_flash" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_SPIFLASH_PATH}) + +# find_library( LIB_TCPIPADAPTER_PATH +# NAMES libtcpip_adapter.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/tcpip_adapter" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_TCPIPADAPTER_PATH}) + +# find_library( LIB_ULP_PATH +# NAMES libulp.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/ulp" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_ULP_PATH}) + +# find_library( LIB_VFS_PATH +# NAMES libvfs.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/vfs" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_VFS_PATH}) + +# find_library( LIB_WEAR_PATH +# NAMES libwear_levelling.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/wear_levelling" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_WEAR_PATH}) + +# find_library( LIB_WPA_PATH +# NAMES libwpa_supplicant.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/wpa_supplicant" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_WPA_PATH}) + +# find_library( LIB_PTHREAD_PATH +# NAMES libpthread.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/pthread" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_PTHREAD_PATH}) + + +# find_library( LIB_DEBUG_PATH +# NAMES libxtensa-debug-module.a +# HINTS "${IDF_NANOFRAMEWORK_BASE}/xtensa-debug-module" +# NO_CMAKE_FIND_ROOT_PATH ) +# list(APPEND PROJECT_LINK_LIBS ${LIB_DEBUG_PATH}) + + +# Path to pre compiled Libs + +set( DIRECT_LINK_LIBS "" ) +set( DIRECT_LINK_PATH "${ESP32_LIBS_PATH}" ) +#message( "direct link path:${DIRECT_LINK_PATH}") + +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libapp_trace.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libapp_update.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libasio.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libaws_iot.a) +#list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libbootloader_support.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libbt.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libcoap.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libconsole.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libcxx.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libdriver.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libefuse.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp-tls.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp32.a) + +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp_adc_cal.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp_event.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp_http_client.a) + +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp_http_server.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp_https_ota.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp_https_server.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libesp_ringbuf.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libespcoredump.a) + +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libethernet.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libexpat.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libfatfs.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libfreemodbus.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libfreertos.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libheap.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libidf_test.a ) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libjsmn.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libjson.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/liblibsodium.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/liblog.a) +# list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libmbedtls.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libmdns.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libmicro-ecc.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libmqtt.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libnewlib.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libnghttp.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libnvs_flash.a) +# list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libopenssl.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libprotobuf-c.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libprotocomm.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libpthread.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libsdmmc.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libsmartconfig_ack.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libsoc.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libspi_flash.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libspiffs.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libtcp_transport.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libtcpip_adapter.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libulp.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libunity.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libvfs.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libwear_levelling.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libwifi_provisioning.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libwpa_supplicant.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libxtensa-debug-module.a) +list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/libbootloader_support.a) + +# Lwip lib is built separately +#list(APPEND DIRECT_LINK_LIBS ${DIRECT_LINK_PATH}/liblwip.a) + +set(PROJECT_LINK_LIBS ${DIRECT_LINK_LIBS}) + +set(TARGET_ESP32_IDF_INCLUDES ${TARGET_ESP32_IDF_INCLUDES} CACHE INTERNAL "make global") +set(PROJECT_LINK_LIBS ${PROJECT_LINK_LIBS} CACHE INTERNAL "make global") +#set(DIRECT_LINK_LIBS ${DIRECT_LINK_LIBS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_16mb.csv b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_16mb.csv new file mode 100644 index 00000000..872173bf --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_16mb.csv @@ -0,0 +1,13 @@ +# Name, Type, SubType, Offset, Size +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +############################################################################################################################### +# if you change the partitions here, make sure to update the BlockRegions array in the device BlockStorage configuration file # +############################################################################################################################### +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +# Factory area for NanoCLR - 1536KB +factory, 0, 0, 0x10000, 0x180000, +# Deployment area for Managed code 1769K +deploy, data, 0x84, 0x190000, 0x1B0000, +# Config data for Network, Wireless, certificates, user data 2MB +config, data, spiffs, 0x340000, 0x200000, diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_2mb.csv b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_2mb.csv new file mode 100644 index 00000000..5008399e --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_2mb.csv @@ -0,0 +1,13 @@ +# Name, Type, SubType, Offset, Size +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +############################################################################################################################### +# if you change the partitions here, make sure to update the BlockRegions array in the device BlockStorage configuration file # +############################################################################################################################### +nvs, data, nvs, 0x9000, 0x4000, +phy_init, data, phy, 0xf000, 0x1000, +# Factory area for NanoCLR - 1088KB +factory, 0, 0, 0x10000, 0x110000, +# Deployment area for Managed code 393K +deploy, data, 0x84, 0x120000, 0x60000, +# Config data for Network, Wireless, certificates, user data 64K +config, data, spiffs, 0x180000, 0x10000, diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_4mb.csv b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_4mb.csv new file mode 100644 index 00000000..3bcfdd51 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_4mb.csv @@ -0,0 +1,13 @@ +# Name, Type, SubType, Offset, Size +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +############################################################################################################################### +# if you change the partitions here, make sure to update the BlockRegions array in the device BlockStorage configuration file # +############################################################################################################################### +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +# Factory area for NanoCLR - 1536KB +factory, 0, 0, 0x10000, 0x180000, +# Deployment area for Managed code 1769K +deploy, data, 0x84, 0x190000, 0x1B0000, +# Config data for Network, Wireless, certificates, user data 256K +config, data, spiffs, 0x340000, 0x40000, diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_8mb.csv b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_8mb.csv new file mode 100644 index 00000000..8814230f --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/IDF/partitions_nanoclr_8mb.csv @@ -0,0 +1,13 @@ +# Name, Type, SubType, Offset, Size +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +############################################################################################################################### +# if you change the partitions here, make sure to update the BlockRegions array in the device BlockStorage configuration file # +############################################################################################################################### +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +# Factory area for NanoCLR - 1536KB +factory, 0, 0, 0x10000, 0x180000, +# Deployment area for Managed code 1769K +deploy, data, 0x84, 0x190000, 0x1B0000, +# Config data for Network, Wireless, certificates, user data 1Mb +config, data, spiffs, 0x340000, 0x100000, diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/CLR_Startup_Thread.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/CLR_Startup_Thread.h new file mode 100644 index 00000000..3c394ef4 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/CLR_Startup_Thread.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _CLRSTARTUPTHREAD_ +#define _CLRSTARTUPTHREAD_ + +// declaration of RTOS thread +void CLRStartupThread(void const * argument); + +#endif //_CLRSTARTUPTHREAD_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Esp32_DeviceMapping.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Esp32_DeviceMapping.h new file mode 100644 index 00000000..c3eacf54 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Esp32_DeviceMapping.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// +// Header file for ESP32 device pin mnapping +// + +#ifndef _ESP32_DEVICEMAPPING_ +#define _ESP32_DEVICEMAPPING_ + +// Default I2C gpio pins +#define I2C1_DATA 18 +#define I2C1_CLOCK 19 +#define I2C2_DATA 25 +#define I2C2_CLOCK 26 + +enum Esp32_MapDeviceType +{ + DEV_TYPE_GPIO, + DEV_TYPE_SPI, + DEV_TYPE_I2C, + DEV_TYPE_SERIAL, + DEV_TYPE_LED_PWM, + DEV_TYPE_ADC, + DEV_TYPE_DAC, + DEV_TYPE_MAX, +}; + +int Esp32_GetMappedDevicePins(Esp32_MapDeviceType DevType, int DevNumber, int PinIndex); +int Esp32_GetMappedDevicePinsWithFunction(uint32_t alternateFunction); + +void Esp32_SetMappedDevicePins( uint8_t pin, int32_t alternateFunction ); + +#endif //_ESP32_DEVICEMAPPING_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/LaunchCLR.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/LaunchCLR.h new file mode 100644 index 00000000..15e319ef --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/LaunchCLR.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _LAUNCHCLR_H_ +#define _LAUNCHCLR_H_ + +void LaunchCLR(uint32_t address); +bool CheckValidCLRImage(uint32_t address); + +#endif //_LAUNCHCLR_H_ + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/TargetPAL_BlockStorage.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/TargetPAL_BlockStorage.h new file mode 100644 index 00000000..805c2e32 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/TargetPAL_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_BLOCKSTORAGE_H_ +#define _TARGET_PAL_BLOCKSTORAGE_H_ 1 + +#include + +#endif // _TARGET_PAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_BlockStorage_Esp32FlashDriver.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_BlockStorage_Esp32FlashDriver.h new file mode 100644 index 00000000..4fa13281 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_BlockStorage_Esp32FlashDriver.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_ESP32FLASH_DRIVER_H_ +#define _TARGET_ESP32FLASH_DRIVER_H_ 1 + +#include +#include + +#include + + +//!< .NanoFramework deploy partition +#define ESP_PARTITION_SUBTYPE_DATA_NANOCLR (esp_partition_subtype_t)0x84 +//--// + +bool Esp32FlashDriver_InitializeDevice(void*); +bool Esp32FlashDriver_UninitializeDevice(void*); +DeviceBlockInfo* Esp32FlashDriver_GetDeviceInfo(void*); +bool Esp32FlashDriver_Read(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer); +bool Esp32FlashDriver_Write(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite); +bool Esp32FlashDriver_IsBlockErased(void*, ByteAddress blockAddress, unsigned int length); +bool Esp32FlashDriver_EraseBlock(void*, ByteAddress address); +void Esp32FlashDriver_SetPowerState(void*, unsigned int state); +bool Esp32FlashDriver_GetMemoryMappedAddress(void*, unsigned int blockRegionIndex, unsigned int blockRangeIndex, unsigned int* address); + +extern const DRAM_ATTR esp_partition_t * g_pFlashDriver_partition; +extern const void * g_esp32_flash_start_ptr; + +#endif //_TARGET_ESP32FLASH_DRIVER_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_Windows_Storage.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_Windows_Storage.h new file mode 100644 index 00000000..888c34fe --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/Target_Windows_Storage.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_WINDOWS_STORAGE_H_ +#define _TARGET_WINDOWS_STORAGE_H_ 1 + +#endif //_TARGET_WINDOWS_STORAGE_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/WireProtocol_ReceiverThread.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/WireProtocol_ReceiverThread.h new file mode 100644 index 00000000..c6b75c3e --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/WireProtocol_ReceiverThread.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_RECEIVERTHREAD_H_ +#define _WIREPROTOCOL_RECEIVERTHREAD_H_ + +// declaration of RTOS thread +void ReceiverThread(void const * argument); + +#endif //_WIREPROTOCOL_RECEIVERTHREAD_H_ + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/esp32_os.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/esp32_os.h new file mode 100644 index 00000000..0dfba6f5 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/esp32_os.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _ESP32_OS_H_ +#define _ESP32_OS_H_ + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/timers.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "task.h" +#include "nvs_flash.h" + +// TODO ONly with network +#include "esp_wifi.h" +#include "esp_wpa2.h" +#include "esp_eth.h" +#include "esp_event_loop.h" + +#include "esp_timer.h" + +#include "spi_master.h" +#include "gpio.h" +#include "i2c.h" +#include "uart.h" +#include "ledc.h" +#include "adc.h" +#include "dac.h" +#include "timer.h" +#include "esp_spiffs.h" +#include "pcnt.h" + +// Uncomment to support Ethernet +//#define ESP32_ETHERNET_SUPPORT 1 + +#endif // _ESP32_OS_H_ \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/platform_target_capabilities.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/platform_target_capabilities.h new file mode 100644 index 00000000..e96158da --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/platform_target_capabilities.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _PLATFORM_TARGET_CAPABILITIES_H_ +#define _PLATFORM_TARGET_CAPABILITIES_H_ 1 + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.Esp32.TargetCapabilities (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +// this platform doesn't have any declared capabilities + +// the targets of this platform don't have any declared capabilities + +#ifdef __cplusplus +} +#endif + +#endif //_PLATFORM_TARGET_CAPABILITIES_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL.h new file mode 100644 index 00000000..d7726299 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL.h @@ -0,0 +1,77 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_H_ +#define _TARGET_HAL_H_ + +#include +#include + +// global mutex protecting the internal state of the interpreter, including event flags +extern portMUX_TYPE globalLockMutex; +#define GLOBAL_LOCK() portENTER_CRITICAL(&globalLockMutex); +#define GLOBAL_UNLOCK() portEXIT_CRITICAL(&globalLockMutex); + +// platform dependent delay +#define PLATFORM_DELAY(milliSecs) vTaskDelay(milliSecs); + +// Definitions for Sockets/Network +#define GLOBAL_LOCK_SOCKETS(x) + +#define PLATFORM_DEPENDENT__SOCKETS_MAX_COUNT 16 + +#define LPCSTR const char* + + +// these macros are to be used at entry/exit of native interrupt handlers +#define NATIVE_INTERRUPT_START SystemState_SetNoLock( SYSTEM_STATE_ISR ); \ + SystemState_SetNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); +#define NATIVE_INTERRUPT_END SystemState_ClearNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); \ + SystemState_ClearNoLock( SYSTEM_STATE_ISR ); + + +// TODO: Doesn't seem to be defined anywhere, used clr corlib math +#define INT32 int32_t +#define TRUE true +#define FALSE false + +#if !defined(BUILD_RTM) + +#define HARD_BREAKPOINT() HARD_Breakpoint() + +// #if defined(_DEBUG) +// #define DEBUG_HARD_BREAKPOINT() HARD_Breakpoint() +// #else +// #define DEBUG_HARD_BREAKPOINT() +// #endif + +// #else + +// #define HARD_BREAKPOINT() +// #define DEBUG_HARD_BREAKPOINT() + +#endif // !defined(BUILD_RTM) + +#define NANOCLR_STOP() HARD_BREAKPOINT() + + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// DEBUGGER HELPER // +// The line below is meant to be used as helper on checking that the execution engine is running. // +// This can be inferred by checking if Events_WaitForEvents loop is running. // +// The implementation should is to be provided by each target at target_common.h.in // +//////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(BUILD_RTM) + #define EVENTS_HEART_BEAT +#else + #ifndef EVENTS_HEART_BEAT + #define EVENTS_HEART_BEAT __asm__ __volatile__ ("nop") + #endif // EVENTS_HEART_BEAT +#endif + +extern int HeapBegin; +extern int HeapEnd; + +#endif //_TARGET_HAL_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Power.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Power.h new file mode 100644 index 00000000..93af4528 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Power.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_POWER_H_ +#define _TARGET_HAL_POWER_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +#endif //_TARGET_HAL_POWER_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Time.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Time.h new file mode 100644 index 00000000..e66b86ce --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetHAL_Time.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_TIME_H_ +#define _TARGET_HAL_TIME_H_ 1 + +#include +#include + +#include + +#define HAL_Time_CurrentSysTicks xTaskGetTickCount +#define ESP32_TICKS_PER_MS(x) ((x * (uint64_t)configTICK_RATE_HZ) / 1000) + +#endif //_TARGET_HAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL.h new file mode 100644 index 00000000..42d1f494 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL.h @@ -0,0 +1,11 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_H_ +#define _TARGETPAL_H_ + + + +#endif // _TARGETPAL_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL_Time.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL_Time.h new file mode 100644 index 00000000..e8383973 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Include/targetPAL_Time.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_TIME_H_ +#define _TARGET_PAL_TIME_H_ 1 + +#include + + +#endif //_TARGET_PAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/CMakeLists.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/CMakeLists.txt new file mode 100644 index 00000000..e5a99638 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/CMakeLists.txt @@ -0,0 +1,50 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# We build Lwip library from sources so as to include patches required for nanoFramework + +list(APPEND COMPONENT_PATH "${ESP32_IDF_PATH}/components") + +# Add current source path for lwipopts.h and sdkconfig.h +list(APPEND TARGET_ESP32_IDF_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/lwip/lwip/src/include") +list(APPEND TARGET_ESP32_IDF_INCLUDES "${COMPONENT_PATH}/lwip/port/esp32/include") + + + +# Lwip Library +list( APPEND TARGET_LWIP_API_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/api/api_lib.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nf_api_msg.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/api/err.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/api/netbuf.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/api/netdb.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/api/netifapi.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/netif/ppp/pppapi.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nf_sockets.c" ) +list( APPEND TARGET_LWIP_API_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/api/tcpip.c" ) + +file( GLOB TARGET_LWIP_APPS1_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/apps/*.c" ) +file( GLOB TARGET_LWIP_APPS2_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/apps/sntp/*.c" ) +file( GLOB TARGET_LWIP_APPS3_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/apps/ping/*.c" ) +file( GLOB TARGET_LWIP_APPS4_SOURCES "${COMPONENT_PATH}/lwip/apps/dhcpserver/dhcpserver.c" ) +file( GLOB TARGET_LWIP_CORE_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/core/*.c" ) +file( GLOB TARGET_LWIP_CORE_IP4_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/core/ipv4/*.c" ) +file( GLOB TARGET_LWIP_CORE_IP6_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/core/ipv6/*.c" ) +file( GLOB TARGET_LWIP_NETIF_SOURCES "${COMPONENT_PATH}/lwip/lwip/src/netif/*.c" ) + +list(APPEND TARGET_LWIP_PORT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nf_sys_arch.c" ) +list(APPEND TARGET_LWIP_PORT_SOURCES "${COMPONENT_PATH}/lwip/port/esp32/netif/ethernetif.c" ) +list(APPEND TARGET_LWIP_PORT_SOURCES "${COMPONENT_PATH}/lwip/port/esp32/netif/wlanif.c" ) +list(APPEND TARGET_LWIP_PORT_SOURCES "${COMPONENT_PATH}/lwip/port/esp32/debug/lwip_debug.c" ) +list(APPEND TARGET_LWIP_PORT_SOURCES "${COMPONENT_PATH}/lwip/port/esp32/vfs_lwip.c" ) + +list(APPEND TARGET_LWIP_SOURCES ${TARGET_LWIP_API_SOURCES} ${TARGET_LWIP_APPS1_SOURCES} ${TARGET_LWIP_APPS2_SOURCES} ${TARGET_LWIP_APPS3_SOURCES} ${TARGET_LWIP_APPS4_SOURCES} ${TARGET_LWIP_CORE_SOURCES} ${TARGET_LWIP_CORE_IP4_SOURCES} ${TARGET_LWIP_CORE_IP6_SOURCES} ${TARGET_LWIP_NETIF_SOURCES} ${TARGET_LWIP_PORT_SOURCES} ) +#list( APPEND CMAKE_C_FLAGS " -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable " ) +#add_library( lwip STATIC ${TARGET_LWIP_SOURCES} ) +#target_include_directories( lwip PUBLIC ${TARGET_ESP32_IDF_INCLUDES} ) + +# make var global +set(TARGET_LWIP_SOURCES ${TARGET_LWIP_SOURCES} CACHE INTERNAL "make global") +set(TARGET_ESP32_IDF_INCLUDES ${TARGET_ESP32_IDF_INCLUDES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/asdkconfig.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/asdkconfig.h new file mode 100644 index 00000000..de06e3dd --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/asdkconfig.h @@ -0,0 +1,203 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Espressif IoT Development Framework Configuration + * + */ +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_TCP_RECVMBOX_SIZE 6 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_LWIP_ETHARP_TRUST_IP_MAC 1 +#define CONFIG_TCP_WND_DEFAULT 5744 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_BLINK_GPIO 5 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_UDP_RECVMBOX_SIZE 6 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_INT_WDT 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE 0 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_EMAC_TASK_PRIORITY 20 +#define CONFIG_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_TCP_MSS 1436 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_ESPTOOLPY_BAUD 115200 +#define CONFIG_INT_WDT_CHECK_CPU1 1 +#define CONFIG_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED 1 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_CONSOLE_UART_NUM 0 +#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1 +#define CONFIG_ESPTOOLPY_BAUD_115200B 1 +#define CONFIG_TCP_OVERSIZE_MSS 1 +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 +#define CONFIG_CONSOLE_UART_DEFAULT 1 +#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384 +#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_TCPIP_TASK_STACK_SIZE 2048 +#define CONFIG_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_TIMER_QUEUE_LENGTH 10 +#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1 +#define CONFIG_DMA_RX_BUF_NUM 10 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_TCP_SYNMAXRTX 6 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_PYTHON "python" +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESPTOOLPY_COMPRESSED 1 +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_TCP_MSL 60000 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2048 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_BROWNOUT_DET_LVL 0 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_ESP32_APPTRACE_DEST_NONE 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET 0x10000 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_STACK_CHECK_NONE 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_BROWNOUT_DET 1 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_MONITOR_BAUD_115200B 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL 3 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_TCP_MAXRTX 12 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_DMA_TX_BUF_NUM 10 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_TIMER_TASK_PRIORITY 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MONITOR_BAUD 115200 +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_TCP_QUEUE_OOSEQ 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_APP_OFFSET 0x10000 +#define CONFIG_MEMMAP_SMP 1 +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_ESPTOOLPY_PORT "/dev/ttyUSB0" +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1 diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/lwipopts.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/lwipopts.h new file mode 100644 index 00000000..509e512c --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/lwipopts.h @@ -0,0 +1,860 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "esp_task.h" +#include "esp_system.h" +#include "sdkconfig.h" + +#include "netif/dhcp_state.h" + +#include +#include + +/* Enable all Espressif-only options */ + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 1 + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#define MEMCPY(dst,src,len) memcpy(dst,src,len) + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) + +#define LWIP_RAND esp_random + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#define MEM_LIBC_MALLOC 1 + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#define MEMP_MEM_MALLOC 1 + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#define MEM_ALIGNMENT 4 + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETCONN CONFIG_LWIP_MAX_SOCKETS + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#define MEMP_NUM_RAW_PCB CONFIG_LWIP_MAX_RAW_PCBS + +/** + * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB CONFIG_LWIP_MAX_ACTIVE_TCP + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB_LISTEN CONFIG_LWIP_MAX_LISTENING_TCP + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#define MEMP_NUM_UDP_PCB CONFIG_LWIP_MAX_UDP_PCBS + +/* + -------------------------------- + ---------- ARP options ------- + -------------------------------- +*/ +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#define ARP_QUEUEING 1 + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#define IP_REASSEMBLY CONFIG_LWIP_IP_REASSEMBLY + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#define IP_FRAG CONFIG_LWIP_IP_FRAG + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#define IP_REASS_MAXAGE 3 + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#define IP_REASS_MAX_PBUFS 10 + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ + +#define LWIP_BROADCAST_PING CONFIG_LWIP_BROADCAST_PING + +#define LWIP_MULTICAST_PING CONFIG_LWIP_MULTICAST_PING + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#define LWIP_RAW 1 + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#define LWIP_DHCP 1 + +#define DHCP_MAXRTX 0 + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#define DHCP_DOES_ARP_CHECK CONFIG_LWIP_DHCP_DOES_ARP_CHECK + + +/** + * CONFIG_LWIP_DHCP_RESTORE_LAST_IP==1: Last valid IP address obtained from DHCP server + * is restored after reset/power-up. + */ +#if CONFIG_LWIP_DHCP_RESTORE_LAST_IP + +#define LWIP_DHCP_IP_ADDR_RESTORE() dhcp_ip_addr_restore(netif) +#define LWIP_DHCP_IP_ADDR_STORE() dhcp_ip_addr_store(netif) +#define LWIP_DHCP_IP_ADDR_ERASE() dhcp_ip_addr_erase(esp_netif[tcpip_if]) + +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +#ifdef CONFIG_LWIP_AUTOIP +#define LWIP_AUTOIP 1 + +/** +* LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on +* the same interface at the same time. +*/ +#define LWIP_DHCP_AUTOIP_COOP 1 + +/** +* LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes +* that should be sent before falling back on AUTOIP. This can be set +* as low as 1 to get an AutoIP address very quickly, but you should +* be prepared to handle a changing IP address when DHCP overrides +* AutoIP. +*/ +#define LWIP_DHCP_AUTOIP_COOP_TRIES CONFIG_LWIP_AUTOIP_TRIES + +#define LWIP_AUTOIP_MAX_CONFLICTS CONFIG_LWIP_AUTOIP_MAX_CONFLICTS + +#define LWIP_AUTOIP_RATE_LIMIT_INTERVAL CONFIG_LWIP_AUTOIP_RATE_LIMIT_INTERVAL + +#endif /* CONFIG_LWIP_AUTOIP */ + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#define LWIP_IGMP 1 + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#define LWIP_DNS 1 + +#define DNS_MAX_SERVERS 3 +#define DNS_FALLBACK_SERVER_INDEX (DNS_MAX_SERVERS - 1) + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ + + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#define TCP_QUEUE_OOSEQ CONFIG_TCP_QUEUE_OOSEQ + +/** + * ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES==1: Keep TCP connection when IP changed + * scenario happens: 192.168.0.2 -> 0.0.0.0 -> 192.168.0.2 or 192.168.0.2 -> 0.0.0.0 + */ + +#define ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES +/* + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. +*/ +#define TCP_MSS CONFIG_TCP_MSS + +/** + * TCP_MSL: The maximum segment lifetime in milliseconds + */ +#define TCP_MSL CONFIG_TCP_MSL + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#define TCP_MAXRTX CONFIG_TCP_MAXRTX + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#define TCP_SYNMAXRTX CONFIG_TCP_SYNMAXRTX + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#define TCP_LISTEN_BACKLOG 1 + + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time + */ +#ifdef CONFIG_TCP_OVERSIZE_MSS +#define TCP_OVERSIZE TCP_MSS +#endif +#ifdef CONFIG_TCP_OVERSIZE_QUARTER_MSS +#define TCP_OVERSIZE (TCP_MSS/4) +#endif +#ifdef CONFIG_TCP_OVERSIZE_DISABLE +#define TCP_OVERSIZE 0 +#endif +#ifndef TCP_OVERSIZE +#error "One of CONFIG_TCP_OVERSIZE_xxx options should be set by sdkconfig" +#endif + +/** + * LWIP_WND_SCALE and TCP_RCV_SCALE: + * Set LWIP_WND_SCALE to 1 to enable window scaling. + * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the + * range of [0..14]). + * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large + * send window while having a small receive window only. + */ +#ifdef CONFIG_LWIP_WND_SCALE +#define LWIP_WND_SCALE 1 +#define TCP_RCV_SCALE CONFIG_TCP_RCV_SCALE +#endif + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ + +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#define LWIP_NETIF_HOSTNAME 1 + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#define LWIP_NETIF_TX_SINGLE_PBUF 1 + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +#ifdef CONFIG_LWIP_NETIF_LOOPBACK +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#define LWIP_NETIF_LOOPBACK 1 + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#define LWIP_LOOPBACK_MAX_PBUFS CONFIG_LWIP_LOOPBACK_MAX_PBUFS +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#define TCPIP_THREAD_NAME "tiT" + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#define TCPIP_THREAD_STACKSIZE ESP_TASK_TCPIP_STACK + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#define TCPIP_THREAD_PRIO ESP_TASK_TCPIP_PRIO + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#define TCPIP_MBOX_SIZE CONFIG_TCPIP_RECVMBOX_SIZE + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_UDP_RECVMBOX_SIZE CONFIG_UDP_RECVMBOX_SIZE + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_TCP_RECVMBOX_SIZE CONFIG_TCP_RECVMBOX_SIZE + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#define DEFAULT_ACCEPTMBOX_SIZE 6 + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#define DEFAULT_THREAD_STACKSIZE TCPIP_THREAD_STACKSIZE + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#define DEFAULT_THREAD_PRIO TCPIP_THREAD_PRIO + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_RAW_RECVMBOX_SIZE 6 + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#define LWIP_TCPIP_CORE_LOCKING 0 + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#define LWIP_SO_SNDTIMEO 1 + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#define LWIP_SO_RCVTIMEO 1 + +/** + * LWIP_SO_LINGER==1: Enable linger option for sockets/netconns + */ +#define LWIP_SO_LINGER 1 + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#define LWIP_TCP_KEEPALIVE 1 + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#define LWIP_SO_RCVBUF CONFIG_LWIP_SO_RCVBUF + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + * This option is set via menuconfig. + */ +#define SO_REUSE CONFIG_LWIP_SO_REUSE + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#define SO_REUSE_RXTOALL CONFIG_LWIP_SO_REUSE_RXTOALL + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ + +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#define LWIP_STATS CONFIG_LWIP_STATS + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#define LWIP_STATS_DISPLAY CONFIG_LWIP_STATS +#endif + + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ + +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#define PPP_SUPPORT CONFIG_PPP_SUPPORT + +#if PPP_SUPPORT + +/** + * PPP_NOTIFY_PHASE==1: Support PPP notify phase. + */ +#define PPP_NOTIFY_PHASE CONFIG_PPP_NOTIFY_PHASE_SUPPORT + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#define PAP_SUPPORT CONFIG_PPP_PAP_SUPPORT + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#define CHAP_SUPPORT CONFIG_PPP_CHAP_SUPPORT + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. + */ +#define MSCHAP_SUPPORT CONFIG_PPP_MSCHAP_SUPPORT + +/** + * CCP_SUPPORT==1: Support CCP. + */ +#define MPPE_SUPPORT CONFIG_PPP_MPPE_SUPPORT + +/** + * PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char. + * TODO: If PPP_MAXIDLEFLAG > 0 and next package is send during PPP_MAXIDLEFLAG time, + * then 0x7E is not added at the begining of PPP package but 0x7E termination + * is always at the end. This behaviour brokes PPP dial with GSM (PPPoS). + * The PPP package should always start and end with 0x7E. + */ + +#define PPP_MAXIDLEFLAG 0 + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#define PPP_DEBUG_ON CONFIG_PPP_DEBUG_ON + +#if PPP_DEBUG_ON +#define PPP_DEBUG LWIP_DBG_ON +#else +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +#endif + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#define LWIP_IPV6 1 + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ +#define LWIP_HOOK_IP4_ROUTE_SRC ip4_route_src_hook +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#define ETHARP_DEBUG LWIP_DBG_OFF + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#define NETIF_DEBUG LWIP_DBG_OFF + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#define PBUF_DEBUG LWIP_DBG_OFF + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#define API_LIB_DEBUG LWIP_DBG_OFF + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#define SOCKETS_DEBUG LWIP_DBG_OFF + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#define ICMP_DEBUG LWIP_DBG_OFF + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#define IP_DEBUG LWIP_DBG_OFF + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#define MEMP_DEBUG LWIP_DBG_OFF + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#define TCP_INPUT_DEBUG LWIP_DBG_OFF + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#define TCPIP_DEBUG LWIP_DBG_OFF + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#define ETHARP_TRUST_IP_MAC CONFIG_LWIP_ETHARP_TRUST_IP_MAC + + +/** + * POSIX I/O functions are mapped to LWIP via the VFS layer + * (see port/vfs_lwip.c) + */ +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 + +/** + * FD_SETSIZE from sys/types.h is the maximum number of supported file + * descriptors and CONFIG_LWIP_MAX_SOCKETS defines the number of sockets; + * LWIP_SOCKET_OFFSET is configured to use the largest numbers of file + * descriptors for sockets. File descriptors from 0 to LWIP_SOCKET_OFFSET-1 + * are non-socket descriptors and from LWIP_SOCKET_OFFSET to FD_SETSIZE are + * socket descriptors. + */ +#define LWIP_SOCKET_OFFSET (FD_SETSIZE - CONFIG_LWIP_MAX_SOCKETS) + +/* Enable all Espressif-only options */ + +#define ESP_LWIP 1 +#define ESP_LWIP_ARP 1 +#define ESP_PER_SOC_TCP_WND 0 +#define ESP_THREAD_SAFE 1 +#define ESP_THREAD_SAFE_DEBUG LWIP_DBG_OFF +#define ESP_DHCP 1 +#define ESP_DNS 1 +#define ESP_IPV6_AUTOCONFIG 1 +#define ESP_PERF 0 +#define ESP_RANDOM_TCP_PORT 1 +#define ESP_IP4_ATON 1 +#define ESP_LIGHT_SLEEP 1 +#define ESP_L2_TO_L3_COPY CONFIG_L2_TO_L3_COPY +#define ESP_STATS_MEM CONFIG_LWIP_STATS +#define ESP_STATS_DROP CONFIG_LWIP_STATS +#define ESP_STATS_TCP 0 +#define ESP_DHCP_TIMER 1 +#define ESP_DHCPS_TIMER 1 +#define ESP_LWIP_LOGI(...) ESP_LOGI("lwip", __VA_ARGS__) +#define ESP_PING 1 +#define ESP_HAS_SELECT 1 +#define ESP_AUTO_RECV 1 +#define ESP_GRATUITOUS_ARP CONFIG_ESP_GRATUITOUS_ARP + +#ifdef ESP_IRAM_ATTR +#undef ESP_IRAM_ATTR +#endif +#define ESP_IRAM_ATTR + +#if ESP_PERF +#define DBG_PERF_PATH_SET(dir, point) +#define DBG_PERF_FILTER_LEN 1000 + +enum { + DBG_PERF_DIR_RX = 0, + DBG_PERF_DIR_TX, +}; + +enum { + DBG_PERF_POINT_INT = 0, + DBG_PERF_POINT_WIFI_IN = 1, + DBG_PERF_POINT_WIFI_OUT = 2, + DBG_PERF_POINT_LWIP_IN = 3, + DBG_PERF_POINT_LWIP_OUT = 4, + DBG_PERF_POINT_SOC_IN = 5, + DBG_PERF_POINT_SOC_OUT = 6, +}; + +#else +#define DBG_PERF_PATH_SET(dir, point) +#define DBG_PERF_FILTER_LEN 1000 +#endif + +#define TCP_SND_BUF CONFIG_TCP_SND_BUF_DEFAULT +#define TCP_WND CONFIG_TCP_WND_DEFAULT + +#if ESP_PER_SOC_TCP_WND +#define TCP_WND_DEFAULT CONFIG_TCP_WND_DEFAULT +#define TCP_SND_BUF_DEFAULT CONFIG_TCP_SND_BUF_DEFAULT +#define TCP_WND(pcb) (pcb->per_soc_tcp_wnd) +#define TCP_SND_BUF(pcb) (pcb->per_soc_tcp_snd_buf) +#define TCP_SND_QUEUELEN(pcb) ((4 * (TCP_SND_BUF((pcb))) + (TCP_MSS - 1))/(TCP_MSS)) +#define TCP_SNDLOWAT(pcb) LWIP_MIN(LWIP_MAX(((TCP_SND_BUF((pcb)))/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF((pcb))) - 1) +#define TCP_SNDQUEUELOWAT(pcb) LWIP_MAX(((TCP_SND_QUEUELEN((pcb)))/2), 5) +#define TCP_WND_UPDATE_THRESHOLD(pcb) LWIP_MIN((TCP_WND((pcb)) / 4), (TCP_MSS * 4)) +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#define DHCP_DEBUG LWIP_DBG_OFF +#define LWIP_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF + +#define CHECKSUM_CHECK_UDP 0 +#define CHECKSUM_CHECK_IP 0 + +#define LWIP_NETCONN_FULLDUPLEX 1 +#define LWIP_NETCONN_SEM_PER_THREAD 1 + +#define LWIP_DHCP_MAX_NTP_SERVERS CONFIG_LWIP_DHCP_MAX_NTP_SERVERS +#define LWIP_TIMEVAL_PRIVATE 0 + +#define SNTP_SET_SYSTEM_TIME_US(sec, us) \ + do { \ + struct timeval tv = { .tv_sec = sec, .tv_usec = us }; \ + settimeofday(&tv, NULL); \ + } while (0); + +#define SNTP_GET_SYSTEM_TIME(sec, us) \ + do { \ + struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; \ + gettimeofday(&tv, NULL); \ + (sec) = tv.tv_sec; \ + (us) = tv.tv_usec; \ + } while (0); + +#define SOC_SEND_LOG //printf + +#endif /* __LWIPOPTS_H__ */ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_api_msg.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_api_msg.c new file mode 100644 index 00000000..b3589fe4 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_api_msg.c @@ -0,0 +1,2129 @@ +/** + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +extern void sys_signal_sock_event(); // MS-CHANGE + +/* netconns are polled once per second (e.g. continue write on memory error) */ +#define NETCONN_TCP_POLL_INTERVAL 2 + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +#if LWIP_TCPIP_CORE_LOCKING +#define WRITE_DELAYED , 1 +#define WRITE_DELAYED_PARAM , u8_t delayed +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define WRITE_DELAYED +#define WRITE_DELAYED_PARAM +#endif /* LWIP_TCPIP_CORE_LOCKING */ +static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM); + +#if ESP_LWIP +#define SIG_CLOSE_PARAM , bool sig_close +#define SIG_CLOSE_TRUE true +#define SIG_CLOSE_FALSE false +static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM SIG_CLOSE_PARAM); +#else +static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM); +#endif + +#endif + +#if LWIP_TCPIP_CORE_LOCKING +#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_TCP +u8_t netconn_aborted; +#endif /* LWIP_TCP */ + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only copies it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + ESP_STATS_DROP_INC(esp.rx_rawmbox_post_fail); + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + pbuf_free(p); + return; + } + + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if (!sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if (!sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + +#if ESP_LWIP +#if LWIP_IPV6 + /* This should be eventually moved to a flag on the UDP PCB, and this drop can happen + more correctly in udp_input(). This will also allow icmp_dest_unreach() to be called. */ + if (conn->flags & NETCONN_FLAG_IPV6_V6ONLY && !ip_current_is_v6()) { + LWIP_DEBUGF(API_MSG_DEBUG, ("recv_udp: Dropping IPv4 UDP packet (IPv6-only socket)")); + pbuf_free(p); + return; + } +#endif +#endif + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ip_addr_set(&buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr(); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ip_addr_set(&buf->toaddr, ip_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + ESP_STATS_DROP_INC(esp.rx_udpmbox_post_fail); + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + if (err != ERR_OK) { + NETCONN_SET_SAFE_ERR(conn, err); + } + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + ESP_STATS_DROP_INC(esp.rx_tcpmbox_post_fail); + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; +#if ESP_LWIP + bool sig_close = false; +#endif + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { +#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER + if (conn->current_msg && conn->current_msg->msg.sd.polls_left) { + conn->current_msg->msg.sd.polls_left--; + } +#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */ +#if ESP_LWIP + /* Delay the netconn close until no one use 'conn' because close frees 'conn'*/ + if (ERR_OK == lwip_netconn_do_close_internal(conn WRITE_DELAYED, SIG_CLOSE_FALSE)) { + sig_close = true; + } +#else + lwip_netconn_do_close_internal(conn WRITE_DELAYED); +#endif + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + +#if ESP_LWIP + if (sig_close) { + sys_sem_t *op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg = NULL; + sys_sem_signal(op_completed_sem); + return ERR_ABRT; + } +#endif + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; +#if ESP_LWIP + bool sig_close = false; +#endif + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn) { + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { +#if ESP_LWIP + /* Delay the netconn close until no one use 'conn' because close frees 'conn'*/ + if (ERR_OK == lwip_netconn_do_close_internal(conn WRITE_DELAYED, SIG_CLOSE_FALSE)) { + sig_close = true; + } +#else + lwip_netconn_do_close_internal(conn WRITE_DELAYED); +#endif + } + + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + +#if ESP_LWIP + if (sig_close) { + sys_sem_t *op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg = NULL; + sys_sem_signal(op_completed_sem); + return ERR_ABRT; + } +#endif + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + if (old_state == NETCONN_CLOSE) { + /* RST during close: let close return success & dealloc the netconn */ + err = ERR_OK; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } else { + /* no check since this is always fatal! */ + SYS_ARCH_SET(conn->last_err, err); + } + + /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ + + /* Notify the user layer about a connection error. Used to signal select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ +#if ESP_STATS_DROP + if (sys_mbox_trypost(&conn->recvmbox, NULL) != ERR_OK){ + ESP_STATS_DROP_INC(esp.err_tcp_rxmbox_post_fail); + } +#else + sys_mbox_trypost(&conn->recvmbox, NULL); +#endif + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ +#if ESP_STATS_DROP + if (sys_mbox_trypost(&conn->acceptmbox, NULL) != ERR_OK) { + ESP_STATS_DROP_INC(esp.err_tcp_rxmbox_post_fail); + } +#else + sys_mbox_trypost(&conn->acceptmbox, NULL); +#endif + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + sys_sem_t* op_completed_sem; + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem)); + conn->current_msg = NULL; + /* wake up the waiting task */ + NETCONN_SET_SAFE_ERR(conn, err); + sys_sem_signal(op_completed_sem); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + if (newpcb == NULL) { + /* out-of-pcbs during connect: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_VAL; + } + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + /* We have to set the callback here even though + * the new socket is unknown. newconn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + /* outof netconns: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + /* handle backlog counter */ + tcp_backlog_delayed(newpcb); + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + ESP_STATS_DROP_INC(esp.acceptmbox_post_fail); + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; +#if ESP_THREAD_SAFE + sys_mbox_set_owner(&newconn->recvmbox, NULL); +#endif + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from lwip_netconn_do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + */ +static void +pcb_new(struct api_msg *msg) +{ + enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4; + + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + +#if LWIP_IPV6 && LWIP_IPV4 + /* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */ + if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) { + iptype = IPADDR_TYPE_ANY; + } +#endif + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); + if (msg->conn->pcb.raw != NULL) { +#if LWIP_IPV6 + /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ + if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { + msg->conn->pcb.raw->chksum_reqd = 1; + msg->conn->pcb.raw->chksum_offset = 2; + } +#endif /* LWIP_IPV6 */ + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new_ip_type(iptype); + if (msg->conn->pcb.udp != NULL) { +#if LWIP_UDPLITE + if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new_ip_type(iptype); + if (msg->conn->pcb.tcp != NULL) { + setup_tcp(msg->conn); + } + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + return; + } + if (msg->conn->pcb.ip == NULL) { + msg->err = ERR_MEM; + } +#if ESP_LWIP +#if LWIP_IPV4 && LWIP_IPV6 + else { + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + /* Convert IPv4 PCB manually to an IPv6 PCB */ + IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6); + IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6); + } + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param m the api_msg_msg describing the connection type + */ +void +lwip_netconn_do_newconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } + + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + goto free_and_return; + } +#if !LWIP_NETCONN_SEM_PER_THREAD + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + sys_mbox_free(&conn->recvmbox); + goto free_and_return; + } +#endif + +#if ESP_THREAD_SAFE + sys_mbox_set_owner(&conn->recvmbox, conn); +#endif + +#if LWIP_TCP +#if ESP_THREAD_SAFE + /* Init acceptmbox to NULL because sys_mbox_set_invalid is implemented as empty macro */ + conn->acceptmbox = NULL; +#endif + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + conn->linger = -1; +#endif /* LWIP_SO_LINGER */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); +#if !ESP_THREAD_SAFE + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); + +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ +#else /* !ESP_THREAD_SAFE */ + sys_mbox_free(&conn->recvmbox); + +#if LWIP_TCP + sys_mbox_free(&conn->acceptmbox); +#endif /* LWIP TCP */ +#endif /* !ESP_THREAD_SAFE */ + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); +#endif + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { + if (mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + if (mem != &netconn_aborted) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static err_t +#if ESP_LWIP +lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM SIG_CLOSE_PARAM) +#else +lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) +#endif +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + u8_t close_finished = 0; + struct tcp_pcb* tpcb; +#if LWIP_SO_LINGER + u8_t linger_wait_required = 0; +#endif /* LWIP_SO_LINGER */ + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + tpcb = conn->pcb.tcp; + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing + (also if RD or WR side was shut down before already) */ + if (shut == NETCONN_SHUT_RDWR) { + close = 1; + } else if (shut_rx && + ((tpcb->state == FIN_WAIT_1) || + (tpcb->state == FIN_WAIT_2) || + (tpcb->state == CLOSING))) { + close = 1; + } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { + close = 1; + } else { + close = 0; + } + + /* Set back some callback pointers */ + if (close) { + tcp_arg(tpcb, NULL); + } + if (tpcb->state == LISTEN) { + tcp_accept(tpcb, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(tpcb, NULL); + tcp_accept(tpcb, NULL); + } + if (shut_tx) { + tcp_sent(tpcb, NULL); + } + if (close) { + tcp_poll(tpcb, NULL, 0); + tcp_err(tpcb, NULL); + } + } + /* Try to close the connection */ + if (close) { +#if LWIP_SO_LINGER + /* check linger possibilites before calling tcp_close */ + err = ERR_OK; + /* linger enabled/required at all? (i.e. is there untransmitted data left?) */ + if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) { + if ((conn->linger == 0)) { + /* data left but linger prevents waiting */ + tcp_abort(tpcb); + tpcb = NULL; + } else if (conn->linger > 0) { + /* data left and linger says we should wait */ + if (netconn_is_nonblocking(conn)) { + /* data left on a nonblocking netconn -> cannot linger */ + err = ERR_WOULDBLOCK; + } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= + (conn->linger * 1000)) { + /* data left but linger timeout has expired (this happens on further + calls to this function through poll_tcp */ + tcp_abort(tpcb); + tpcb = NULL; + } else { + /* data left -> need to wait for ACK after successful close */ + linger_wait_required = 1; + } + } + } + if ((err == ERR_OK) && (tpcb != NULL)) +#endif /* LWIP_SO_LINGER */ + { + err = tcp_close(tpcb); + } + } else { + err = tcp_shutdown(tpcb, shut_rx, shut_tx); + } + if (err == ERR_OK) { + close_finished = 1; +#if LWIP_SO_LINGER + if (linger_wait_required) { + /* wait for ACK of all unsent/unacked data by just getting called again */ + close_finished = 0; + err = ERR_INPROGRESS; + } +#endif /* LWIP_SO_LINGER */ + } else { + if (err == ERR_MEM) { + /* Closing failed because of memory shortage, try again later. Even for + nonblocking netconns, we have to wait since no standard socket application + is prepared for close failing because of resource shortage. + Check the timeout: this is kind of an lwip addition to the standard sockets: + we wait for some time when failing to allocate a segment for the FIN */ +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout > 0) { + close_timeout = conn->send_timeout; + } +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_LINGER + if (conn->linger >= 0) { + /* use linger timeout (seconds) */ + close_timeout = conn->linger * 1000U; + } +#endif + if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + if (conn->current_msg->msg.sd.polls_left == 0) { +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + close_finished = 1; + if (close) { + /* in this case, we want to RST the connection */ + tcp_abort(tpcb); + err = ERR_OK; + } + } + } else { + /* Closing failed for a non-memory error: give up */ + close_finished = 1; + } + } + if (close_finished) { + /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->state = NETCONN_NONE; + if (err == ERR_OK) { + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + /* wake up the application task */ +#if ESP_LWIP + if (sig_close) { + conn->current_msg = NULL; + sys_sem_signal(op_completed_sem); + } +#else + sys_sem_signal(op_completed_sem); +#endif + } + return ERR_OK; + } + if (!close_finished) { + /* Closing failed and we want to wait: restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN)); + if (shut_tx) { + tcp_sent(tpcb, sent_tcp); + } + /* when waiting for close, set up poll interval to 500ms */ + tcp_poll(tpcb, poll_tcp, 1); + tcp_err(tpcb, err_tcp); + tcp_arg(tpcb, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ + LWIP_ASSERT("err != ERR_OK", err != ERR_OK); + return err; +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_delconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + enum netconn_state state = msg->conn->state; + LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ + (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); +#if ESP_LWIP + msg->err = ERR_OK; +#endif + +#if LWIP_NETCONN_FULLDUPLEX + /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ + if (state != NETCONN_NONE) { + if ((state == NETCONN_WRITE) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* close requested, abort running write/connect */ + sys_sem_t* op_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); +#if ESP_LWIP + msg->err = ERR_INPROGRESS; +#endif + sys_sem_signal(op_completed_sem); + } + } +#else /* LWIP_NETCONN_FULLDUPLEX */ + if (((state != NETCONN_NONE) && + (state != NETCONN_LISTEN) && + (state != NETCONN_CONNECT)) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* This means either a blocking write or blocking connect is running + (nonblocking write returns and sets state to NONE) */ + msg->err = ERR_INPROGRESS; + } else +#endif /* LWIP_NETCONN_FULLDUPLEX */ + { +#if !ESP_LWIP + LWIP_ASSERT("blocking connect in progress", + (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + msg->err = ERR_OK; +#endif + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING +#if ESP_LWIP + if (lwip_netconn_do_close_internal(msg->conn, 0, SIG_CLOSE_TRUE) != ERR_OK) { +#else + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { +#endif + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ +#if ESP_LWIP + lwip_netconn_do_close_internal(msg->conn, SIG_CLOSE_TRUE); +#else + lwip_netconn_do_close_internal(msg->conn); +#endif +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { + TCPIP_APIMSG_ACK(msg); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +lwip_netconn_do_bind(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + +#if ESP_LWIP +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind + */ + if (ip_addr_cmp(API_EXPR_REF(msg->msg.bc.ipaddr), IP6_ADDR_ANY) && + (netconn_get_ipv6only(msg->conn) == 0)) { + /* change PCB type to IPADDR_TYPE_ANY */ + IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY); + IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY); + + /* bind to IPADDR_TYPE_ANY */ + API_EXPR_REF(msg->msg.bc.ipaddr) = IP_ANY_TYPE; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + sys_sem_t* op_completed_sem = NULL; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + } + if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + LWIP_ASSERT("blocking connect state error", + (was_blocking && op_completed_sem != NULL) || + (!was_blocking && op_completed_sem == NULL)); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(op_completed_sem); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +lwip_netconn_do_connect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state == NETCONN_CONNECT) { + msg->err = ERR_ALREADY; + } else if (msg->conn->state != NETCONN_NONE) { + msg->err = ERR_ISCONN; + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), + msg->msg.bc.port, lwip_netconn_do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), + when the connection is established! */ +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + return; + } + } + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Disconnect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param m the api_msg_msg pointing to the connection to disconnect + */ +void +lwip_netconn_do_disconnect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_listen(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { + struct tcp_pcb* lpcb; + if (msg->conn->pcb.tcp->state != CLOSED) { + /* connection is not closed, cannot listen */ + msg->err = ERR_VAL; + } else { + err_t err; + u8_t backlog; +#if TCP_LISTEN_BACKLOG + backlog = msg->msg.lb.backlog; +#else /* TCP_LISTEN_BACKLOG */ + backlog = TCP_DEFAULT_LISTEN_BACKLOG; +#endif /* TCP_LISTEN_BACKLOG */ +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen + */ + if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) && + (netconn_get_ipv6only(msg->conn) == 0)) { + /* change PCB type to IPADDR_TYPE_ANY */ + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY); + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err); + + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = err; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { +#if ESP_THREAD_SAFE + sys_mbox_set_owner(&msg->conn->acceptmbox, msg->conn); +#endif + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } else if (msg->conn->state == NETCONN_LISTEN) { + /* already listening, allow updating of the backlog */ + msg->err = ERR_OK; + tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog); + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_send(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; +#if ESP_LWIP +#if LWIP_IPV4 && LWIP_IPV6 + } else if ((msg->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) && + IP_IS_V4MAPPEDV6(&msg->msg.b->addr)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("lwip_netconn_do_send: Dropping IPv4 packet on IPv6-only socket")); + msg->err = ERR_VAL; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + &msg->msg.b->addr, msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_recv(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + } while (remaining != 0); + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if TCP_LISTEN_BACKLOG +/** Indicate that a TCP pcb has been accepted + * Called from netconn_accept + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_accepted(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + tcp_backlog_accepted(msg->conn->pcb.tcp); + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* TCP_LISTEN_BACKLOG */ + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from lwip_netconn_do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + const void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock; + u8_t apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + + apiflags = conn->current_msg->msg.w.apiflags; + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + conn->write_offset = 0; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock) { + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + err_t out_err; + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + } + out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else if (err == ERR_MEM) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called. + For blocking sockets, we do NOT return to the application + thread, since ERR_MEM is only a temporary error! Non-blocking + will remain non-writable until sent_tcp/poll_tcp is called */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + err_t out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } else if (dontblock) { + /* non-blocking write is done on ERR_MEM */ + err = ERR_WOULDBLOCK; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->write_offset = 0; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + sys_sem_signal(op_completed_sem); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else { + return ERR_MEM; + } +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_write(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by lwip_netconn_do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG + since lwip_netconn_do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_getaddr(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->local_ip); + } else { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->remote_ip); + } + + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + if ((msg->msg.ad.local == 0) && + ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { + /* pcb is not connected and remote name is requested */ + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close or half-shutdown a TCP pcb contained in a netconn + * Called from netconn_close + * In contrast to closing sockets, the netconn is not deallocated. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_close(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_TCP + enum netconn_state state = msg->conn->state; + /* First check if this is a TCP netconn and if it is in a correct state + (LISTEN doesn't support half shutdown) */ + if ((msg->conn->pcb.tcp != NULL) && + (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) && + ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) { + /* Check if we are in a connected state */ + if (state == NETCONN_CONNECT) { + /* TCP connect in progress: cannot shutdown */ + msg->err = ERR_CONN; + } else if (state == NETCONN_WRITE) { +#if LWIP_NETCONN_FULLDUPLEX + if (msg->msg.sd.shut & NETCONN_SHUT_WR) { + /* close requested, abort running write */ + sys_sem_t* write_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(write_completed_sem); + } else { + LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); + /* In this case, let the write continue and do not interfere with + conn->current_msg or conn->state! */ + msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); + } + } + if (state == NETCONN_NONE) { +#else /* LWIP_NETCONN_FULLDUPLEX */ + msg->err = ERR_INPROGRESS; + } else { +#endif /* LWIP_NETCONN_FULLDUPLEX */ + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING +#if ESP_LWIP + if (lwip_netconn_do_close_internal(msg->conn, 0, SIG_CLOSE_TRUE) != ERR_OK) { +#else + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { +#endif + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ +#if ESP_LWIP + lwip_netconn_do_close_internal(msg->conn, SIG_CLOSE_TRUE); +#else + lwip_netconn_do_close_internal(msg->conn); +#endif +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_join_leave_group(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP +#if LWIP_IPV6 && LWIP_IPV6_MLD + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } + } + else +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + { +#if LWIP_IGMP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + /* we trust the internal implementation to be correct :-) */ + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + API_EXPR_DEREF(msg->err) = ERR_VAL; + } else { + /* address was resolved */ + API_EXPR_DEREF(msg->err) = ERR_OK; + API_EXPR_DEREF(msg->addr) = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); + + //[MS_CHANGE] + sys_signal_sock_event(); + //[END_MS_CHANGE] +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +lwip_netconn_do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + u8_t addrtype = +#if LWIP_IPV4 && LWIP_IPV6 + msg->dns_addrtype; +#else + LWIP_DNS_ADDRTYPE_DEFAULT; +#endif + + API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name, + API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype); + if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sockets.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sockets.c new file mode 100644 index 00000000..5ed0f8fc --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sockets.c @@ -0,0 +1,3584 @@ +/** + * @file + * Sockets BSD-Like API module + * + * @defgroup socket Socket API + * @ingroup sequential_api + * BSD-style socket API.\n + * Thread-safe, to be called from non-TCPIP threads only.\n + * Can be activated by defining @ref LWIP_SOCKET to 1.\n + * Header is in posix/sys/socket.h\b + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/mld6.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/priv/api_msg.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +extern void sys_signal_sock_event(); // MS-CHANGE + +/* If the netconn API is not required publicly, then we include the necessary + files here to get the implementation */ +#if !LWIP_NETCONN +#undef LWIP_NETCONN +#define LWIP_NETCONN 1 +#include "api_msg.c" +#include "api_lib.c" +#include "netbuf.c" +#undef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +#if LWIP_IPV4 +#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ + (sin)->sin_len = sizeof(struct sockaddr_in); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = lwip_htons((port)); \ + inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ + memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) +#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ + inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ + (port) = lwip_ntohs((sin)->sin_port); }while(0) +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ + (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = lwip_htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ + inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ + (sin6)->sin6_scope_id = 0; }while(0) +#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ + inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ + (port) = lwip_ntohs((sin6)->sin6_port); }while(0) +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 && LWIP_IPV6 +static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port); + +#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ + ((namelen) == sizeof(struct sockaddr_in6))) +#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ + ((name)->sa_family == AF_INET6)) +#define SOCK_ADDR_TYPE_MATCH(name, sock) \ + ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ + (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ + if (IP_IS_V6(ipaddr)) { \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ + } else { \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ + } } while(0) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) +#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ + (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#endif /* LWIP_IPV6 */ + +#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ + IS_SOCK_ADDR_TYPE_VALID(name)) +#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ + SOCK_ADDR_TYPE_MATCH(name, sock)) +#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) + + +#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if ((sock)->conn == NULL) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ + if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) + + +#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) +#if LWIP_MPU_COMPATIBLE +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ + name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ + if (name == NULL) { \ + sock_set_errno(sock, ENOMEM); \ + return -1; \ + } }while(0) +#else /* LWIP_MPU_COMPATIBLE */ +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) +#endif /* LWIP_MPU_COMPATIBLE */ + +#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) +#else +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ + s32_t loc = (val); \ + ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ + ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) +#endif + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +#if !defined IOV_MAX +#define IOV_MAX 0xFFFF +#elif IOV_MAX > 0xFFFF +#error "IOV_MAX larger than supported by LwIP" +#endif /* IOV_MAX */ + +/** This is overridable for the rare case where more than 255 threads + * select on the same socket... + */ +#ifndef SELWAIT_T +#define SELWAIT_T u8_t +#endif + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ + u8_t err; + +#if ESP_THREAD_SAFE + /* lock is used to protect state/ref field, however this lock is not a perfect lock, e.g + * taskA and taskB can access sock X, then taskA freed sock X, before taskB detect + * this, taskC reuse sock X, then when taskB try to access sock X, problem may happen. + * A mitigation solution may be, when allocate a socket, alloc the least frequently used + * socket. + */ + sys_mutex_t lock; + + /* can be LWIP_SOCK_OPEN/LWIP_SOCK_CLOSING/LWIP_SOCK_CLOSED */ + u8_t state; + + /* if ref is 0, the sock need/can to be freed */ + s8_t ref; + + /* indicate how long the sock is in LWIP_SOCK_CLOSED status */ + u8_t age; +#endif + + /** counter of how many threads are waiting for this socket using select */ + SELWAIT_T select_waiting; +}; + +#if ESP_THREAD_SAFE + +#define LWIP_SOCK_OPEN 0 +#define LWIP_SOCK_CLOSING 1 +#define LWIP_SOCK_CLOSED 2 + +#define LWIP_SOCK_LOCK(sock) \ +do{\ + /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("l\n"));*/\ + sys_mutex_lock(&sock->lock);\ + /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("l ok\n"));*/\ +}while(0) + + +#define LWIP_SOCK_UNLOCK(sock) \ +do{\ + sys_mutex_unlock(&sock->lock);\ + /*LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG1, ("unl\n"));*/\ +}while(0) + +#define LWIP_FREE_SOCK(sock) \ +do{\ + if(sock->conn && NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP){\ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free tcp sock\n"));\ + free_socket(sock, 1);\ + } else {\ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free non-tcp sock\n"));\ + free_socket(sock, 0);\ + }\ +}while(0) + +#define LWIP_SET_CLOSE_FLAG() \ +do{\ + LWIP_SOCK_LOCK(__sock);\ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mark sock closing\n"));\ + __sock->state = LWIP_SOCK_CLOSING;\ + LWIP_SOCK_UNLOCK(__sock);\ +}while(0) + +#define LWIP_API_LOCK() \ + struct lwip_sock *__sock;\ + int __ret;\ +\ + __sock = get_socket(s);\ + if (!__sock) {\ + return -1;\ + }\ +\ +do{\ + LWIP_SOCK_LOCK(__sock);\ + __sock->ref ++;\ + if (__sock->state != LWIP_SOCK_OPEN) {\ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_LOCK:soc is %d, return\n", __sock->state));\ + __sock->ref --;\ + LWIP_SOCK_UNLOCK(__sock);\ + return -1;\ + }\ +\ + LWIP_SOCK_UNLOCK(__sock);\ +}while(0) + +#define LWIP_API_UNLOCK() \ +do{\ + LWIP_SOCK_LOCK(__sock);\ + __sock->ref --;\ + if (__sock->state == LWIP_SOCK_CLOSING) {\ + if (__sock->ref == 0){\ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK:ref 0, free __sock\n"));\ + LWIP_FREE_SOCK(__sock);\ + LWIP_SOCK_UNLOCK(__sock);\ + return __ret;\ + }\ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK: soc state is closing, return\n"));\ + LWIP_SOCK_UNLOCK(__sock);\ + return __ret;\ + }\ +\ + LWIP_SOCK_UNLOCK(__sock);\ + return __ret;\ +}while(0) + +#endif + +#if LWIP_NETCONN_SEM_PER_THREAD +#define SELECT_SEM_T sys_sem_t* +#define SELECT_SEM_PTR(sem) (sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define SELECT_SEM_T sys_sem_t +#define SELECT_SEM_PTR(sem) (&(sem)) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + SELECT_SEM_T sem; +}; + +/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ + * sockaddr_in6 if instantiated. + */ +union sockaddr_aligned { + struct sockaddr sa; +#if LWIP_IPV6 + struct sockaddr_in6 sin6; +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + struct sockaddr_in sin; +#endif /* LWIP_IPV4 */ +}; + +#if LWIP_IGMP +/* Define the number of IPv4 multicast memberships, default is one per socket */ +#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS +#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS +#endif + +/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when + a socket is closed */ +#if ESP_LWIP +struct lwip_socket_multicast_pair { + /** the socket (+1 to not require initialization) */ + int sa; + /** the interface address */ + ip_addr_t if_addr; + /** the group address */ + ip_addr_t multi_addr; +}; + +struct lwip_socket_multicast_pair socket_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; + +static int lwip_socket_register_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr); +static void lwip_socket_unregister_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr); + +#else +struct lwip_socket_multicast_pair { + /** the socket */ + struct lwip_sock* sock; + /** the interface address */ + ip4_addr_t if_addr; + /** the group address */ + ip4_addr_t multi_addr; +}; + +struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; + +static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +#endif + +static void lwip_socket_drop_registered_memberships(int s); +#endif /* LWIP_IGMP */ + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +#if ESP_THREAD_SAFE +static bool sockets_init_flag = false; +#endif +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is changed + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +#if LWIP_SOCKET_SET_ERRNO +#ifndef set_errno +#define set_errno(err) do { if (err) { errno = (err); } } while(0) +#endif +#else /* LWIP_SOCKET_SET_ERRNO */ +#define set_errno(err) +#endif /* LWIP_SOCKET_SET_ERRNO */ + +#define sock_set_errno(sk, e) do { \ + const int sockerr = (e); \ + sk->err = (u8_t)sockerr; \ + set_errno(sockerr); \ +} while (0) + +/* Forward declaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +#if !LWIP_TCPIP_CORE_LOCKING +static void lwip_getsockopt_callback(void *arg); +static void lwip_setsockopt_callback(void *arg); +#endif +static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); +static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); + +#if LWIP_IPV4 && LWIP_IPV6 +static void +sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port) +{ + if ((sockaddr->sa_family) == AF_INET6) { + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V6; + } else { + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V4; + } +} +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void +lwip_socket_thread_init(void) +{ + netconn_thread_init(); +} + +/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ +void +lwip_socket_thread_cleanup(void) +{ + netconn_thread_cleanup(); +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +#if ESP_LWIP +static struct lwip_sock * ESP_IRAM_ATTR +#else +static struct lwip_sock * +#endif +get_socket(int s) +{ + struct lwip_sock *sock; + + s -= LWIP_SOCKET_OFFSET; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + s -= LWIP_SOCKET_OFFSET; + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + +#if ESP_THREAD_SAFE + bool found = false; + int oldest = -1; + + SYS_ARCH_PROTECT(lev); + + if (sockets_init_flag == false){ + sockets_init_flag = true; + memset(sockets, 0, sizeof(sockets)); + } + + for (i = 0; i < NUM_SOCKETS; ++i) { + sockets[i].age ++; + + if (found == true){ + continue; + } + + if (!sockets[i].conn && (sockets[i].state == LWIP_SOCK_OPEN)) { + found = true; + oldest = i; + continue; + } + + if (!sockets[i].conn){ + if (oldest == -1 || sockets[i].age > sockets[oldest].age){ + oldest = i; + } + } + } + + if ((oldest != -1) && !sockets[oldest].conn) { + found = true; + sockets[oldest].conn = newconn; + } + + SYS_ARCH_UNPROTECT(lev); + + if (found == true) { + sockets[oldest].lastdata = NULL; + sockets[oldest].lastoffset = 0; + sockets[oldest].rcvevent = 0; + + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[oldest].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[oldest].errevent = 0; + sockets[oldest].err = 0; + sockets[oldest].select_waiting = 0; + + sockets[oldest].state = LWIP_SOCK_OPEN; + sockets[oldest].age = 0; + sockets[oldest].ref = 0; + if (!sockets[oldest].lock){ + /* one time init and never free */ + if (sys_mutex_new(&sockets[oldest].lock) != ERR_OK){ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("new sock lock fail\n")); + return -1; + } + } + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("alloc_socket: alloc %d ok\n", oldest)); + + return oldest + LWIP_SOCKET_OFFSET; + } + + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("alloc_socket: failed\n")); + +#else + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn && (sockets[i].select_waiting == 0)) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; + return i + LWIP_SOCKET_OFFSET; + } + SYS_ARCH_UNPROTECT(lev); + } + +#endif + + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + +#if ESP_THREAD_SAFE + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("free_sockset:free socket s=%p is_tcp=%d\n", sock, is_tcp)); +#endif + + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; +#if ESP_THREAD_SAFE + if (sock->conn){ + netconn_free(sock->conn); + } + + SYS_ARCH_PROTECT(lev); + sock->age = 0; + sock->conn = NULL; + sock->state = LWIP_SOCK_CLOSED; + SYS_ARCH_UNPROTECT(lev); +#endif + + /* Protect socket array */ + SYS_ARCH_SET(sock->conn, NULL); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + pbuf_free((struct pbuf *)lastdata); + } else { + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ip_addr_t naddr; + u16_t port = 0; + int newsock; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + set_errno(EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + } else if (err == ERR_CLSD) { + sock_set_errno(sock, EINVAL); + } else { + sock_set_errno(sock, err_to_errno(err)); + } + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); +#if ESP_AUTO_RECV + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(newconn, 1); +#endif + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (addr != NULL) { + union sockaddr_aligned tempaddr; + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + free_socket(nsock, 1); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); + if (*addrlen > tempaddr.sa.sa_len) { + *addrlen = tempaddr.sa.sa_len; + } + MEMCPY(addr, &tempaddr, *addrlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + } else { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); + } + + // [MS_CHANGE] - Signal the CLR that a socket event has occured + // TODO: We may want to investigate other ways to signal + // the CLR (maybe based on which socket received the + // event). + if(nsock->rcvevent > 0 ) { + sys_signal_sock_event(); + } + //[END_MS_CHANGE] + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ip_addr_t local_addr; + u16_t local_port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(namelen); + + SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr)); + IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_bind(sock->conn, &local_addr, local_port); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; +#if ESP_THREAD_SAFE + LWIP_DEBUGF(SOCKETS_DEBUG|ESP_THREAD_SAFE_DEBUG, ("lwip_close: is_tcp=%d\n", is_tcp)); +#endif + } else { + LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); + } + +#if ESP_LWIP +#if (LWIP_IGMP) || (LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS) + /* drop all possibly joined IGMP memberships */ + lwip_socket_drop_registered_memberships(s); +#endif +#else +#if LWIP_IGMP + /* drop all possibly joined IGMP memberships */ + lwip_socket_drop_registered_memberships(s); +#endif /* LWIP_IGMP */ +#endif + + + err = netconn_delete(sock->conn); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + +#if !ESP_THREAD_SAFE + free_socket(sock, is_tcp); +#endif + + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + LWIP_UNUSED_ARG(namelen); + if (name->sa_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ip_addr_t remote_addr; + u16_t remote_port; + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr)); + IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_connect(sock->conn, &remote_addr, remote_port); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +#if ESP_LWIP +int ESP_IRAM_ATTR +#else +int +#endif +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { +#if ESP_AUTO_RECV + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); +#endif + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); +#if ESP_LWIP + sock_set_errno(sock, EWOULDBLOCK); +#else + set_errno(EWOULDBLOCK); +#endif + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { +#if ESP_AUTO_RECV + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); +#endif + if (err == ERR_CLSD) { + /* closed but already received data, ensure select gets the FIN, too */ + event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0); + } + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ((len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK) != 0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { +#if !SOCKETS_DEBUG + if (from && fromlen) +#endif /* !SOCKETS_DEBUG */ + { + u16_t port; + ip_addr_t tmpaddr; + ip_addr_t *fromaddr; + union sockaddr_aligned saddr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + fromaddr = &tmpaddr; + netconn_getaddr(sock->conn, fromaddr, &port, 0); + } else { + port = netbuf_fromport((struct netbuf *)buf); + fromaddr = netbuf_fromaddr((struct netbuf *)buf); + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr)); + IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); + ip_addr_debug_print(SOCKETS_DEBUG, fromaddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); +#if SOCKETS_DEBUG + if (from && fromlen) +#endif /* SOCKETS_DEBUG */ + { + if (*fromlen > saddr.sa.sa_len) { + *fromlen = saddr.sa.sa_len; + } + MEMCPY(from, &saddr, *fromlen); + } + } +#if ESP_LWIP + /*fix the code for setting the UDP PROTO's remote infomation by liuh at 2014.8.27*/ + if (!from || !fromlen) { + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP) { + u16_t port; + ip_addr_t *fromaddr; + + port = netbuf_fromport((struct netbuf *)buf); + fromaddr = netbuf_fromaddr((struct netbuf *)buf); + + sock->conn->pcb.udp->remote_ip.u_addr.ip4.addr = fromaddr->u_addr.ip4.addr; + sock->conn->pcb.udp->remote_port = port; + } + } +#endif + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + buf = NULL; + } + } + } while (!done); + +#if ESP_AUTO_RECV + if ((off > 0) && (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && + ((flags & MSG_PEEK) == 0)) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + } +#endif + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)written : -1); +} + +ssize_t +lwip_recvmsg(int s, struct msghdr *message, int flags) +{ + struct lwip_sock *sock; + int i; + ssize_t buflen; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvmsg(%d, message=%p, flags=0x%x)\n", s, (void *)message, flags)); + LWIP_ERROR("lwip_recvmsg: invalid message pointer", message != NULL, return ERR_ARG;); + LWIP_ERROR("lwip_recvmsg: unsupported flags", (flags & ~(MSG_PEEK|MSG_DONTWAIT)) == 0, + set_errno(EOPNOTSUPP); return -1;); + + if ((message->msg_iovlen <= 0) || (message->msg_iovlen > IOV_MAX)) { + set_errno(EMSGSIZE); + return -1; + } + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* check for valid vectors */ + buflen = 0; + for (i = 0; i < message->msg_iovlen; i++) { + if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len <= 0) || + ((size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) || + ((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) <= 0)) { + sock_set_errno(sock, ERR_VAL); + return -1; + } + buflen = (ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len); + } + + int recv_flags = flags; + message->msg_flags = 0; + /* recv the data */ + buflen = 0; + for (i = 0; i < message->msg_iovlen; i++) { + /* try to receive into this vector's buffer */ + ssize_t recvd_local = lwip_recvfrom(s, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, recv_flags, NULL, NULL); + if (recvd_local > 0) { + /* sum up received bytes */ + buflen += recvd_local; + } + if ((recvd_local < 0) || (recvd_local < (int)message->msg_iov[i].iov_len) || + (flags & MSG_PEEK)) { + /* returned prematurely (or peeking, which might actually be limitated to the first iov) */ + if (buflen <= 0) { + /* nothing received at all, propagate the error */ + buflen = recvd_local; + } + break; + } + /* pass MSG_DONTWAIT to lwip_recv_tcp() to prevent waiting for more data */ + recv_flags |= MSG_DONTWAIT; + } + if (buflen > 0) { + /* reset socket error since we have received something */ + sock_set_errno(sock, 0); + } + + return buflen; +} + +int +lwip_sendmsg(int s, const struct msghdr *msg, int flags) +{ + struct lwip_sock *sock; + int i; +#if LWIP_TCP + u8_t write_flags; + size_t written; +#endif + int size = 0; + err_t err = ERR_OK; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + LWIP_UNUSED_ARG(msg->msg_control); + LWIP_UNUSED_ARG(msg->msg_controllen); + LWIP_UNUSED_ARG(msg->msg_flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + + for (i = 0; i < msg->msg_iovlen; i++) { + u8_t apiflags = write_flags; + if (i + 1 < msg->msg_iovlen) { + apiflags |= NETCONN_MORE; + } + written = 0; + err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); + if (err == ERR_OK) { + size += written; + /* check that the entire IO vector was accepected, if not return a partial write */ + if (written != msg->msg_iov[i].iov_len) + break; + } + /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */ + else if (err == ERR_WOULDBLOCK && size > 0) { + err = ERR_OK; + /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */ + break; + } else { + size = -1; + break; + } + } + sock_set_errno(sock, err_to_errno(err)); + return size; +#else /* LWIP_TCP */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + /* else, UDP and RAW NETCONNs */ +#if LWIP_UDP || LWIP_RAW + { + struct netbuf *chain_buf; + + LWIP_UNUSED_ARG(flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || + IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + /* initialize chain buffer with destination */ + chain_buf = netbuf_new(); + if (!chain_buf) { + sock_set_errno(sock, err_to_errno(ERR_MEM)); + return -1; + } + if (msg->msg_name) { + u16_t remote_port; + SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); + netbuf_fromport(chain_buf) = remote_port; + } +#if LWIP_NETIF_TX_SINGLE_PBUF + for (i = 0; i < msg->msg_iovlen; i++) { + size += msg->msg_iov[i].iov_len; + } + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { + err = ERR_MEM; + } else { + /* flatten the IO vectors */ + size_t offset = 0; + for (i = 0; i < msg->msg_iovlen; i++) { + MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); + offset += msg->msg_iov[i].iov_len; + } +#if LWIP_CHECKSUM_ON_COPY + { + /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ + u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); + netbuf_set_chksum(chain_buf, chksum); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain + manually to avoid having to allocate, chain, and delete a netbuf for each iov */ + for (i = 0; i < msg->msg_iovlen; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (p == NULL) { + err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ + break; + } + p->payload = msg->msg_iov[i].iov_base; + LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); + p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; + /* netbuf empty, add new pbuf */ + if (chain_buf->p == NULL) { + chain_buf->p = chain_buf->ptr = p; + /* add pbuf to existing pbuf chain */ + } else { + pbuf_cat(chain_buf->p, p); + } + } + /* save size of total chain */ + if (err == ERR_OK) { + size = netbuf_len(chain_buf); + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr)); + IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, chain_buf); + } + + /* deallocated the buffer */ + netbuf_delete(chain_buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? size : -1); + } +#else /* LWIP_UDP || LWIP_RAW */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_UDP || LWIP_RAW */ +} + +#if ESP_LWIP +int ESP_IRAM_ATTR +#else +int +#endif +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + u16_t remote_port; + struct netbuf buf; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + (IS_SOCK_ADDR_LEN_VALID(tolen) && + IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(tolen); + + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { + remote_port = 0; + ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); + } + netbuf_fromport(&buf) = remote_port; + + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + MEMCPY(buf.p->payload, data, short_size); + } + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr)); + IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + + LWIP_UNUSED_ARG(domain); /* @todo: check this */ + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), + (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, + ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , + event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); +#if ESP_AUTO_RECV + if (conn != NULL) { + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(conn, 1); + } +#endif + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +int +lwip_writev(int s, const struct iovec *iov, int iovcnt) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + /* Hack: we have to cast via number to cast from 'const' pointer to non-const. + Blame the opengroup standard for this inconsistency. */ + msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return lwip_sendmsg(s, &msg, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in set of sockets to check for read events + * @param writeset_in set of sockets to check for write events + * @param exceptset_in set of sockets to check for error events + * @param readset_out set of sockets that had read events + * @param writeset_out set of sockets that had write events + * @param exceptset_out set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + /* if this FD is not in the set, continue */ + if (!(readset_in && FD_ISSET(i, readset_in)) && + !(writeset_in && FD_ISSET(i, writeset_in)) && + !(exceptset_in && FD_ISSET(i, exceptset_in))) { + continue; + } + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + void* lastdata = sock->lastdata; + s16_t rcvevent = sock->rcvevent; + u16_t sendevent = sock->sendevent; + u16_t errevent = sock->errevent; + SYS_ARCH_UNPROTECT(lev); + + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } else { + SYS_ARCH_UNPROTECT(lev); + /* continue on to next FD in list */ + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + int i; + int maxfdp2; +#if LWIP_NETCONN_SEM_PER_THREAD + int waited = 0; +#endif + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + maxfdp2 = maxfdp1; + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + } else { + /* Not a valid socket */ + nready = -1; + maxfdp2 = i; + SYS_ARCH_UNPROTECT(lev); + break; + } + SYS_ARCH_UNPROTECT(lev); + } + } + + if (nready >= 0) { + /* Call lwip_selscan again: there could have been events between + the last scan (without us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); +#if LWIP_NETCONN_SEM_PER_THREAD + waited = 1; +#endif + } + } + + /* Decrease select_waiting for each socket we are interested in */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + /* for now, handle select_waiting==0... */ + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + if (sock->select_waiting > 0) { + sock->select_waiting--; + } + } else { + /* Not a valid socket */ + nready = -1; + } + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + +#if LWIP_NETCONN_SEM_PER_THREAD + if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { + /* don't leave the thread-local semaphore signalled */ + sys_arch_sem_wait(select_cb.sem, 1); + } +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_sem_free(&select_cb.sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + if (nready < 0) { + /* This happens when a socket got closed while waiting */ + set_errno(EBADF); + return -1; + } + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +#if ESP_LWIP +static void ESP_IRAM_ATTR +#else +static void +#endif +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + // [MS_CHANGE] - Signal the CLR that a socket event has occured + // TODO: We may want to investigate other ways to signal + // the CLR (maybe based on which socket received the + // event). + sys_signal_sock_event(); + //[END_MS_CHANGE] + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + /* remember the state of select_cb_list to detect changes */ + last_select_cb_ctr = select_cb_ctr; + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidating the semaphore. */ + sys_sem_signal(SELECT_SEM_PTR(scb->sem)); + } + } + /* unlock interrupts with each step */ + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); + // [MS_CHANGE] - Signal the CLR that a socket event has occured + // TODO: We may want to investigate other ways to signal + // the CLR (maybe based on which socket received the + // event). + sys_signal_sock_event(); + //[END_MS_CHANGE] +} + +/** + * Close one end of a full-duplex connection. + */ +int +lwip_shutdown(int s, int how) +{ + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + } else { + sock_set_errno(sock, ENOTCONN); + return -1; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if (how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return -1; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + union sockaddr_aligned saddr; + ip_addr_t naddr; + u16_t port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* get the IP address and port */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && + IP_IS_V4_VAL(naddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr)); + IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); + + if (*namelen > saddr.sa.sa_len) { + *namelen = saddr.sa.sa_len; + } + MEMCPY(name, &saddr, *namelen); + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_getsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; +#if !LWIP_MPU_COMPATIBLE + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; +#endif /* !LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* write back optlen and optval */ + *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); +#endif /* LWIP_MPU_COMPATIBLE */ + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_getsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_getsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.p, +#endif /* LWIP_MPU_COMPATIBLE */ + &data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_getsockopt_impl: the actual implementation of getsockopt: + * same argument as lwip_getsockopt, either called directly or through callback + */ +static u8_t +lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + +#if LWIP_TCP + case SO_ACCEPTCONN: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { + return ENOPROTOOPT; + } + if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { + *(int*)optval = 1; + } else { + *(int*)optval = 0; + } + break; +#endif /* LWIP_TCP */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = netconn_type(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); + /* only overwrite ERR_OK or temporary errors */ + if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err); + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + s16_t conn_linger; + struct linger* linger = (struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger); + conn_linger = sock->conn->linger; + if (conn_linger >= 0) { + linger->l_onoff = 1; + linger->l_linger = (int)conn_linger; + } else { + linger->l_onoff = 0; + linger->l_linger = 0; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", + s, *(int *)optval)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if ESP_LWIP +#if LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS /* Multicast options, similar to LWIP_IGMP options for IPV4 */ + case IPV6_MULTICAST_IF: /* NB: like IP_MULTICAST_IF, this returns an IP not an index */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in6_addr); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + inet6_addr_from_ip6addr((struct in6_addr*)optval, + udp_get_multicast_netif_ip6addr(sock->conn->pcb.udp)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IPV6_MULTICAST_HOPS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + *(u8_t*)optval = sock->conn->pcb.udp->mcast_ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; + case IPV6_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; + +#endif /* LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS */ +#endif + +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); + if (sock->conn->pcb.raw->chksum_reqd == 0) { + *(int *)optval = -1; + } else { + *(int *)optval = sock->conn->pcb.raw->chksum_offset; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", + s, (*(int*)optval)) ); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_setsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); +#else /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; +#endif /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_setsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_setsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.pc, +#endif /* LWIP_MPU_COMPATIBLE */ + data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_setsockopt_impl: the actual implementation of setsockopt: + * same argument as lwip_setsockopt, either called directly or through callback + */ +static u8_t +lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* SO_ACCEPTCONN is get-only */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + if (*(const int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(const int*)optval?"on":"off"))); + break; + + /* SO_TYPE is get-only */ + /* SO_ERROR is get-only */ + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); + netconn_set_recvbufsize(sock->conn, *(const int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + const struct linger* linger = (const struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger); + if (linger->l_onoff) { + int lingersec = linger->l_linger; + if (lingersec < 0) { + return EINVAL; + } + if (lingersec > 0xFFFF) { + lingersec = 0xFFFF; + } + sock->conn->linger = (s16_t)lingersec; + } else { + sock->conn->linger = -1; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + if (*(const int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); + break; + case IP_MULTICAST_IF: + { + ip4_addr_t if_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); + inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval); + udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr); + } + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(const u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#if LWIP_IGMP + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + /* @todo: assign membership to this socket so that it is dropped when closing the socket */ + err_t igmp_err; + const struct ip_mreq *imr = (const struct ip_mreq *)optval; +#if ESP_LWIP + ip_addr_t if_addr; + ip_addr_t multi_addr; +#else + ip4_addr_t if_addr; + ip4_addr_t multi_addr; +#endif + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); +#if ESP_LWIP + inet_addr_to_ip4addr(ip_2_ip4(&if_addr), &imr->imr_interface); + inet_addr_to_ip4addr(ip_2_ip4(&multi_addr), &imr->imr_multiaddr); +#else + inet_addr_to_ip4addr(&if_addr, &imr->imr_interface); + inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr); +#endif + if (optname == IP_ADD_MEMBERSHIP) { + if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { + /* cannot track membership (out of memory) */ + err = ENOMEM; + igmp_err = ERR_OK; + } else { +#if ESP_LWIP + igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); +#else + igmp_err = igmp_joingroup(&if_addr, &multi_addr); +#endif + } + } else { +#if ESP_LWIP + igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); +#else + igmp_err = igmp_leavegroup(&if_addr, &multi_addr); +#endif + lwip_socket_unregister_membership(s, &if_addr, &multi_addr); + } + if (igmp_err != ERR_OK) { + err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + if (*(const int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(const int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: +#if ESP_LWIP + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); +#else + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); +#endif + if (*(const int*)optval) { + netconn_set_ipv6only(sock->conn, 1); + } else { + netconn_set_ipv6only(sock->conn, 0); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", + s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); + break; + +#if ESP_LWIP +#if LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS /* Multicast options, similar to LWIP_IGMP options for IPV4 */ + case IPV6_MULTICAST_IF: /* NB: like IP_MULTICAST_IF, this takes an IP not an index */ + { + ip6_addr_t if_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in6_addr, NETCONN_UDP); + inet6_addr_to_ip6addr(&if_addr, (const struct in6_addr*)optval); + udp_set_multicast_netif_ip6addr(sock->conn->pcb.udp, &if_addr); + } + break; + case IPV6_MULTICAST_HOPS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + sock->conn->pcb.udp->mcast_ttl = (u8_t)(*(const u8_t*)optval); + break; + case IPV6_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(const u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; + case IPV6_ADD_MEMBERSHIP: + case IPV6_DROP_MEMBERSHIP: + { + err_t mld_err; + const struct ip6_mreq *imr = (const struct ip6_mreq *)optval; + ip_addr_t if_addr; + ip_addr_t multi_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip6_mreq, NETCONN_UDP); + inet6_addr_to_ip6addr(ip_2_ip6(&if_addr), &imr->ipv6mr_interface); + inet6_addr_to_ip6addr(ip_2_ip6(&multi_addr), &imr->ipv6mr_multiaddr); + if (optname == IPV6_ADD_MEMBERSHIP) { + if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { + /* cannot track membership (out of memory) */ + err = ENOMEM; + mld_err = ERR_OK; + } else { + mld_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); + } + } else { + mld_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); + lwip_socket_unregister_membership(s, &if_addr, &multi_addr); + } + if (mld_err != ERR_OK) { + err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS */ +#endif + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + /* It should not be possible to disable the checksum generation with ICMPv6 + * as per RFC 3542 chapter 3.1 */ + if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { + return EINVAL; + } + + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); + if (*(const int *)optval < 0) { + sock->conn->pcb.raw->chksum_reqd = 0; + } else if (*(const int *)optval & 1) { + /* Per RFC3542, odd offsets are not allowed */ + return EINVAL; + } else { + sock->conn->pcb.raw->chksum_reqd = 1; + sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", + s, sock->conn->pcb.raw->chksum_reqd)); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } +#if LWIP_FIONREAD_LINUXMODE + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + struct pbuf *p; + if (sock->lastdata) { + p = ((struct netbuf *)sock->lastdata)->p; + *((int*)argp) = p->tot_len - sock->lastoffset; + } else { + struct netbuf *rxbuf; + err_t err; + if (sock->rcvevent <= 0) { + *((int*)argp) = 0; + } else { + err = netconn_recv(sock->conn, &rxbuf); + if (err != ERR_OK) { + *((int*)argp) = 0; + } else { + sock->lastdata = rxbuf; + sock->lastoffset = 0; + *((int*)argp) = rxbuf->p->tot_len; + } + } + } + return 0; + } +#endif /* LWIP_FIONREAD_LINUXMODE */ + +#if LWIP_SO_RCVBUF + /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((int*)argp) = recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((int*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#else /* LWIP_SO_RCVBUF */ + break; +#endif /* LWIP_SO_RCVBUF */ +#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + + case (long)FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + break; + } /* switch (cmd) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + sock_set_errno(sock, 0); + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + sock_set_errno(sock, 0); + } else { + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + break; + } + return ret; +} + +#if ESP_LWIP +#if LWIP_IGMP || (LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS) +/** Register a new IGMP membership. On socket close, the membership is dropped automatically. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + * + * @return 1 on success, 0 on failure + */ +static int +lwip_socket_register_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr) +{ + /* s+1 is stored in the array to prevent having to initialize the array + (default initialization is to 0) */ + int sa = s + 1; + int i; + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_multicast_memberships[i].sa == 0) { + socket_multicast_memberships[i].sa = sa; + ip_addr_copy(socket_multicast_memberships[i].if_addr, *if_addr); + ip_addr_copy(socket_multicast_memberships[i].multi_addr, *multi_addr); + return 1; + } + } + return 0; +} + +/** Unregister a previously registered membership. This prevents dropping the membership + * on socket close. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_unregister_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr) +{ + /* s+1 is stored in the array to prevent having to initialize the array + (default initialization is to 0) */ + int sa = s + 1; + int i; + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if ((socket_multicast_memberships[i].sa == sa) && + ip_addr_cmp(&socket_multicast_memberships[i].if_addr, if_addr) && + ip_addr_cmp(&socket_multicast_memberships[i].multi_addr, multi_addr)) { + socket_multicast_memberships[i].sa = 0; + ip_addr_set_zero(&socket_multicast_memberships[i].if_addr); + ip_addr_set_zero(&socket_multicast_memberships[i].multi_addr); + return; + } + } +} + +/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. + * + * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). + */ +static void lwip_socket_drop_registered_memberships(int s) +{ + /* s+1 is stored in the array to prevent having to initialize the array + (default initialization is to 0) */ + int sa = s + 1; + int i; + struct lwip_sock *sock = get_socket(s); + + LWIP_ASSERT("socket has no netconn", sock->conn != NULL); + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_multicast_memberships[i].sa == sa) { + socket_multicast_memberships[i].sa = 0; + netconn_join_leave_group(sock->conn, + &socket_multicast_memberships[i].multi_addr, + &socket_multicast_memberships[i].if_addr, + NETCONN_LEAVE); + ip_addr_set_zero(&socket_multicast_memberships[i].if_addr); + ip_addr_set_zero(&socket_multicast_memberships[i].multi_addr); + } + } +} +#endif /* LWIP_IGMP || (LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS) */ + +#else +#if LWIP_IGMP +static int +lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return 0; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == NULL) { + socket_ipv4_multicast_memberships[i].sock = sock; + ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); + ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); + return 1; + } + } + return 0; +} + +/** Unregister a previously registered membership. This prevents dropping the membership + * on socket close. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if ((socket_ipv4_multicast_memberships[i].sock == sock) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + return; + } + } +} + + +/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. + * + * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_drop_registered_memberships(int s) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == sock) { + ip_addr_t multi_addr, if_addr; + ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); + ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + + netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE); + } + } +} +#endif /* LWIP_IGMP */ +#endif /* ESP_LWIP */ + +#if ESP_THREAD_SAFE + +int ESP_IRAM_ATTR +lwip_sendto_r(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + LWIP_API_LOCK(); + __ret = lwip_sendto(s, data, size, flags, to, tolen); + LWIP_API_UNLOCK(); +} + +int +lwip_send_r(int s, const void *data, size_t size, int flags) +{ + LWIP_API_LOCK(); + __ret = lwip_send(s, data, size, flags); + LWIP_API_UNLOCK(); +} + +int ESP_IRAM_ATTR +lwip_recvfrom_r(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + LWIP_API_LOCK(); + __ret = lwip_recvfrom(s, mem, len, flags, from, fromlen); + LWIP_API_UNLOCK(); +} + +int ESP_IRAM_ATTR +lwip_recv_r(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom_r(s, mem, len, flags, NULL, NULL); +} + +int +lwip_read_r(int s, void *mem, size_t len) +{ + return lwip_recvfrom_r(s, mem, len, 0, NULL, NULL); +} + +int +lwip_sendmsg_r(int s, const struct msghdr *msg, int flags) +{ + LWIP_API_LOCK(); + __ret = lwip_sendmsg(s, msg, flags); + LWIP_API_UNLOCK(); +} + +int +lwip_write_r(int s, const void *data, size_t size) +{ + return lwip_send_r(s, data, size, 0); +} + +int +lwip_writev_r(int s, const struct iovec *iov, int iovcnt) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + /* Hack: we have to cast via number to cast from 'const' pointer to non-const. + Blame the opengroup standard for this inconsistency. */ + msg.msg_iov = (struct iovec *)(size_t)iov; + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return lwip_sendmsg_r(s, &msg, 0); +} + +int +lwip_connect_r(int s, const struct sockaddr *name, socklen_t namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_connect(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_recvmsg_r(int s, struct msghdr *msg, int flags) +{ + LWIP_API_LOCK(); + __ret = lwip_recvmsg(s, msg, flags); + LWIP_API_UNLOCK(); +} + +int +lwip_listen_r(int s, int backlog) +{ + LWIP_API_LOCK(); + __ret = lwip_listen(s, backlog); + LWIP_API_UNLOCK(); +} + +int +lwip_bind_r(int s, const struct sockaddr *name, socklen_t namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_bind(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_accept_r(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + LWIP_API_LOCK(); + __ret = lwip_accept(s, addr, addrlen); + LWIP_API_UNLOCK(); +} + +int +lwip_ioctl_r(int s, long cmd, void *argp) +{ + LWIP_API_LOCK(); + __ret = lwip_ioctl(s, cmd, argp); + LWIP_API_UNLOCK(); +} + +int +lwip_fcntl_r(int s, int cmd, int val) +{ + LWIP_API_LOCK(); + __ret = lwip_fcntl(s, cmd, val); + LWIP_API_UNLOCK(); +} + +int +lwip_setsockopt_r(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + LWIP_API_LOCK(); + __ret = lwip_setsockopt(s, level, optname, optval, optlen); + LWIP_API_UNLOCK(); +} + +int +lwip_getsockopt_r(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + LWIP_API_LOCK(); + __ret = lwip_getsockopt(s, level, optname, optval, optlen); + LWIP_API_UNLOCK(); +} + +int +lwip_getpeername_r(int s, struct sockaddr *name, socklen_t *namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_getpeername(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_getsockname_r(int s, struct sockaddr *name, socklen_t *namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_getsockname(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_close_r(int s) +{ + LWIP_API_LOCK(); + LWIP_SET_CLOSE_FLAG(); + __ret = lwip_close(s); + LWIP_API_UNLOCK(); +} + +int +lwip_shutdown_r(int s, int how) +{ + LWIP_API_LOCK(); + __ret = lwip_shutdown(s, how); + LWIP_API_UNLOCK(); +} + +#endif + +// get last socket error +// lwIP is clearly missing an API to get the last error from a socket +uint32_t lwip_socket_get_err(int s) +{ + struct lwip_sock *sock = get_socket(s); + return sock->err; +} + +#endif /* LWIP_SOCKET */ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sys_arch.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sys_arch.c new file mode 100644 index 00000000..5f539fcf --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Lwip/nf_sys_arch.c @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ + +#include +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "arch/sys_arch.h" +#include "lwip/stats.h" +#include "esp_log.h" + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 4 +#define TAG "lwip_arch" + +static sys_mutex_t g_lwip_protect_mutex = NULL; + +static pthread_key_t sys_thread_sem_key; +static void sys_thread_sem_free(void* data); + +#if !LWIP_COMPAT_MUTEX +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t +sys_mutex_new(sys_mutex_t *pxMutex) +{ + err_t xReturn = ERR_MEM; + + *pxMutex = xSemaphoreCreateMutex(); + + if (*pxMutex != NULL) { + xReturn = ERR_OK; + } + + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mutex_new: m=%p\n", *pxMutex)); + + return xReturn; +} + +/** Lock a mutex + * @param mutex the mutex to lock */ +void ESP_IRAM_ATTR +sys_mutex_lock(sys_mutex_t *pxMutex) +{ + while (xSemaphoreTake(*pxMutex, portMAX_DELAY) != pdPASS); +} + +err_t +sys_mutex_trylock(sys_mutex_t *pxMutex) +{ + if (xSemaphoreTake(*pxMutex, 0) == pdPASS) return 0; + else return -1; +} + +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void ESP_IRAM_ATTR +sys_mutex_unlock(sys_mutex_t *pxMutex) +{ + xSemaphoreGive(*pxMutex); +} + +/** Delete a semaphore + * @param mutex the mutex to delete */ +void +sys_mutex_free(sys_mutex_t *pxMutex) +{ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mutex_free: m=%p\n", *pxMutex)); + vQueueDelete(*pxMutex); +} +#endif + +/*-----------------------------------------------------------------------------------*/ +// Creates and returns a new semaphore. The "count" argument specifies +// the initial state of the semaphore. TBD finish and test +err_t +sys_sem_new(sys_sem_t *sem, u8_t count) +{ + err_t xReturn = ERR_MEM; + vSemaphoreCreateBinary(*sem); + + if ((*sem) != NULL) { + if (count == 0) { // Means it can't be taken + xSemaphoreTake(*sem, 1); + } + + xReturn = ERR_OK; + } else { + ; // TBD need assert + } + + return xReturn; +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void ESP_IRAM_ATTR +sys_sem_signal(sys_sem_t *sem) +{ + xSemaphoreGive(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore (from ISR) +int sys_sem_signal_isr(sys_sem_t *sem) +{ + BaseType_t woken = pdFALSE; + xSemaphoreGiveFromISR(*sem, &woken); + return woken == pdTRUE; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t ESP_IRAM_ATTR +sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + portTickType StartTime, EndTime, Elapsed; + unsigned long ulReturn; + + StartTime = xTaskGetTickCount(); + + if (timeout != 0) { + if (xSemaphoreTake(*sem, timeout / portTICK_PERIOD_MS) == pdTRUE) { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_PERIOD_MS; + + if (Elapsed == 0) { + Elapsed = 1; + } + + ulReturn = Elapsed; + } else { + ulReturn = SYS_ARCH_TIMEOUT; + } + } else { // must block without a timeout + while (xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE); + + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_PERIOD_MS; + + if (Elapsed == 0) { + Elapsed = 1; + } + + ulReturn = Elapsed; + } + + return ulReturn ; // return time blocked +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void +sys_sem_free(sys_sem_t *sem) +{ + vSemaphoreDelete(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +err_t +sys_mbox_new(sys_mbox_t *mbox, int size) +{ + *mbox = mem_malloc(sizeof(struct sys_mbox_s)); + if (*mbox == NULL){ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("fail to new *mbox\n")); + return ERR_MEM; + } + + (*mbox)->os_mbox = xQueueCreate(size, sizeof(void *)); + + if ((*mbox)->os_mbox == NULL) { + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("fail to new *mbox->os_mbox\n")); + free(*mbox); + return ERR_MEM; + } + +#if ESP_THREAD_SAFE + (*mbox)->owner = NULL; +#endif + + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("new *mbox ok mbox=%p os_mbox=%p\n", *mbox, (*mbox)->os_mbox)); + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void ESP_IRAM_ATTR +sys_mbox_post(sys_mbox_t *mbox, void *msg) +{ + while (xQueueSendToBack((*mbox)->os_mbox, &msg, portMAX_DELAY) != pdTRUE); +} + +/*-----------------------------------------------------------------------------------*/ +err_t ESP_IRAM_ATTR +sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + err_t xReturn; + + if (xQueueSend((*mbox)->os_mbox, &msg, (portTickType)0) == pdPASS) { + xReturn = ERR_OK; + } else { + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("trypost mbox=%p fail\n", (*mbox)->os_mbox)); + xReturn = ERR_MEM; + } + + return xReturn; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t ESP_IRAM_ATTR +sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ + void *dummyptr; + portTickType StartTime, EndTime, Elapsed; + unsigned long ulReturn; + + StartTime = xTaskGetTickCount(); + if (msg == NULL) { + msg = &dummyptr; + } + + if (*mbox == NULL){ + *msg = NULL; + return -1; + } + + if (timeout == 0) { + timeout = portMAX_DELAY; + } else { + timeout = timeout / portTICK_PERIOD_MS; + } + + *msg = NULL; + if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), timeout)) { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_PERIOD_MS; + + if (Elapsed == 0) { + Elapsed = 1; + } + + ulReturn = Elapsed; + } else { // timed out blocking for message + ulReturn = SYS_ARCH_TIMEOUT; + } + + return ulReturn ; // return time blocked TBD test +} + +/*-----------------------------------------------------------------------------------*/ +u32_t +sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ + void *pvDummy; + unsigned long ulReturn; + + if (msg == NULL) { + msg = &pvDummy; + } + + if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), 0)) { + ulReturn = ERR_OK; + } else { + ulReturn = SYS_MBOX_EMPTY; + } + + return ulReturn; +} + +/*-----------------------------------------------------------------------------------*/ + +void +sys_mbox_set_owner(sys_mbox_t *mbox, void* owner) +{ + if (mbox && *mbox) { + (*mbox)->owner = owner; + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("set mbox=%p owner=%p", *mbox, owner)); + } +} + +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void +sys_mbox_free(sys_mbox_t *mbox) +{ + uint32_t mbox_message_num = 0; + + if ( (NULL == mbox) || (NULL == *mbox) ) { + return; + } + + mbox_message_num = uxQueueMessagesWaiting((*mbox)->os_mbox); + + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: mbox=%p os_mbox=%p owner=%p msg_num=%d\n", + *mbox, (*mbox)->os_mbox, (*mbox)->owner, mbox_message_num)); + +#if ESP_THREAD_SAFE + if ((*mbox)->owner) { + if (0 == mbox_message_num) { + /* + * If mbox->owner is not NULL, it indicates the mbox is recvmbox or acceptmbox, + * we need to post a NULL message to mbox in case some application tasks are blocked + * on this mbox + */ + if (sys_mbox_trypost(mbox, NULL) != ERR_OK) { + /* Should never be here because post a message to empty mbox should always be successful */ + ESP_LOGW(TAG, "WARNING: failed to post NULL msg to mbox\n"); + } else { + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: post null successfully\n")); + } + } + (*mbox)->owner = NULL; + } else { + if (mbox_message_num > 1) { + ESP_LOGW(TAG, "WARNING: mbox has %d message, potential memory leaking\n", mbox_message_num); + } + + if (mbox_message_num > 0) { + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: reset mbox queue\n")); + xQueueReset((*mbox)->os_mbox); + } + + /* For recvmbox or acceptmbox, free them in netconn_free() when all sockets' API are returned */ + vQueueDelete((*mbox)->os_mbox); + free(*mbox); + *mbox = NULL; + } +#else + vQueueDelete((*mbox)->os_mbox); + free(*mbox); + *mbox = NULL; +#endif +} + +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t +sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) +{ + xTaskHandle created_task; + portBASE_TYPE result; + + result = xTaskCreatePinnedToCore(thread, name, stacksize, arg, prio, &created_task, + CONFIG_TCPIP_TASK_AFFINITY); + + if (result != pdPASS) { + return NULL; + } + + return created_task; +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void +sys_init(void) +{ + if (ERR_OK != sys_mutex_new(&g_lwip_protect_mutex)) { + ESP_LOGE(TAG, "sys_init: failed to init lwip protect mutex\n"); + } + + // Create the pthreads key for the per-thread semaphore storage + pthread_key_create(&sys_thread_sem_key, sys_thread_sem_free); + + esp_vfs_lwip_sockets_register(); +} + +// MS-CHANGE for NetMf, extended for nanaoframework so called function +// can be set externally +void (*signal_sock_functionPtr)() = 0; + +void set_signal_sock_function( void (*funcPtr)() ) +{ + signal_sock_functionPtr = funcPtr; +} + + +void sys_signal_sock_event() +{ + if ( signal_sock_functionPtr != 0 ) + signal_sock_functionPtr(); +} + +/*-----------------------------------------------------------------------------------*/ +u32_t +sys_jiffies(void) +{ + return xTaskGetTickCount(); +} + +/*-----------------------------------------------------------------------------------*/ +u32_t +sys_now(void) +{ + return (xTaskGetTickCount()*portTICK_PERIOD_MS); +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t +sys_arch_protect(void) +{ + sys_mutex_lock(&g_lwip_protect_mutex); + return (sys_prot_t) 1; +} + +/*-----------------------------------------------------------------------------------*/ +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void +sys_arch_unprotect(sys_prot_t pval) +{ + sys_mutex_unlock(&g_lwip_protect_mutex); +} + +/* + * get per thread semphore + */ +sys_sem_t* sys_thread_sem_get(void) +{ + sys_sem_t *sem = pthread_getspecific(sys_thread_sem_key); + + if (!sem) { + sem = sys_thread_sem_init(); + } + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem_get s=%p\n", sem)); + return sem; +} + +static void sys_thread_sem_free(void* data) // destructor for TLS semaphore +{ + sys_sem_t *sem = (sys_sem_t*)(data); + + if (sem && *sem){ + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem del, sem=%p\n", *sem)); + vSemaphoreDelete(*sem); + } + + if (sem) { + LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem pointer del, sem_p=%p\n", sem)); + free(sem); + } +} + +sys_sem_t* sys_thread_sem_init(void) +{ + sys_sem_t *sem = (sys_sem_t*)mem_malloc(sizeof(sys_sem_t*)); + + if (!sem){ + ESP_LOGE(TAG, "thread_sem_init: out of memory"); + return 0; + } + + *sem = xSemaphoreCreateBinary(); + if (!(*sem)){ + free(sem); + ESP_LOGE(TAG, "thread_sem_init: out of memory"); + return 0; + } + + pthread_setspecific(sys_thread_sem_key, sem); + return sem; +} + +void sys_thread_sem_deinit(void) +{ + sys_sem_t *sem = pthread_getspecific(sys_thread_sem_key); + if (sem != NULL) { + sys_thread_sem_free(sem); + pthread_setspecific(sys_thread_sem_key, NULL); + } +} + +void sys_delay_ms(uint32_t ms) +{ + vTaskDelay(ms / portTICK_PERIOD_MS); +} + + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/CMakeLists.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/CMakeLists.txt new file mode 100644 index 00000000..35fff0f5 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append networking files, if enabled +list(APPEND TARGET_ESP32_NETWORK_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Network.cpp") +list(APPEND TARGET_ESP32_NETWORK_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/target_Network.cpp") +list(APPEND TARGET_ESP32_NETWORK_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Esp32_Ethernet_Lan8720.cpp") +list(APPEND TARGET_ESP32_NETWORK_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Esp32_Wireless.cpp") +list(APPEND TARGET_ESP32_NETWORK_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Esp32_SmartConfig.cpp") + +# make var global +set(TARGET_ESP32_NETWORK_SOURCES ${TARGET_ESP32_NETWORK_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Ethernet_Lan8720.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Ethernet_Lan8720.cpp new file mode 100644 index 00000000..2553f487 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Ethernet_Lan8720.cpp @@ -0,0 +1,138 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// This file includes the board specific Ethernet Intialisation + +#include +#include "Esp32_os.h" +#include "eth_phy/phy_lan8720.h" +#include "soc/emac_reg_v2.h" + + + +extern "C" +{ +#include "lwip\netif.h" +} + +extern struct netif * Esp32_find_netif(esp_interface_t esp_if); + + +// +// Olimex ESP32-EVB Rev B, OLimex ESP32-Gateway, Generic Lan8270 +// +#define CONFIG_PHY_LAN8720 1 +#define CONFIG_PHY_ADDRESS 0 +#define CONFIG_PHY_SMI_MDC_PIN 23 +#define CONFIG_PHY_SMI_MDIO_PIN 18 + + +// Uncomment one of these following lines to support switching of a power gpio used on some boards +//#define CONFIG_PIN_PHY_POWER 12 // Olimex_POE +//#define CONFIG_PIN_PHY_POWER 5 // Olimex_gateway revs newer than C + + + +#ifdef CONFIG_PHY_LAN8720 +#include "eth_phy/phy_lan8720.h" +#define DEFAULT_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config +#endif + +#ifdef CONFIG_PHY_TLK110 +#include "eth_phy/phy_tlk110.h" +#define DEFAULT_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config +#endif + +#define PIN_SMI_MDC CONFIG_PHY_SMI_MDC_PIN +#define PIN_SMI_MDIO CONFIG_PHY_SMI_MDIO_PIN + +static void eth_gpio_config_rmii(void) +{ + // RMII data pins are fixed: + // TXD0 = GPIO19 + // TXD1 = GPIO22 + // TX_EN = GPIO21 + // RXD0 = GPIO25 + // RXD1 = GPIO26 + // CLK == GPIO0 + phy_rmii_configure_data_interface_pins(); + // MDC is GPIO 23, MDIO is GPIO 18 + phy_rmii_smi_configure_pins(PIN_SMI_MDC, PIN_SMI_MDIO); +} + +#ifdef CONFIG_PIN_PHY_POWER +static void phy_device_power_enable_via_gpio(bool enable) +{ + if (!enable) + phy_lan8720_default_ethernet_config.phy_power_enable(false); + + gpio_pad_select_gpio((gpio_num_t)CONFIG_PIN_PHY_POWER); + gpio_set_direction((gpio_num_t)CONFIG_PIN_PHY_POWER, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)CONFIG_PIN_PHY_POWER, (int)enable); + + // Allow the power up/down to take effect, min 300us + vTaskDelay(1); + + if (enable) + phy_lan8720_default_ethernet_config.phy_power_enable(true); +} +#endif + + +esp_err_t Esp32_InitialiseEthernet( uint8_t * pMacAdr) +{ + (void)pMacAdr; + + // Config Ethernet interface which will depend on current hardware + eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG; + /* Set the PHY address in the example configuration */ + config.phy_addr = PHY0; + config.gpio_config = eth_gpio_config_rmii; + config.tcpip_input = tcpip_adapter_eth_input; + +#ifdef CONFIG_PIN_PHY_POWER + config.phy_power_enable = phy_device_power_enable_via_gpio; +#endif + esp_err_t ret = esp_eth_init(&config); + if(ret != ESP_OK) return ret; + + // esp_eth_set_mac( pMacAdr ); // need later IDF + esp_eth_enable(); + + return ESP_OK; +} + +// +// Open Ethernet Network driver +// +int Esp32_Ethernet_Open(int index, HAL_Configuration_NetworkInterface * config) +{ + (void)index; + + if ( Esp32_InitialiseEthernet(config->MacAddress) == ESP_OK ) + { + // Return NetIf number for Esp32 wireless station + + // FIXME find a better way to get the netif ptr + struct netif *pNetIf; + while(true) + { + vTaskDelay(100 / portTICK_PERIOD_MS); + + // Return NetIf number for Esp32 wireless station + pNetIf = Esp32_find_netif(ESP_IF_ETH); + if (pNetIf != NULL) break; + } + if (pNetIf != NULL) return pNetIf->num; + } + + return SOCK_SOCKET_ERROR; +} + +bool Esp32_Ethernet_Close(int index) +{ + (void)index; + return esp_eth_disable() == ESP_OK; +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_SmartConfig.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_SmartConfig.cpp new file mode 100644 index 00000000..bf9b46c6 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_SmartConfig.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "Esp32_os.h" +#include "esp_smartconfig.h" + +static const int ESPTOUCH_DONE_BIT = BIT1; +static const char *TAG = "sc"; + +static EventGroupHandle_t sc_wifi_event_group; + +static void sc_callback(smartconfig_status_t status, void *pdata) +{ + switch (status) { + case SC_STATUS_WAIT: + ESP_LOGI(TAG, "SC_STATUS_WAIT"); + break; + + case SC_STATUS_FIND_CHANNEL: + ESP_LOGI(TAG, "SC_STATUS_FINDING_CHANNEL"); + break; + + case SC_STATUS_GETTING_SSID_PSWD: + ESP_LOGI(TAG, "SC_STATUS_GETTING_SSID_PSWD"); + break; + + case SC_STATUS_LINK: + ESP_LOGI(TAG, "SC_STATUS_LINK"); + { + wifi_config_t *wifi_config = (wifi_config_t *)pdata; + ESP_LOGI(TAG, "SSID:%s", wifi_config->sta.ssid); + ESP_LOGI(TAG, "PASSWORD:%s", wifi_config->sta.password); + + // Try to connect and Save config + Network_Interface_Connect( 0, + (const char *)wifi_config->sta.ssid, + (const char *)wifi_config->sta.password, + NETWORK_CONNECT_SAVE_CONFIG + NETWORK_CONNECT_RECONNECT + ); + + } + break; + + case SC_STATUS_LINK_OVER: + ESP_LOGI(TAG, "SC_STATUS_LINK_OVER"); + if (pdata != NULL) + { + uint8_t phone_ip[4] = { 0 }; + memcpy(phone_ip, (uint8_t* )pdata, 4); + ESP_LOGI(TAG, "Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]); + } + xEventGroupSetBits(sc_wifi_event_group, ESPTOUCH_DONE_BIT); + break; + + default: + break; + } +} + +void smartconfig_task(void * parm) +{ + EventBits_t uxBits; + + sc_wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) ); + ESP_ERROR_CHECK( esp_smartconfig_start(sc_callback) ); + while (1) { + uxBits = xEventGroupWaitBits(sc_wifi_event_group, ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); + if(uxBits & ESPTOUCH_DONE_BIT) { + ESP_LOGI(TAG, "smartconfig over"); + esp_smartconfig_stop(); + vEventGroupDelete(sc_wifi_event_group); + vTaskDelete(NULL); + } + } +} + + +void Start_wifi_smart_config(void) +{ + xTaskCreate(smartconfig_task, "smartconfig_task", 4096, NULL, 3, NULL); +} + + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Wireless.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Wireless.cpp new file mode 100644 index 00000000..79dee5df --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Esp32_Wireless.cpp @@ -0,0 +1,389 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// This file includes the board specific Ethernet Intialisation + +#include +#include "Esp32_os.h" + +extern "C" +{ +#include "lwip\netif.h" +} + +static const char *TAG = "wifi"; +static bool WifiInitialised = false; +static wifi_mode_t wifiMode; + +// Forward / external references +struct netif * Esp32_find_netif(esp_interface_t esp_if); +int Esp32_Wait_NetNumber(esp_interface_t esp_if); +void Start_wifi_smart_config(); +esp_err_t Esp32_WirelessAP_Configure(HAL_Configuration_NetworkInterface * pConfig ); + +// +// Check what is the required Wifi mode +// Station only or AP only or Station and AP +// +// See what network interfaces are enabled +// +wifi_mode_t Esp32_CheckWifiMode() +{ + wifi_mode_t mode = WIFI_MODE_NULL; + + // Check Wifi station available + if ( g_TargetConfiguration.NetworkInterfaceConfigs->Count >= 1 ) + { + // Check if Station config available + HAL_Configuration_NetworkInterface * pCfgSta = g_TargetConfiguration.NetworkInterfaceConfigs->Configs[0]; + + // Wireless Config with SSID setup + if ( pCfgSta->InterfaceType == NetworkInterfaceType::NetworkInterfaceType_Wireless80211 ) + { + HAL_Configuration_Wireless80211 * pWirelessSta = ConfigurationManager_GetWirelessConfigurationFromId(pCfgSta->SpecificConfigId); + if (pWirelessSta != 0 ) + { + if ( pWirelessSta->Flags & WirelessFlags_Enable ) + { + mode = WIFI_MODE_STA; + } + } + } + } + + // Check if AP config available + if ( g_TargetConfiguration.NetworkInterfaceConfigs->Count >= 2 ) + { + HAL_Configuration_NetworkInterface * pCfgAP = g_TargetConfiguration.NetworkInterfaceConfigs->Configs[1]; + + // Wireless Config with SSID setup + if ( pCfgAP->InterfaceType == NetworkInterfaceType::NetworkInterfaceType_WirelessAP ) + { + HAL_Configuration_WirelessAP * pWirelessAp = ConfigurationManager_GetWirelessAPConfigurationFromId(pCfgAP->SpecificConfigId); + if (pWirelessAp != 0 ) + { + if ( pWirelessAp->Flags & WirelessAPFlags_Enable ) + { + // Use STATION + AP or just AP + mode = ( mode == WIFI_MODE_STA)? WIFI_MODE_APSTA : WIFI_MODE_AP; + } + } + } + } + + return mode; +} + +wifi_mode_t Esp32_GetWifiMode() +{ + wifi_mode_t current_wifi_mode; + esp_wifi_get_mode(¤t_wifi_mode); + return current_wifi_mode; +} + +void Esp32_DeinitWifi() +{ + WifiInitialised = false; + esp_wifi_stop(); + esp_wifi_deinit(); +} + +esp_err_t Esp32_InitaliseWifi() +{ + esp_err_t ec = ESP_OK; + + wifi_mode_t wifi_mode = Esp32_CheckWifiMode(); + + if ( WifiInitialised ) + { + // Check if we are running correct mode + // if not force a new init + if ( Esp32_GetWifiMode() != wifi_mode ) + { + Esp32_DeinitWifi(); + } + } + + if (!WifiInitialised) + { + // Init WiFi Alloc resource for WiFi driver, such as WiFi control structure, + // RX/TX buffer, WiFi NVS structure etc, this WiFi also start WiFi task. + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ec = esp_wifi_init(&cfg); + if ( ec != ESP_OK) return ec; + + esp_wifi_set_mode(wifi_mode); + + // We need to start the WIFI stack before the station can Connect + // Also we can only get the NetIf number used by ESP Idf after it has been started. + // Starting will also start the Soft- AP (if we have enabled it). + // So make sure it configured as per wireless config otherwise we will get the default SSID + if (wifi_mode & WIFI_MODE_AP ) + { + HAL_Configuration_NetworkInterface * pConfig = g_TargetConfiguration.NetworkInterfaceConfigs->Configs[1]; + ec = Esp32_WirelessAP_Configure(pConfig); + } + + ec = esp_wifi_start(); + if ( ec != ESP_OK) return ec; + + WifiInitialised = true; + } + + return ec; +} + +esp_err_t Esp32_Wireless_Connect(HAL_Configuration_Wireless80211 * pWireless) +{ + esp_err_t ec; + + // Connect directly + wifi_config_t sta_config = {}; + hal_strncpy_s( (char *)sta_config.sta.ssid, sizeof(sta_config.sta.ssid), (char *)pWireless->Ssid, hal_strlen_s((char *)pWireless->Ssid) ); + hal_strncpy_s( (char*)sta_config.sta.password, sizeof(sta_config.sta.password), (char *)pWireless->Password, hal_strlen_s((char *)pWireless->Password) ); + sta_config.sta.bssid_set = false; + + ec = esp_wifi_set_config(WIFI_IF_STA, &sta_config); + if(ec != ESP_OK) return ec; + + ec = esp_wifi_connect(); + ESP_LOGI(TAG, "WiFi Connect to %s result %d", sta_config.sta.ssid, ec); + if(ec != ESP_OK) return ec; + + return ESP_OK; +} + +esp_err_t Esp32_Wireless_Disconnect() +{ + esp_err_t ec; + + ec = esp_wifi_disconnect(); + if(ec != ESP_OK) return ec; + + return ESP_OK; +} + +int Esp32_Wireless_Open(int index, HAL_Configuration_NetworkInterface * pConfig) +{ + (void)index; + + esp_err_t ec; + + ec = Esp32_InitaliseWifi(); + if(ec != ESP_OK) return SOCK_SOCKET_ERROR; + + // Get Wireless config + HAL_Configuration_Wireless80211 * pWireless = ConfigurationManager_GetWirelessConfigurationFromId(pConfig->SpecificConfigId); + if (pWireless == 0 ) return SOCK_SOCKET_ERROR; + + // Wireless station not enabled + if ( !(Esp32_GetWifiMode() & WIFI_MODE_STA) ) return SOCK_SOCKET_ERROR; + + if ( !(pWireless->Flags & WirelessFlags_Enable)) return SOCK_SOCKET_ERROR; + + // Connect if Auto connect and we have an ssid + if ( (pWireless->Flags & WirelessFlags_Auto) && (hal_strlen_s((const char *)pWireless->Ssid) > 0) ) + { + Esp32_Wireless_Connect(pWireless); + + // Maybe remove SmartConfig flag if conected ok + } + + if ( pWireless->Flags & WirelessFlags_SmartConfig) + { + // FIXME + // Disable for now, When the smart_config starts it scans for wireless AP + // If it doesn't find any AP it ends up with a exception which causes the device to restart + + // Start Smart config (if enabled) + //Start_wifi_smart_config(); + } + + return Esp32_Wait_NetNumber(ESP_IF_WIFI_STA); +} + +bool Esp32_Wireless_Close(int index) +{ + (void)index; + + if ( WifiInitialised ) + { + esp_wifi_deinit(); + WifiInitialised = false; + } + return false; +} + +// Start a scan +int Esp32_Wireless_Scan() +{ + wifi_scan_config_t config = {}; + + config.scan_type = WIFI_SCAN_TYPE_PASSIVE; + config.scan_time.passive = 500; // 500 ms + + // Start a WIFI scan + // When complete a Scan Complete event will be fired + esp_err_t res = esp_wifi_scan_start( &config, false ); + return (int)res; +} + +wifi_auth_mode_t MapAuthentication( AuthenticationType type) +{ + wifi_auth_mode_t mapAuth[] = { + WIFI_AUTH_OPEN, // 0 None + WIFI_AUTH_OPEN, // 1 EAP + WIFI_AUTH_OPEN, // 2 PEAP + WIFI_AUTH_OPEN, // 3 WCN + WIFI_AUTH_OPEN, // 4 Open + WIFI_AUTH_OPEN, // 5 Shared + WIFI_AUTH_WEP, // 6 WEP + WIFI_AUTH_WPA_PSK, // 7 WPA + WIFI_AUTH_WPA_WPA2_PSK // 8 WPA2 + }; + + return mapAuth[type]; +} + +esp_err_t Esp32_WirelessAP_Configure(HAL_Configuration_NetworkInterface * pConfig ) +{ + esp_err_t ec; + + tcpip_adapter_ip_info_t tcpip_info; + + ec = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &tcpip_info); + + if ( pConfig->IPv4Address != 0 ) + { + tcpip_info.ip.addr = pConfig->IPv4Address; + tcpip_info.netmask.addr = pConfig->IPv4NetMask; + tcpip_info.gw.addr = pConfig->IPv4GatewayAddress; + ec = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &tcpip_info ); + } + else + { + pConfig->IPv4Address = tcpip_info.ip.addr; + pConfig->IPv4NetMask = tcpip_info.netmask.addr; + pConfig->IPv4GatewayAddress = tcpip_info.gw.addr; + } + + HAL_Configuration_WirelessAP * pWireless = ConfigurationManager_GetWirelessAPConfigurationFromId(pConfig->SpecificConfigId); + if (pWireless == 0 ) return ESP_FAIL; + + wifi_config_t ap_config = { 0 }; + + hal_strncpy_s( (char *)ap_config.ap.ssid, sizeof(ap_config.ap.ssid), (char *)pWireless->Ssid, hal_strlen_s((char *)pWireless->Ssid) ); + hal_strncpy_s( (char*)ap_config.ap.password, sizeof(ap_config.ap.password), (char *)pWireless->Password, hal_strlen_s((char *)pWireless->Password) ); + + ap_config.ap.ssid_len = hal_strlen_s((char *)pWireless->Ssid); + ap_config.ap.channel = pWireless->Channel; + ap_config.ap.ssid_hidden = (pWireless->Flags & WirelessAPFlags_Hidden_SSID)? 1 : 0; + ap_config.ap.authmode = MapAuthentication(pWireless->Authentication); + + if (hal_strlen_s((char *)ap_config.ap.password) == 0) + { + ap_config.ap.authmode = WIFI_AUTH_OPEN; + } + + // Max connections for ESP32 + ap_config.ap.max_connection = pWireless->MaxConnections; + if (ap_config.ap.max_connection > ESP_WIFI_MAX_CONN_NUM) + { + ap_config.ap.max_connection = ESP_WIFI_MAX_CONN_NUM; + } + + ap_config.ap.beacon_interval = 100; + + ec = esp_wifi_set_config(ESP_IF_WIFI_AP, &ap_config); + if (ec != ESP_OK) + { + ESP_LOGE(TAG, "WiFi set AP config - result %d", ec); + } + + return ec; +} + +// +// Open Wireless Soft AP +// +// If AP is enabled it will have been configured and started running when the WiFI stack is initialised +// All we need to do here is return the NetIf number used by ESP IDF +// Also make sure WIfi in initialised correctly if config is changed +int Esp32_WirelessAP_Open(int index, HAL_Configuration_NetworkInterface * pConfig) +{ + (void)index; + esp_err_t ec; + + // Initialise Wifi stack if required + ec = Esp32_InitaliseWifi(); + if(ec != ESP_OK) return SOCK_SOCKET_ERROR; + + // AP mode enabled ? + if ( !(Esp32_GetWifiMode() & WIFI_MODE_AP) ) + { + return SOCK_SOCKET_ERROR; + } + + // Return NetIf number + // FIXME find a better way to get the netif ptr + // This becomes available on the event AP STARTED + // for the moment we just wait for it + return Esp32_Wait_NetNumber(ESP_IF_WIFI_AP); +} + +// +// Closing down AP +// +// Either config being updated or shutdown +// Closing AP will also stop Station +// +bool Esp32_WirelessAP_Close(int index) +{ + (void)index; + + Esp32_DeinitWifi(); + + return true; +} + +// +// Find the netif * for the passed esp_interface_t +// +extern struct netif * Esp32_find_netif(esp_interface_t esp_if) +{ + struct netif *pNetIf; + + for (pNetIf = netif_list; pNetIf != NULL; pNetIf = pNetIf->next) + { + if (esp_if == tcpip_adapter_get_esp_if((void *)pNetIf)) + { + return pNetIf; + } + } + return NULL; +} + +// Esp32_Wait_NetNumber +// +// Find the NetiF number used by esp_interface_t +// If not availbale then loop and wait for interface to start +// +int Esp32_Wait_NetNumber(esp_interface_t esp_if) +{ + int number = 0; + + // FIXME find a better way to get the netif ptr + struct netif *pNetIf; + while(true) + { + // Return NetIf number for Esp32 wireless station + pNetIf = Esp32_find_netif(esp_if); + if (pNetIf != NULL) break; + + vTaskDelay(20 / portTICK_PERIOD_MS); + } + + return pNetIf->num; +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Target_Network.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Target_Network.cpp new file mode 100644 index 00000000..dfe7e736 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/Target_Network.cpp @@ -0,0 +1,271 @@ + +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "Esp32_os.h" + + +// +// Works with the Target_NetworkConfig to map the Network_Interface_XXXXX calls to the correct driver + +int Esp32_Wireless_Open(int index, HAL_Configuration_NetworkInterface * config); +bool Esp32_Wireless_Close(int index); +int Esp32_WirelessAP_Open(int index, HAL_Configuration_NetworkInterface * config); +bool Esp32_WirelessAP_Close(int index); +int Esp32_Ethernet_Open(int index, HAL_Configuration_NetworkInterface * config); +bool Esp32_Ethernet_Close(int index); +int Esp32_Wireless_Scan(); +int Esp32_Wireless_Disconnect(); +int Esp32_Wireless_Connect(HAL_Configuration_Wireless80211 * pWireless); + +bool StoreConfigBlock(DeviceConfigurationOption configType, uint32_t configurationIndex, void * pConfigBlock, size_t writeSize ); + + +bool Network_Interface_Bind(int index) +{ + (void)index; + + return true; +} + +int Network_Interface_Open(int configIndex) +{ + HAL_Configuration_NetworkInterface * pConfig; + + // Check index in range + if ( g_TargetConfiguration.NetworkInterfaceConfigs->Count <= configIndex ) return SOCK_SOCKET_ERROR; + + // load network interface configuration from storage + pConfig = g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configIndex]; + + switch((tcpip_adapter_if_t)configIndex) + { + // Wireless + case TCPIP_ADAPTER_IF_STA: + return Esp32_Wireless_Open(configIndex, pConfig); + + // Soft AP + case TCPIP_ADAPTER_IF_AP: + return Esp32_WirelessAP_Open(configIndex, pConfig); + +#if ESP32_ETHERNET_SUPPORT + // Ethernet + case TCPIP_ADAPTER_IF_ETH: + return Esp32_Ethernet_Open(configIndex, pConfig); +#endif + default: + break; + } + return SOCK_SOCKET_ERROR; +} + +bool Network_Interface_Close(int configIndex) +{ + switch((tcpip_adapter_if_t)configIndex) + { + // Wireless + case TCPIP_ADAPTER_IF_STA: + return Esp32_Wireless_Close(configIndex); + + // Soft AP + case TCPIP_ADAPTER_IF_AP: + return Esp32_WirelessAP_Close(configIndex); + +#if ESP32_ETHERNET_SUPPORT + // Ethernet + case TCPIP_ADAPTER_IF_ETH: + return Esp32_Ethernet_Close(configIndex); +#endif + default: + break; + + } + return false; +} + + +bool Network_Interface_Start_Scan(int configIndex) +{ + switch((tcpip_adapter_if_t)configIndex) + { + // Wireless + case TCPIP_ADAPTER_IF_STA: + return (Esp32_Wireless_Scan() == 0); + + } + + return false; +} + +bool GetWirelessConfig(int configIndex, HAL_Configuration_Wireless80211 ** pWireless) +{ + HAL_Configuration_NetworkInterface * pConfig; + + // Check index in range + if ( g_TargetConfiguration.NetworkInterfaceConfigs->Count <= configIndex ) return false; + + // load network interface configuration from storage + pConfig = g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configIndex]; + if ( pConfig->InterfaceType != NetworkInterfaceType_Wireless80211) return false; + + *pWireless = ConfigurationManager_GetWirelessConfigurationFromId(pConfig->SpecificConfigId); + + return true; +} + +// +// Connect to wireless network SSID using passphase +// +int Network_Interface_Connect(int configIndex, const char * ssid, const char * passphase, int options) +{ + HAL_Configuration_Wireless80211 * pWireless; + + if ( GetWirelessConfig(configIndex, & pWireless) == false ) return SOCK_SOCKET_ERROR; + + pWireless->Flags = WirelessFlags_Enable; + + if ( options & NETWORK_CONNECT_RECONNECT) + { + pWireless->Flags |= WirelessFlags_Auto; + } + else + { + pWireless->Flags ^= WirelessFlags_Auto; + } + + // Update Wireless structure with new SSID and passphase + hal_strcpy_s( (char *)pWireless->Ssid, sizeof(pWireless->Ssid), ssid ); + hal_strcpy_s( (char *)pWireless->Password, sizeof(pWireless->Password), passphase ); + + // Option to Save new config + if ( options & NETWORK_CONNECT_SAVE_CONFIG) + { + StoreConfigBlock( DeviceConfigurationOption_Wireless80211Network, configIndex, pWireless, sizeof(HAL_Configuration_Wireless80211) ); + } + + switch((tcpip_adapter_if_t)configIndex) + { + // Wireless + case TCPIP_ADAPTER_IF_STA: + esp_err_t err = Esp32_Wireless_Connect( pWireless); + + return (int)err; + + } + + return SOCK_SOCKET_ERROR; +} + +int Network_Interface_Disconnect(int configIndex) +{ + switch((tcpip_adapter_if_t)configIndex) + { + // Wireless + case TCPIP_ADAPTER_IF_STA: + esp_err_t err = Esp32_Wireless_Disconnect(); + + return (err == ESP_OK); + + } + + return false; +} + + +wifi_sta_info_t wireless_sta[ESP_WIFI_MAX_CONN_NUM] = { 0 }; + +// +// Update save stations with rssi +// +void Network_Interface_update_Stations() +{ + esp_err_t ec; + wifi_sta_list_t stations; + + ec = esp_wifi_ap_get_sta_list(&stations); + + if (ec == ESP_OK) + { + // Find save station and update + for (int x = 0; x < stations.num; x++) + { + for (int y = 0; y < ESP_WIFI_MAX_CONN_NUM; y++) + { + if (wireless_sta[y].reserved) + { + if (memcmp( wireless_sta[y].mac, stations.sta[x].mac, 6) == 0 ) + { + memcpy(&wireless_sta[y], &stations.sta[x], sizeof(wifi_sta_info_t)); + wireless_sta[y].reserved = 1; + break; + } + } + } + } + + } +} + +// +// Add a station to our list of Stations +// +void Network_Interface_Add_Station(uint16_t index, uint8_t * macAddress) +{ + if (index < ESP_WIFI_MAX_CONN_NUM) + { + memcpy( wireless_sta[index].mac, macAddress , 6); + wireless_sta[index].reserved = 1; + Network_Interface_update_Stations(); + } +} + +// +// Remove a station from our list of stations +void Network_Interface_Remove_Station(uint16_t index) +{ + if (index < ESP_WIFI_MAX_CONN_NUM) + { + wireless_sta[index].reserved = 0; + Network_Interface_update_Stations(); + } +} + +// Return the maximum number of stations +int Network_Interface_Max_Stations() +{ + return ESP_WIFI_MAX_CONN_NUM; +} + +// +// +// +bool Network_Interface_Get_Station(uint16_t index, uint8_t * macAddress, uint8_t * rssi, uint32_t * phyModes) +{ + if (wireless_sta[index].reserved) + { + memcpy(macAddress, wireless_sta[index].mac, 6); + *rssi = wireless_sta[index].rssi; + *phyModes = wireless_sta[index].phy_11b | + (wireless_sta[index].phy_11g << 1) | + (wireless_sta[index].phy_11n << 2) | + (wireless_sta[index].phy_lr << 3); + return true; + } + + return false; +} + +// +// De-Auth connected stations +// +void Network_Interface_Deauth_Station(uint16_t stationIndex) +{ + stationIndex++; + if (stationIndex>=1 && stationIndex<= ESP_WIFI_MAX_CONN_NUM) + { + esp_wifi_deauth_sta(stationIndex); + } +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/targetHAL_Network.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/targetHAL_Network.cpp new file mode 100644 index 00000000..4cc56a0a --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Network/targetHAL_Network.cpp @@ -0,0 +1,261 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// This file includes the board specific Network Intialisation + +#include +#include "Esp32_os.h" +#include "LWIP_Sockets.h" +#include "apps/sntp.h" +#include + +extern "C" void set_signal_sock_function( void (*funcPtr)() ); + +#define WIFI_EVENT_TYPE_SCAN_COMPLETE 1 + +//#define NetEventPrint 1 + + +// +// Callback from LWIP on event +// +void sys_signal_sock_event() +{ + Events_Set(SYSTEM_EVENT_FLAG_SOCKET); +} + +// +// Dummy Ethernet Initialisation, board specific Initialisation in separate file +__nfweak void InitialiseEthernet() +{ +} + +static void PostAddressChanged(uint netIndex) +{ + Network_PostEvent(NetworkEventType_AddressChanged, 0, netIndex); +} + +static void PostAvailabilityOn(uint netIndex) +{ + Network_PostEvent(NetworkEventType_AvailabilityChanged, 1, netIndex); +} + +static void PostAvailabilityOff(uint netIndex) +{ + Network_PostEvent(NetworkEventType_AvailabilityChanged, 0, netIndex); +} + +static void PostScanComplete(uint netIndex) +{ + PostManagedEvent( EVENT_WIFI, WiFiEventType_ScanComplete, 0, netIndex ); +} + +static void PostAPStationChanged(uint connect, uint netInfo) +{ + Network_PostEvent(NetworkEventType_APClientChanged, connect, netInfo); +} + +static void initialize_sntp() +{ + sntp_stop(); + sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_setservername(0, SNTP_SERVER_DEFAULT_ADDRESS); + sntp_init(); +} + +// +// Network event loop handler +// +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + (void)ctx; + int stationIndex; + + #ifdef NetEventPrint + ets_printf("Network event %d\n", event->event_id); + #endif + + switch(event->event_id) + { + // Wifi station events + case SYSTEM_EVENT_STA_START: + // Smart config commented out as giving exception when running + // xTaskCreate(smartconfig_task, "smartconfig_example_task", 4096, NULL, 3, NULL); + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_START\n"); + #endif + break; + + case SYSTEM_EVENT_STA_GOT_IP: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_GOT_IP\n"); + #endif + PostAddressChanged(TCPIP_ADAPTER_IF_STA); + initialize_sntp(); + //xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + break; + + case SYSTEM_EVENT_STA_LOST_IP: + PostAddressChanged(TCPIP_ADAPTER_IF_STA); + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_LOST_IP\n"); + #endif + break; + + case SYSTEM_EVENT_STA_CONNECTED: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_CONNECTED\n"); + #endif + PostAvailabilityOn(TCPIP_ADAPTER_IF_STA); + break; + + case SYSTEM_EVENT_STA_DISCONNECTED: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_DISCONNECTED\n"); + #endif + PostAvailabilityOff(TCPIP_ADAPTER_IF_STA); + esp_wifi_connect(); + //xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + + // Scan of available Wifi networks complete + case SYSTEM_EVENT_SCAN_DONE: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_SCAN_DONE\n"); + #endif + PostScanComplete(TCPIP_ADAPTER_IF_STA); + break; + + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: + // system_event_sta_authmode_change_t *auth_change = &event->event_info.auth_change; + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_AUTHMODE_CHANGE"); + #endif + break; + + case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_WPS_ER_SUCCESS\n"); + #endif + break; + + case SYSTEM_EVENT_STA_WPS_ER_FAILED: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_WPS_ER_FAILED\n"); + #endif + break; + + case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_WPS_ER_TIMEOUT\n"); + #endif + break; + + case SYSTEM_EVENT_STA_WPS_ER_PIN: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_STA_WPS_ER_PIN\n"); + #endif + break; + + // Wireless AP events + case SYSTEM_EVENT_AP_START: + PostAvailabilityOn(TCPIP_ADAPTER_IF_AP); + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_AP_START\n"); + #endif + break; + + case SYSTEM_EVENT_AP_STOP: + PostAvailabilityOff(TCPIP_ADAPTER_IF_AP); + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_AP_STOP\n"); + #endif + break; + + case SYSTEM_EVENT_AP_STACONNECTED: + stationIndex = event->event_info.sta_connected.aid - 1; + Network_Interface_Add_Station(stationIndex, event->event_info.sta_connected.mac); + + // Post the Network interface + Client ID in top 8 bits + PostAPStationChanged(1, TCPIP_ADAPTER_IF_AP + (stationIndex << 8)); + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_AP_STACONNECTED %d\n", event->event_info.sta_connected.aid); + #endif + break; + + case SYSTEM_EVENT_AP_STADISCONNECTED: + stationIndex = event->event_info.sta_connected.aid - 1; + Network_Interface_Remove_Station(stationIndex); + PostAPStationChanged(0, TCPIP_ADAPTER_IF_AP + (stationIndex << 8)); + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_AP_STADISCONNECTED %d\n", event->event_info.sta_disconnected.aid); + PrintStations(); + #endif + break; + + case SYSTEM_EVENT_AP_STA_GOT_IP6: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_AP_STA_GOT_IP6\n"); + #endif + break; + + case SYSTEM_EVENT_AP_PROBEREQRECVED: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_AP_PROBEREQRECVEDxz\n"); + #endif + break; + + // Ethernet events + case SYSTEM_EVENT_ETH_START: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_ETH_START\n"); + #endif + break; + + case SYSTEM_EVENT_ETH_STOP: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_ETH_STOP\n"); + #endif + break; + + case SYSTEM_EVENT_ETH_CONNECTED: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_ETH_CONNECTED\n"); + #endif + PostAvailabilityOn(TCPIP_ADAPTER_IF_ETH); + break; + + case SYSTEM_EVENT_ETH_GOT_IP: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_ETH_GOT_IP\n"); + #endif + PostAddressChanged(TCPIP_ADAPTER_IF_ETH); + initialize_sntp(); + break; + + case SYSTEM_EVENT_ETH_DISCONNECTED: + #ifdef NetEventPrint + ets_printf("SYSTEM_EVENT_ETH_DISCONNECTED\n"); + #endif + PostAvailabilityOff(TCPIP_ADAPTER_IF_ETH); + break; + + default: + break; + } + + return ESP_OK; +} + +void nanoHAL_Network_Initialize() +{ + // Initialise the Lwip CLR signal callback + set_signal_sock_function( &sys_signal_sock_event ); + + // Initialise Tcp adpater + tcpip_adapter_init(); + + esp_event_loop_init(event_handler, NULL); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/README.md b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/README.md new file mode 100644 index 00000000..be005778 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/README.md @@ -0,0 +1,10 @@ +# ESP32 WROOM-32 + +This reference target _fits_ all EPS32 boards carrying an ESP32-WROOM-32 module. + +Check the details at the documentation website [here](http://docs.nanoframework.net/articles/reference-targets/esp32-wroom-32.html) + +Getting started guides and build instructions can also be found at the documentation website: + +- [Build instructions](https://docs.nanoframework.net/content/getting-started-guides/build-esp32.html) +- [Getting started with managed code (C#)](https://docs.nanoframework.net/content/getting-started-guides/getting-started-managed.html) diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Target_Windows_Storage.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Target_Windows_Storage.c new file mode 100644 index 00000000..557e977d --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/Target_Windows_Storage.c @@ -0,0 +1,161 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// +// Initialise SD card and mount on VFS +// Supports MMC and SPI SD cards +// MMC supports 4bit or 1 bit + +// == Boards == +// OLimex EVB - 1 bit SD/MMC ( DAT0 - GPIO2, CMD/DI - GPIO15 ), No Card detect, No Write protect +// Wrover V4 - 4 bit SD/MMC ( Card detect ) +// D0 = 2, D1 = 4, D2 = 12, D3 = 13 +// CLK = 14, CMD = 15, DETECT = 21 + + +// SPI test +// MISO = 2, MOSI = 15, CLK = 14, CS = 15 + +// 5 VSPICS0 (cs) +// 18 VSPICLK (clockPin) * +// 19 VSPIQ (miso) * +// 21 VSPIHD (HD) +// 22 VSPIWP (WP) +// 23 VSPID (mosi) * + +#include +#include +#include +#include +#include "esp_err.h" +#include "esp_log.h" +#include "esp_vfs_fat.h" +#include "driver/sdmmc_host.h" +#include "driver/sdspi_host.h" +#include "sdmmc/include/sdmmc_cmd.h" +#include + +static const char *TAG = "SDCard"; + +// Pin mapping when using SPI mode. +// With this mapping, SD card can be used both in SPI and 1-line SD mode. +// Note that a pull-up on CS line is required in SD mode. +//#define PIN_NUM_MISO 2 +//#define PIN_NUM_MOSI 15 +//#define PIN_NUM_CLK 14 +//#define PIN_NUM_CS 13 + +#if defined(HAL_USE_SDC) + +bool Storage_UnMountSDCard() +{ + if (esp_vfs_fat_sdmmc_unmount() != ESP_OK) + return false; + + return true; +} + +// +// Mount the SDCard device as a FAT device on the VFS +// +bool Storage_MountSDCard(char * vfsName, sdmmc_host_t * host, void* slot_config, bool formatOnMount, int maxFiles ) +{ + + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = formatOnMount, + .max_files = maxFiles, + .allocation_unit_size = 16 * 1024 + }; + + sdmmc_card_t* card; + esp_err_t ret = esp_vfs_fat_sdmmc_mount(vfsName, host, (sdmmc_slot_config_t*)slot_config, &mount_config, &card); + if (ret == ESP_ERR_INVALID_STATE) + { + // Invalid state means its already mounted, this can happen if you are trying to debug mount from managed code + // and the code has already run & mounted + Storage_UnMountSDCard(); + ret = esp_vfs_fat_sdmmc_mount(vfsName, host, (sdmmc_slot_config_t*)slot_config, &mount_config, &card); + } + + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount filesystem. "); + } + else { + ESP_LOGE(TAG, "Failed to initialize the card (%s). ", esp_err_to_name(ret)); + } + return false; + } + + return true; +} + + +// Storage_InitSDCardMMC +// Initial the SD card Slot 1 - 4/1 bit ( hs2_* signals ) +// +// vfsName - Name of disk for vfs - i.e "/SDSPI" +// maxFiles- Maximum number of open files +// bit1Mode- true to use 1 bit MMC interface +// +// return true if OK +// +bool Storage_InitSDCardMMC(char * vfsName, int maxFiles, bool bit1Mode) +{ + ESP_LOGI(TAG, "Initializing MMC SD card"); + + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + + // Using 1 bit data ( OLimex EVB etc ) + if (bit1Mode) + { + host.flags = SDMMC_HOST_FLAG_1BIT; + host.max_freq_khz = SDMMC_FREQ_PROBING; + } + + // This initializes the slot without card detect (CD) and write protect (WP) signals. + // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + + // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups. + // Internal pull-ups are not sufficient. However, enabling internal pull-ups + // does make a difference some boards, so we do that here. + gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes + gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes + + if (!bit1Mode) + { + gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only + gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only + gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4-line modes only + } + + return Storage_MountSDCard(vfsName, &host, &slot_config, false, maxFiles); +} + +// Storage_InitSDCardSPI +// Initial the SD card connected by SPI) +// +// vfsName - Name of disk for vfs - i.e "/SDSPI" +// maxFiles- Maximum number of open files +// +// return true if OK +// +bool Storage_InitSDCardSPI(char * vfsName, int maxFiles, int pin_Miso, int pin_Mosi, int pin_Clk, int pin_Cs) +{ + ESP_LOGI(TAG, "Initializing SPI SD card"); + + sdmmc_host_t host = SDSPI_HOST_DEFAULT(); + sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); + slot_config.gpio_miso = pin_Miso; + slot_config.gpio_mosi = pin_Mosi; + slot_config.gpio_sck = pin_Clk; + slot_config.gpio_cs = pin_Cs; + + return Storage_MountSDCard(vfsName, &host, &slot_config, false, maxFiles); +} + +#endif + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/CMakeLists.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/CMakeLists.txt new file mode 100644 index 00000000..c6518ee9 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append target ESP32 source files +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platform_heap.c") + +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_ReceiverThread.c") +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_HAL_Interface.c") + +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Target_BlockStorage_ESP32FlashDriver.c") +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platform_BlockStorage.c") +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage.c") + + +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/FreeRTOS-openocd.c") + +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Esp32_DeviceMapping.cpp") + +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/GenericPort.cpp") + +# append nanoHAL +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL.c") +list(APPEND TARGET_ESP32_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Time.cpp") + +# make vars global +set(TARGET_ESP32_COMMON_SOURCES ${TARGET_ESP32_COMMON_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Device_BlockStorage.c new file mode 100644 index 00000000..f913b4ab --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Device_BlockStorage.c @@ -0,0 +1,137 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +#include +#include + +// the block ranges mirror the partition table +// spliting each partition on it's own block range is required to use memory mapping + + +const BlockRange BlockRange1[] = +{ + // factory + { BlockRange_BLOCKTYPE_CODE , 0, 0 }, // 0x010000 nanoCLR +}; + +const BlockRange BlockRange2[] = +{ + // deploy + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 0 }, // 0x110000 deployment +}; + +const BlockRange BlockRange3[] = +{ + // config + { BlockRange_BLOCKTYPE_CONFIG , 0, 0 } // 0x2D0000 config +}; + +BlockRegionInfo BlockRegions[] = +{ + // nanoCLR + { + (0), // no attributes for this region + 0x010000, // start address for block region + 1, // total number of blocks in this region + 0x100000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + // Deployment area + { + (BlockRegionAttribute_MemoryMapped), // this region is memory mapped + 0x110000, // start address for block region + 1, // total number of blocks in this region + 0x70000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + // Config, SPIFS partition + { + (0), // no attributes for this region + 0x0, // start address for block region + 1, // total number of blocks in this region + 0x10000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + } +}; + + +const DeviceBlockInfo Device_BlockInfo = +{ + (0), // ESP32 storage doesn't supports XIP, instead it provides memory mapped read access to SPI storage + 1, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; + + + +// +// Fix up Block region info based on current partion layout +// +void FixUpBlockRegionInfo() +{ + // nanoCLR + const esp_partition_t * part_nanoClr = esp_partition_find_first(ESP_PARTITION_TYPE_APP, 0, 0); + if (part_nanoClr) + { + BlockRegions[0].Start = part_nanoClr->address; + BlockRegions[0].BytesPerBlock = part_nanoClr->size; + } + // Deployment + const esp_partition_t * part_deploy = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, 0x84, 0); + if (part_deploy) + { + BlockRegions[1].Start = part_deploy->address; + BlockRegions[1].BytesPerBlock = part_deploy->size; + } + + // Config + const esp_partition_t * part_config = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, 0); + if (part_config) + { + BlockRegions[2].Start = part_config->address; + BlockRegions[2].BytesPerBlock = part_config->size; + } + +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Esp32_DeviceMapping.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Esp32_DeviceMapping.cpp new file mode 100644 index 00000000..c8c637af --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Esp32_DeviceMapping.cpp @@ -0,0 +1,199 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "Esp32_os.h" +#include "Esp32_DeviceMapping.h" + + +// SPI +// 2 devices +// Map pins mosi, miso, clock +// +int8_t Esp32_SPI_DevicePinMap[2][3] = +{ + {GPIO_NUM_23, GPIO_NUM_25, GPIO_NUM_19}, // SPI1 - Wrover SPI display pins + {-1, -1, -1} // SPI2 - no pins assigned +}; + +// Serial +// 3 devices COM1,COM2, COM3 ( UART_NUM_0, UART_NUM_1, UART_NUM_2 ) +// Map pins Tx, RX, RTS, CTS +// Set default direct pins +int8_t Esp32_SERIAL_DevicePinMap[3][4] = +{ + // COM 1 - pins 1, 3, 19, 22 + {UART_NUM_0_TXD_DIRECT_GPIO_NUM, UART_NUM_0_RXD_DIRECT_GPIO_NUM, UART_NUM_0_RTS_DIRECT_GPIO_NUM, UART_NUM_0_CTS_DIRECT_GPIO_NUM}, + + // COM 2 - 10, 9, 6, 11 + {UART_NUM_1_TXD_DIRECT_GPIO_NUM, UART_NUM_1_RXD_DIRECT_GPIO_NUM, UART_NUM_1_RTS_DIRECT_GPIO_NUM, UART_NUM_1_CTS_DIRECT_GPIO_NUM}, + + // COM3 - 17, 16, 8, 7 + {UART_NUM_2_TXD_DIRECT_GPIO_NUM, UART_NUM_2_RXD_DIRECT_GPIO_NUM, UART_NUM_2_RTS_DIRECT_GPIO_NUM, UART_NUM_2_CTS_DIRECT_GPIO_NUM} + }; + +// ============================================= +// I2C +// 2 devices I2C1 & I2C2 +// Map pins Data & Clock +int8_t Esp32_I2C_DevicePinMap[2][2] = +{ + // I2C1 - pins 18, 19, + {I2C1_DATA, I2C1_CLOCK}, + // I2C2 - pins 25, 26 + {I2C2_DATA, I2C2_CLOCK} +}; + +// ============================================= +// LED PWM +// 16 channels LED1 to LED16 or PWM1 to PWM16 +// Map pins Data & Clock +int8_t Esp32_LED_DevicePinMap[16] = +{ + // Channels ( non assigned ) + -1, // 1 + -1, // 2 + -1, // 3 + -1, // 4 + -1, // 5 + -1, // 6 + -1, // 7 + -1, // 8 + -1, // 9 + -1, // 10 + -1, // 11 + -1, // 12 + -1, // 13 + -1, // 14 + -1, // 15 + -1, // 16 +}; + +// We use "ADC1" for 20 logical channels +// Mapped to ESP32 controllers +// ESP32 ADC1 channels 0 - 7 +// " ADC1 channel 8 - Internal Temperture sensor (VP) +// " ADC1 channel 9 - Internal Hall Sensor (VN) +// " ADC2 channels 10 - 19 +int8_t Esp32_ADC_DevicePinMap[20] = +{ + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 36, 37, 38, 39, 32, 33, 34, 35, 36, 39, 04, 00, 02, 15, 13, 12, 14, 27, 25, 26 +}; + +// +// We use "DAC1" for 2 DAC channels on ESP32 +// These are fixed pins so can't be re-assigned +// +int8_t Esp32_DAC_DevicePinMap[2] = +{ + // 0 1 + 25, 26 +}; + +void Esp32_DecodeAlternateFunction(uint32_t alternateFunction, Esp32_MapDeviceType & deviceType, uint8_t & busIndex, uint16_t & PinIndex) +{ + deviceType = (Esp32_MapDeviceType)((alternateFunction >> 16) & 0x00ff); + busIndex = (uint8_t)((alternateFunction >> 8) & 0x00ff) - 1; + PinIndex = (uint16_t)(alternateFunction & 0x00ff); +} + +int Esp32_GetMappedDevicePins( Esp32_MapDeviceType deviceType, int DevNumber, int PinIndex) +{ + if ( DevNumber >= 0) + { + switch( deviceType ) + { + case DEV_TYPE_SPI: + return (int)Esp32_SPI_DevicePinMap[DevNumber][PinIndex]; + + case DEV_TYPE_I2C: + return (int)Esp32_I2C_DevicePinMap[DevNumber][PinIndex]; + + case DEV_TYPE_SERIAL: + return (int)Esp32_SERIAL_DevicePinMap[DevNumber][PinIndex]; + + case DEV_TYPE_LED_PWM: + return (int)Esp32_LED_DevicePinMap[DevNumber]; + + case DEV_TYPE_ADC: + return (int)Esp32_ADC_DevicePinMap[PinIndex]; + + case DEV_TYPE_DAC: + return (int)Esp32_DAC_DevicePinMap[PinIndex]; + + default: + break; + }; + } + return -1; +} + +int Esp32_GetMappedDevicePinsWithFunction(uint32_t alternateFunction) +{ + Esp32_MapDeviceType deviceType; + uint8_t deviceIndex; + uint16_t pinIndex; + + Esp32_DecodeAlternateFunction(alternateFunction, deviceType, deviceIndex, pinIndex); + + return Esp32_GetMappedDevicePins(deviceType, deviceIndex, pinIndex); +} + + +// Esp32_SetMappedDevicePins +// +// alternateFunction 32 bit integer where 00DDIIFF +// DD= device type +// II= device index 1,2,3 etc +// FF= functional pin i.e data, clock, tx,rx +// +void Esp32_SetMappedDevicePins( uint8_t pin, int32_t alternateFunction ) +{ + Esp32_MapDeviceType deviceType; + uint8_t deviceIndex; + uint16_t mapping; + + Esp32_DecodeAlternateFunction(alternateFunction, deviceType, deviceIndex, mapping); + + // Set the pins used by a device type / index + switch( deviceType ) + { + case DEV_TYPE_GPIO: + // Just opening a GPIO pin will set it to GPIO function + break; + + case DEV_TYPE_SPI: + if (deviceIndex <= 1 && mapping <= 2) + { + Esp32_SPI_DevicePinMap[deviceIndex][mapping] = pin; + } + break; + + case DEV_TYPE_I2C: + if (deviceIndex <= 1 && mapping <= 1) + { + Esp32_I2C_DevicePinMap[deviceIndex][mapping] = pin; + } + break; + + case DEV_TYPE_SERIAL: + if (deviceIndex <= 2 && mapping <= 3) + { + Esp32_SERIAL_DevicePinMap[deviceIndex][mapping] = pin; + } + break; + + case DEV_TYPE_LED_PWM: + if (deviceIndex <= 15 ) + { + Esp32_LED_DevicePinMap[deviceIndex] = pin; + } + break; + + + default: // ignore + break; + } +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/FreeRTOS-openocd.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/FreeRTOS-openocd.c new file mode 100644 index 00000000..1960231b --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/FreeRTOS-openocd.c @@ -0,0 +1,24 @@ +/* + * Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer + * present in the kernel, so it has to be supplied by other means for + * OpenOCD's threads awareness. + * + * Add this file to your project, and, if you're using --gc-sections, + * ``--undefined=uxTopUsedPriority'' (or + * ``-Wl,--undefined=uxTopUsedPriority'' when using gcc for final + * linking) to your LDFLAGS; same with all the other symbols you need. + */ + +#include "FreeRTOS.h" +#include "esp_attr.h" +#include "sdkconfig.h" + +#ifdef __GNUC__ +#define USED __attribute__((used)) +#else +#define USED +#endif + +//#ifdef CONFIG_ESP32_DEBUG_OCDAWARE +const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1; +//#endif \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/GenericPort.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/GenericPort.cpp new file mode 100644 index 00000000..e219b941 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/GenericPort.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +#include "nanoCLR_Types.h" +#include "nanoCLR_Runtime.h" + +uint32_t GenericPort_Write( int portNum, const char* data, size_t size ) +{ + // FIXME + // It's only enabled if the C# programm is in running mode and no source level debugger (C# debugger) + // is attached. In all other conditions it's better to be quiet. + // If the debugger is attached we don't output the data because the debugger use the same serial link. + // Maybe later it can also redirect output to the ESP32 app trace + // which is redirected to JTAG/openocd interface + (void)portNum; + if (g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions == CLR_RT_ExecutionEngine::c_fDebugger_StateProgramRunning) + { + char* p = (char*)data; + int counter = 0; + + // send characters directly to the trace port + while(*p != '\0' || counter < (int)size) + { + ets_printf( "%c", *p++); + counter++; + } + return counter; + } + else + { + return (uint32_t)size; + } +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Target_BlockStorage_ESP32FlashDriver.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Target_BlockStorage_ESP32FlashDriver.c new file mode 100644 index 00000000..1021d492 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/Target_BlockStorage_ESP32FlashDriver.c @@ -0,0 +1,269 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +extern int ets_printf(const char *fmt, ...); + +const DRAM_ATTR esp_partition_t * g_pFlashDriver_partition; +const void * g_esp32_flash_start_ptr; +spi_flash_mmap_handle_t g_esp32_flash_out_handle; + +static const char* TAG = "FlashDriver"; + +bool Esp32FlashDriver_InitializeDevice(void* context) +{ + (void)context; + + //ets_printf("InitializeDevice enter\n"); + + g_esp32_flash_start_ptr = NULL; + + // Find the application partition and save partition entry + g_pFlashDriver_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NANOCLR, NULL); + if (g_pFlashDriver_partition == NULL) + { + ESP_LOGE(TAG, "InitializeDevice failed\n"); + return false; + } + + //ets_printf("InitializeDevice partition found\n"); + + // Map Partition into memory + if (esp_partition_mmap(g_pFlashDriver_partition, 0, g_pFlashDriver_partition->size, SPI_FLASH_MMAP_DATA, &g_esp32_flash_start_ptr, &g_esp32_flash_out_handle) != ESP_OK) + { + ESP_LOGE(TAG, "Map memory failed\n"); + return false; + } + + //ets_printf("InitializeDevice flash adr %X mapped %X\n", g_pFlashDriver_partition->address, g_esp32_flash_start_ptr); + + return true; +} + +bool Esp32FlashDriver_UninitializeDevice(void* context) +{ + (void)context; + + // Unmap the flash memory + if (g_esp32_flash_start_ptr != NULL) + { + spi_flash_munmap(g_esp32_flash_out_handle); + g_esp32_flash_start_ptr = NULL; + } + + return true; +} + +DeviceBlockInfo* Esp32FlashDriver_GetDeviceInfo(void* context) +{ + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = context; + + return config->BlockConfig.BlockDeviceInformation; +} + +bool Esp32FlashDriver_Read(void* context, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer) +{ + // ets_printf("Flash Read adr %X bytes %X target %X\n", startAddress, numBytes, buffer); + + uint32_t regionIndex, rangeIndex; + unsigned char* memStartAdr = NULL; + + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; + DeviceBlockInfo* deviceInfo = config->BlockConfig.BlockDeviceInformation; + + if(!DeviceBlockInfo_FindRegionFromAddress(deviceInfo, startAddress, ®ionIndex, &rangeIndex)) + { + return false; + } + + BlockRegionInfo* region = &deviceInfo->Regions[regionIndex]; + ByteAddress readAddress = BlockRegionInfo_OffsetFromBlock(region, startAddress); + + // setup memory mapped start address + switch(BlockRange_GetBlockUsage(deviceInfo->Regions[regionIndex].BlockRanges[rangeIndex])) + { + case BlockUsage_CODE: + memStartAdr = 0; + break; + + case BlockUsage_DEPLOYMENT: + memStartAdr = (unsigned char *)g_esp32_flash_start_ptr + readAddress; + break; + + default: + return false; + } + + // sanity check for region address overflowing + if ((readAddress + numBytes) > BlockRegionInfo_Size(region) ) + { + ESP_LOGE(TAG, "Invalid Invalid flash address/length\n"); + return false; + } + + // copy from memory mapped address to buffer + memcpy(buffer, memStartAdr, numBytes); + + //ets_printf("Flash Read memStartAdr %X memEndAdr %X Target %X\n", memStartAdr, memStartAdr + numBytes, buffer); + + return true; +} + +bool Esp32FlashDriver_Write(void* context, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite) +{ + uint32_t regionIndex, rangeIndex; + + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; + DeviceBlockInfo* deviceInfo = config->BlockConfig.BlockDeviceInformation; + if(!DeviceBlockInfo_FindRegionFromAddress(deviceInfo, startAddress, ®ionIndex, &rangeIndex)) + { + return false; + } + + BlockRegionInfo* region = &deviceInfo->Regions[regionIndex]; + ByteAddress offsetAddress = BlockRegionInfo_OffsetFromBlock(region, startAddress); + + //ets_printf("Flash write adr %X bytes %X src %X\n", startAddress, numBytes, buffer); + + // Check in range of partition + if (numBytes > (BlockRegionInfo_Size(region) - offsetAddress)) + { + ESP_LOGE(TAG, "Invalid Invalid flash address/length\n"); + return false; + } + + if (readModifyWrite) + { + return false; + } + + // write buffer to partition + if (esp_partition_write(g_pFlashDriver_partition, offsetAddress, (const void*)buffer, (size_t)numBytes) != ESP_OK) + { + return false; + } + + return true; +} + +bool Esp32FlashDriver_IsBlockErased(void* context, ByteAddress blockAddress, unsigned int length) +{ + uint32_t regionIndex, rangeIndex; + unsigned char* memStartAdr = NULL; + unsigned char* memEndAdr = NULL; + + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; + DeviceBlockInfo* deviceInfo = config->BlockConfig.BlockDeviceInformation; + if(!DeviceBlockInfo_FindRegionFromAddress(deviceInfo, blockAddress, ®ionIndex, &rangeIndex)) + { + return false; + } + + BlockRegionInfo* region = &deviceInfo->Regions[regionIndex]; + + // get memory mapped start address + switch(BlockRange_GetBlockUsage(deviceInfo->Regions[regionIndex].BlockRanges[rangeIndex])) + { + case BlockUsage_CODE: + memStartAdr = 0; + break; + + case BlockUsage_DEPLOYMENT: + memStartAdr = (unsigned char *)g_esp32_flash_start_ptr; + break; + + default: + return false; + } + + // end address + memEndAdr = memStartAdr + length; + + //ets_printf("IsBlockErased %X %X start mem %X\n", blockAddress, length, g_esp32_flash_start_ptr); + + if ( length > BlockRegionInfo_Size(region)) + { + ESP_LOGE(TAG, "Invalid Invalid flash address/length\n"); + return false; + } + + //ets_printf("IsBlockErased mem start %X end %X\n", memStartAdr, memEndAdr); + + // go through memory anf check for content other than 0xFF (flash erased value) + while (memStartAdr < memEndAdr) + { + if (*memStartAdr != 0xff) + { + //ets_printf("IsBlockErased exit FALSE\n"); + return false; + } + memStartAdr++; + } + + //ets_printf("IsBlockErased exit true\n"); + + return true; +} + +bool Esp32FlashDriver_EraseBlock(void* context, ByteAddress address) +{ + uint32_t regionIndex, rangeIndex; + + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; + DeviceBlockInfo* deviceInfo = config->BlockConfig.BlockDeviceInformation; + if(!DeviceBlockInfo_FindRegionFromAddress(deviceInfo, address, ®ionIndex, &rangeIndex)) + { + return false; + } + + BlockRegionInfo* region = &deviceInfo->Regions[regionIndex]; + ByteAddress startAddress = BlockRegionInfo_OffsetFromBlock(region, address); + uint32_t size = BlockRegionInfo_Size(region); + + //ets_printf("EraseBlock start part adr:%X start mem: %X size:%X erase adr:%X\n", g_pFlashDriver_partition->address, g_esp32_flash_start_ptr, g_pFlashDriver_partition->size, address); + //ets_printf("EraseBlock start addr %X\n", start_addr); + + if (esp_partition_erase_range(g_pFlashDriver_partition, startAddress, size) != ESP_OK) + { + ESP_LOGE(TAG, "EraseBlock Fail\n"); + return false; + } + + //ets_printf("EraseBlock OK\n"); + + return true; +} + +bool Esp32FlashDriver_GetMemoryMappedAddress(void* context, unsigned int blockRegionIndex, unsigned int blockRangeIndex, unsigned int* address) +{ + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; + DeviceBlockInfo* deviceInfo = config->BlockConfig.BlockDeviceInformation; + + #if defined(DEBUG) + // sanity check for non-existent block region + if(blockRegionIndex > (deviceInfo->NumRegions + 1)) + { + return false; + } + #endif + + switch(BlockRange_GetBlockUsage(deviceInfo->Regions[blockRegionIndex].BlockRanges[blockRangeIndex])) + { + case BlockUsage_CODE: + *address = 0; + break; + + case BlockUsage_DEPLOYMENT: + *address = (unsigned int)g_esp32_flash_start_ptr; + break; + + default: + return false; + } + + return true; +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_HAL_Interface.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_HAL_Interface.c new file mode 100644 index 00000000..ce87a44d --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_HAL_Interface.c @@ -0,0 +1,142 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#include + +#include +#include +#include +#include + +WP_Message inboundMessage; + +bool WP_Initialise(COM_HANDLE port); + +//////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////// +// The functions below are the ones that need to be ported to new channels/HALs when required +// These are to be considered as a reference implementations when working on new ports +// +// This reference implementation provides communication through: +// - serial port (UART/USART) +// +//////////////////////////////////////////////////////////////////////////////////////////////// +#if (HAL_USE_SERIAL == TRUE) + +static bool WP_Port_Intitialised = false; +static uart_port_t WP_Port = UART_NUM_0; + +#define ESP32_UART_RXD_PINS {3,32,16} +#define ESP32_UART_TXD_PINS {1,33,17} +#define ESP32_UART_CTS_PINS {19,6,8} +#define ESP32_UART_RTS_PINS {22,11,7} + + +// Pins +static const char g_ESP32_Uart_RxD_Pins[] = ESP32_UART_RXD_PINS; +static const char g_ESP32_Uart_TxD_Pins[] = ESP32_UART_TXD_PINS; + + +bool WP_Initialise(COM_HANDLE port) +{ + (void)port; + + if ( WP_Port > UART_NUM_2 ) return false; + + uart_config_t uart_config = { + .baud_rate = 921600, //baudrate + .data_bits = UART_DATA_8_BITS, //data bit mode + .parity = UART_PARITY_DISABLE, //parity mode + .stop_bits = UART_STOP_BITS_1, //stop bit mode + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, //hardware flow control(cts/rts) + .rx_flow_ctrl_thresh = 120, //flow control threshold + }; + + uart_param_config(WP_Port, &uart_config); + + uart_set_pin(WP_Port, g_ESP32_Uart_TxD_Pins[WP_Port], g_ESP32_Uart_RxD_Pins[WP_Port], UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + + // Setup UART driver(without UART queue) + uart_driver_install(WP_Port, 1024 * 2, 512, 0, NULL, 0); + + WP_Port_Intitialised = true; + + return true; +} + + +int WP_ReceiveBytes(uint8_t* ptr, uint16_t* size) +{ + // TODO: Initialise Port if not already done, Wire Protocol should be calling this directly at startup + if (!WP_Port_Intitialised) WP_Initialise(WP_Port); + + // save for latter comparison + uint16_t requestedSize = *size; + + //int readData = 0; + // sanity check for request of 0 size + if(*size) + { + ////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + ////////////////////////////////////////////////////////// + // change here to read (size) bytes from the input stream + // preferably with read timeout and being able to check + // if the requested number of bytes was actually read + ////////////////////////////////////////////////////////// + + // non blocking read from serial port with 100ms timeout + volatile size_t read = uart_read_bytes( WP_Port, ptr, (uint32_t)requestedSize, (TickType_t) 100 / portTICK_PERIOD_MS); + + ptr += read; + *size -= read; + + // check if the requested read matches the actual read count + return (requestedSize == read); + } + + return true; +} + +#else +#error "Wire Protocol needs a transport. Please make sure that HAL_USE_SERIAL and/or HAL_USE_SERIAL_USB are set to TRUE in 'halconf.h'" +#endif + +#if (HAL_USE_SERIAL == TRUE) + +int WP_TransmitMessage(WP_Message* message) +{ + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // change here to write (size) bytes to the output stream + // preferably with timeout and being able to check + // if the write was sucessfull or at least buffered + ////////////////////////////////////////////////////////// + + if (!WP_Port_Intitialised) WP_Initialise(WP_Port); + + //TODO Check if timeout required + // write header to output stream + + if ( uart_write_bytes( WP_Port, (const char*)&message->m_header, sizeof(message->m_header) ) != sizeof(message->m_header)) return false; + + // if there is anything on the payload send it to the output stream + if(message->m_header.m_size && message->m_payload) + { + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // see description above + ////////////////////////////////////////////////////////// + if (uart_write_bytes(WP_Port, (const char*)message->m_payload, message->m_header.m_size ) != (int)message->m_header.m_size ) return false; + } + + return true; +} + +#else +#error "Wire Protocol needs a transport. Please make sure that HAL_USE_SERIAL and/or HAL_USE_SERIAL_USB are set to TRUE in 'halconf.h'" +#endif + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_ReceiverThread.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_ReceiverThread.c new file mode 100644 index 00000000..ba1c1292 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/WireProtocol_ReceiverThread.c @@ -0,0 +1,33 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "WireProtocol_HAL_Interface.h" + +extern WP_Message inboundMessage; + +void WP_Message_Initialize(WP_Message* a); +void WP_Message_PrepareReception(WP_Message* a); +void WP_Message_Process(WP_Message* a); + + +void ReceiverThread(void const * argument) +{ + (void)argument; + + // loop forever + while (1) { + + WP_Message_Initialize(&inboundMessage); + WP_Message_PrepareReception(&inboundMessage); + + WP_Message_Process(&inboundMessage); + + // Allow other tasks a chance to run + vTaskDelay(0); + } + + // nothing to deinitialize or cleanup, so it's safe to return +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/mbedtls_entropy_hardware_pool.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/mbedtls_entropy_hardware_pool.c new file mode 100644 index 00000000..542b3ddb --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/mbedtls_entropy_hardware_pool.c @@ -0,0 +1,25 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +// Get len bytes of entropy from the hardware RNG. +int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen ) +{ + (void)data; + + for(size_t i = 0; i < len; i++) + { + // our generator returns 32bits numbers + *output = (unsigned char)esp_random(); + + output++; + } + + // callers require this to be set + *olen = len; + + return 0; +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_BlockStorage.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_BlockStorage.c new file mode 100644 index 00000000..f1e22e9c --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_BlockStorage.c @@ -0,0 +1,22 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// map here the Block Storage Interface to the ESP32 driver +IBlockStorageDevice ESP32Flash_BlockStorageInterface = +{ + &Esp32FlashDriver_InitializeDevice, + &Esp32FlashDriver_UninitializeDevice, + &Esp32FlashDriver_GetDeviceInfo, + &Esp32FlashDriver_Read, + &Esp32FlashDriver_Write, + NULL, + &Esp32FlashDriver_IsBlockErased, + &Esp32FlashDriver_EraseBlock, + NULL, + &Esp32FlashDriver_GetMemoryMappedAddress, +}; diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_heap.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_heap.c new file mode 100644 index 00000000..6eaecdac --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/platform_heap.c @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void* platform_malloc(size_t size) { + return malloc(size); +} + +void platform_free(void* ptr) { + free(ptr); +} + +void* platform_realloc(void* ptr, size_t size) { + return realloc(ptr, size); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL.c new file mode 100644 index 00000000..35dac5ad --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL.c @@ -0,0 +1,50 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +inline void HAL_AssertEx() +{ + asm("break.n 1"); + while(true) { /*nop*/ } +} + +#if !defined(BUILD_RTM) + +inline void HARD_Breakpoint() +{ + asm("break.n 1"); + while(true) { /*nop*/ } +}; + +#endif // !defined(BUILD_RTM) + +// Provides information whether the configuration block storage requires erase command before sending the update command +// ESP32 is storing this using its non-volatile storage therefore no erase is required. +__nfweak bool Target_ConfigUpdateRequiresErase() +{ + return false; +}; + +inline bool Target_HasNanoBooter() +{ + return false; +}; + +// declarations of platform capabilities +uint32_t GetPlatformCapabilities() +{ + return 0; +}; + +// declarations of target capabilities +// If a target has something to declare it has to provide a 'strong' implementation of this. +__nfweak uint32_t GetTargetCapabilities() +{ + return 0; +}; + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL_Time.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL_Time.cpp new file mode 100644 index 00000000..1de75c87 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/common/targetHAL_Time.cpp @@ -0,0 +1,25 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +// Converts FreeRTOS Tickcount to .NET ticks (100 nanoseconds) +uint64_t HAL_Time_SysTicksToTime(unsigned int sysTicks) +{ + return (((int64_t)sysTicks * (int64_t)1000000 + (int64_t)configTICK_RATE_HZ - 1) / (int64_t)configTICK_RATE_HZ) * 10; +} + +// because HAL_Time_SysTicksToTime needs to be called from C we need a proxy to allow it to be called from 'C' code +extern "C" { + + uint64_t HAL_Time_SysTicksToTime_C(unsigned int sysTicks) + { + return HAL_Time_SysTicksToTime(sysTicks); + } +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32.project.ld b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32.project.ld new file mode 100644 index 00000000..c1b973dd --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32.project.ld @@ -0,0 +1,620 @@ +/* Automatically generated file; DO NOT EDIT */ +/* Espressif IoT Development Framework Linker Script */ +/* Generated from: C:/esp32_tools/esp-idf-v3.3/components/esp32/ld/esp32.project.ld.in */ + +/* Default entry point: */ +ENTRY(call_start_cpu0); + +SECTIONS +{ + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + + *( .rtc.literal .rtc.text .rtc.text.*) + + *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + _rtc_text_end = ABSOLUTE(.); + } > rtc_iram_seg + + /* + This section is required to skip rtc.text area because rtc_iram_seg and + rtc_data_seg are reflect the same address space on different buses. + */ + .rtc.dummy : + { + _rtc_dummy_start = ABSOLUTE(.); + _rtc_fast_start = ABSOLUTE(.); + . = SIZEOF(.rtc.text); + _rtc_dummy_end = ABSOLUTE(.); + } > rtc_data_seg + + /* This section located in RTC FAST Memory area. + It holds data marked with RTC_FAST_ATTR attribute. + See the file "esp_attr.h" for more information. + */ + .rtc.force_fast : + { + . = ALIGN(4); + _rtc_force_fast_start = ABSOLUTE(.); + *(.rtc.force_fast .rtc.force_fast.*) + . = ALIGN(4) ; + _rtc_force_fast_end = ABSOLUTE(.); + } > rtc_data_seg + + /* RTC data section holds RTC wake stub + data/rodata, including from any source file + named rtc_wake_stub*.c and the data marked with + RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. + The memory location of the data is dependent on + CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + + *( .rtc.data .rtc.data.* .rtc.rodata .rtc.rodata.*) + + *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } > rtc_data_location + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) + *rtc_wake_stub*.*(COMMON) + + *( .rtc.bss) + + _rtc_bss_end = ABSOLUTE(.); + } > rtc_data_location + + /* This section holds data that should not be initialized at power up + and will be retained during deep sleep. + User data marked with RTC_NOINIT_ATTR will be placed + into this section. See the file "esp_attr.h" for more information. + The memory location of the data is dependent on + CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. + */ + .rtc_noinit (NOLOAD): + { + . = ALIGN(4); + _rtc_noinit_start = ABSOLUTE(.); + *(.rtc_noinit .rtc_noinit.*) + . = ALIGN(4) ; + _rtc_noinit_end = ABSOLUTE(.); + } > rtc_data_location + + /* This section located in RTC SLOW Memory area. + It holds data marked with RTC_SLOW_ATTR attribute. + See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4) ; + _rtc_force_slow_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Get size of rtc slow data based on rtc_data_location alias */ + _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_slow_end - _rtc_data_start) + : (_rtc_force_slow_end - _rtc_force_slow_start); + + _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_fast_end - _rtc_fast_start) + : (_rtc_noinit_end - _rtc_fast_start); + + ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)), + "RTC_SLOW segment data does not fit.") + + ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)), + "RTC_FAST segment data does not fit.") + + /* Send .iram0 code to iram */ + .iram0.vectors : + { + _iram_start = ABSOLUTE(.); + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + } > iram0_0_seg + + .iram0.text : + { + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + *( .iram1 .iram1.*) + *libspi_flash.a:spi_flash_rom_patch.*( .literal .literal.* .text .text.*) + *libesp_ringbuf.a:( .literal .literal.* .text .text.*) + *libhal.a:( .literal .literal.* .text .text.*) + *libapp_trace.a:( .literal .literal.* .text .text.*) + *libesp32.a:panic.*( .literal .literal.* .text .text.*) + *libespcoredump.a:core_dump_port.*( .literal .literal.* .text .text.*) + *libespcoredump.a:core_dump_common.*( .literal .literal.* .text .text.*) + *libespcoredump.a:core_dump_flash.*( .literal .literal.* .text .text.*) + *libespcoredump.a:core_dump_uart.*( .literal .literal.* .text .text.*) + *librtc.a:( .literal .literal.* .text .text.*) + *libgcc.a:lib2funcs.*( .literal .literal.* .text .text.*) + *libsoc.a:cpu_util.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_clk.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_init.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_periph.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_clk_init.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_wdt.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_sleep.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_pm.*( .literal .literal.* .text .text.*) + *libsoc.a:rtc_time.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strftime.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-timelocal.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strtoul.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strtol.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strlwr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-gettzinfo.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strndup.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-tzset_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-atoi.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isblank.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strlcpy.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-ispunct.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-impure.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-fflush.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-systimes.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-open.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-ctime_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-rand.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-lcltime_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strdup.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strsep.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-asctime_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isdigit.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-utoa.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-memmove.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-toupper.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-memcmp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strlen.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strcmp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strnlen.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-toascii.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lock.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-wsetup.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-month_lengths.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-environ.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-memset.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strspn.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-memcpy.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-sf_nan.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-memchr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strncat.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-longjmp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strncasecmp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-envlock.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-wctomb_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strcasecmp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-memccpy.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isprint.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-ungetc.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-rshift.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-syswrite.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-stdio.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-sbrk.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-tzcalc_limits.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-syssbrk.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strcat.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-fclose.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-sccl.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strdup_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strrchr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isascii.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-rand_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strupr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-read.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-itoa.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-asctime.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-sysread.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-ctype_.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strtok_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-ldiv.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-atol.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-fputwc.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-system.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-setjmp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isgraph.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-wcrtomb.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-wbuf.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-fwalk.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-gmtime.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strptime.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strncpy.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strndup_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strlcat.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-getenv_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strstr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-gmtime_r.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-quorem.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-s_fpclassify.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strcasestr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strcpy.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isalpha.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-lcltime.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-makebuf.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-time.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-refill.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-labs.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isupper.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-bzero.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:isatty.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-findfp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-fvwrite.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-mktime.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-sysclose.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-abs.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-raise.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-tzset.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-iscntrl.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-srand.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strcspn.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-ctime.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strchr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-tolower.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strncmp.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isalnum.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-tzlock.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-islower.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-isspace.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-tzvars.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-memrchr.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-close.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-div.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-strcoll.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:creat.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-sysopen.*( .literal .literal.* .text .text.*) + *libc-psram-workaround.a:lib_a-creat.*( .literal .literal.* .text .text.*) + *libpp.a:( .wifi0iram .wifi0iram.*) + *libfreertos.a:( .literal .literal.* .text .text.*) + *libgcov.a:( .literal .literal.* .text .text.*) + *libxtensa-debug-module.a:eri.*( .literal .literal.* .text .text.*) + *libheap.a:multi_heap_poisoning.*( .literal .literal.* .text .text.*) + *libheap.a:multi_heap.*( .literal .literal.* .text .text.*) + *libnet80211.a:( .wifi0iram .wifi0iram.*) + + _iram_text_end = ABSOLUTE(.); + _iram_end = ABSOLUTE(.); + } > iram0_0_seg + + ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") + + .dram0.data : + { + _data_start = ABSOLUTE(.); + _bt_data_start = ABSOLUTE(.); + *libbt.a:(.data .data.*) + . = ALIGN (4); + _bt_data_end = ABSOLUTE(.); + _btdm_data_start = ABSOLUTE(.); + *libbtdm_app.a:(.data .data.*) + . = ALIGN (4); + _btdm_data_end = ABSOLUTE(.); + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + + *( .data .data.* .dram1 .dram1.*) + *libapp_trace.a:( .rodata .rodata.*) + *libesp32.a:panic.*( .rodata .rodata.*) + *libphy.a:( .rodata .rodata.*) + *libsoc.a:rtc_clk.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strftime.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-timelocal.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strtoul.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strtol.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strlwr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-gettzinfo.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strndup.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-tzset_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-atoi.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isblank.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strlcpy.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-ispunct.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-impure.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-fflush.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-systimes.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-open.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-ctime_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-rand.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-lcltime_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strdup.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strsep.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-asctime_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isdigit.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-utoa.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-memmove.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-toupper.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-memcmp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strlen.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strcmp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strnlen.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-toascii.*( .rodata .rodata.*) + *libc-psram-workaround.a:lock.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-wsetup.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-month_lengths.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-environ.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-memset.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strspn.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-memcpy.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-sf_nan.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-memchr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strncat.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-longjmp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strncasecmp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-envlock.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-wctomb_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strcasecmp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-memccpy.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isprint.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-ungetc.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-rshift.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-syswrite.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-stdio.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-sbrk.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-tzcalc_limits.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-syssbrk.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strcat.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-fclose.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-sccl.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strdup_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strrchr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isascii.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-rand_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strupr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-read.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-itoa.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-asctime.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-sysread.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-ctype_.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strtok_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-ldiv.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-atol.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-fputwc.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-system.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-setjmp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isgraph.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-wcrtomb.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-wbuf.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-fwalk.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-gmtime.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strptime.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strncpy.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strndup_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strlcat.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-getenv_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strstr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-gmtime_r.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-quorem.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-s_fpclassify.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strcasestr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strcpy.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isalpha.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-lcltime.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-makebuf.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-time.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-refill.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-labs.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isupper.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-bzero.*( .rodata .rodata.*) + *libc-psram-workaround.a:isatty.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-findfp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-fvwrite.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-mktime.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-sysclose.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-abs.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-raise.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-tzset.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-iscntrl.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-srand.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strcspn.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-ctime.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strchr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-tolower.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strncmp.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isalnum.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-tzlock.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-islower.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-isspace.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-tzvars.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-memrchr.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-close.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-div.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-strcoll.*( .rodata .rodata.*) + *libc-psram-workaround.a:creat.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-sysopen.*( .rodata .rodata.*) + *libc-psram-workaround.a:lib_a-creat.*( .rodata .rodata.*) + *libgcov.a:( .rodata .rodata.*) + *libheap.a:multi_heap_poisoning.*( .rodata .rodata.*) + *libheap.a:multi_heap.*( .rodata .rodata.*) + + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } > dram0_0_seg + + /*This section holds data that should not be initialized at power up. + The section located in Internal SRAM memory region. The macro _NOINIT + can be used as attribute to place data into this section. + See the esp_attr.h file for more information. + */ + .noinit (NOLOAD): + { + . = ALIGN(4); + _noinit_start = ABSOLUTE(.); + *(.noinit .noinit.*) + . = ALIGN(4) ; + _noinit_end = ABSOLUTE(.); + } > dram0_0_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.ext_ram.bss*) + _bt_bss_start = ABSOLUTE(.); + *libbt.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _bt_bss_end = ABSOLUTE(.); + _btdm_bss_start = ABSOLUTE(.); + *libbtdm_app.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _btdm_bss_end = ABSOLUTE(.); + + *( .bss .bss.* COMMON) + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.share.mem) + *(.gnu.linkonce.b.*) + + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + /* The heap starts right after end of this section */ + _heap_start = ABSOLUTE(.); + } > dram0_0_seg + + ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), + "DRAM segment data does not fit.") + + .flash.rodata : + { + _rodata_start = ABSOLUTE(.); + + *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ + *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + + *(EXCLUDE_FILE(*libapp_trace.a *libesp32.a:panic.* *libphy.a *libsoc.a:rtc_clk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-time.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-strftime.* *libgcov.a *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.*) .rodata EXCLUDE_FILE(*libapp_trace.a *libesp32.a:panic.* *libphy.a *libsoc.a:rtc_clk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-time.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-strftime.* *libgcov.a *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.*) .rodata.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.*(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.*(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + /* Addresses of memory regions reserved via + SOC_RESERVE_MEMORY_REGION() */ + soc_reserved_memory_region_start = ABSOLUTE(.); + KEEP (*(.reserved_memory_address)) + soc_reserved_memory_region_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(4); + } >drom0_0_seg + + .flash.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + + *(EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_time.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-time.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-strftime.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.*) .literal EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_time.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-time.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-strftime.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.*) .literal.* EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_time.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-time.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-strftime.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.*) .text EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_time.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-time.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-strftime.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.*) .text.* EXCLUDE_FILE(*libpp.a *libnet80211.a) .wifi0iram EXCLUDE_FILE(*libpp.a *libnet80211.a) .wifi0iram.*) + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + + /* Similar to _iram_start, this symbol goes here so it is + resolved by addr2line in preference to the first symbol in + the flash.text segment. + */ + _flash_cache_start = ABSOLUTE(0); + } >iram0_2_seg +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32_out.ld b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32_out.ld new file mode 100644 index 00000000..21c516fc --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/esp32_out.ld @@ -0,0 +1,74 @@ +/* ESP32 Linker Script Memory Layout + + This file describes the memory layout (memory blocks) as virtual + memory addresses. + + esp32.project.ld contains output sections to link compiler output + into these memory blocks. + + *** + + This linker script is passed through the C preprocessor to include + configuration options. + + Please use preprocessor features sparingly! Restrict + to simple macros with numeric values, and/or #if/#endif blocks. +*/ +/* + * + * Automatically generated file; DO NOT EDIT. + * Espressif IoT Development Framework Configuration + * + */ +/* If BT is not built at all */ +MEMORY +{ + /* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length + of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but + are connected to the data port of the CPU and eg allow bytewise access. */ + /* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */ + iram0_0_seg (RX) : org = 0x40080000, len = 0x20000 + /* Even though the segment name is iram, it is actually mapped to flash + */ + iram0_2_seg (RX) : org = 0x400D0018, len = 0x330000-0x18 + /* + (0x18 offset above is a convenience for the app binary image generation. Flash cache has 64KB pages. The .bin file + which is flashed to the chip has a 0x18 byte file header. Setting this offset makes it simple to meet the flash + cache MMU's constraint that (paddr % 64KB == vaddr % 64KB).) + */ + /* Shared data RAM, excluding memory reserved for ROM bss/data/stack. + + Enabling Bluetooth & Trace Memory features in menuconfig will decrease + the amount of RAM available. + + Note: Length of this section *should* be 0x50000, and this extra DRAM is available + in heap at runtime. However due to static ROM memory usage at this 176KB mark, the + additional static memory temporarily cannot be used. + */ + dram0_0_seg (RW) : org = 0x3FFB0000 + 0xdb5c, + len = 0x2c200 - 0xdb5c + /* Flash mapped constant data */ + drom0_0_seg (R) : org = 0x3F400018, len = 0x400000-0x18 + /* (See iram0_2_seg for meaning of 0x18 offset in the above.) */ + /* RTC fast memory (executable). Persists over deep sleep. + */ + rtc_iram_seg(RWX) : org = 0x400C0000, len = 0x2000 + /* RTC fast memory (same block as above), viewed from data bus */ + rtc_data_seg(RW) : org = 0x3ff80000, len = 0x2000 + /* RTC slow memory (data accessible). Persists over deep sleep. + + Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled. + */ + rtc_slow_seg(RW) : org = 0x50000000 + 512, + len = 0x1000 - 512 + /* external memory ,including data and text */ + extern_ram_seg(RWX) : org = 0x3F800000, + len = 0x400000 +} +/* Heap ends at top of dram0_0_seg */ +_heap_end = 0x40000000 - 0x0; +_data_seg_org = ORIGIN(rtc_data_seg); +/* The lines below define location alias for .rtc.data section based on Kconfig option. + When the option is not defined then use slow memory segment + else the data will be placed in fast memory segment */ +REGION_ALIAS("rtc_data_location", rtc_slow_seg ); diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/mbedtls_config.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/mbedtls_config.h new file mode 100644 index 00000000..ab0f8731 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/mbedtls_config.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved +// See LICENSE file in the project root for full license information. +// + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* For test certificates */ +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_PEM_PARSE_C + +// #define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +// #define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +// #define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +// #define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +// #define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +// #define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET + +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +// #define MBEDTLS_SSL_DEBUG_ALL +// #define MBEDTLS_VERSION_FEATURES +// #define MBEDTLS_CERTS_C +// #define MBEDTLS_ERROR_C +// #define MBEDTLS_VERSION_C + +// uncomment the defines below to enable static memory allocation feature +#if 0 +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_MEMORY +#endif + +#ifdef USE_LCD +#include "lcd_log.h" +#define MBEDTLS_PLATFORM_PRINTF_MACRO LCD_UsrLog +#endif + +// uncomment the defines bellow to generate debug output +// set below the threshold level for debug messages +// check mbed TLS mbedtls/debug.h header for details. +// Debug levels: +// 0 No debug +// 1 Error +// 2 State change +// 3 Informational +// 4 Verbose + +// #define MBEDTLS_DEBUG_C +// #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define MBEDTLS_DEBUG_THRESHOLD 2 + +#endif // MBEDTLS_CONFIG_H diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoBooter/readme.md b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoBooter/readme.md new file mode 100644 index 00000000..776e0449 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoBooter/readme.md @@ -0,0 +1,4 @@ + +//////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET HAVE IT'S OWN BOOTER // +//////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CLR_Startup_Thread.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CLR_Startup_Thread.c new file mode 100644 index 00000000..aa7140dc --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CLR_Startup_Thread.c @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +#include +#include +#include + +void CLRStartupThread(void const * argument) +{ + CLR_SETTINGS* clrSettings = (CLR_SETTINGS*)argument; + + nanoHAL_Initialize_C(); + + ClrStartup(*clrSettings); + + // nothing to deinitialize or cleanup, so it's safe to return +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..026e8a57 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/CMakeLists.txt @@ -0,0 +1,71 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +include(NF_NativeAssemblies) + +# add header file with common target definitions +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_platform.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_platform.h" @ONLY) + +# append target Esp32 nanoCLR source files +list(APPEND TARGET_ESP32_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/app_main.c) +list(APPEND TARGET_ESP32_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_App_Interface.c) +list(APPEND TARGET_ESP32_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_MonitorCommands.c) +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/CLR_Startup_Thread.c") +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL.c") +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# append target HAL source files +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Power.c") +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Time.cpp") + +# Either NVS or SPIFSS storage for config, NVS is unable to store large Certificate bundles(over 1864 bytes) +#list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigStorageNVS.cpp") + +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigStorageSPIFFS.cpp") + +# alternative to using NVS or Spiffs but requires minimum of 528K partition size +#list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigStorageFATFS.cpp") + +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigurationManager.cpp") + +# append target PAL source files +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL_Events.cpp") +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL_Time.cpp") + +# append other CLR core files +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Memory.cpp") + +# append nanoCRT +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoCRT.cpp") + +# append nanoHAL +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL.cpp") + +# append files from Runtime.Native +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp") + +# append nanoHAL +list(APPEND TARGET_ESP32_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetRandom.cpp") + +# add native assemblies +ParseNativeAssemblies() + +# make var global +set(TARGET_ESP32_NANOCLR_SOURCES ${TARGET_ESP32_NANOCLR_SOURCES} CACHE INTERNAL "make global") + +# append target nanoCLR include directory +list(APPEND TARGET_ESP32_NANOCLR_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) +list(APPEND TARGET_ESP32_NANOCLR_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) +list(APPEND TARGET_ESP32_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) + +# append PAL include directory +list(APPEND TARGET_ESP32_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) + +# append Runtime.Native include directory +list(APPEND TARGET_ESP32_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Runtime.Native) + +# make var global +set(TARGET_ESP32_NANOCLR_INCLUDE_DIRS ${TARGET_ESP32_NANOCLR_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Memory.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Memory.cpp new file mode 100644 index 00000000..a0b8ab80 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Memory.cpp @@ -0,0 +1,84 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +// +// Allocate Memory for Managed heap +// +// if spiRam is available then use all available ram - SPI_ALLOW_FREE +// +// if no spiRam or spiRam malloc fails then malloc from normal ram +// +// The CLR calls this multiple times. Once memory is allocated return the same memory for all +// subsequent calls. + + +static const char* TAG = "Memory"; + +// Space to leave free in spiRam +#define SPI_ALLOW_FREE (256 * 1024) + +// You can't go much bigger than this when allocating in normal memory to +// get memory in one continous lump. +#define NORMAL_MEMORY_SIZE (64 * 1024) + + +// Saved memory allocation for when heap is reset so we can return same value. +unsigned char* pManagedHeap = NULL; +size_t managedHeapSize = 0; + +// +// Return the location and size of the managed heap +// If called a 2nd time then always return same value +// +void HeapLocation(unsigned char*& baseAddress, unsigned int& sizeInBytes) +{ + NATIVE_PROFILE_PAL_HEAP(); + + // Memory allocated yet ? + if (pManagedHeap == NULL) + { + // Memory size to allocate in normal memory if spiRam not available + managedHeapSize = NORMAL_MEMORY_SIZE; + + // See if we have any SPIRAM + size_t spiramMaxSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_32BIT | MALLOC_CAP_SPIRAM); + + // Sanity check - Make sure there is at least managedHeapSize available in SPIRAM + if (spiramMaxSize > (SPI_ALLOW_FREE + managedHeapSize)) + { + // Allocate heap from SPIRAM + managedHeapSize = spiramMaxSize - SPI_ALLOW_FREE; + pManagedHeap = (unsigned char *)heap_caps_malloc(managedHeapSize, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT | MALLOC_CAP_SPIRAM); + if (pManagedHeap) + ESP_LOGI(TAG, "Managed heap allocated, spiRam size:%d max:%d", managedHeapSize, spiramMaxSize); + } + + while(pManagedHeap == NULL) + { + // Allocate heap from Internal RAM + pManagedHeap = (unsigned char *)heap_caps_malloc(managedHeapSize, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT); + if (pManagedHeap) + { + ESP_LOGI(TAG, "Managed heap allocated, internal size:%d", managedHeapSize); + } + else + { + // Subtract 1K and try again + managedHeapSize -= 1024; + if (managedHeapSize <= 0) + { + ESP_LOGE(TAG, "Unable to allocate any Managed heap"); + return; + } + } + } + } + + baseAddress = pManagedHeap; + sizeInBytes = managedHeapSize; +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp new file mode 100644 index 00000000..a2ff1286 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacChannel.cpp @@ -0,0 +1,98 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_dev_dac_native_target.h" + + + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacChannel::NativeWriteValue___VOID__U2(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* dacController = NULL; + int channelNumber; + int controllerId; + dac_channel_t dacChannel = DAC_CHANNEL_1; + + // Get value argumant and mask to 0 - 255 range + uint16_t value = (stack.Arg1().NumericByRefConst().u2 & 0xff); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from _channelNumber field + channelNumber = pThis[FIELD___channelNumber].NumericByRef().s4; + + // need to get the controllerId for the DAC controller of this channel + // get pointer to DacController field + dacController = pThis[FIELD___dacController].Dereference(); + + // get pointer to _controllerId field in DacController + controllerId = dacController[Library_sys_dev_dac_native_System_Devices_Dac_DacController::FIELD___controllerId].NumericByRef().s4; + + // only one DAC controller, but check it anyways + if (controllerId != 1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + switch(channelNumber) + { + case 0: + dacChannel = DAC_CHANNEL_1; + break; + + case 1: + dacChannel = DAC_CHANNEL_2; + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + dac_output_voltage(dacChannel, value); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacChannel::NativeDispose___VOID__BOOLEAN(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + int channelNumber; + bool disposeController = false; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get disposeController flag + disposeController = (bool)stack.Arg1().NumericByRef().u1; + + + if (disposeController) + { + // Get channel from _channelNumber field + channelNumber = pThis[FIELD___channelNumber].NumericByRef().s4; + + switch (channelNumber) + { + case 1: + dac_output_disable(DAC_CHANNEL_1); + break; + + case 2: + dac_output_disable(DAC_CHANNEL_2); + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + } + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp new file mode 100644 index 00000000..dc97db1a --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_System_Devices_Dac_DacController.cpp @@ -0,0 +1,124 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "sys_dev_dac_native_target.h" + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeOpenChannel___VOID__I4(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + int controllerId; + int channelNumber; + dac_channel_t dacChannel = DAC_CHANNEL_1; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from argument + channelNumber = stack.Arg1().NumericByRef().s4; + + // get controller ID + controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + // only one DAC controller for now, but check it anyways + if(controllerId != 1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + switch(channelNumber) + { + case 0: + dacChannel = DAC_CHANNEL_1; + break; + + case 1: + dacChannel = DAC_CHANNEL_2; + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Enable DAC for this channel + dac_output_enable(dacChannel); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeGetChannelCount___I4(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + int controllerId; + int channelCount = 0; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + controllerId = pThis[ FIELD___controllerId ].NumericByRefConst().s4; + + switch(controllerId) + { + case 1: + channelCount = DacChannelCount; + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Return value to the managed application + stack.SetResult_I4(channelCount); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeGetResolutionInBits___I4(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + // Fixed at 8 bit + stack.SetResult_I4(DacResolutionInBits); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + int controllerId; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get pointer to _controllerId field in AdcController + controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + // all required initialization for DAC is already handled in ChibiOS driver + + switch(controllerId) + { + case 1: + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_sys_dev_dac_native_System_Devices_Dac_DacController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String("DAC1"); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h new file mode 100644 index 00000000..1c8b7616 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/System.Devices.Dac/sys_dev_dac_native_target.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _SYS_DEV_DAC_NATIVE_TARGET_H_ +#define _SYS_DEV_DAC_NATIVE_TARGET_H_ + +#include +#include + + +#define DacChannelCount 2 +#define DacResolutionInBits 8 + +#endif //_SYS_DEV_DAC_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp new file mode 100644 index 00000000..049be349 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +extern "C" uint8_t temprature_sens_read(); + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeReadValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int reading = 0; + esp_err_t result; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from _channelNumber field + int channelNumber = pThis[FIELD___channelNumber].NumericByRef().s4; + + // need to get the controllerId for the ADC controller of this channel + // get pointer to AdcController field + //CLR_RT_HeapBlock* adcController = pThis[FIELD___adcController].Dereference(); + + // get pointer to _controllerId field +// int adcNumber = adcController[Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::FIELD___controllerId].NumericByRef().s4; + int adcNumber = channelNumber <= 9 ? 1 : 2; + + if ( adcNumber == 1) + { + switch(channelNumber) + { + case 8: + reading = temprature_sens_read(); break; + case 9: + reading = hall_sensor_read(); break; + default: + reading = adc1_get_raw( (adc1_channel_t)channelNumber); break; + } + } + else if ( adcNumber == 2) + { + result = adc2_get_raw( (adc2_channel_t)channelNumber, ADC_WIDTH_12Bit, &reading); + if ( result != ESP_OK) + NANOCLR_SET_AND_LEAVE(CLR_E_PIN_UNAVAILABLE); + } + else + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + stack.SetResult_I4(reading); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeDisposeChannel___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // left empty on purpose, nothing to do here + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp new file mode 100644 index 00000000..53a45bad --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp @@ -0,0 +1,183 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +// ESP32 ADC controller +// +// Contains ADC1 and ADC2 +// ADC1 with 8 channels ( GPIO 32 - 39 ) 0=36, 1=37, 2=38, 3=39, 4=32, 5=33, 6=34, 7=35 +// channel 8/9 are logical channles for temperture sensor and is the built in Esp32 Hall sensor. +// For hall sensor there is a restriction channel 0 and 3 must be unused +// ADC2 with 10 channels (GPIO 0,2,4,12-15 and 25-27) +// Note : ADC2 cannot be used if Wifi started and other restrictions as pins used for other things. +// +// ESP_DevKitC Gpio 0 cannot be used +// ESP-Wrover_kit V3 GPIO 0,2,4 and 15 can't be used + +// Typical marked inputs on boards +// VP - GPIO36 ( channel 0 ) +// VN - GPIO39 ( channel 3 ) + +// From managed code we treat all ADC channels as 1 logical ADC unit (ADC1) +// Logical channels +// ADC1 / 0 - 7 - 8 channels - ( GPIO 32 - 39 ) 0=36, 1=37, 2=38, 3=39, 4=32, 5=33, 6=34, 7=35 +// 8 - Internal Temperture sensor +// 9 - Internal Hall Sensor +// ADC2 / 10 - 19 - 10 Channels -( GPIOs 0, 2, 4, 12 - 15 and 25 - 27. ) + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeOpenChannel___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + esp_err_t result; + adc_bits_width_t width_bit = ADC_WIDTH_BIT_12; // default to 12 + adc_atten_t atten = ADC_ATTEN_DB_11; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from argument + int channel = stack.Arg1().NumericByRef().s4; + + if ( channel < ADC_CHANNEL_0 || channel > 19 ) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + // Get ADC device number from channel + int adcUnit = channel <= 9 ? 1 : 2; + + adc_power_on(); // Make sure powered on + + switch(adcUnit) + { + case 1: + // Normal channel 0-7 ? + if ( channel <= 7 ) + { + adc1_config_width( width_bit ); + + result = adc1_config_channel_atten( (adc1_channel_t)channel, atten); + if ( result != ESP_OK ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PIN_UNAVAILABLE); + } + } + break; + + case 2: + result = adc2_config_channel_atten( (adc2_channel_t)channel, atten ); + if ( result != ESP_OK ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PIN_UNAVAILABLE); + } + break; + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetChannelCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int channelCount = 20; + + // Return value to the managed application + stack.SetResult_I4(channelCount); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMaxValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Currently fixed 12 bit so return 4095 + stack.SetResult_I4(4095); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMinValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // Return 0 for now, is this signed ? + stack.SetResult_I4(0); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeIsChannelModeSupported___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int mode = stack.Arg1().NumericByRef().s4; + + // Only support Single ended mode for now + AdcChannelMode singleEndedMode = SingleEnded; + stack.SetResult_Boolean( (mode == (int)singleEndedMode) ) ; + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetResolutionInBits___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Fixed at 12 bit for now + stack.SetResult_I4(12); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + int controllerId; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get pointer to _controllerId field in AdcController + controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + // all required initialization for ADC are already handled + // this is only to check if the requested controllerId is available in hardware + + // expect only 1 + if(controllerId == 1) + { + // we are OK + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string + // ADC1 and ADC2 + // ADC1 with 8 channels + Temperture sensor and and internal hall sensor + // ADC2 with 10 channeld but cannot be used if Wifi started + // + // These are now combined into 1 logical ADC (ADC1) + char deviceSelectorString[] = + "ADC1"; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h new file mode 100644 index 00000000..ed808e7e --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_ADC_NATIVE_TARGET_H_ +#define _WIN_DEV_ADC_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_DEV_ADC_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp new file mode 100644 index 00000000..3bdc6d4b --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp @@ -0,0 +1,303 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_gpio_native.h" + +// Map Gpio pin number to 1 of 8 ESP32 counters, -1 = not mapped +// Each pulse counter is a 16 bit signed value. +// The managed code requires a 64 bit counter so we accumulate the overflows in an interrupt when count gets to 0x7fff + +static int8_t IsrInstalled = 0; +static int8_t GpioCounterMap[8] = { -1,-1,-1,-1,-1,-1,-1,-1 }; +static uint64_t OverflowCount[8]; + +#define MAX_COUNTER_VALUE 0x7fff + +extern void Remove_Gpio_Interrupt(gpio_num_t pinNumber); + + +// Interrupt routine used to catch overflows so we can have a 64 bit counter +static void IRAM_ATTR pcnt_intr_handler(void *arg) +{ + (void)arg; + + uint32_t intr_status = PCNT.int_st.val; + + for (int i = 0; i < PCNT_UNIT_MAX; i++) + { + if (intr_status & (BIT(i))) + { + + uint32_t status = PCNT.status_unit[i].val; + // Hit high limit MAX_COUNTER_VALUE + if (status & PCNT_STATUS_H_LIM_M) + { + OverflowCount[i] += MAX_COUNTER_VALUE; + } + + PCNT.int_clr.val = BIT(i); + } + } +} + + +// Find an unused counter, returns counter index or -1 if not found +static int FindFreeCounter(int gpioPin) +{ + int counterIndex; + + for (counterIndex = 0; counterIndex < 8; counterIndex++) + { + if (GpioCounterMap[counterIndex] == -1) + { + GpioCounterMap[counterIndex] = gpioPin; + return counterIndex; + } + } + return -1; +} + +// Find the index of counter for a gpio pin, returns index or -1 if not found +static int FindCounterForGpio(int gpioPin) +{ + int counterIndex; + + for (counterIndex = 0; counterIndex < 8; counterIndex++) + { + if (GpioCounterMap[counterIndex] == gpioPin) return counterIndex; + } + return -1; +} + +// Initalise the ESP32 counter +// return true if ok +static bool InitialiseCounter(int counterIndex, int gpioNum, bool countRising, bool countFalling) +{ + esp_err_t ec; + + // Prepare configuration for the PCNT unit */ + pcnt_config_t pcnt_config; + + // Set PCNT input signal and control GPIOs + pcnt_config.pulse_gpio_num = gpioNum; + pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED; // ignore + + pcnt_config.channel = PCNT_CHANNEL_0; + pcnt_config.unit = (pcnt_unit_t)counterIndex; + + // What to do on the positive / negative edge of pulse input? + pcnt_config.pos_mode = countRising ? PCNT_COUNT_INC : PCNT_COUNT_DIS; // positive edge count ? + pcnt_config.neg_mode = countFalling ? PCNT_COUNT_INC : PCNT_COUNT_DIS; // falling edge count ? + + // What to do when control input is low or high? + pcnt_config.lctrl_mode = PCNT_MODE_KEEP; // Keep the primary counter mode if low + pcnt_config.hctrl_mode = PCNT_MODE_KEEP; // Keep the primary counter mode if high + + // Set the maximum and minimum limit values to watch + pcnt_config.counter_h_lim = MAX_COUNTER_VALUE; + pcnt_config.counter_l_lim = 0; + + //* Initialize PCNT unit + ec = pcnt_unit_config(&pcnt_config); + if (ec != ESP_OK) return false; + + return true; +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeInit___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + int16_t pinNumber = pThis[FIELD___pinNumber].NumericByRefConst().s4; + + bool InputMode = (bool)pThis[FIELD___inputMode].NumericByRefConst().u1; + if (InputMode) + { + int index = FindFreeCounter(pinNumber); + if (index == -1) + { + // No free counters + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + // Make sure GPIO pin doesn't have a GPIO Isr asscoiatted with it otherwise it will not support + // faster count frequencies + Remove_Gpio_Interrupt((gpio_num_t)pinNumber); + } + else + { + // Output not currently supported + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeRead___U8__BOOLEAN(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if (pThis[Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::FIELD___disposedValue].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int pinNumber = pThis[FIELD___pinNumber].NumericByRefConst().s4; + + int counterIndex = FindCounterForGpio(pinNumber); + if (counterIndex == -1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + bool resetAfterRead = (bool)stack.Arg0().NumericByRef().u1; + + int16_t counter; + + pcnt_get_counter_value((pcnt_unit_t)counterIndex, &counter); + + // relativeTime Read Time, Number of micro seconds since boot + int64_t relativeTime = esp_timer_get_time(); + + // Combine to make a 64 bit value + uint64_t totalCount = OverflowCount[counterIndex] + (uint64_t)counter; + + if (resetAfterRead) + { + pcnt_counter_clear((pcnt_unit_t)counterIndex); + OverflowCount[counterIndex] = 0; + } + + + // Return results + // Update the Relative _readTime field (convert micro sec to 100ns ticks) + *&pThis[FIELD___readTime].NumericByRef().s8 = (relativeTime * 10); + + // Return value to the managed application + stack.SetResult_U8(totalCount); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStart___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + bool countRising = false; + bool countFalling = false; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if (pThis[Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::FIELD___disposedValue].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int pinNumber = pThis[FIELD___pinNumber].NumericByRefConst().s4; + + int counterIndex = FindCounterForGpio(pinNumber); + if (counterIndex == -1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + GpioChangePolarity polarity = (GpioChangePolarity)pThis[FIELD___polarity].NumericByRefConst().s4; + + switch (polarity) + { + case Both: countRising = true; countFalling = true; break; + case Rising: countRising = true; break; + case Falling: countFalling = true; break; + } + + if (!InitialiseCounter(counterIndex, pinNumber, countRising, countFalling)) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + // Posible filter ( debounce ) future. + // pcnt_set_filter_value((pcnt_unit_t)counterIndex, 10); + // pcnt_filter_enable((pcnt_unit_t)counterIndex); + + pcnt_event_enable((pcnt_unit_t)counterIndex, PCNT_EVT_H_LIM); + + pcnt_counter_pause((pcnt_unit_t)counterIndex); + + pcnt_counter_clear((pcnt_unit_t)counterIndex); + OverflowCount[counterIndex] = 0; + + // Register ISR handler and enable interrupts for PCNT unit */ + if (IsrInstalled == 0) + { + pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL); + IsrInstalled = 1; + } + + // enable interrupts for PCNT unit + pcnt_intr_enable((pcnt_unit_t)counterIndex); + + pcnt_counter_resume((pcnt_unit_t)counterIndex); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStop___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if (pThis[Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::FIELD___disposedValue].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int pinNumber = pThis[FIELD___pinNumber].NumericByRefConst().s4; + + int counterIndex = FindCounterForGpio(pinNumber); + if (counterIndex == -1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + pcnt_counter_pause((pcnt_unit_t)counterIndex); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeDispose___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + int pinNumber = pThis[FIELD___pinNumber].NumericByRefConst().s4; + + int counterIndex = FindCounterForGpio(pinNumber); + if (counterIndex == -1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + pcnt_intr_disable((pcnt_unit_t)counterIndex); + + // Disable counter, remove gpio pin + InitialiseCounter(counterIndex, PCNT_PIN_NOT_USED, false, false); + + // Clear counter / gpio mapping + GpioCounterMap[counterIndex] = -1; + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp new file mode 100644 index 00000000..a2fc54c1 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_gpio_native_target.h" + + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController::get_PinCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Return value to the managed application + stack.SetResult_I4( GPIO_PIN_COUNT ); + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp new file mode 100644 index 00000000..7aafaade --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp @@ -0,0 +1,369 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// ESP32 GPIO ( 40 physical GPIO pads) +// +// GPIO6-11 used for PSI flash +// +// GPIO34-39 Only input mode +// + +#include +#include "win_dev_gpio_native_target.h" +#include "nf_rt_events_native.h" + +#include "Esp32_DeviceMapping.h" + +static const char* TAG = "GpioPin"; +static bool Gpio_Initialised = false; + +// this array keeps track of the Gpio pins that are assigned to each channel +CLR_RT_HeapBlock* channelPinMapping[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + + +void Initialize_gpio() +{ + esp_err_t ret = gpio_install_isr_service( 0); + if ( ret != ESP_OK ) + { + ESP_LOGE( TAG, "Install isr service"); + } +} + +void Gpio_Interupt_ISR(void * args) +{ + uint32_t pinNumber = (uint32_t)args; + + NATIVE_INTERRUPT_START + + CLR_RT_HeapBlock* pThis = channelPinMapping[pinNumber]; + if ( pThis == NULL ) + { + NATIVE_INTERRUPT_END + + return; + } + + // check if object has been disposed + if( pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + // object has been disposed, leave now + NATIVE_INTERRUPT_END + return; + } + + // flag to determine if there are any callbacks registered in managed code + bool callbacksRegistered = (pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___callbacks ].Dereference() != NULL); + if ( callbacksRegistered ) + { + // if handle registed then post a managed event with the current pin reading + PostManagedEvent( EVENT_GPIO, 0, pinNumber, gpio_get_level((gpio_num_t)pinNumber) ); + } + + NATIVE_INTERRUPT_END +} + +void Add_Gpio_Interrupt(gpio_num_t pinNumber) +{ + if ( !Gpio_Initialised ) + { + Initialize_gpio(); + Gpio_Initialised = true; + } + + esp_err_t ret = gpio_isr_handler_add( pinNumber, Gpio_Interupt_ISR, (void *)pinNumber); + if ( ret != ESP_OK ) + { + ESP_LOGE( TAG, "Add interrupt to pin"); + } +} + + +void Remove_Gpio_Interrupt(gpio_num_t pinNumber) +{ + if (channelPinMapping[pinNumber] != NULL) + { + // Remove from interrupts + gpio_isr_handler_remove((gpio_num_t)pinNumber); + + // clear this channel in channel pin mapping + channelPinMapping[pinNumber] = NULL; + } +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Read___WindowsDevicesGpioGpioPinValue( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + gpio_num_t pinNumber = (gpio_num_t)pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + stack.SetResult_I4( gpio_get_level(pinNumber) ); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Toggle___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int16_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[ FIELD___driveMode ].NumericByRefConst().s4; + + // sanity check for drive mode set to output so we don't mess up writing to an input pin + if ((driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSource) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + // ESP32 GPIO API doesn't offer a 'toggle', so need to rely on the last output value field and toggle that one + GpioPinValue newState = (GpioPinValue)(GpioPinValue_High ^ (GpioPinValue)pThis[ FIELD___lastOutputValue ].NumericByRef().s4); + + // ...write back to the GPIO... + gpio_set_level((gpio_num_t)pinNumber, newState); + + // ... and finally store it + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = newState; + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // set pin to input to save power + // clear interrupts + // releases the pin + int16_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + Remove_Gpio_Interrupt((gpio_num_t)pinNumber); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + GpioPinDriveMode driveMode = (GpioPinDriveMode)stack.Arg1().NumericByRef().s4; + + bool driveModeSupported = false; + + // check if the requested drive mode is support by ChibiOS config + if ((driveMode == GpioPinDriveMode_Input) || + (driveMode == GpioPinDriveMode_InputPullDown) || + (driveMode == GpioPinDriveMode_InputPullUp) || + (driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain)) + { + driveModeSupported = true; + } + + // Return value to the managed application + stack.SetResult_Boolean( driveModeSupported ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + signed int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + signed int driveMode = stack.Arg1().NumericByRef().s4; + + // Valid PinNumber + if ( ! GPIO_IS_VALID_GPIO(pinNumber) ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Check Pin is output capable + if ( driveMode >= 3 && !GPIO_IS_VALID_OUTPUT_GPIO(pinNumber) ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + gpio_mode_t mode = GPIO_MODE_DISABLE; + gpio_pullup_t pull_up_en = GPIO_PULLUP_DISABLE; + gpio_pulldown_t pull_down_en = GPIO_PULLDOWN_DISABLE; + gpio_int_type_t intr_type = GPIO_INTR_ANYEDGE; + + switch (driveMode) + { + case GpioPinDriveMode_Input : + mode = GPIO_MODE_INPUT; + break; + case GpioPinDriveMode_InputPullDown : + mode = GPIO_MODE_INPUT; + pull_down_en = GPIO_PULLDOWN_ENABLE; + break; + case GpioPinDriveMode_InputPullUp : + mode = GPIO_MODE_INPUT; + pull_up_en = GPIO_PULLUP_ENABLE; + break; + case GpioPinDriveMode_Output : + mode = GPIO_MODE_OUTPUT; + break; + case GpioPinDriveMode_OutputOpenDrain : + mode = GPIO_MODE_OUTPUT_OD; + break; + case GpioPinDriveMode_OutputOpenDrainPullUp : + mode = GPIO_MODE_OUTPUT_OD; + pull_up_en = GPIO_PULLUP_ENABLE; + break; + case GpioPinDriveMode_OutputOpenSource: + mode = GPIO_MODE_OUTPUT_OD; + break; + case GpioPinDriveMode_OutputOpenSourcePullDown: + mode = GPIO_MODE_OUTPUT_OD; + pull_down_en = GPIO_PULLDOWN_ENABLE; + break; + } + + gpio_config_t GPIOConfig; + + GPIOConfig.pin_bit_mask = (1ULL << pinNumber); + GPIOConfig.mode = mode; + GPIOConfig.pull_up_en = pull_up_en; + GPIOConfig.pull_down_en = pull_down_en; + GPIOConfig.intr_type = intr_type; + + gpio_config( &GPIOConfig ); + + // Enable interrupts for all pins + Add_Gpio_Interrupt( (gpio_num_t)pinNumber ); + + // save pin reference + channelPinMapping[pinNumber] = pThis; + + // protect this from GC so that the callback is where it's supposed to + CLR_RT_ProtectFromGC gc( *pThis ); + + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeInit___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + int16_t pinNumber = stack.Arg1().NumericByRef().s4; + + // TODO is probably a good idea keep track of the used pins, so we can check that here + // TODO is probably a good idea to check if this pin exists + + if ( !GPIO_IS_VALID_GPIO((gpio_num_t)pinNumber) ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Return value to the managed application + stack.SetResult_Boolean(true ); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDebounceTimeout___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // nothing to do here as the debounce timeout is grabbed from the managed object when required + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::WriteNative___VOID__WindowsDevicesGpioGpioPinValue( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int16_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[ FIELD___driveMode ].NumericByRefConst().s4; + + GpioPinValue state = (GpioPinValue)stack.Arg1().NumericByRef().s4; + + // sanity check for drive mode set to output so we don't mess up writing to an input pin + if ((driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSource) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + gpio_set_level( (gpio_num_t)pinNumber, state); + + // store the output value in the field + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = state; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetAlternateFunction___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // get pin number and take the port and pad references from that one + int16_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + // get alternate function argument + int32_t alternateFunction = stack.Arg1().NumericByRef().s4; + + Esp32_SetMappedDevicePins( (uint8_t)pinNumber, alternateFunction ); + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h new file mode 100644 index 00000000..7666fe1c --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_GPIO_NATIVE_TARGET_H_ +#define _WIN_DEV_GPIO_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_DEV_GPIO_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp new file mode 100644 index 00000000..896e2190 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp @@ -0,0 +1,228 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include "win_dev_i2c_native_target.h" +#include "Esp32_DeviceMapping.h" + +static const char* TAG = "I2C"; + +typedef Library_win_dev_i2c_native_Windows_Devices_I2c_I2cConnectionSettings I2cConnectionSettings; + +static char Esp_I2C_Initialised_Flag[I2C_NUM_MAX] = {0,0}; + +void Esp32_I2c_UnitializeAll() +{ + for (int c = 0; c < I2C_NUM_MAX; c++) + { + if (Esp_I2C_Initialised_Flag[c]) + { + // Delete bus driver + i2c_driver_delete((i2c_port_t)c); + Esp_I2C_Initialised_Flag[c] = 0; + } + } +} + +void SetConfig(i2c_port_t bus, CLR_RT_HeapBlock* config) +{ + int busSpeed = config[ I2cConnectionSettings::FIELD___busSpeed ].NumericByRef().s4; + + gpio_num_t DataPin = (gpio_num_t)Esp32_GetMappedDevicePins( DEV_TYPE_I2C, bus, 0); + gpio_num_t ClockPin = (gpio_num_t)Esp32_GetMappedDevicePins( DEV_TYPE_I2C, bus, 1); + + i2c_config_t conf; + conf.mode = I2C_MODE_MASTER; + conf.sda_io_num = DataPin; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_io_num = ClockPin; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.master.clk_speed = (busSpeed==0)? 100000 : 400000; + + i2c_param_config(bus, &conf); +} + + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details, subtract 1 to get ESP32 bus number + i2c_port_t bus = (i2c_port_t)((pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000) - 1); + if ( bus != I2C_NUM_0 && bus != I2C_NUM_1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // Set the Bus parameters + SetConfig( bus, pConfig); + + // If this is first devcie on Bus then init driver + if ( Esp_I2C_Initialised_Flag[bus] == 0 ) + { + esp_err_t res = i2c_driver_install( bus, I2C_MODE_MASTER, 0, 0, 0); + if ( res != ESP_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Ensure driver gets unitialized during soft reboot + HAL_AddSoftRebootHandler(Esp32_I2c_UnitializeAll); + Esp_I2C_Initialised_Flag[bus]++; + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeDispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + i2c_port_t bus = (i2c_port_t)((pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000) - 1); + + Esp_I2C_Initialised_Flag[bus]--; + + if ( Esp_I2C_Initialised_Flag[bus] <= 0 ) + { + i2c_driver_delete(bus); + + Esp_I2C_Initialised_Flag[bus] = 0; + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeTransmit___WindowsDevicesI2cI2cTransferResult__SZARRAY_U1__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + unsigned char * writeData = NULL; + unsigned char * readData = NULL; + int writeSize = 0; + int readSize = 0; + esp_err_t i2cStatus; + + CLR_RT_HeapBlock* result; + // create the return object (I2cTransferResult) + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details, subtract 1 to get ESP32 bus number + i2c_port_t bus = (i2c_port_t)((pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000) - 1); + + int slaveAddress = pConfig[ I2cConnectionSettings::FIELD___slaveAddress ].NumericByRef().s4; + + // dereference the write and read buffers from the arguments + CLR_RT_HeapBlock_Array* writeBuffer = stack.Arg1().DereferenceArray(); + if (writeBuffer != NULL) + { + // grab the pointer to the array by getting the first element of the array + writeData = writeBuffer->GetFirstElement(); + + // get the size of the buffer by reading the number of elements in the HeapBlock array + writeSize = writeBuffer->m_numOfElements; + } + + CLR_RT_HeapBlock_Array* readBuffer = stack.Arg2().DereferenceArray(); + if (readBuffer != NULL) + { + // grab the pointer to the array by getting the first element of the array + readData = readBuffer->GetFirstElement(); + + // get the size of the buffer by reading the number of elements in the HeapBlock array + readSize = readBuffer->m_numOfElements; + } + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + + if ( writeSize != 0 ) // Write + { + i2c_master_start(cmd); + i2c_master_write_byte( cmd, ( slaveAddress << 1 ) | I2C_MASTER_WRITE, 1); + i2cStatus = i2c_master_write(cmd, &writeData[0], writeSize, true); + if (i2cStatus != ESP_OK) ESP_LOGE( TAG, "i2c_master_write error:%d", i2cStatus ); + + } + if (readSize != 0) // Read + { + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (slaveAddress << 1) | I2C_MASTER_READ, 1); + if (readSize > 1) + { + // Additional read bytes with ACK + i2c_master_read(cmd, &readData[0], readSize - 1, I2C_MASTER_ACK); + } + // Last read byte with NACK + i2c_master_read_byte(cmd, &readData[readSize - 1], I2C_MASTER_NACK); + } + + i2c_master_stop(cmd); + + i2cStatus = i2c_master_cmd_begin(bus, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + + // create return object + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_I2cTransferResult)); + result = top.Dereference(); FAULT_ON_NULL(result); + + if (i2cStatus != ESP_OK) + { + uint32_t transferResult = I2cTransferStatus_FullTransfer; + + // set the result field + if ( i2cStatus == ESP_FAIL ) + { + transferResult = I2cTransferStatus_SlaveAddressNotAcknowledged; + } + else if (i2cStatus == ESP_ERR_TIMEOUT ) + { + transferResult = I2cTransferStatus_ClockStretchTimeout; + } + else + { + transferResult = I2cTransferStatus_UnknownError; + } + + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___status ].SetInteger((CLR_UINT32)transferResult); + + // set the bytes transferred field + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___bytesTransferred ].SetInteger(0); + } + else + { + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___status ].SetInteger((CLR_UINT32)I2cTransferStatus_FullTransfer); + + // set the bytes transferred field + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___bytesTransferred ].SetInteger((CLR_UINT32)(writeSize + readSize)); + + if(readSize > 0) + { + // because this was a Read transaction, need to copy from DMA buffer to managed buffer + memcpy(readBuffer->GetFirstElement(), &readData[0], readSize); + } + } + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp new file mode 100644 index 00000000..0552f96c --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include "win_dev_i2c_native_target.h" +#include "Esp32_DeviceMapping.h" + + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "I2C1,I2C2,I2C3," + terminator and init with the terminator + char deviceSelectorString[ 15 + 1] = { 0 }; + + strcat(deviceSelectorString, "I2C1,I2C2"); + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h new file mode 100644 index 00000000..8dd64a47 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h @@ -0,0 +1,11 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_I2C_NATIVE_TARGET_H_ +#define _WIN_DEV_I2C_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_DEV_I2C_NATIVE_TARGET_H_ \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp new file mode 100644 index 00000000..c85e0e0b --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp @@ -0,0 +1,113 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "win_dev_pwm_native_target.h" + +uint32_t PwmController_Timer_resolution[8]; + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MaxFrequency___R8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // 40mhz with 1 bit duty cycle (50% fixed duty) + double maxFrequency = 40000000.0; + + stack.SetResult_R8(maxFrequency); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MinFrequency___R8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // FIXME : how can this value be determined ? + stack.SetResult_R8(1.0); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_PinCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Returns number of pins for Pwm ( number of channels for Led Pwm) + int pinCount = 16; + + stack.SetResult_I4(pinCount); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::NativeSetDesiredFrequency___U4__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties ( 0 - 7 ) + int timerId = (int)(pThis[ FIELD___controllerId ].NumericByRef().u4); + + unsigned int desiredFrequency = (unsigned int)stack.Arg1().NumericByRef().u4; + + ledc_timer_t timer = (ledc_timer_t)(timerId & 0x03); + ledc_mode_t mode = (timerId <= 4) ? LEDC_HIGH_SPEED_MODE : LEDC_LOW_SPEED_MODE; + + // Work out the optimumal duty resolution based on current frequency, default to 1 if not found + // Working from 15 bit duty resolution down until we have a valid divisor + int optimumDutyResolution = 1; + for( int dutyResolution=15; dutyResolution>0; dutyResolution--) + { + uint32_t precision = ( 0x1 << dutyResolution ); // 2**depth + + uint64_t divParam = ( (uint64_t) LEDC_APB_CLK_HZ << 8 ) / desiredFrequency / precision; + if ( divParam > 256) + { + optimumDutyResolution = dutyResolution; + break; + } + } + + ledc_timer_bit_t duty_res = (ledc_timer_bit_t)optimumDutyResolution; + + // Save resolution for working out values for percent duty cycle + PwmController_Timer_resolution[timerId] = ( 0x1 << optimumDutyResolution ); + + ledc_timer_config_t timer_conf { + mode, + duty_res, + timer, + desiredFrequency + }; + + esp_err_t result = ledc_timer_config( &timer_conf); + if ( result != ESP_OK ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + stack.SetResult_R8((double)desiredFrequency); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string + // TIM0 to TIM3 are hish speed timers + // TIM4 to TIM7 are low speed timers + char deviceSelectorString[] = + "TIM0,TIM1,TIME2,TIM3,TIM4,TIM5,TIM6,TIM7"; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp new file mode 100644 index 00000000..a599d594 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp @@ -0,0 +1,233 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "win_dev_pwm_native_target.h" + +// Used to map a PWM channel number to a pin number for High and low speed channels +static char HighSpeedPinMap[8] = { 255,255,255,255,255,255,255,255 }; +static char LowSpeedPinMap[8] = { 255,255,255,255,255,255,255,255 }; + +#define GetSpeedMode(timer) (ledc_mode_t)((timer>3) ? LEDC_LOW_SPEED_MODE : LEDC_HIGH_SPEED_MODE ) +#define IDF_ERROR(result) if ( result != ESP_OK ) { NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); } + +extern uint32_t PwmController_Timer_resolution[8]; + + +// +// Look up Pin number to find channel, if create true and not present then add pin +// return channel number or -1 if error +// +int GetChannel (int pin, int timerId, bool create) +{ + int channel = -1; // Return if not found + + // Selct map depending if high or low speed timers + char * pMap = (timerId > 3)? LowSpeedPinMap: HighSpeedPinMap; + char * pMap2 = pMap; + + //look for pin in map + for( int index=0; index<8; index++, pMap++ ) + { + if (*pMap == pin ) { channel = index; break; } + } + + if ( create && channel == -1) + { + // if pin/channel not found then allocate one + for( int index=0; index<8; index++, pMap2++ ) + { + if (*pMap2 == 255 ) { channel = index; *pMap2 = pin; break; } + } + } + + return channel; +} + +// +// Work out the duty Cycle for the current duty resolution and polarity +// +uint32_t CalculateDuty(int timerId, uint32_t dutyCycle, PwmPulsePolarity polarity) +{ + // if polarity Active low then reverse duty cycle + if (polarity == ActiveLow ) dutyCycle = 10000 - dutyCycle; + + // Return a duy cycle in the range of the current timer duty resolution + return PwmController_Timer_resolution[timerId] * dutyCycle / 10000; +} + +HRESULT ConfigureAndStart(CLR_RT_HeapBlock* pThis, bool create, bool noStart) +{ + NANOCLR_HEADER(); + { + // Retrieves the needed parameters from private class properties or method parameters + int timerId = (int)(pThis[ Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::FIELD___pwmTimer ].NumericByRef().u4); + int pinNumber = (int)(pThis[ Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::FIELD___pinNumber ].NumericByRef().u4); + uint32_t dutyCycle = (uint32_t)(pThis[ Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::FIELD___dutyCycle ].NumericByRef().u4); + PwmPulsePolarity polarity = (PwmPulsePolarity)(pThis[ Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::FIELD___polarity ].NumericByRef().u4); + + // Configure channel + ledc_mode_t mode = GetSpeedMode(timerId); + ledc_channel_t channel = (ledc_channel_t)GetChannel(pinNumber, timerId, create); + if ( channel == -1 ) + { + // Unable to create a new channel, all channels used up ? + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + ledc_timer_t timer_sel = (ledc_timer_t)(timerId & 0x03); + + // Work out the duty Cycle for the current duty resolution + dutyCycle = CalculateDuty( timerId, dutyCycle, polarity ); + + ledc_channel_config_t ledc_conf { + pinNumber, + mode, + channel, + LEDC_INTR_DISABLE, + timer_sel, + dutyCycle, + 0 + }; + + // Configure Channel which will also start it + IDF_ERROR( ledc_channel_config(&ledc_conf) ); + + // Because it is started from the configure we optionally stop it and set idle level based on polarity + if ( noStart) ledc_stop(mode, channel, polarity); + + } + NANOCLR_NOCLEANUP(); +} + +// +// Pwmpin created +// Validate pin and create an entry in Channel/Pin map +// +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Check pin number is a valid for output + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + if ( !GPIO_IS_VALID_OUTPUT_GPIO(pinNumber) ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Create a new entry in channel table and configure channel which will also start channel + NANOCLR_CHECK_HRESULT( ConfigureAndStart(pThis, true, true) ); + } + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetActiveDutyCyclePercentage___VOID__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties or method parameters + int timerId = (int)(pThis[ FIELD___pwmTimer ].NumericByRef().u4); + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + PwmPulsePolarity polarity = (PwmPulsePolarity)(pThis[ FIELD___polarity ].NumericByRef().u4); + + // retrieve Percents as 0 to 10000 ( 0% to 100%) + uint32_t dutyCycle = (uint32_t)stack.Arg1().NumericByRef().u4; + + // Get channel number usd for this pinNumber + // FIXME check result + ledc_channel_t channel = (ledc_channel_t)GetChannel (pinNumber, timerId, false); + + // Get speed mode based on Timer used + ledc_mode_t speed_mode = GetSpeedMode(timerId); + + // Work out the duty Cycle for the current duty resolution + dutyCycle = CalculateDuty( timerId, dutyCycle, polarity ); + + // Update duty on channel + IDF_ERROR( ledc_set_duty(speed_mode, channel, dutyCycle) ); + + // Activate duty on channel + IDF_ERROR( ledc_update_duty( speed_mode, channel) ); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetPolarity___VOID__U1( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + // Nothing to do here, we handle it other places + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStart___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Call configure to start PWM channel + NANOCLR_CHECK_HRESULT( ConfigureAndStart(pThis, false, false) ); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStop___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties or method parameters + int timerId = (int)(pThis[ FIELD___pwmTimer ].NumericByRef().u4); + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + int polarity = (int)(pThis[ FIELD___polarity ].NumericByRef().u4); + + ledc_mode_t speed_mode = GetSpeedMode(timerId); + + // FIX ME check result + ledc_channel_t channel = (ledc_channel_t)GetChannel(pinNumber, timerId, false); + + ledc_stop(speed_mode, channel, (uint32_t)polarity); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties or method parameters + int timerId = (int)(pThis[ FIELD___pwmTimer ].NumericByRef().u4); + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + + // Remove pin from pin/channel Map + char * pMap = (timerId > 3)? LowSpeedPinMap: HighSpeedPinMap; + + for( int index=0; index<8; index++, pMap++ ) + { + if (*pMap == pinNumber ) { *pMap = 255; break; } + } + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h new file mode 100644 index 00000000..b102b091 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_PWM_NATIVE_TARGET_H_ +#define _WIN_DEV_PWM_NATIVE_TARGET_H_ + +#include + +enum PwmPulsePolarity +{ + /// + /// Configures the PWM signal to start in the active high state. + /// + ActiveHigh, + /// + /// Configures the PWM signal to start in the active low state. + /// + ActiveLow +}; + +#endif //_WIN_DEV_PWM_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp new file mode 100644 index 00000000..fee59e23 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice.cpp @@ -0,0 +1,547 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "win_dev_serial_native_target.h" +#include "Esp32_DeviceMapping.h" + +// buffers size +// tx buffer size: 256 bytes +#define UART_TX_BUFER_SIZE 256 +// rx buffer size: 256 bytes +#define UART_RX_BUFER_SIZE 256 + +// in UWP the COM ports are named COM1, COM2, COM3. But ESP32 uses internally UART0, UART1, UART2. This maps the port index 1, 2 or 3 to the uart number 0, 1 or 2 +#define PORT_INDEX_TO_UART_NUM(portIndex) ((portIndex) - 1) +// in UWP the COM ports are named COM1, COM2, COM3. But ESP32 uses internally UART0, UART1, UART2. This maps the uart number 0, 1 or 2 to the port index 1, 2 or 3 +#define UART_NUM_TO_PORT_INDEX(uart_num) ((uart_num) + 1) + +static const char* TAG = "SerialDevice"; + +static char Esp_Serial_Initialised_Flag[UART_NUM_MAX] = {0, 0, 0}; +static QueueHandle_t Uart_Event_Queue[UART_NUM_MAX]; +static bool Uart_Post_SerialData_Chars_Event[UART_NUM_MAX] = {true, true, true}; +CLR_RT_HeapBlock* Serial_Device_Instance[UART_NUM_MAX]; +static int Uart_writeLength[UART_NUM_MAX]; + +void Esp32_Serial_UnitializeAll() +{ + for (int uart_num = 0; uart_num < UART_NUM_MAX; uart_num++) + { + if (Esp_Serial_Initialised_Flag[uart_num]) + { + // Delete uart driver and send the exit signal to the UART event handling queue + uart_driver_delete((uart_port_t)uart_num); + xQueueSend(Uart_Event_Queue[uart_num], (void*)UART_EVENT_MAX, (portTickType)0); + Uart_Post_SerialData_Chars_Event[uart_num] = false; + Serial_Device_Instance[uart_num] = NULL; + Esp_Serial_Initialised_Flag[uart_num] = 0; + } + } +} + +static void uart_event_task(void *pvParameters) +{ + int uart_num = (int)pvParameters; + uart_event_t event; + bool run = true; + + while(run) + { + // Waiting for UART event. + if(xQueueReceive(Uart_Event_Queue[uart_num], (void*)&event, (portTickType)portMAX_DELAY)) { + switch(event.type) { + // Data received + case UART_DATA: + // only if no one is reading the chars already and only if an event handler is attached + if (Uart_Post_SerialData_Chars_Event[uart_num] && Serial_Device_Instance[uart_num][Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___callbacksDataReceivedEvent].Dereference() != NULL) + { + // post a managed event with the port index and the chars event code; uart_num + 1 because UART0 maps to COM1 + PostManagedEvent(EVENT_SERIAL, 0, UART_NUM_TO_PORT_INDEX(uart_num), SerialData_Chars); + // supress the event for the following chars; prevents spamming with the SerialData_Chars event + // the flag will be reset if NativeRead will be called + Uart_Post_SerialData_Chars_Event[uart_num] = false; + } + break; + // Pattern detection used for the WatchChar + case UART_PATTERN_DET: + // only if an event handler is attached + if (Serial_Device_Instance[uart_num][Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___callbacksDataReceivedEvent].Dereference() != NULL) + { + // post a managed event with the port index and the watch char event code; uart_num + 1 because UART0 maps to COM1 + PostManagedEvent(EVENT_SERIAL, 0, UART_NUM_TO_PORT_INDEX(uart_num), SerialData_WatchChar); + } + break; + // signal to end the task (UART_EVENT_MAX used) + case UART_EVENT_MAX: + run = false; + break; + // Others + default: + break; + } + } + } + vQueueDelete(Uart_Event_Queue[uart_num]); + vTaskDelete(NULL); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeDispose___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + // uninstall the driver and send the exit signal to the UART event handling queue + uart_driver_delete(uart_num); + xQueueSend(Uart_Event_Queue[uart_num], (void*)UART_EVENT_MAX, (portTickType)portMAX_DELAY); + Uart_Post_SerialData_Chars_Event[uart_num] = false; + Serial_Device_Instance[uart_num] = NULL; + Esp_Serial_Initialised_Flag[uart_num] = 0; + } + NANOCLR_NOCLEANUP(); +} + +// +// Initialise a new Serial port +// +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + if ( uart_num > UART_NUM_2 || uart_num < 0 ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // call the configure and abort if not OK + HRESULT res = NativeConfig___VOID(stack); + if (res != S_OK) + { + NANOCLR_SET_AND_LEAVE(res); + } + + // Install driver + esp_err_t esp_err = uart_driver_install(uart_num, + UART_RX_BUFER_SIZE, // rx_buffer_size, + UART_TX_BUFER_SIZE, // tx_buffer_size, not buffered + 20, // queue_size + &Uart_Event_Queue[uart_num], // QueueHandle_t *uart_queue ( none for now ) + 0 // intr_alloc_flags + ); + if ( esp_err != ESP_OK ) + { + ESP_LOGE( TAG, "Failed to install uart driver"); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // receive the SerialData_Chars events and store the SerialDevice instance + Uart_Post_SerialData_Chars_Event[uart_num] = true; + Serial_Device_Instance[uart_num] = pThis; + + // Create a task to handle UART event from ISR + char task_name[16]; + sprintf(task_name, "uart%d_events", uart_num); + xTaskCreate(uart_event_task, task_name, 2048, (void*)uart_num, 12, NULL); + + // Ensure driver gets unitialized during soft reboot + HAL_AddSoftRebootHandler(Esp32_Serial_UnitializeAll); + Esp_Serial_Initialised_Flag[uart_num] = 1; + + Uart_writeLength[uart_num] = 0; + } + NANOCLR_NOCLEANUP(); +} + +// +// Set up serial port Configuration +// +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeConfig___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uart_config_t uart_config; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + if ( uart_num > UART_NUM_2 || uart_num < 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // setup configuration + // data bits / baud rate + uart_config.baud_rate = (uart_word_length_t)pThis[ FIELD___baudRate ].NumericByRef().s4; //baudrate + + switch( pThis[ FIELD___dataBits ].NumericByRef().s4 ) //data bit mode + { + case 5: + uart_config.data_bits = UART_DATA_5_BITS; break; + case 6: + uart_config.data_bits = UART_DATA_6_BITS; break; + case 7: + uart_config.data_bits = UART_DATA_7_BITS; break; + case 8: + uart_config.data_bits = UART_DATA_8_BITS; break; + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // parity + switch ((SerialParity)pThis[ FIELD___parity ].NumericByRef().s4) + { + default: + case SerialParity_None : + uart_config.parity = UART_PARITY_DISABLE ; + break; + case SerialParity_Even : + uart_config.parity = UART_PARITY_EVEN ; + break; + case SerialParity_Odd : + uart_config.parity = UART_PARITY_ODD ; + break; + } + + // stop bits + switch ((SerialStopBitCount)pThis[ FIELD___stopBits ].NumericByRef().s4) + { + default: + case SerialStopBitCount_One : + uart_config.stop_bits = UART_STOP_BITS_1; + break; + case SerialStopBitCount_OnePointFive : + uart_config.stop_bits = UART_STOP_BITS_1_5; + break; + case SerialStopBitCount_Two : + uart_config.stop_bits = UART_STOP_BITS_2; + break; + } + + uart_config.rx_flow_ctrl_thresh = 0; + + bool EnableXonXoff = false; + switch ((SerialHandshake)pThis[ FIELD___handshake ].NumericByRef().s4) + { + default: + case SerialHandshake_None : + uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; + break; + case SerialHandshake_RequestToSend : + uart_config.flow_ctrl = UART_HW_FLOWCTRL_RTS ; + uart_config.rx_flow_ctrl_thresh = 122; + break; + + case SerialHandshake_RequestToSendXOnXOff : + uart_config.flow_ctrl = UART_HW_FLOWCTRL_RTS ; + uart_config.rx_flow_ctrl_thresh = 122; + EnableXonXoff = true; + break; + + case SerialHandshake_XOnXOff : + EnableXonXoff = true; + break; + } + + uart_param_config(uart_num, &uart_config); + + if ( EnableXonXoff ) + uart_set_sw_flow_ctrl(uart_num, true, 20, 40); + + // Map to currently assigned pins + int txPin = Esp32_GetMappedDevicePins(DEV_TYPE_SERIAL, uart_num, 0); + int rxPin = Esp32_GetMappedDevicePins(DEV_TYPE_SERIAL, uart_num, 1); + int rtsPin = Esp32_GetMappedDevicePins(DEV_TYPE_SERIAL, uart_num, 2); + int ctsPin = Esp32_GetMappedDevicePins(DEV_TYPE_SERIAL, uart_num, 3); + + // Don't use RTS/CTS if no hardware handshake enabled + if ( uart_config.flow_ctrl == UART_HW_FLOWCTRL_DISABLE ) + { + rtsPin = UART_PIN_NO_CHANGE; + ctsPin = UART_PIN_NO_CHANGE; + } + + uart_set_pin(uart_num, txPin, rxPin, rtsPin, ctsPin); + + // null pointers and vars + pThis = NULL; + } + NANOCLR_NOCLEANUP(); +} + +// +// Write data into buffer +// +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeWrite___VOID__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uint8_t* data; + size_t length = 0; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // dereference the data buffer from the argument + CLR_RT_HeapBlock_Array* dataBuffer = stack.Arg1().DereferenceArray(); + + // get a the pointer to the array by using the first element of the array + data = dataBuffer->GetFirstElement(); + + // get the size of the buffer + length = (size_t)dataBuffer->m_numOfElements; + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + + + // Write data to ring bufferand start sending + size_t bytesWritten = uart_write_bytes( uart_num, (const char*)data, length); + + // check if all requested bytes were written + if(bytesWritten != length) + { + // not sure if this is the best exception to throw here... + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + Uart_writeLength[uart_num] += bytesWritten; + + // // need to update the _unstoredBufferLength field in the SerialDeviceOutputStream + // // get pointer to outputStream field + // CLR_RT_HeapBlock* outputStream = pThis[Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___outputStream].Dereference(); + + // // get pointer to _unstoredBufferLength field and udpate field value + // outputStream[Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDeviceOutputStream::FIELD___unstoredBufferLength].NumericByRef().s4 = palUart->TxRingBuffer.Length(); + + // null pointers and vars + pThis = NULL; + } + NANOCLR_NOCLEANUP(); +} + +// +// Store - Send buffer and wait +// +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeStore___U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + + // get value for writetimeout + // the way to access this it's somewhat convoluted but it is what it is + // get pointer to the field + CLR_RT_HeapBlock* timeout = &pThis[ Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___writeTimeout ]; + + // now get a pointer to the actual value + int64_t* timeoutTicks = Library_corlib_native_System_TimeSpan::GetValuePtr( *timeout ); + + // now get the value in ticks and convert it to milliseconds + int64_t timeoutMillisecondsValue = *timeoutTicks / TIME_CONVERSION__TICKUNITS; + + // Wait for max. writetimeout timespan for data to be sent + esp_err_t esp_err = uart_wait_tx_done( uart_num, (TickType_t) timeoutMillisecondsValue / portTICK_PERIOD_MS); + if (esp_err == ESP_ERR_TIMEOUT) + { + NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); + } + else if (esp_err != ESP_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // return how many bytes were send to the UART + stack.SetResult_U4(Uart_writeLength[uart_num]); + + Uart_writeLength[uart_num] = 0; + + // null pointers and vars + pThis = NULL; + } + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeRead___U4__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uint8_t* data; + size_t dataLength = 0; + + size_t count = 0; + int bytesRead = 0; + size_t toRead = 0; + + InputStreamOptions options = InputStreamOptions_None; + + CLR_RT_HeapBlock* timeout; + int64_t* timeoutTicks; + int64_t timeoutMillisecondsValue; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // dereference the data buffer from the argument + CLR_RT_HeapBlock_Array* dataBuffer = stack.Arg1().DereferenceArray(); + + // get a the pointer to the array by using the first element of the array + data = dataBuffer->GetFirstElement(); + + // get the length of the data buffer + dataLength = dataBuffer->m_numOfElements; + + // get how many bytes are requested to read + count = stack.Arg2().NumericByRef().s4; + + // get the InputStreamOptions option + options = (InputStreamOptions)stack.Arg3().NumericByRef().s4; + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + + // Bytes requested to read + toRead = count; + + // is the read ahead option enabled? + if(options == InputStreamOptions_ReadAhead) + { + // yes + // check how many bytes we can store in the buffer argument + size_t bufferedLength = 0; + uart_get_buffered_data_len(uart_num, &bufferedLength); + + if(dataLength < bufferedLength ) + { + // read as many bytes has the buffer can hold + toRead = dataLength; + } + else + { + // read everything that's available in the ring buffer + toRead = bufferedLength; + } + } + + // get value for readtimeout + // the way to access this it's somewhat convoluted but it is what it is + // get pointer to the field + timeout = &pThis[ Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::FIELD___readTimeout ]; + + // now get a pointer to the actual value + timeoutTicks = Library_corlib_native_System_TimeSpan::GetValuePtr( *timeout ); + + // now get the value in ticks and convert it to miliseconds + timeoutMillisecondsValue = *timeoutTicks / TIME_CONVERSION__TICKUNITS; + + // suppress the SerialData_Chars event during the reading of the chars; prevents spamming with the SerialData_Chars event + Uart_Post_SerialData_Chars_Event[uart_num] = false; + bytesRead = uart_read_bytes(uart_num, data, toRead, timeoutMillisecondsValue / portTICK_RATE_MS); + Uart_Post_SerialData_Chars_Event[uart_num] = true; + + if ( bytesRead < 0 ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + // return how many bytes were read from the Rx buffer and/or UART + stack.SetResult_U4(bytesRead); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::NativeSetWatchChar___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + + // Get the watch char + uint8_t watchChar = (uint8_t)pThis[ FIELD___watchChar ].NumericByRef().u1; + + // Enable pattern detection for the serial device + uart_enable_pattern_det_intr(uart_num, watchChar, 1, 10000, 10, 10); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::get_BytesToRead___U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD___disposed ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // Get Uart number for serial device + uart_port_t uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[ FIELD___portIndex ].NumericByRef().s4); + + // check how many bytes are in the buffer + size_t bufferedLength = 0; + uart_get_buffered_data_len(uart_num, &bufferedLength); + + // return how many bytes can be read from the Rx buffer + stack.SetResult_U4(bufferedLength); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_serial_native_Windows_Devices_SerialCommunication_SerialDevice::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "COM1,COM2,COM3" + terminator + char deviceSelectorString[ 15 ] = "COM1,COM2,COM3"; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h new file mode 100644 index 00000000..18bad9df --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.SerialCommunication/win_dev_serial_native_target.h @@ -0,0 +1,11 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_SERIAL_NATIVE_TARGET_H_ +#define _WIN_DEV_SERIAL_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_DEV_SERIAL_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp new file mode 100644 index 00000000..f6ee56c6 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_spi_native_target.h" + + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MaxClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + stack.SetResult_I4 ( MAX_CLOCK_FREQUENCY ); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MinClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + stack.SetResult_I4 ( 1000000 ); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp new file mode 100644 index 00000000..f3ed2f04 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native_target.h" + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "SPI1,SPI2" + terminator and init with the terminator + char deviceSelectorString[ 15 ] = { "SPI1,SPI2" }; // HSPI & VSPI + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp new file mode 100644 index 00000000..13000258 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp @@ -0,0 +1,437 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// Esp32 has 4 SPI devices called SPI0, SPI1, HSPI and VSPI +// SPIO, SPI1 are dedicated entirely to flash +// +// HSPI("SPI1") and VSPI("SPI2") are free to use +// +// For maximum speed access the IOMUX must be used ( 80mhz ) +// if pins are through the GPIO matrix the speed is limited to 26.6mhz ( 40mhz half duplex and no dma ) +// +// SPI IOMUX ( direct pins ) +// GPIO Function +// 2 HSPIWP (WP) +// 4 HSPIHD (HD) +// 12 HSPIQ (miso) * +// 13 HSPID (mosi) * +// 14 HSPICLK (clockPin) * +// 15 HSPICS0 (cs) +// +// 5 VSPICS0 (cs) +// 18 VSPICLK (clockPin) * +// 19 VSPIQ (miso) * +// 21 VSPIHD (HD) +// 22 VSPIWP (WP) +// 23 VSPID (mosi) * +// +// The defaults pins for SPI1 are the Wrover SPI display pins +// mosiPin = GPIO_NUM_23, misoPin = GPIO_NUM_25, clockPin = GPIO_NUM_19 +// +// SPI2 - The pins are not assigned so need to be assigned. + +#include +#include +#include +#include +#include "win_dev_spi_native_target.h" +#include "Esp32_DeviceMapping.h" + +static nfSpiBusConfig spiconfig[NUM_SPI_BUSES]; +static bool nfSpiInited = false; + + +// define this type here to make it shorter and improve code readability +typedef Library_win_dev_spi_native_Windows_Devices_Spi_SpiConnectionSettings SpiConnectionSettings; + +// Tag for ESP32 logging +static const char* TAG = "SpiDevice"; + + +// Define this to allow access to device config in spi master driver +struct spi_device_t { + QueueHandle_t trans_queue; + QueueHandle_t ret_queue; + spi_device_interface_config_t cfg; +}; + + +void Remove_Spi_Device(int bus, int deviceIndex) +{ + // Remove device from bus + spi_bus_remove_device( spiconfig[bus].deviceHandles[deviceIndex] ); + spiconfig[bus].deviceHandles[deviceIndex] = 0; + spiconfig[bus].deviceId[deviceIndex] = 0; +} + +int FindFreeDeviceSlotSpi(int bus) +{ + for (int deviceIndex = 0; deviceIndex < MAX_SPI_DEVICES; deviceIndex++) + { + if (spiconfig[bus].deviceHandles[deviceIndex] == 0) return deviceIndex; + } + return -1; +} + +// Unitialise SPI on restart +void Esp32_Spi_UnitializeAll() +{ + for (int bus = 0; bus < NUM_SPI_BUSES; bus++) + { + if (spiconfig[bus].spiBusInited) + { + // Remove any devices + for( int deviceIndex=0; deviceIndex < MAX_SPI_DEVICES; deviceIndex++) + { + if ( spiconfig[bus].deviceHandles[deviceIndex] != 0 ) + Remove_Spi_Device(bus, deviceIndex); + } + + // Delete bus driver + spi_bus_free((spi_host_device_t)bus); + spiconfig[bus].spiBusInited = false; + } + } +} + +// Inialise the SPI Bus +static void InitSpiBus( spi_host_device_t bus) +{ + int busIndex = bus - 1; + + gpio_num_t mosiPin = (gpio_num_t)Esp32_GetMappedDevicePins( DEV_TYPE_SPI, busIndex, 0); + gpio_num_t misoPin = (gpio_num_t)Esp32_GetMappedDevicePins( DEV_TYPE_SPI, busIndex, 1); + gpio_num_t clockPin = (gpio_num_t)Esp32_GetMappedDevicePins( DEV_TYPE_SPI, busIndex, 2); + + spi_bus_config_t bus_config + { + mosi_io_num: mosiPin, // mosi pin + miso_io_num : misoPin, // miso pin + sclk_io_num : clockPin, // Clock + quadwp_io_num : -1, // Quad Write protect + quadhd_io_num : -1, // Quad Hold + max_transfer_sz : 0, // Default max transfer size ( 4096 ) + flags : 0, // SPICOMMON_BUSFLAG_* flags + intr_flags : 0 // Interrupt flags + }; + + esp_err_t ret = spi_bus_initialize(bus, &bus_config, 1); + if ( ret != ESP_OK ) + { + ESP_LOGE( TAG, "Unable to init SPI bus"); + return; + } +} + +// Give a complete low-level SPI configuration from user's managed connectionSettings +spi_device_interface_config_t GetConfig( int bus, CLR_RT_HeapBlock* config) +{ + (void)bus; + + int csPin = config[ SpiConnectionSettings::FIELD___csLine ].NumericByRef().s4; + uint8_t spiMode = (uint8_t)config[ SpiConnectionSettings::FIELD___spiMode ].NumericByRef().s4; + int bitOrder = config[ SpiConnectionSettings::FIELD___bitOrder ].NumericByRef().s4; + int clockHz = config[ SpiConnectionSettings::FIELD___clockFrequency ].NumericByRef().s4; + + // if clock frequency is unset use the maximum frequency + if (clockHz == 0) + { + clockHz = MAX_CLOCK_FREQUENCY; + } + + //ets_printf( "Spi config cspin:%d spiMode:%d bitorder:%d clockHz:%d\n", csPin, spiMode, bitOrder, clockHz); + uint32_t flags = (bitOrder == 1) ? (SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST) : 0; + + // Fill in device config + spi_device_interface_config_t dev_config + { + 0, // Command bits + 0, // Address bits + 0, // Dummy bits + spiMode, // SPi Mode + 0, // Duty cycle 50/50 + 0, // cs_ena_pretrans + 0, // cs_ena_posttrans + clockHz, // Clock speed in Hz + 0, // Input_delay_ns + csPin, // Chip select + flags, // SPI_DEVICE flags + 1, // Queue size + 0, // Callback before + 0, // Callback after + }; + + return dev_config; +} + +// +// Add new device and return device index +// return -1 if no more devices avalaible +// +int Add_Spi_Device(int bus, CLR_RT_HeapBlock* pThis) +{ + spi_device_interface_config_t dev_config; + nfSpiBusConfig * pBusConfig = &spiconfig[bus]; + + int deviceIndex = FindFreeDeviceSlotSpi(bus); + // Check if all device slots used + if (deviceIndex < 0) return -1; + + // Get a complete low-level SPI configuration, depending on user's managed parameters + dev_config = GetConfig(bus, pThis[ Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::FIELD___connectionSettings ].Dereference()); + + // Add device to bus + spi_device_handle_t deviceHandle; + if ( spi_bus_add_device( (spi_host_device_t)bus, &dev_config, &deviceHandle ) != ESP_OK ) + { + ESP_LOGE( TAG, "Unable to init SPI device"); + return -1; + } + + // Add next Device + pBusConfig->deviceId[deviceIndex] = pThis[ Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::FIELD___deviceId ].NumericByRef().s4; + pBusConfig->deviceHandles[deviceIndex] = deviceHandle; + + return deviceIndex; +} + +// +// Get the Bus and device index +// return false if error +// +bool GetDevice( CLR_RT_HeapBlock* pThis, uint8_t * pBus, int * pDeviceIndex) +{ + int32_t deviceId = pThis[ Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::FIELD___deviceId ].NumericByRef().s4; + *pBus = (uint8_t)(deviceId / 1000); + + // Find device in spiconfig + for( int index=0; index < MAX_SPI_DEVICES; index++) + { + if ( spiconfig[*pBus].deviceId[index] == deviceId ) + { + // Device found with same deviceId + *pDeviceIndex = index; + return true; + } + } + return false; +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + return NativeTransfer( stack, false ); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + return NativeTransfer( stack, true ); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer( CLR_RT_StackFrame& stack, bool data16 ) +{ + NANOCLR_HEADER(); + { + unsigned char * writeData = NULL; + unsigned char * originalReadData = NULL; + unsigned char * readData = NULL; + int writeSize = 0; + int readSize = 0; + + stack.m_customState = 1; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index and Device index + uint8_t bus; + int deviceIndex; + if ( GetDevice( pThis, &bus, &deviceIndex) == false ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // get data bit length + int databitLength = pConfig[ SpiConnectionSettings::FIELD___databitLength ].NumericByRef().s4; + if (databitLength <= 0) databitLength = 8; + if ( data16 ) databitLength = 16; + + // dereference the write and read buffers from the arguments + CLR_RT_HeapBlock_Array* writeBuffer = stack.Arg1().DereferenceArray(); + if (writeBuffer != NULL) + { + // grab the pointer to the array by getting the first element of the array + if ( data16 ) + writeData = (unsigned char * )writeBuffer->GetFirstElementUInt16(); + else + writeData = writeBuffer->GetFirstElement(); + + // get the size of the buffer by reading the number of elements in the HeapBlock array + writeSize = writeBuffer->m_numOfElements; + } + + CLR_RT_HeapBlock_Array* readBuffer = stack.Arg2().DereferenceArray(); + if (readBuffer != NULL) + { + // grab the pointer to the array by getting the first element of the array + if ( data16 ) + originalReadData = (unsigned char * )readBuffer->GetFirstElementUInt16(); + else + originalReadData = readBuffer->GetFirstElement(); + + // get the size of the buffer by reading the number of elements in the HeapBlock array + readSize = readBuffer->m_numOfElements; + } + + // Are we using SPI full-duplex for transfer ? + // The SPI doesn't support half duplex operation with DMA and without DMA the receive length is limited to 4 bytes + // So we run in full duplex mode all the time and simulate half duplex mode by creating a larger receive buffer for + // the whole of the transaction and then copying the rx part to original buffer + // For full duplex we just use passed buffers. + bool fullDuplex = (bool)stack.Arg3().NumericByRef().u1; + + int MaxDatalength; + if (fullDuplex) + { + // for full duplex just use largest element + MaxDatalength= (readSize > writeSize)? readSize: writeSize; + readData = originalReadData; + } + else + { + // for Halfduplex its the length of both items + MaxDatalength = writeSize + readSize; + + if (readSize) + { + // Allocate a new read buffer to include total length(DMA capable) + readData = (unsigned char *)heap_caps_malloc(MaxDatalength, MALLOC_CAP_DMA); + if ( readData == 0) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + } + + // Set up SPI Transaction + spi_transaction_t trans_desc; + + trans_desc.flags = 0; + trans_desc.cmd = 0; + trans_desc.addr = 0; + // length - Full duplex is total length, half duplex the TX length + trans_desc.length = databitLength * MaxDatalength; + // rxlength - Full duplex is same as length or 0, half duplex is read length + trans_desc.rxlength = 0; + trans_desc.user = NULL; + trans_desc.tx_buffer = writeData; + trans_desc.rx_buffer = readData; + + // Start tranfer ( this calls spi_device_queue_trans & spi_device_get_trans_result) + // Next release of IDF has a direct plling mode that should be faster + esp_err_t ret = spi_device_transmit( spiconfig[bus].deviceHandles[deviceIndex], &trans_desc); + if ( ret != ESP_OK ) + { + if (!fullDuplex) heap_caps_free(readData); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Finish up half duplex + if (!fullDuplex) + { + if (readSize) + { + // Copy the read data + memcpy( originalReadData, readData + writeSize, readSize); + heap_caps_free(readData); + } + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); //FAULT_ON_NULL(pThis); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details ( 1 or 2 ) + int32_t deviceId = pThis[ FIELD___deviceId ].NumericByRef().s4; + + spi_host_device_t bus = (spi_host_device_t)( deviceId / 1000 ); + + // Check valid bus + if ( bus < HSPI_HOST || bus > VSPI_HOST ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if ( !nfSpiInited ) + { + for( int i=0; i +#include + +// # buses but first can't be used as SPI flash +#define NUM_SPI_BUSES 3 +#define MAX_SPI_DEVICES 3 + +// Max clock frequency is 20 MHz +#define MAX_CLOCK_FREQUENCY 20000000 + +struct nfSpiBusConfig +{ + bool spiBusInited; + int deviceId[MAX_SPI_DEVICES]; // Used to find correct device in config + spi_device_handle_t deviceHandles[MAX_SPI_DEVICES]; // Max 3 devices per bus (IDF limit ) +}; + +#endif //_WIN_DEV_SPI_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native.h new file mode 100644 index 00000000..42fe779c --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native.h @@ -0,0 +1,89 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_WIFI_NATIVE_TARGET_H_ +#define _WIN_DEV_WIFI_NATIVE_TARGET_H_ + +#include +#include +#include +#include + + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter +{ + static const int FIELD_STATIC__s_eventListener = 0; + + static const int FIELD___networkInterface = 1; + static const int FIELD___syncLock = 2; + static const int FIELD__AvailableNetworksChanged = 3; + static const int FIELD___disposedValue = 4; + + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(NativeConnect___WindowsDevicesWiFiWiFiConnectionStatus__STRING__STRING__WindowsDevicesWiFiWiFiReconnectionKind); + NANOCLR_NATIVE_DECLARE(NativeDisconnect___VOID); + NANOCLR_NATIVE_DECLARE(NativeScanAsync___VOID); + NANOCLR_NATIVE_DECLARE(GetNativeScanReport___SZARRAY_U1); + NANOCLR_NATIVE_DECLARE(NativeFindWirelessAdapters___STATIC__SZARRAY_U1); + + //--// + + static HRESULT GetNetInterfaceIndex(CLR_RT_StackFrame& stack, int * pNetIndex); +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAvailableNetwork +{ + static const int FIELD___bsid = 1; + static const int FIELD___ssid = 2; + static const int FIELD___rssi = 3; + static const int FIELD___networkKind = 4; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiConnectionResult +{ + static const int FIELD___ConnectionStatus = 1; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiEvent +{ + static const int FIELD__EventType = 3; + static const int FIELD__Time = 4; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiEventListener +{ + static const int FIELD__wifiAdapters = 1; + + + //--// + +}; + +struct Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiNetworkReport +{ + static const int FIELD___wifiNetworks = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Wifi; + +#endif //_WIN_DEV_WIFI_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native_Windows_Devices_WIFI_WifiAdapter.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native_Windows_Devices_WIFI_WifiAdapter.cpp new file mode 100644 index 00000000..f40c3f9f --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Devices.Wifi/win_dev_wifi_native_Windows_Devices_WIFI_WifiAdapter.cpp @@ -0,0 +1,315 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "win_dev_wifi_native.h" +#include "nf_rt_events_native.h" + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.WiFi (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// +struct ScanRecord +{ + uint8_t bssid[6]; + uint8_t ssid[33]; + uint8_t rssi; + uint8_t authMode; + uint8_t cypherType; +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.WiFi (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// +enum WiFiConnectionStatus +{ + AccessRevoked = 0, + InvalidCredential, + NetworkNotAvailable, + Success, + Timeout, + UnspecifiedFailure, + UnsupportedAuthenticationProtocol +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.WiFi (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// +enum WiFiNetworkKind +{ + Adhoc = 0, + Any, + Infrastructure +}; + + /////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.WiFi (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// +enum WiFiReconnectionKind +{ + Automatic = 0, + Manual +}; + +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + (void)stack; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + (void)stack; + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +// +// Pickup Net interface index and do checks +// +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::GetNetInterfaceIndex(CLR_RT_StackFrame& stack, int * pNetIndex) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + *pNetIndex = pThis[ FIELD___networkInterface ].NumericByRefConst().s4; + } + NANOCLR_NOCLEANUP(); +} + +// +// Connect to Wireless connection to passed SSID / passPhase +// +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeConnect___WindowsDevicesWiFiWiFiConnectionStatus__STRING__STRING__WindowsDevicesWiFiWiFiReconnectionKind( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + const char* szSsid; + const char* szPassPhase; + int reconnectionKind; + esp_err_t res; + int netIndex; + + NANOCLR_CHECK_HRESULT( GetNetInterfaceIndex(stack, &netIndex ) ); + + WiFiConnectionStatus Status = Success; + + // Get SSID + szSsid = stack.Arg1().RecoverString(); FAULT_ON_NULL(szSsid); + + // Get Password + szPassPhase = stack.Arg2().RecoverString(); FAULT_ON_NULL(szPassPhase); + + // Reconnect kind + reconnectionKind = stack.Arg3().NumericByRef().s4; + + res = (esp_err_t)Network_Interface_Connect(netIndex, szSsid, szPassPhase, reconnectionKind); + switch(res) + { + case ESP_OK: + Status = Success; + break; + case ESP_ERR_WIFI_SSID: + Status = NetworkNotAvailable; + break; + case ESP_ERR_WIFI_PASSWORD: + Status = InvalidCredential; + break; + case ESP_ERR_WIFI_TIMEOUT: + Status = Timeout; + break; + + default: + case ESP_ERR_WIFI_NOT_INIT: + case ESP_ERR_WIFI_NOT_STARTED: + case ESP_ERR_WIFI_CONN: + Status = UnspecifiedFailure; + break; + } + + // Return value to the managed application + stack.SetResult_I4( Status ); + } + NANOCLR_NOCLEANUP(); +} + +// +// Disconnect WiFi connection +// +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeDisconnect___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int netIndex; + + NANOCLR_CHECK_HRESULT( GetNetInterfaceIndex(stack, &netIndex ) ); + + Network_Interface_Disconnect(netIndex); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeScanAsync___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int netIndex; + + NANOCLR_CHECK_HRESULT( GetNetInterfaceIndex(stack, &netIndex ) ); + + // Start scan + if ( Network_Interface_Start_Scan(netIndex) == false) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + } + NANOCLR_NOCLEANUP(); +} + +// +// Stores Ap records to target string. +// if pTarget == 0 then just calculates length of target +// +// unint_8[6] MAC; +// unint_8[33] SSID +// unit8_t RSSI +// +// Return : length in pTarget +int StoreApRecordsToString( uint8_t * pTarget, wifi_ap_record_t * apRecords, uint16_t recordCount ) +{ + int index; + + if ( pTarget != 0 ) + { + // Store record count as first of returned byte[] + *pTarget++ = (uint8_t)recordCount; + + ScanRecord * pScanRec = (ScanRecord *)pTarget; + + for( index=0; index < recordCount; index++) + { + memcpy(pScanRec->bssid, apRecords[index].bssid, 6); + memcpy(pScanRec->ssid, apRecords[index].ssid, 33); + pScanRec->rssi = apRecords[index].rssi; + pScanRec->authMode = apRecords[index].authmode; + pScanRec->cypherType = apRecords[index].pairwise_cipher; + pScanRec++; + } + } + + // Fixed length records so we can calculate length + return (recordCount * sizeof(ScanRecord) + sizeof(uint16_t)); +} + +// private extern WiFiNetworkReport NativeNetworkReport(); +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::GetNativeScanReport___SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // Temporary ap record storage + wifi_ap_record_t * ap_records = 0; + { + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock_Array* array; + CLR_UINT8* buf; + uint16_t number = 0; + int rlen = 2; + + esp_err_t res = esp_wifi_scan_get_ap_num( &number ); + if ( res != ESP_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if ( number != 0 ) + { + // Allocate room for ap records + ap_records = (wifi_ap_record_t *)platform_malloc(sizeof(wifi_ap_record_t) * number ); + if (ap_records == 0) NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + + res = esp_wifi_scan_get_ap_records( &number, ap_records); + if ( res != ESP_OK) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Store AP records in string and return to managed code to sort out + // MAC, SSID, RSSI, Auth mode, + + // Find out how big a string is required + rlen = StoreApRecordsToString( 0, ap_records, number ); + } + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, rlen, g_CLR_RT_WellKnownTypes.m_UInt8 )); + array = top.DereferenceArray(); + buf = array->GetFirstElement(); + + // Store into returned uint8 array + StoreApRecordsToString( buf, ap_records, number ); + } + + NANOCLR_CLEANUP(); + + if(ap_records) + { + platform_free(ap_records); + } + + NANOCLR_CLEANUP_END(); +} + +// +// Find wireless adapters in network config +// return count of adapters found +// +int FindWirelessAdaptersStore( uint8_t * pTarget ) +{ + int wirelessCount = 0; + + for( int index=0; index < g_TargetConfiguration.NetworkInterfaceConfigs->Count; index++) + { + HAL_Configuration_NetworkInterface* pNetInterface = g_TargetConfiguration.NetworkInterfaceConfigs->Configs[index]; + + if (pNetInterface->InterfaceType == NetworkInterfaceType_Wireless80211) + { + wirelessCount++; + if ( pTarget != 0) *pTarget++ = (uint8_t)index; + } + } + + return wirelessCount; +} + +HRESULT Library_win_dev_wifi_native_Windows_Devices_WiFi_WiFiAdapter::NativeFindWirelessAdapters___STATIC__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock_Array* array; + CLR_UINT8* buf; + int rlen; + + // Find number of wireless adapters so we can allocated return array + rlen = FindWirelessAdaptersStore( 0 ); + + // Return interface indexes + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, rlen, g_CLR_RT_WellKnownTypes.m_UInt8 )); + array = top.DereferenceArray(); + buf = array->GetFirstElement(); + + // Store adapters indexes in to returned array + FindWirelessAdaptersStore( buf ); + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp new file mode 100644 index 00000000..3492d2bf --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_Windows_Networking_Sockets_SocketNative.cpp @@ -0,0 +1,594 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "win_net_sockets_native_target.h" + +// TODO - Check if required, for now just ignore +#define SwapEndianIfBEc16(x) (x) + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::socket___STATIC__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_INT32 family = stack.Arg0().NumericByRef().s4; + CLR_INT32 type = stack.Arg1().NumericByRef().s4; + CLR_INT32 protocol = stack.Arg2().NumericByRef().s4; + + CLR_INT32 nonBlocking = 1; + CLR_INT32 sock = SOCK_socket( family, type, protocol ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, sock )); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, SOCK_ioctl( sock, SOCK_FIONBIO, &nonBlocking ) )); + + stack.SetResult_I4( sock ); + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::bind___STATIC__VOID__OBJECT__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + return BindConnectHelper( stack, true ); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::connect___STATIC__VOID__OBJECT__SZARRAY_U1__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + return BindConnectHelper( stack, false ); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::send___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::recv___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::close___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_INT32 handle, ret; + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); FAULT_ON_NULL(socket); + + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + ret = SOCK_close( handle ); + + //If a socket gets closed, we need to make sure to wake up any threads that are waiting on it. + Events_Set( SYSTEM_EVENT_FLAG_SOCKET ); + + stack.SetResult_I4( ret ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::listen___STATIC__VOID__OBJECT__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 backlog = stack.Arg1().NumericByRef().s4; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + ret = SOCK_listen( handle, backlog ); + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::accept___STATIC__I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 ret; + CLR_INT32 nonBlocking = 1; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + + /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see + * if our handle has been shutdown before continuing. */ + if (handle == DISPOSED_HANDLE) + { + ThrowError(stack, CLR_E_OBJECT_DISPOSED); + NANOCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION); + } + + ret = SOCK_accept( handle, NULL, NULL ); + + if(ret != SOCK_SOCKET_ERROR) + { + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, SOCK_ioctl( ret, SOCK_FIONBIO, &nonBlocking ) )); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + stack.SetResult_I4( ret ); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::shutdown___STATIC__VOID__OBJECT__I4__BYREF_I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::sendto___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::recvfrom___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4__I4__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getpeername___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getsockname___STATIC__VOID__OBJECT__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::getsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::setsockopt___STATIC__VOID__OBJECT__I4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::poll___STATIC__BOOLEAN__OBJECT__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::ioctl___STATIC__VOID__OBJECT__U4__BYREF_U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + + + +//--// + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::BindConnectHelper( CLR_RT_StackFrame& stack, bool fBind ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + SOCK_sockaddr addr; + CLR_UINT32 addrLen = sizeof(addr); + CLR_INT32 ret; + bool fThrowOnWouldBlock = false; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, stack.Arg1() )); + + if(fBind) + { + ret = SOCK_bind( handle, &addr, addrLen ); + } + else + { + ret = SOCK_connect( handle, &addr, addrLen ); + + fThrowOnWouldBlock = (stack.Arg2().NumericByRefConst().s4 != 0); + + if(!fThrowOnWouldBlock && SOCK_getlasterror() == SOCK_EWOULDBLOCK) + { + NANOCLR_SET_AND_LEAVE(S_OK); + } + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::MarshalSockAddress( CLR_RT_HeapBlock& blkDst, const struct SOCK_sockaddr* addrSrc, CLR_UINT32 addrLenSrc ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* arr = NULL; + + CLR_RT_HeapBlock blkArr; blkArr.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( blkArr ); + SOCK_sockaddr_in* dst; + SOCK_sockaddr_in* src = (SOCK_sockaddr_in*)addrSrc; + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( blkArr, addrLenSrc, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + arr = blkArr.DereferenceArray(); + + _ASSERTE(arr); + + dst = (SOCK_sockaddr_in*)arr->GetFirstElement(); + + dst->sin_family = SwapEndianIfBEc16(src->sin_family); + dst->sin_port = src->sin_port; + dst->sin_addr.S_un.S_addr = src->sin_addr.S_un.S_addr; + + memcpy(dst->sin_zero, src->sin_zero, sizeof(dst->sin_zero)); + + _ASSERTE(blkDst.DataType() == DATATYPE_BYREF || blkDst.DataType() == DATATYPE_ARRAY_BYREF); + + NANOCLR_CHECK_HRESULT(blkArr.StoreToReference( blkDst, 0 )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::MarshalSockAddress( struct SOCK_sockaddr* addrDst, CLR_UINT32& addrLen, const CLR_RT_HeapBlock& blkSockAddress ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* ptrSockAddress; + SOCK_sockaddr_in* dst = (SOCK_sockaddr_in*)addrDst; + SOCK_sockaddr_in* src; + + ptrSockAddress = blkSockAddress.DereferenceArray(); + FAULT_ON_NULL(ptrSockAddress); + + if(ptrSockAddress->m_numOfElements > addrLen) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + src = (SOCK_sockaddr_in*)ptrSockAddress->GetFirstElement(); + + dst->sin_family = SwapEndianIfBEc16(src->sin_family); + dst->sin_port = src->sin_port; + dst->sin_addr.S_un.S_addr = src->sin_addr.S_un.S_addr; //already in network byte order + + memcpy(dst->sin_zero, src->sin_zero, sizeof(dst->sin_zero)); + + addrLen = ptrSockAddress->m_numOfElements; + + NANOCLR_NOCLEANUP(); +} + +// HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::SendRecvHelper( CLR_RT_StackFrame& stack, bool fSend, bool fAddress ) +// { +// NATIVE_PROFILE_CLR_NETWORK(); +// NANOCLR_HEADER(); + +// CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); +// CLR_INT32 handle; +// CLR_RT_HeapBlock_Array* arrData = stack.Arg1().DereferenceArray(); +// CLR_UINT32 offset = stack.Arg2().NumericByRef().u4; +// CLR_UINT32 count = stack.Arg3().NumericByRef().u4; +// CLR_INT32 flags = stack.Arg4().NumericByRef().s4; +// CLR_INT32 timeout_ms = stack.Arg5().NumericByRef().s4; +// CLR_RT_HeapBlock hbTimeout; + +// CLR_INT64* timeout; +// CLR_UINT8* buf; +// bool fRes = true; +// CLR_INT32 totReadWrite; +// CLR_INT32 ret = 0; + +// FAULT_ON_NULL(socket); +// FAULT_ON_NULL(arrData); + +// handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + +// /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see +// * if our handle has been shutdown before continuing. */ +// if (handle == DISPOSED_HANDLE) +// { +// ThrowError( stack, CLR_E_OBJECT_DISPOSED ); +// NANOCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION); +// } + +// if(offset + count > arrData->m_numOfElements) NANOCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); + + +// hbTimeout.SetInteger( timeout_ms ); + +// NANOCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout )); + +// // +// // Push "totReadWrite" onto the eval stack. +// // +// if(stack.m_customState == 1) +// { +// stack.PushValueI4( 0 ); + +// stack.m_customState = 2; +// } + +// totReadWrite = stack.m_evalStack[ 1 ].NumericByRef().s4; + +// buf = arrData->GetElement( offset + totReadWrite ); +// count -= totReadWrite; + +// while(count > 0) +// { +// CLR_INT32 bytes = 0; + +// // first make sure we have data to read or ability to write +// while(fRes) +// { +// ret = Helper__SelectSocket( handle, fSend ? 1 : 0 ); + +// if(ret != 0) break; + +// // non-blocking - allow other threads to run while we wait for handle activity +// NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); +// } + +// // timeout expired +// if(!fRes) +// { +// ret = SOCK_SOCKET_ERROR; + +// ThrowError( stack, SOCK_ETIMEDOUT ); + +// NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); +// } + +// // socket is in the excepted state, so let's bail out +// if(SOCK_SOCKET_ERROR == ret) +// { +// break; +// } + +// if(fAddress) +// { +// struct SOCK_sockaddr addr; +// CLR_UINT32 addrLen = sizeof(addr); +// CLR_RT_HeapBlock& blkAddr = stack.Arg6(); + +// if(fSend) +// { +// NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, blkAddr )); + +// bytes = SOCK_sendto( handle, (const char*)buf, count, flags, &addr, addrLen ); +// } +// else +// { +// CLR_RT_HeapBlock* pBlkAddr = blkAddr.Dereference(); + +// NANOCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, *pBlkAddr )); + +// bytes = SOCK_recvfrom( handle, (char*)buf, count, flags, &addr, (int*)&addrLen ); + +// if(bytes != SOCK_SOCKET_ERROR) +// { +// NANOCLR_CHECK_HRESULT(MarshalSockAddress( blkAddr, &addr, addrLen )); +// } +// } +// } +// else +// { +// if(fSend) +// { +// bytes = SOCK_send( handle, (const char*)buf, count, flags ); +// } +// else +// { +// bytes = SOCK_recv( handle, (char*)buf, count, flags ); +// } +// } + +// // send/recv/sendto/recvfrom failed +// if(bytes == SOCK_SOCKET_ERROR) +// { +// CLR_INT32 err = SOCK_getlasterror(); + +// if(err != SOCK_EWOULDBLOCK) +// { +// ret = SOCK_SOCKET_ERROR; +// break; +// } + +// continue; +// } +// // zero recv bytes indicates the handle has been closed. +// else if(!fSend && (bytes == 0)) +// { +// break; +// } + +// buf += bytes; +// totReadWrite += bytes; +// count -= bytes; + +// stack.m_evalStack[ 1 ].NumericByRef().s4 = totReadWrite; + +// // receive returns immediately after receiving bytes. +// if(!fSend && (totReadWrite > 0)) +// { +// break; +// } + +// } + +// stack.PopValue(); // totReadWrite +// stack.PopValue(); // Timeout + +// NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + +// stack.SetResult_I4( totReadWrite ); + +// NANOCLR_NOCLEANUP(); +// } + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::SockOptHelper( CLR_RT_StackFrame& stack, bool fGet ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 level = stack.Arg1().NumericByRef().s4; + CLR_INT32 optname = stack.Arg2().NumericByRef().s4; + CLR_RT_HeapBlock_Array* arrOpt = stack.Arg3().DereferenceArray(); + char* optval; + CLR_INT32 optlen; + CLR_INT32 ret; + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + FAULT_ON_NULL(arrOpt); + + optval = (char*)arrOpt->GetFirstElement(); + optlen = arrOpt->m_numOfElements; + + if(fGet) + { + ret = SOCK_getsockopt( handle, level, optname, optval, &optlen ); + _ASSERTE( optlen <= (CLR_INT32)arrOpt->m_numOfElements ); + } + else + { + ret = SOCK_setsockopt( handle, level, optname, optval, optlen ); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::SockNameHelper( CLR_RT_StackFrame& stack, bool fPeer ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); + CLR_INT32 handle; + CLR_INT32 ret; + + struct SOCK_sockaddr addr; + CLR_INT32 addrLen = sizeof(addr); + + FAULT_ON_NULL(socket); + handle = socket[ FIELD__m_Handle ].NumericByRef().s4; + + if(fPeer) + { + ret = SOCK_getpeername( handle, &addr, &addrLen ); + } + else + { + ret = SOCK_getsockname( handle, &addr, &addrLen ); + } + + NANOCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); + + NANOCLR_CHECK_HRESULT(MarshalSockAddress( stack.Arg1(), &addr, addrLen )); + + NANOCLR_NOCLEANUP(); +} + + + + +void Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::ThrowError( CLR_RT_StackFrame& stack, CLR_INT32 errorCode ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + // CLR_RT_HeapBlock& res = stack.m_owningThread->m_currentException; + + // if((Library_corlib_native_System_Exception::CreateInstance( res, g_CLR_RT_WellKnownTypes.m_SocketException, CLR_E_FAIL, &stack )) == S_OK) + // { + // res.Dereference()[ Library_system_sockets_System_Net_Sockets_SocketException::FIELD___errorCode ].SetInteger( errorCode ); + // } +} + +HRESULT Library_win_net_sockets_native_Windows_Networking_Sockets_SocketNative::ThrowOnError( CLR_RT_StackFrame& stack, CLR_INT32 res ) +{ + NATIVE_PROFILE_CLR_NETWORK(); + NANOCLR_HEADER(); + + if(res == SOCK_SOCKET_ERROR) + { + CLR_INT32 err = SOCK_getlasterror(); + + ThrowError( stack, err ); + + NANOCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); + } + + NANOCLR_NOCLEANUP(); +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h new file mode 100644 index 00000000..e885142e --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Networking.Sockets/win_net_sockets_native_target.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_NET_SOCKETS_NATIVE_TARGET_H_ +#define _WIN_NET_SOCKETS_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_NET_SOCKETS_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp new file mode 100644 index 00000000..d92723aa --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_Devices_SDCard.cpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_storage_native_target.h" +#include +#include +#include + +#include "Esp32_DeviceMapping.h" + +// Defines for Windows.Storage.c +extern "C" +{ + bool Storage_InitSDCardSPI(char * vfsName, int maxFiles, int pin_Miso, int pin_Mosi, int pin_Clk, int pin_Cs); + bool Storage_InitSDCardMMC(char * vfsName, int maxFiles, bool bit1Mode); + bool Storage_UnMountSDCard(); +} + +HRESULT Library_win_storage_native_Windows_Storage_Devices_SDCard::MountMMCNative___STATIC__VOID__BOOLEAN(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + +#if defined(HAL_USE_SDC) + bool bit1Mode = stack.Arg0().NumericByRef().s4; + char mountPoint[] = INDEX0_DRIVE_LETTER; + + // Change fatfs drive letter to mount point D: -> /D + mountPoint[1] = mountPoint[0]; + mountPoint[0] = '/'; + + // Try mounting + if (!Storage_InitSDCardMMC(mountPoint, SDC_MAX_OPEN_FILES, bit1Mode) ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } +#else + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); +#endif + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_storage_native_Windows_Storage_Devices_SDCard::MountSpiNative___STATIC__VOID__I4__I4(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + +#if defined(HAL_USE_SDC) + + int spiBus; + uint32_t CSPin; + char mountPoint[] = INDEX0_DRIVE_LETTER; + + // Change fatfs drive letter to mount point D: -> /D + mountPoint[1] = mountPoint[0]; + mountPoint[0] = '/'; + + // Get passed SPi bus number 1 or 2 + spiBus = stack.Arg0().NumericByRef().s4; + + // get Gpio pin for Chip select + CSPin = stack.Arg1().NumericByRef().s4; + + // Get current gpio pins used by SPI device + spiBus--; // Spi devnumber 0 & 1 + int mosiPin = Esp32_GetMappedDevicePins(DEV_TYPE_SPI, spiBus, 0); + int misoPin = Esp32_GetMappedDevicePins(DEV_TYPE_SPI, spiBus, 1); + int clockPin = Esp32_GetMappedDevicePins(DEV_TYPE_SPI, spiBus, 2); + + // Try mounting + if ( !Storage_InitSDCardSPI(mountPoint, SDC_MAX_OPEN_FILES, misoPin, mosiPin, clockPin, CSPin) ) + { + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } +#else + (void)stack; + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); +#endif + + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_win_storage_native_Windows_Storage_Devices_SDCard::UnmountNative___STATIC__VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + (void)stack; + +#if defined(HAL_USE_SDC) + + // Unmount SPI device + if (!Storage_UnMountSDCard()) + { + // SDcard not mounted + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + +#else + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); +#endif + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp new file mode 100644 index 00000000..4a8bf2c4 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_FileIO.cpp @@ -0,0 +1,677 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "win_storage_native_target.h" +#include +#include +#include + + +// defining these types here to make it shorter and improve code readability +typedef Library_win_storage_native_Windows_Storage_StorageFolder StorageFolder; +typedef Library_win_storage_native_Windows_Storage_StorageFile StorageFile; + +extern "C" +{ + bool Storage_InitSDCardMMC(char * vfsName, int maxFiles, bool bit1Mode); + bool Storage_InitSDCardSPI(char * vfsName, int maxFiles, int pin_Miso, int pin_Mosi, int pin_Clk, int pin_Cs); +}; + +// Queue length for IO task +#define StorageQueueLength 4 + + +////////////////////////////////////////// + +enum FileOperationType { READ_TEXT, WRITE_TEXT, READ_BINARY, WRITE_BINARY, EXIT }; + +struct FileOperation +{ + FileOperationType Operation; + FILE* File; + char* Content; + uint32_t ContentLength; +}; + +struct OperationResult +{ + FRESULT result; +}; + + +// Queues for passing Storage IO operations to thread abd returning results +static QueueHandle_t StorageInputQueue; +static QueueHandle_t StorageResultQueue; + + +char * ConvertToESP32Path(const char * filepath); + + +// Send IO operation to Queue +BaseType_t SendIOtoQueue(FileOperationType type, FILE *file, char * content, uint32_t contentLength) +{ + FileOperation fileIoOperation; + + // setup FileIO operation + fileIoOperation.Operation = type; + fileIoOperation.File = file; + fileIoOperation.Content = content; + fileIoOperation.ContentLength = contentLength; + + return xQueueSendToBack(StorageInputQueue, &fileIoOperation, portMAX_DELAY); +} + +// Wait for Result of IO operation +FRESULT WaitIOResult() +{ + OperationResult result; + + xQueueReceive(StorageResultQueue, &result, portMAX_DELAY); + + return result.result; +} + +// All file IO is serialised by queue job to this IO thread. +// + +// this is the FileIO working thread +// because FatFS is supposed to be atomic we won't have any concurrent threads + +// ReadText working thread +static FRESULT StorageReadText(FileOperation* fileIoOperation ) +{ + FRESULT operationResult; + + // need an extra one for the terminator + uint32_t readLength = fileIoOperation->ContentLength + 1; + + // read string + if (fgets(fileIoOperation->Content, readLength, fileIoOperation->File) ) + { + operationResult = FR_OK; + } + else + { + operationResult = FR_DISK_ERR; + } + + // close file + fclose(fileIoOperation->File); + + return operationResult; +} + + +// WriteBinary working thread +static FRESULT StorageWriteBinary(FileOperation* fileIoOperation) +{ + FRESULT operationResult = FR_DISK_ERR; + size_t bytesWritten; + + bytesWritten = fwrite(fileIoOperation->Content, 1, fileIoOperation->ContentLength, fileIoOperation->File); + if( bytesWritten == fileIoOperation->ContentLength ) + { + // expected number of bytes written + operationResult = FR_OK; + } + + // close file + fclose(fileIoOperation->File); + + return operationResult; +} + +// ReadBinary working thread +static FRESULT StorageReadBinary(FileOperation* fileIoOperation) +{ + FRESULT operationResult = FR_DISK_ERR; + UINT bytesRead; + + bytesRead = fread( fileIoOperation->Content, 1, fileIoOperation->ContentLength, fileIoOperation->File); + + + if( bytesRead == fileIoOperation->ContentLength) + { + // expected number of bytes read + operationResult = FR_OK; + } + + // close file + fclose(fileIoOperation->File); + + return operationResult; +} + + +void StorageIOTask(void *pvParameters) +{ + (void)pvParameters; + + bool bExit = false; + struct FileOperation fileOpMessage; + struct OperationResult operationResult; + + while (!bExit) + { + // Wait for message on Storage Queue + if (xQueueReceive(StorageInputQueue, &fileOpMessage, (TickType_t)10)) + { + switch (fileOpMessage.Operation) + { + case EXIT: + bExit = true; + operationResult.result = FR_OK; + break; + + case READ_TEXT: + operationResult.result = StorageReadText(&fileOpMessage); + break; + + case READ_BINARY: + operationResult.result = StorageReadBinary(&fileOpMessage); + break; + + case WRITE_TEXT: + case WRITE_BINARY: + operationResult.result = StorageWriteBinary(&fileOpMessage); + break; + + default: + operationResult.result = FR_OK; + break; + }; + + // Queue result and fire event + xQueueSend(StorageResultQueue, &operationResult, portMAX_DELAY); + + // fire event for FileIO operation complete + if (fileOpMessage.Operation != EXIT) + Events_Set(SYSTEM_EVENT_FLAG_STORAGE_IO); + } + } + + vTaskDelete(NULL); +} + +void CreateStorageIOTask() +{ + StorageInputQueue = xQueueCreate(StorageQueueLength, sizeof(FileOperation)); + StorageResultQueue = xQueueCreate(StorageQueueLength, sizeof(OperationResult)); + + xTaskCreate(StorageIOTask, "StorageIOTask", 2500, 0, 6, NULL); +} + +void DeleteQueues() +{ + vQueueDelete(StorageInputQueue); + vQueueDelete(StorageResultQueue); +} + +void Storage_Initialize() +{ + // Start IO Task + CreateStorageIOTask(); +} + +void Storage_Uninitialize() +{ + // Close down IO task + SendIOtoQueue(EXIT, 0, 0, 0); + WaitIOResult(); + + DeleteQueues(); +} + +//////////////////////////////////////////////// +// Developer notes: +// Depending on the content size these operations have the potential to be a long running ones as the string or buffer is written to the storage. +// Despite we are not (yet!) async this is better handled by spawning a thread where the actual data transfer occurs and not blocking the execution. +// The underlying RTOS inheritably takes care of making this happen "in the background". +// When the operation is completed a CLR event is fired and the thread execution resumes. +// Being hard to estimate the expected duration of the operation (depends on storage hardware, CPU clock, transfer speed, etc) +// the timeout is set to an infinite timeout +// the catch is that the working thread MUST ALWAYS return at some point +//////////////////////////////////////////////// + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteBytes___STATIC__VOID__WindowsStorageIStorageFile__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_Array* bufferArray; + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + char* buffer; + uint32_t bufferLength; + + const TCHAR* filePath; + char * workingPath = NULL; + FILE* file; + FRESULT operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the buffer + bufferArray = stack.Arg1().DereferenceArray(); + + buffer = (char*)bufferArray->GetFirstElement(); + + bufferLength = bufferArray->m_numOfElements; + + // get a pointer to the file path + filePath = (TCHAR*)pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + if(stack.m_customState == 1) + { + // open file (which is supposed to already exist) + // need to use FA_OPEN_ALWAYS("w+") because we are writting the file content from start + workingPath = ConvertToESP32Path(filePath); + file = fopen(workingPath, "w+"); + if(file == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + else + { + // protect the StorageFile and the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcStorageFile( *pThis ); + CLR_RT_ProtectFromGC gcContent( *bufferArray ); + + // setup FileIO operation + if ( SendIOtoQueue(WRITE_BINARY, file, buffer, bufferLength) == errQUEUE_FULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + operationResult = WaitIOResult(); + + if(operationResult == FR_DISK_ERR) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(operationResult == FR_NO_FILE) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(operationResult == FR_INVALID_DRIVE) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::WriteText___STATIC__VOID__WindowsStorageIStorageFile__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_String* content; + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + const TCHAR* filePath; + char * workingPath = NULL; + FILE * file; + FRESULT operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the content + content = stack.Arg1().DereferenceString(); + + // get a pointer to the file path + filePath = (TCHAR*)pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + if(stack.m_customState == 1) + { + + // open file (which is supposed to already exist) + // need to use FA_OPEN_ALWAYS("w+") because we are writting the file content from start + workingPath = ConvertToESP32Path(filePath); + file = fopen(workingPath, "w+" ); + if(file == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + else + { + // protect the StorageFile and the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcStorageFile( *pThis ); + CLR_RT_ProtectFromGC gcContent( *content ); + + if (SendIOtoQueue(WRITE_TEXT, file, (char*)content->StringText(), hal_strlen_s(content->StringText())) == errQUEUE_FULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + operationResult = WaitIOResult(); + + if(operationResult == FR_DISK_ERR) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(operationResult == FR_NO_FILE) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(operationResult == FR_INVALID_DRIVE) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadBufferNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + const TCHAR* filePath; + char * workingPath = NULL; + + FILE* file; + struct stat fileStat; + FRESULT operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // get a pointer to the file path + filePath = (TCHAR*)pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + if(stack.m_customState == 1) + { + // protect the StorageFile from GC + CLR_RT_ProtectFromGC gcStorageFile( *pThis ); + + // open file (which is supposed to already exist) + // need to use FA_OPEN_EXISTING("r") because we are reading an existing file content from start + workingPath = ConvertToESP32Path(filePath); + file = fopen(workingPath, "r"); + if(file == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + else + { + // get file details + stat(workingPath, &fileStat); + + CLR_RT_HeapBlock buffer; + buffer.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc2( buffer ); + + // create a new byte array with the appropriate size (and type) + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(buffer, (CLR_INT32)fileStat.st_size, g_CLR_RT_WellKnownTypes.m_UInt8)); + + // store this to the argument passed byref + NANOCLR_CHECK_HRESULT(buffer.StoreToReference( stack.Arg1(), 0 )); + + // get a pointer to the buffer array to improve readability on the code ahead + CLR_RT_HeapBlock_Array* bufferArray = buffer.DereferenceArray(); + + if (SendIOtoQueue(READ_BINARY, file, (char*)bufferArray->GetFirstElement(), bufferArray->m_numOfElements) == errQUEUE_FULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + operationResult = WaitIOResult(); + + if(operationResult == FR_DISK_ERR) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(operationResult == FR_NO_FILE) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(operationResult == FR_INVALID_DRIVE) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_FileIO::ReadTextNative___STATIC__VOID__WindowsStorageIStorageFile__BYREF_STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + const TCHAR* filePath; + char * workingPath = NULL; + + FILE * file; + struct stat fileStat; + FRESULT operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // get a pointer to the file path + filePath = (TCHAR*)pThis[ StorageFile::FIELD___path ].DereferenceString()->StringText(); + + if(stack.m_customState == 1) + { + // protect the StorageFile and the content buffer from GC so the working thread can access those + CLR_RT_ProtectFromGC gcStorageFile( *pThis ); + + // open file (which is supposed to already exist) + // need to use FA_OPEN_EXISTING("r") because we are reading an existing file content from start + workingPath = ConvertToESP32Path(filePath); + file = fopen(workingPath, "r"); + if(file == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + else + { + // get file details + stat(workingPath, &fileStat); + + // create a new string object with the appropriate size + CLR_RT_HeapBlock hbText; + hbText.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( hbText ); + + CLR_RT_HeapBlock_String* textString = CLR_RT_HeapBlock_String::CreateInstance( hbText, (CLR_UINT32)fileStat.st_size ); + FAULT_ON_NULL(textString); + + // store this to the argument passed byref + NANOCLR_CHECK_HRESULT(hbText.StoreToReference( stack.Arg1(), 0 )); + + // get a pointer to the buffer array to improve readability on the code ahead + hbText.DereferenceString(); + + if ( SendIOtoQueue(READ_TEXT, file, (char*)textString->StringText(), fileStat.st_size) == errQUEUE_FULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + // bump custom state + stack.m_customState = 2; + } + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the write operation to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_StorageIo, eventResult )); + + if(eventResult) + { + // event occurred + operationResult = WaitIOResult(); + + if(operationResult == FR_DISK_ERR) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_IO ); + } + else if(operationResult == FR_NO_FILE) + { + NANOCLR_SET_AND_LEAVE( CLR_E_FILE_NOT_FOUND ); + } + else if(operationResult == FR_INVALID_DRIVE) + { + // failed to change drive + NANOCLR_SET_AND_LEAVE(CLR_E_VOLUME_NOT_FOUND); + } + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE( CLR_E_TIMEOUT ); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp new file mode 100644 index 00000000..7ab328fb --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFile.cpp @@ -0,0 +1,194 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_storage_native_target.h" + +extern char * ConvertToESP32Path(const char * filepath); +extern uint64_t GetFileTimeFromPath(char * path); + +HRESULT Library_win_storage_native_Windows_Storage_StorageFile::DeleteFileNative___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + char* workingPath = NULL; + const char* managedPath; + int operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path].DereferenceString()->StringText(); + + // Convert to ESP32 form path ( linux like ) + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(managedPath); + + // Delete folder, 0=succesfull + operationResult = unlink(workingPath); + if (operationResult < 0) operationResult = errno; + if (operationResult != 0) + { + // folder doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); + +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFile::RenameFileNative___VOID__STRING(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + char* workingPath = NULL; + char* desiredWorkingPath = NULL; + const char* managedPath; + const char* desiredPath; + int operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path].DereferenceString()->StringText(); + + // Convert to ESP32 form path ( linux like ) + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(managedPath); + + // get a pointer to the desired folder path + desiredPath = stack.Arg1().DereferenceString()->StringText(); + desiredWorkingPath = ConvertToESP32Path(desiredPath); + + // rename folder, 0=succesfull + operationResult = rename(workingPath, desiredWorkingPath); + if (operationResult < 0) operationResult = errno; + if (operationResult == ENOENT) + { + // Invalid path/file not found + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + else if (operationResult == EEXIST) + { + // file already exists + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + } + else if (operationResult != 0) + { + // Some other error + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + if (desiredWorkingPath != NULL) + { + platform_free(desiredWorkingPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFile::GetFileFromPathNative___STATIC__WindowsStorageStorageFile__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFileTypeDef; + CLR_RT_HeapBlock* storageFile; + + const char* fileName; + const char* managedfilePath; + char * workingPath = NULL; + + static struct stat fileInfo; + + int operationResult; + + // get a pointer to the file path + managedfilePath = stack.Arg0().DereferenceString()->StringText(); + + // get a pointer to the file name + fileName = stack.Arg1().DereferenceString()->StringText(); + + workingPath = ConvertToESP32Path(managedfilePath); + + // check if path exists + operationResult = stat(workingPath, &fileInfo); + if(operationResult < 0) + { + operationResult = errno; + } + + if( operationResult == ENOENT ) + { + // path doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + + if( operationResult == 0 ) + { + // Is this a file + if (fileInfo.st_mode & S_IFREG) + { + // path represents a file, we are good + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFile", "Windows.Storage", storageFileTypeDef); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name], fileName)); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path], managedfilePath)); + + // get the date time details and fill in the managed field + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + + // get the date time details and fill in the managed field + // compute file date + // ...and set it + *pRes = GetFileTimeFromPath(workingPath); + } + else + { + // path exists but it's a folder + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + } + + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp new file mode 100644 index 00000000..754adc4e --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_Windows_Storage_StorageFolder.cpp @@ -0,0 +1,1158 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_storage_native_target.h" +#include +#include +#include +#include +#include "dirent.h" + +// +// Converts from windows type path "c:\folder\folder\file.ext" +// to linux type path used in ESP32 VFS "/c/folder/folder/file.exe +// where /c is the mount point +// +char * ConvertToESP32Path(const char * filepath) +{ + char * startPath = NULL; + char * path = NULL; + + int pathlen = hal_strlen_s(filepath); + startPath = (char*)platform_malloc(pathlen + 1); + path = startPath; + hal_strcpy_s(path, pathlen + 1, filepath); + + if (hal_strlen_s(path) >= 2) + { + // Map Drive: -> /C + char drive = *path; + *path++ = '/'; + *path++ = drive; + + // Convert '\' to '/' + while (*path) + { + if (*path == '\\') + *path++ = '/'; + else + path++; + } + } + + return startPath; +} + +void CombinePath(char * outpath, const char * path1, const char * path2) +{ + strcat(outpath, path1); + + // Add "\" to path if required + if (outpath[hal_strlen_s(outpath) - 1] != '\\') + { + strcat(outpath, "\\"); + } + strcat(outpath, path2); +} + +SYSTEMTIME GetDateTime(time_t * time) +{ + SYSTEMTIME fileTime; + + memset(&fileTime, 0, sizeof(SYSTEMTIME)); + + tm * ptm = gmtime(time); + + // Year from 1601 + fileTime.wYear = ptm->tm_year + 1900; // from Year based 1900 + // Month 1-12 + fileTime.wMonth = ptm->tm_mon + 1; // from Month 0-11 + // Day of month 1 - 31 + fileTime.wDay = ptm->tm_mday; + // Day of week 0 = Sunday + fileTime.wDayOfWeek = ptm->tm_wday; // 0 = Sunday + // Hour 0 to 23. + fileTime.wHour = ptm->tm_hour; + // Minutes 0 to 59. + fileTime.wMinute = ptm->tm_min; + // seconds 0 to 59 + fileTime.wSecond = ptm->tm_sec; + + return fileTime; +} + +uint64_t GetFileTimeFromPath(char * path) +{ + char * workingPath = NULL; + struct stat fileInfo; + SYSTEMTIME fileInfoTime; + + // Convert folder path back to ESP32 VFS format so + // we can stat folder + workingPath = ConvertToESP32Path(path); + + memset(&fileInfo, 0, sizeof(fileInfo)); + + // compute folder/file date/time + if (stat(workingPath, &fileInfo) == 0) + { + fileInfoTime = GetDateTime(&fileInfo.st_ctime); + } + else + { + // Spiffs don't have stat so zero date/time + memset(&fileInfoTime, 0, sizeof(SYSTEMTIME)); + // Make it a valid date + fileInfoTime.wYear = 1900; + fileInfoTime.wMonth = 1; + fileInfoTime.wDay = 1; + } + + if (workingPath != NULL) + { + platform_free(workingPath); + } + + return HAL_Time_ConvertFromSystemTime(&fileInfoTime); +} + + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetRemovableStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + char* stringBuffer; + uint32_t driveCount = 0; + char workingDrive[sizeof(DRIVE_PATH_LENGTH)]; + uint16_t driveIterator = 0; + + bool sdCardDrivePresent = false; + + CLR_RT_HeapBlock* storageFolder; + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* hbObj; + CLR_RT_HeapBlock& top = stack.PushValue(); + + + #if HAL_USE_SDC + // add count + driveCount++; + + // Esp32 doesn't currently have card present so make always true + sdCardDrivePresent = true; + #endif + + // start composing the reply + // find type definition, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, driveCount, storageFolderTypeDef )); + + if(driveCount > 0) + { + // there are driver present and enumerated + + // get a pointer to the first object in the array (which is of type ) + storageFolder = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFolder, storageFolderTypeDef)); + + // loop until we've loaded all the possible drives + // because we are iterating through an enum, need to use its integer values + for(; driveIterator < SUPPORTED_DRIVES_COUNT; driveIterator++ ) + { + // fill the folder name and path + if (driveIterator == 0 && sdCardDrivePresent == true ) + { + memcpy(workingDrive, INDEX0_DRIVE_PATH, DRIVE_PATH_LENGTH); + } + else + { + // skip this drive type + continue; + } + + // dereference the object in order to reach its fields + hbObj = storageFolder->Dereference(); + + // set the managed fields + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], workingDrive )); + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], workingDrive )); + + // malloc stringBuffer to work with FS + stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(stringBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + else + { + // clear buffer + memset(stringBuffer, 0, FF_LFN_BUF + 1); + + // TODO call FATFS method for this as function not present in VFS + // read the drive volume label + // don't bother checking the result, if anything goes wrong we'll end up with an empty string which is OK +// f_getlabel(workingDrive, stringBuffer, NULL); + + // add the driver letter separated it with an empty space, if the volume label isn't empty + if(*stringBuffer != '\0') + { + strcat(stringBuffer, " "); + } + strcat(stringBuffer, "("); + strcat(stringBuffer, workingDrive); + strcat(stringBuffer, ")"); + + // set the field with the volume label + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], stringBuffer )); + + + // free stringBuffer + platform_free(stringBuffer); + } + + // move pointer to the next folder item + storageFolder++; + } + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetInternalStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + char workingDrive[sizeof(DRIVE_PATH_LENGTH)]; + + uint32_t driveCount = 0; + + CLR_RT_HeapBlock* storageFolder; + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* hbObj; + CLR_RT_HeapBlock& top = stack.PushValue(); + + // One internal drive + driveCount++; + + // start composing the reply + // find type definition, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFolder", "Windows.Storage", storageFolderTypeDef); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, driveCount, storageFolderTypeDef)); + + if (driveCount > 0) + { + // get a pointer to the first object in the array (which is of type ) + storageFolder = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFolder, storageFolderTypeDef)); + + // dereference the object in order to reach its fields + hbObj = storageFolder->Dereference(); + + memcpy(workingDrive, INTERNAL_DRIVE_PATH, DRIVE_PATH_LENGTH); + + // set the managed fields + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name], workingDrive)); + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path], workingDrive)); + } + } + NANOCLR_NOCLEANUP(); +} + + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFoldersNative___SZARRAY_WindowsStorageStorageFolder( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* storageFolder; + CLR_RT_HeapBlock* hbObj; + + const char* managedPath; + + DIR * dir = NULL; + struct dirent * dirInfo; + + uint16_t directoryCount = 0; + char* stringBuffer = NULL; + char* workingBuffer = NULL; + char * workingPath = NULL; + + CLR_RT_HeapBlock& top = stack.PushValue(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // Convert to ESP32 form path for VFS ( linux like ) + // returns allocated converted path, must be freed + workingPath = ConvertToESP32Path(managedPath); + + // open directory + dir = opendir(workingPath); + if(dir) + { + // need to perform this in two steps + // 1st: count the directory objects + // 2nd: create the array items with each directory object + + // perform 1st pass + for (;;) + { + // read next directory item + dirInfo = readdir(dir); + + // break on error or at end of dir + if (dirInfo == NULL) + { + break; + } + + // check if this is a directory + // but skip if: + if (dirInfo->d_type == DT_DIR) + { + directoryCount++; + } + } + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, directoryCount, storageFolderTypeDef )); + + // get a pointer to the first object in the array (which is of type ) + storageFolder = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + if(directoryCount > 0) + { + // allocate memory for buffers + stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); + workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(stringBuffer == NULL || workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // perform 2nd pass + // need to rewind the directory read index first + rewinddir(dir); + + for (;;) + { + // read next directory item + dirInfo = readdir(dir); + + // break on error or at end of dir + if (dirInfo == NULL) + { + break; + } + + // check if this is a directory + // but skip if: + if (dirInfo->d_type == DT_DIR) + { + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFolder, storageFolderTypeDef)); + + // dereference the object in order to reach its fields + hbObj = storageFolder->Dereference(); + + // directory name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], dirInfo->d_name)); + + // clear working buffer + memset(workingBuffer, 0, 2 * FF_LFN_BUF + 1); + + // compose return directory path + CombinePath(workingBuffer, managedPath, (const char*)dirInfo->d_name); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], workingBuffer )); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = hbObj[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it + *pRes = GetFileTimeFromPath(workingBuffer); + + // move the storage folder pointer to the next item in the array + storageFolder++; + } + } + } + + + } + else + { + // error or directory empty + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFolder", "Windows.Storage", storageFolderTypeDef); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, directoryCount, storageFolderTypeDef)); + } + + NANOCLR_CLEANUP(); + + if (dir) + { + // close directory + closedir(dir); + } + + // free buffers memory, if allocated + if(stringBuffer != NULL) + { + platform_free(stringBuffer); + } + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + + + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetStorageFilesNative___SZARRAY_WindowsStorageStorageFile__U4__U4(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFileTypeDef; + CLR_RT_HeapBlock* storageFile; + CLR_RT_HeapBlock* hbObj; + + const char* managedPath; + char * workingPath = NULL; + + uint32_t startIndex; + uint32_t maxItemsToRetrieve; + uint32_t itemIndex = 0; + + DIR * dir = NULL; + struct dirent * dirInfo; + uint16_t fileCount = 0; + char* stringBuffer = NULL; + char* workingBuffer = NULL; + + CLR_RT_HeapBlock& top = stack.PushValue(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get start index + startIndex = stack.Arg1().NumericByRef().u4; + + // get max items to retrieve + maxItemsToRetrieve = stack.Arg2().NumericByRef().u4; + + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path].DereferenceString()->StringText(); + + // Convert to ESP32 form path ( linux like ) + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(managedPath); + + dir = opendir(workingPath); + if (dir) + { + // need to perform this in two steps + // 1st: count the file objects + // 2nd: create the array items with each file object + + // perform 1st pass + for (;;) + { + // read next directory item + dirInfo = readdir(dir); + + // break on error or at end of dir + if (dirInfo == NULL) + { + break; + } + + // check if this is a file + // but skip if diretory: + if (dirInfo->d_type == DT_REG) + { + // check if this file is within the requested parameters + if ((itemIndex >= startIndex) && + (fileCount < maxItemsToRetrieve)) + { + fileCount++; + } + + itemIndex++; + } + } + + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFile", "Windows.Storage", storageFileTypeDef); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, fileCount, storageFileTypeDef)); + + // get a pointer to the first object in the array (which is of type ) + storageFile = (CLR_RT_HeapBlock*)top.DereferenceArray()->GetFirstElement(); + + if (fileCount > 0) + { + // allocate memory for buffers + stringBuffer = (char*)platform_malloc(FF_LFN_BUF + 1); + workingBuffer = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if (stringBuffer == NULL || workingBuffer == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // perform 2nd pass + // need to rewind the directory read index first + rewinddir(dir); + + // and reset the file iterator vars too + itemIndex = 0; + fileCount = 0; + + + for (;;) + { + // read next directory item + dirInfo = readdir(dir); + + // break on error or at end of dir + if (dirInfo == NULL) + { + break; + } + + // check if this is a file + // but skip if diretory: + if (dirInfo->d_type == DT_REG) + { + // check if this file is within the requested parameters + if ((itemIndex >= startIndex) && + (fileCount < maxItemsToRetrieve)) + { + // create an instance of + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*storageFile, storageFileTypeDef)); + + // dereference the object in order to reach its fields + hbObj = storageFile->Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name], dirInfo->d_name)); + + // clear working buffer + memset(workingBuffer, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(workingBuffer, managedPath, (const char*)dirInfo->d_name); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path], workingBuffer)); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = hbObj[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + // ...and set it + *pRes = GetFileTimeFromPath(workingBuffer); + + // move the storage folder pointer to the next item in the array + storageFile++; + + // update iterator var + fileCount++; + } + + // update iterator var + itemIndex++; + } + } + } + else + { + // empty directory + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFile", "Windows.Storage", storageFileTypeDef); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, fileCount, storageFileTypeDef)); + } + } + else + { + // error or directory empty + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFile", "Windows.Storage", storageFileTypeDef); + + // create an array of + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(top, fileCount, storageFileTypeDef)); + } + + NANOCLR_CLEANUP(); + + // close directory + if (dir) + { + closedir(dir); + } + + // free buffers memory, if allocated + if(stringBuffer != NULL) + { + platform_free(stringBuffer); + } + if(workingBuffer != NULL) + { + platform_free(workingBuffer); + } + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFileNative___WindowsStorageStorageFile__STRING__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFileTypeDef; + CLR_RT_HeapBlock* storageFile; + + const char* fileName; + const char* managedPath; + char * workingPath = NULL; + + CreationCollisionOption options; + bool fileExists = false; + + FILE * file; + char mode[5] = { 'r' }; + char* filePath = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get creation collision options + options = (CreationCollisionOption)stack.Arg2().NumericByRef().u4; + + // get a pointer to the StorageFolder path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // get a pointer to the desired file name + fileName = stack.Arg1().DereferenceString()->StringText(); + + // setup file path + filePath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(filePath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(filePath, 0, 2 * FF_LFN_BUF + 1); + + // compose file path + CombinePath(filePath, managedPath, fileName); + + // Convert to ESP32 VFS path + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(filePath); + + // Check if file exists + file = fopen(workingPath, "r"); + if (file) + { + fclose(file); + fileExists = true; + } + + // compute mode flags from CreationCollisionOption + switch (options) + { + case CreationCollisionOption_ReplaceExisting: + mode[0] = 'w'; + mode[1] = '+'; + break; + + case CreationCollisionOption_FailIfExists: + // Check if it exists + if (fileExists) + { + // file already exists + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + } + + //modeFlags = FA_CREATE_NEW; + mode[0] = 'w'; + break; + + case CreationCollisionOption_OpenIfExists: + if (fileExists) + { + // Open existing file + mode[0] = 'r'; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + break; + + case CreationCollisionOption_GenerateUniqueName: + // this operation is not supported in nanoFramework + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + + default: + break; + } + + // open file + file = fopen(workingPath, mode); + if (file) + { + // file created (or opened) succesfully + // OK to close it + fclose(file); + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFile", "Windows.Storage", storageFileTypeDef ); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFileTypeDef)); + + // get a handle to the storage file + storageFile = stack.TopValue().Dereference(); + + // file name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___name ], fileName )); + + // file path + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___path ], filePath )); + + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFile[Library_win_storage_native_Windows_Storage_StorageFile::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + + // ...and set it + *pRes = GetFileTimeFromPath(workingPath); + } + else + { + // file doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_NOT_FOUND); + } + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if(filePath != NULL) + { + platform_free(filePath); + } + + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + + + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::CreateFolderNative___WindowsStorageStorageFolder__STRING__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* storageFolder; + + const char* folderName; + char* workingPath = NULL; + const char* managedPath; + + CreationCollisionOption options; + + static struct stat fileInfo; + + int operationResult; + char* folderPath = NULL; + bool folderAlreadyExists = false; + + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get creation collision options + options = (CreationCollisionOption)stack.Arg2().NumericByRef().u4; + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ].DereferenceString()->StringText(); + + // get a pointer to the desired folder name + folderName = stack.Arg1().DereferenceString()->StringText(); + + folderPath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if(folderPath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(folderPath, 0, 2 * FF_LFN_BUF + 1); + + // compose folder path + CombinePath(folderPath, managedPath, folderName); + + // Convert to ESP32 form path ( linux like ) + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(folderPath); + + //First check if folder already exists + operationResult = stat(workingPath, &fileInfo); + if (operationResult == 0) folderAlreadyExists = true; + + + // Folder doesn't exist so create it + if ( !folderAlreadyExists ) + { + // create directory + operationResult = mkdir(workingPath,0); + if (operationResult < 0) operationResult = errno; + } + else + { + // Folder already exists + if ( options == CreationCollisionOption_FailIfExists ) + { + // folder already exists - fail + operationResult = EEXIST; + } + + // handle request for open if it exists and replace existing + if ((options == CreationCollisionOption_OpenIfExists) || + (options == CreationCollisionOption_ReplaceExisting)) + { + operationResult = 0; + } + else + { + operationResult = EEXIST; + } + } + + if(operationResult == 0) + { + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef( "StorageFolder", "Windows.Storage", storageFolderTypeDef ); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFolderTypeDef)); + + // get a handle to the storage folder + storageFolder = stack.TopValue().Dereference(); + + // folder name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name ], folderName )); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path ], folderPath )); + + // get the date time details and fill in the managed field + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___dateCreated ]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + + // get the date time details and fill in the managed field + // compute directory date + // ...and set it + *pRes = GetFileTimeFromPath(workingPath); + } + else + { + switch(operationResult) + { + case ENOTSUP: + // Folders not supported, SPIFFS volume + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + case ENOENT: + // Invalid path + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + case EEXIST: + NANOCLR_SET_AND_LEAVE(CLR_E_PATH_ALREADY_EXISTS); + + default: + // failed to create the folder + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + } + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if(folderPath != NULL) + { + platform_free(folderPath); + } + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::DeleteFolderNative___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + char* workingPath = NULL; + const char* managedPath; + int operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path].DereferenceString()->StringText(); + + // Convert to ESP32 form path ( linux like ) + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(managedPath); + + // Delete folder, 0=succesfull + operationResult = rmdir(workingPath); + if (operationResult < 0) operationResult = errno; + if (operationResult == ENOENT) + { + // Invalid path + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + else if (operationResult == EACCES) + { + // folder not empty + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_EMPTY); + } + + else if (operationResult != 0) + { + // folder doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::RenameFolderNative___VOID__STRING(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + char* workingPath = NULL; + char* desiredWorkingPath = NULL; + const char* managedPath; + const char* desiredPath; + int operationResult; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path].DereferenceString()->StringText(); + + // Convert to ESP32 form path ( linux like ) + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(managedPath); + + // get a pointer to the desired folder name + desiredPath = stack.Arg1().DereferenceString()->StringText(); + desiredWorkingPath = ConvertToESP32Path(desiredPath); + + // rename folder, 0=succesfull + operationResult = rename(workingPath, desiredWorkingPath); + if (operationResult < 0) operationResult = errno; + if (operationResult == ENOENT) + { + // Invalid path + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + else if (operationResult != 0) + { + // folder doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (workingPath != NULL) + { + platform_free(workingPath); + } + if (desiredWorkingPath != NULL) + { + platform_free(desiredWorkingPath); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT Library_win_storage_native_Windows_Storage_StorageFolder::GetFolderNative___WindowsStorageStorageFolder__STRING(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + CLR_RT_TypeDef_Index storageFolderTypeDef; + CLR_RT_HeapBlock* storageFolder; + + const char* folderName; + char* workingPath = NULL; + const char* managedPath; + + static struct stat fileInfo; + + int operationResult; + char* folderPath = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the path in managed field + managedPath = pThis[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path].DereferenceString()->StringText(); + + // get a pointer to the desired folder name + folderName = stack.Arg1().DereferenceString()->StringText(); + + folderPath = (char*)platform_malloc(2 * FF_LFN_BUF + 1); + + // sanity check for successfull malloc + if (folderPath == NULL) + { + // failed to allocate memory + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + // clear working buffer + memset(folderPath, 0, 2 * FF_LFN_BUF + 1); + + // compose folder path + CombinePath(folderPath, managedPath, folderName); + + // Convert to ESP32 form path ( linux like ) + // return allocated converted path, must be freed + workingPath = ConvertToESP32Path(folderPath); + + // Check Directory exists directory + operationResult = stat(workingPath, &fileInfo); + if (operationResult < 0) operationResult = errno; + + if ( operationResult == ENOENT ) + { + // folder doesn't exist + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + + if (operationResult == 0) + { + // Is this a file + if (fileInfo.st_mode & S_IFREG) + { + // Path represents a file + NANOCLR_SET_AND_LEAVE(CLR_E_DIRECTORY_NOT_FOUND); + } + + + // compose return object + // find type, don't bother checking the result as it exists for sure + g_CLR_RT_TypeSystem.FindTypeDef("StorageFolder", "Windows.Storage", storageFolderTypeDef); + + // create a + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(stack.PushValue(), storageFolderTypeDef)); + + // get a handle to the storage folder + storageFolder = stack.TopValue().Dereference(); + + // folder name + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___name], folderName)); + + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance(storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___path], folderPath)); + + // get the date time details and fill in the managed field + // get a reference to the dateCreated managed field... + CLR_RT_HeapBlock& dateFieldRef = storageFolder[Library_win_storage_native_Windows_Storage_StorageFolder::FIELD___dateCreated]; + CLR_INT64* pRes = (CLR_INT64*)&dateFieldRef.NumericByRef().s8; + + // get the date time details and fill in the managed field + // compute directory date + // ...and set it + *pRes = GetFileTimeFromPath(workingPath); + } + else + { + // failed to create the folder + NANOCLR_SET_AND_LEAVE(CLR_E_FILE_IO); + } + + NANOCLR_CLEANUP(); + + // free buffer memory, if allocated + if (folderPath != NULL) + { + platform_free(folderPath); + } + if (workingPath != NULL) + { + platform_free(workingPath); + } + + NANOCLR_CLEANUP_END(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_target.h new file mode 100644 index 00000000..ed4998bf --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/Windows.Storage/win_storage_native_target.h @@ -0,0 +1,11 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_STORAGE_NATIVE_TARGET_H_ +#define _WIN_STORAGE_NATIVE_TARGET_H_ + +#include + +#endif //_WIN_STORAGE_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_App_Interface.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_App_Interface.c new file mode 100644 index 00000000..327686c3 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_App_Interface.c @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + + +// declaration for wrapper function +extern bool CLR_Messaging_ProcessPayload(WP_Message* msg); + +// defining this array here makes is local helping reduce the image size because of compiler opmitizations +static const CommandHandlerLookup c_Lookup_Request[] = +{ + /*******************************************************************************************************************************************************************/ +#define DEFINE_CMD(cmd) { CLR_DBG_Commands_c_Monitor_##cmd, &Monitor_##cmd } + DEFINE_CMD(Ping ), + // DEFINE_CMD(Reboot ), + // // + // DEFINE_CMD(ReadMemory ), + // DEFINE_CMD(WriteMemory), + // DEFINE_CMD(CheckMemory), + // DEFINE_CMD(EraseMemory), + // // + // DEFINE_CMD(Execute ), + // DEFINE_CMD(MemoryMap ), + // // + // DEFINE_CMD(CheckSignature), + // // + // DEFINE_CMD(FlashSectorMap ), + // DEFINE_CMD(SignatureKeyUpdate), + + DEFINE_CMD(OemInfo), + +#undef DEFINE_CMD + /*******************************************************************************************************************************************************************/ +}; + +//////////////////////////////////////////////////// + +// defining this array here makes is local helping reduce the image size because of compiler optimizations +static const CommandHandlerLookup c_Lookup_Reply[] = +{ + /*******************************************************************************************************************************************************************/ +#define DEFINE_CMD(cmd) { CLR_DBG_Commands_c_Monitor_##cmd, &Monitor_##cmd } + DEFINE_CMD(Ping), +#undef DEFINE_CMD + /*******************************************************************************************************************************************************************/ +}; + +int WP_App_ProcessHeader(WP_Message* message) +{ + // check for reception buffer overflow + if(message->m_header.m_size > sizeof(receptionBuffer)) + { + return false; + } + + message->m_payload = receptionBuffer; + return true; +} + +int WP_App_ProcessPayload(WP_Message* message) +{ + return CLR_Messaging_ProcessPayload(message); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_MonitorCommands.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_MonitorCommands.c new file mode 100644 index 00000000..3a3646b0 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/WireProtocol_MonitorCommands.c @@ -0,0 +1,7 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// file empty on purpose +// in nanoCLR the MonitorCommands are implemented in Debugger diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/app_main.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/app_main.c new file mode 100644 index 00000000..65d746a8 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/app_main.c @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +#include +#include +#include +#include +#include + +extern void CLRStartupThread(void const * argument); + +// Mutex for GLOBAL_LOCK / GLOBAL_UNLOCK +portMUX_TYPE globalLockMutex = portMUX_INITIALIZER_UNLOCKED; + +void receiver_task(void *pvParameter) +{ + (void)pvParameter; + + ReceiverThread( 0); + + vTaskDelete(NULL); +} + +// Main task start point +void main_task(void *pvParameter) +{ + (void)pvParameter; + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + CLRStartupThread(&clrSettings); + + vTaskDelete(NULL); +} + +// App_main +// Called from Esp32 IDF start up code before scheduler starts +// +void app_main() +{ + // Switch off logging so as not to interfere with WireProtocol over Uart0 + esp_log_level_set("*", ESP_LOG_NONE); + + ESP_ERROR_CHECK( nvs_flash_init() ); + + xTaskCreatePinnedToCore(&receiver_task, "ReceiverThread", 2048, NULL, 5, NULL, 1); + + // Start the main task pinned to 2nd core + xTaskCreatePinnedToCore(&main_task, "main_task", 15000, NULL, 5, NULL, 1); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/mbedtls_entropy_hardware_pool.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/mbedtls_entropy_hardware_pool.c new file mode 100644 index 00000000..542b3ddb --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/mbedtls_entropy_hardware_pool.c @@ -0,0 +1,25 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +// Get len bytes of entropy from the hardware RNG. +int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen ) +{ + (void)data; + + for(size_t i = 0; i < len; i++) + { + // our generator returns 32bits numbers + *output = (unsigned char)esp_random(); + + output++; + } + + // callers require this to be set + *olen = len; + + return 0; +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoCRT.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoCRT.cpp new file mode 100644 index 00000000..2a780218 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoCRT.cpp @@ -0,0 +1,206 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include + +//--// +/* STDIO stubs */ +//--// + +#if !defined(BUILD_RTM) + +void hal_fprintf_SetLoggingCallback( LOGGING_CALLBACK fpn ) +{ + (void)fpn; + NATIVE_PROFILE_PAL_CRT(); + +} + +#endif + +//--// + +#if defined(PLATFORM_EMULATED_FLOATINGPOINT) + +// no floating point, fixed point + +int hal_snprintf_float( char* buffer, size_t len, const char* format, int32_t f ) +{ + NATIVE_PROFILE_PAL_CRT(); + + uint32_t i ; + uint32_t dec; + + if ( f < 0 ) + { + // negative number + i = (uint32_t) -f ; + dec = i & (( 1<>HAL_FLOAT_SHIFT); + + if (dec !=0) dec = (dec * (uint32_t)HAL_FLOAT_PRECISION + (1<< (HAL_FLOAT_SHIFT-1))) >>HAL_FLOAT_SHIFT; + + return hal_snprintf( buffer, len, "-%d.%03u", i, (uint32_t)dec); + + } + else + { + // positive number + i = (uint32_t) f ; + dec = f & (( 1<>HAL_FLOAT_SHIFT); + + if (dec !=0) dec = (dec * (uint32_t)HAL_FLOAT_PRECISION + (1<< (HAL_FLOAT_SHIFT-1))) >>HAL_FLOAT_SHIFT; + + return hal_snprintf( buffer, len, "%d.%03u", i, (uint32_t)dec); + } +} + +int hal_snprintf_double( char* buffer, size_t len, const char* format, int64_t& d ) +{ + NATIVE_PROFILE_PAL_CRT(); + + uint64_t i; + uint32_t dec; // 32 bit is enough for decimal part + + if ( d < 0 ) + { + // negative number + i = (uint64_t)-d; + + i += ((1 << (HAL_DOUBLE_SHIFT-1)) / HAL_DOUBLE_PRECISION); // add broad part of rounding increment before split + + dec = i & (( 1<> HAL_DOUBLE_SHIFT ; + + if (dec !=0) dec = (dec * HAL_DOUBLE_PRECISION + ((1 << (HAL_DOUBLE_SHIFT-1)) % HAL_DOUBLE_PRECISION)) >> HAL_DOUBLE_SHIFT; + + return hal_snprintf( buffer, len, "-%lld.%04u", (int64_t)i, (uint32_t)dec); + + } + else + { + + // positive number + i = (uint64_t)d; + + i += ((1 << (HAL_DOUBLE_SHIFT-1)) / HAL_DOUBLE_PRECISION); // add broad part of rounding increment before split + + dec = i & (( 1<> HAL_DOUBLE_SHIFT; + + if (dec !=0) dec = (dec * HAL_DOUBLE_PRECISION + ((1 << (HAL_DOUBLE_SHIFT-1)) % HAL_DOUBLE_PRECISION)) >> HAL_DOUBLE_SHIFT; + + return hal_snprintf( buffer, len, "%lld.%04u", (int64_t)i, (uint32_t)dec); + } +} + +#else + +#endif + +// because debug_printf needs to be called in both C and C++ we need a proxy to allow it to be called in 'C' +extern "C" { + +#if !defined(BUILD_RTM) + + void debug_printf(const char* format, ...) + { + char buffer[256]; + va_list arg_ptr; + + va_start( arg_ptr, format ); + + int len = vsnprintf( buffer, sizeof(buffer)-1, format, arg_ptr ); + + DebuggerPort_Write( HalSystemConfig.stdio, buffer, len, 0 ); // skip null terminator + + va_end( arg_ptr ); + } + +#else + __inline void debug_printf( const char *format, ... ) {} +#endif // !defined(BUILD_RTM) +} + +int hal_strcpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strcpy + + size_t len; + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + len = hal_strlen_s(strSrc); + if(sizeInBytes < len + 1) {_ASSERTE(FALSE); return 1;} + + strcpy( strDst, strSrc ); + return 0; + +#define strcpy DoNotUse_*strcpy [] +} + +int hal_strncpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc, size_t count ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strncpy + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + if (sizeInBytes < count + 1) + { + _ASSERTE(FALSE); + strDst[0] = 0; + return 1; + } + + strDst[count] = 0; + strncpy( strDst, strSrc, count ); + return 0; + +#define strncpy DoNotUse_*strncpy [] +} + +size_t hal_strlen_s (const char * str) +{ + NATIVE_PROFILE_PAL_CRT(); + + const char *eos = str; + while( *eos++ ) ; + return( eos - str - 1 ); +} + +int hal_strncmp_s ( const char* str1, const char* str2, size_t num ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strncmp + if(str1 == NULL || str2 == NULL) {_ASSERTE(FALSE); return 1;} + + return strncmp( str1, str2, num ); + +#define strncmp DoNotUse_*strncmp [] +} + +// Compares 2 ASCII strings case insensitive. Does not take locale into account. +int hal_stricmp( const char * dst, const char * src ) +{ + int f = 0, l = 0; + + do + { + if ( ((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z') ) + { + f -= 'A' - 'a'; + } + if ( ((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z') ) + { + l -= 'A' - 'a'; + } + } + while ( f && (f == l) ); + + return(f - l); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp new file mode 100644 index 00000000..eb8929e0 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController.cpp @@ -0,0 +1,579 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "nf_devices_onewire_native_target.h" +#include "target_nf_devices_onewire_config.h" + +// struct for working threads +static OneWireFindStruct FindStruct; +static bool OneWireOperationResult; +static TaskHandle_t WaitingTask; +static uint8_t LastDiscrepancy; +static uint8_t LastFamilyDiscrepancy; +static uint8_t LastDevice; +static uint8_t SerialNum[8]; +// UART to use for 1-Wire comm +static uart_port_t UartDriver; +// Driver state. +static oneWireState DriverState; + +#if ONEWIRE_USE_MUTUAL_EXCLUSION +// Mutex protecting the peripheral +static mutex_t DriverLock; +#endif // ONEWIRE_USE_MUTUAL_EXCLUSION + +bool oneWireInit() +{ + // TODO: make configurable + DriverState = ONEWIRE_STOP; + UartDriver = NF_ONEWIRE_ESP32_UART_NUM; + + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 0, + .use_ref_tick = false + }; + + if (uart_param_config(UartDriver, &uart_config) != ESP_OK) return false; + if (uart_set_pin(UartDriver, NF_ONEWIRE_ESP32_UART_TX_PIN, NF_ONEWIRE_ESP32_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE) != ESP_OK) return false; + if (uart_driver_install(UartDriver, UART_FIFO_LEN*2, 0, 0, NULL, 0) != ESP_OK) return false; + + #if (ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE) + osalMutexObjectInit(&DriverLock); + #endif + + DriverState = ONEWIRE_READY; + return true; +} + +void oneWireStop() +{ + // stop UART + uart_driver_delete(UartDriver); + + // driver is stopped + DriverState = ONEWIRE_STOP; +} + +uint8_t oneWireTouchReset(void) +{ + char reset = 0xF0; + uint8_t presence; + + // flush DMA buffer to ensure cache coherency + uart_flush(UartDriver); + // set UART baud rate to 9600bps (required to send the RESET condition to the 1-Wire bus) + uart_set_baudrate(UartDriver, 9600); + + uart_write_bytes(UartDriver, (const char *)&reset, 1); + uart_read_bytes(UartDriver, &presence, 1, 20 / portTICK_RATE_MS); + + // set UART baud rate to 115200bps (normal comm is performed at this baud rate) + uart_set_baudrate(UartDriver, 115200); + + // check for presence pulse + return (presence != reset); +} + +bool oneWireTouchBit(bool sendbit) +{ + // need to send 1-Wire write 1 or 0 according to sendbit + char write = sendbit ? IWIRE_WR1 : IWIRE_WR0; + uint8_t reply; + + // flush DMA buffer to ensure cache coherency + uart_flush(UartDriver); + + uart_write_bytes(UartDriver, (const char *)&write, 1); + uart_read_bytes(UartDriver, &reply, 1, 20 / portTICK_RATE_MS); + + // interpret 1-Wire reply + return (reply == IWIRE_RD); +} + +uint8_t oneWireTouchByte(uint8_t sendbyte) +{ + uint8_t send_mask = 0x01, result = 0; + uint8_t i = 0; + char writeBuffer[8]; + uint8_t readBuffer[8]; + + // send byte + while (send_mask) + { + writeBuffer[i] = (sendbyte & send_mask) ? IWIRE_WR1 : IWIRE_WR0; + i++; + // rotates the position mask transmit bit + send_mask<<=1; + }; + + + // flush DMA buffer to ensure cache coherency + uart_flush(UartDriver); + + uart_write_bytes(UartDriver, (const char *)writeBuffer, 8); + uart_read_bytes(UartDriver, readBuffer, 8, 20 / portTICK_RATE_MS); + + // reset send mask to interpret the reply + send_mask = 0x01; + + for (uint32_t i = 0; i < 8; i++) + { + if (readBuffer[i] == IWIRE_RD) + { + result |= send_mask; + } + send_mask<<=1; + } + + return result; +} + +void oneWireAquire() +{ +#if (ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE) + osalMutexLock(&Driver.Lock); +#endif +} + +void oneWireRelease() +{ +#if (ONEWIRE_USE_MUTUAL_EXCLUSION == TRUE) + osalMutexUnlock(&Driver.Lock); +#endif +} + +// compute CRC8 using running algorith (slower but saves FLASH) +uint8_t doCrc8(uint8_t oldCrc, uint8_t x) +{ + uint8_t crc = oldCrc; + + for (uint8_t i = 8; i; i--) + { + uint8_t mix = (crc ^ x) & 0x01; + crc >>= 1; + if (mix) crc ^= 0x8C; + x >>= 1; + } + + return crc; +} + +/******************************************************************************* +** NAME: oneWireSerialNum ************************************************** +******************************************************************************** + +DESCRIPTION: + // The 'oneWireSerialNum' function either reads or sets the SerialNum buffer + // that is used in the search functions 'owFirst' and 'owNext'. + // This function contains two parameters, 'serialnum_buf' is a pointer + // to a buffer provided by the caller. 'serialnum_buf' should point to + // an array of 8 unsigned chars. The second parameter is a flag called + // 'do_read' that is TRUE (1) if the operation is to read and FALSE + // (0) if the operation is to set the internal SerialNum buffer from + // the data in the provided buffer. + // + // 'serialnum_buf' - buffer to that contains the serial number to set + // when do_read = FALSE (0) and buffer to get the serial + // number when do_read = TRUE (1). + // 'do_read' - flag to indicate reading (1) or setting (0) the current + // serial number. + // + +USAGE EXAMPLES: + +AUTHOR: jassimoes + +COMMENTS: + +*******************************************************************************/ +void oneWireSerialNum(uint8_t* serialnum_buf, uint8_t do_read) +{ + uint8_t i; + + //-------------------------------------------------// + // read the internal buffer and place in 'serialnum_buf' + if (do_read) + { + for (i = 0; i < 8; i++) + { + serialnum_buf[i] = SerialNum[i]; + } + } + // set the internal buffer from the data in 'serialnum_buf' + else + { + for (i = 0; i < 8; i++) + { + SerialNum[i] = serialnum_buf[i]; + } + } +} + +/******************************************************************************* +** NAME: oneWireFindNext ******************************************************* +********************************************************************************/ +// The 'oneWireFindNext' function does a general search. +// This function continues from the previos search state. The search state +// can be reset by using the 'oneWireFindFirst' function. +// This function contains one parameter 'alarmOnly'. +// When 'alarmOnly' is TRUE (1) the find alarm command +// 0xEC is sent instead of the normal search command 0xF0. +// Using the find alarm command 0xEC will limit the search to only +// 1-Wire devices that are in an 'alarm' state. +// +// 'doReset' - TRUE (1) perform reset before search, FALSE (0) do not +// perform reset before search. +// 'alarmOnly' - TRUE (1) the find alarm command 0xEC is +// sent instead of the normal search command 0xF0 +// +// Returns: TRUE (1) : when a 1-Wire device was found and it's +// Serial Number placed in the global SerialNum +// FALSE (0): when no new device was found. Either the +// last search was the last device or there +// are no devices on the 1-Wire Net. +bool oneWireFindNext (bool doReset, bool alarmOnly) +{ + uint8_t romBitIndex = 1; + uint8_t romByteIndex = 0; + uint8_t bitMask = 1; + uint8_t attempt = 0; + uint8_t discrepMarker = 0; + bool outBit = 0; + bool result = FALSE; + uint8_t lastcrc8 = 0; + + // clear serial number buffer for new search + memset(SerialNum, 0, 8); + + // if the last call was the last one + if (LastDevice) + { + // reset the search + LastDiscrepancy = 0; + LastDevice = FALSE; + LastFamilyDiscrepancy = 0; + + return FALSE; + } + + // check if reset bus was requested + if (doReset) + { + // reset the 1-Wire bus + // if there is no presence pulse there is nothing to do here, return FALSE + if (!oneWireTouchReset()) + { + // reset the search + LastDiscrepancy = 0; + LastFamilyDiscrepancy = 0; + return FALSE; + } + } + + // send search command + if (alarmOnly) + { + // conditional search command (devices in alarm condition) + oneWireTouchByte(COND_SEARCH_ROM); + } + else + { + // ROM search command + oneWireTouchByte(SEARCH_ROM); + } + + do + { + attempt = 0; + + if (oneWireTouchBit(TRUE) == 1) + { + attempt = 2; + } + + if (oneWireTouchBit(TRUE) == 1) + { + attempt |= 1; + } + + if (attempt == 3) + { + // no devices present, done here + break; + } + else + { + if (attempt > 0) + { + // all connected devices reply with 0 or 1 + // write bit to perform search + outBit = attempt >> 1; + } + else + { + if (romBitIndex < LastDiscrepancy) + { + outBit = ((SerialNum[romByteIndex] & bitMask) > 0); + } + else + { + // set to 1 if it's the same, otherwise 0 + outBit = (romBitIndex == LastDiscrepancy); + } + + // on 0 record position on bitMask + if (outBit == 0) + { + discrepMarker = romBitIndex; + } + } + + // isolate bit in ROM[n] with bitMask + if (outBit == 1) + { + SerialNum[romByteIndex] |= bitMask; + } + else + { + SerialNum[romByteIndex] &= ~bitMask; + } + + // ROM search write + oneWireTouchBit(outBit); + + romBitIndex++; + + bitMask = bitMask << 1; + + // if the mask has reached 0 then go for a new ROM + if (bitMask == 0) + { + // reset mask and perform CRC8 + lastcrc8 = doCrc8(lastcrc8, SerialNum[romByteIndex]); + + romByteIndex++; + bitMask++; + } + } + + } + while (romByteIndex < 8); // loop until we have all ROM bytes + + if ((romBitIndex < 65) || (lastcrc8 != 0)) + { + // search was unsuccessful reset the last discrepancy + LastDiscrepancy = 0; + } + else + { + // search was successful: set last discrepancy, device and result + LastDiscrepancy = discrepMarker; + LastDevice = (LastDiscrepancy == 0); + + // search isn't completed there are more devices present in the bus + result = TRUE; + } + + return result; +} + +/******************************************************************************* +** NAME: oneWireFindFirst ****************************************************** +********************************************************************************/ +// The 'oneWireFindFirst' finds the first device on the 1-Wire Net. +// This function contains one parameter 'alarmOnly'. When +// 'alarmOnly' is TRUE (1) the find alarm command 0xEC is +// sent instead of the normal search command 0xF0. +// Using the find alarm command 0xEC will limit the search to only +// 1-Wire devices that are in an 'alarm' state. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'doReset' - TRUE (1) perform reset before search, FALSE (0) do not +// perform reset before search. +// 'alarmOnly' - TRUE (1) the find alarm command 0xEC is +// sent instead of the normal search command 0xF0 +// +// Returns: TRUE (1) : when a 1-Wire device was found and it's +// Serial Number placed in the global SerialNum +// FALSE (0): There are no devices on the 1-Wire Net. +bool oneWireFindFirst (bool doReset, bool alarmOnly) +{ + // reset the search state + LastDiscrepancy = 0; + LastDevice = FALSE; + LastFamilyDiscrepancy = 0; + + // Call Next and return it's return value; + return oneWireFindNext(doReset, alarmOnly); +} + +// OneWire Find First/Next working thread +static void OneWireFindWorkingThread(void *pvParameters) +{ + OneWireFindStruct* findStruct = (OneWireFindStruct*)pvParameters; + + OneWireOperationResult = findStruct->FindFirst ? + oneWireFindFirst(findStruct->DoReset, findStruct->AlarmOnly) : + oneWireFindNext(findStruct->DoReset, findStruct->AlarmOnly); + + // fire event for 1-Wire operation completed + xTaskNotifyGive(WaitingTask); + vTaskDelete(NULL); +} + +HRESULT FindOneDevice(CLR_RT_StackFrame& stack, bool findFirst) +{ + uint8_t* serialNumberPointer; + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + TaskHandle_t task; + + // ensure the device is initialized + if (DriverState != ONEWIRE_READY && !oneWireInit()) return CLR_E_INVALID_PARAMETER; + + // set an infinite timeout to wait forever for the operation to complete + // this value has to be in ticks to be properly loaded by SetupTimeoutFromTicks() below + hbTimeout.SetInteger((CLR_INT64)-1); + HRESULT result = stack.SetupTimeoutFromTicks(hbTimeout, timeout); + if (result != S_OK) return result; + + // this is going to be used to check for the right event in case of simultaneous 1-Wire operations + if(stack.m_customState == 1) + { + FindStruct.DoReset = stack.Arg1().NumericByRefConst().u1 != 0; + FindStruct.AlarmOnly = stack.Arg2().NumericByRefConst().u1 != 0; + FindStruct.FindFirst = findFirst; + + // because the 1-Wire bus is shared, acquire the module + oneWireAquire(); + + // spawn working thread to perform the 1-Wire operations + WaitingTask = xTaskGetCurrentTaskHandle(); + xTaskCreate(OneWireFindWorkingThread, "OWWT", 2048, &FindStruct, 12, &task); + + // bump custom state + stack.m_customState = 2; + } + + // wait for 1-Wire operation complete + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + oneWireRelease(); + + // get the result from the working thread execution + if(OneWireOperationResult) + { + // update serialNumber field + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); + if (pThis == NULL) return CLR_E_NULL_REFERENCE; + + // get a pointer to the serial number field in the OneWireController instance + CLR_RT_HeapBlock_Array* serialNumberField = pThis[Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::FIELD___serialNumber].DereferenceArray(); + + _ASSERTE(serialNumberField->m_numOfElements == 8); + + // get a pointer to the first element of the byte array + serialNumberPointer = (uint8_t*)serialNumberField->GetFirstElement(); + + oneWireSerialNum(serialNumberPointer, TRUE); + } + + // pop timeout heap block from stack + stack.PopValue(); + + // set result + stack.SetResult_Boolean(OneWireOperationResult); + + return S_OK; +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchReset___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // ensure the device is initialized + if (DriverState != ONEWIRE_READY && !oneWireInit()) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + stack.SetResult_Boolean(oneWireTouchReset()) ; + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchBit___BOOLEAN__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // ensure the device is initialized + if (DriverState != ONEWIRE_READY && !oneWireInit()) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + stack.SetResult_Boolean(oneWireTouchBit(stack.Arg1().NumericByRefConst().u1 != 0)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::TouchByte___U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // ensure the device is initialized + if (DriverState != ONEWIRE_READY && !oneWireInit()) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + stack.SetResult_U1(oneWireTouchByte((uint8_t)stack.Arg1().NumericByRefConst().u1)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::WriteByte___U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t sendbyte; + + // ensure the device is initialized + if (DriverState != ONEWIRE_READY && !oneWireInit()) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + sendbyte = (uint8_t)stack.Arg1().NumericByRefConst().u1; + stack.SetResult_U1(oneWireTouchByte(sendbyte) == sendbyte ? TRUE : FALSE); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::ReadByte___U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // ensure the device is initialized + if (DriverState != ONEWIRE_READY && !oneWireInit()) NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + stack.SetResult_U1(oneWireTouchByte(0xFF)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::FindFirstDevice___BOOLEAN__BOOLEAN__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(FindOneDevice(stack, true)); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_devices_onewire_native_nanoFramework_Devices_OneWire_OneWireController::FindNextDevice___BOOLEAN__BOOLEAN__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_CHECK_HRESULT(FindOneDevice(stack, false)); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h new file mode 100644 index 00000000..c2979ffa --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Devices.OneWire/nf_devices_onewire_native_target.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _NF_DEVICES_ONEWIRE_NATIVE_TARGET_H_ +#define _NF_DEVICES_ONEWIRE_NATIVE_TARGET_H_ + +#include + +// struct with parameters for 1-Wire working thread +struct OneWireFindStruct +{ + bool DoReset; + bool AlarmOnly; + bool FindFirst; +}; + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + ONEWIRE_UNINIT, /* Not initialized. */ + ONEWIRE_STOP, /* Stopped. */ + ONEWIRE_READY, /* Ready. */ + ONEWIRE_ACTIVE /* Generating random number. */ +} oneWireState; + +//character to send on the UART to mimic 1-Wire bus signals +#define IWIRE_WR0 0x00 // 1-Wire write 0 time slot +#define IWIRE_WR1 0xFF // 1-Wire write 1 time slot +#define IWIRE_RD 0xFF // 1-Wire read time slot + +// ROM commands +#define SEARCH_ROM 0xF0 /* search ROM */ +#define COND_SEARCH_ROM 0xEC /* conditional search ROM */ + +#endif //_NF_DEVICES_ONEWIRE_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.cpp new file mode 100644 index 00000000..2365024e --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.cpp @@ -0,0 +1,76 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nanoFramework_hardware_esp32_native.h" + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Logging::NativeSetLogLevel___STATIC__VOID__STRING__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByTimer___STATIC__nanoFrameworkHardwareEsp32EspNativeError__U8, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByPin___STATIC__nanoFrameworkHardwareEsp32EspNativeError__nanoFrameworkHardwareEsp32SleepWakeupGpioPin__I4, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByMultiPins___STATIC__nanoFrameworkHardwareEsp32EspNativeError__nanoFrameworkHardwareEsp32SleepWakeupGpioPin__nanoFrameworkHardwareEsp32SleepWakeupMode, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByTouchPad___STATIC__nanoFrameworkHardwareEsp32EspNativeError, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeStartLightSleep___STATIC__nanoFrameworkHardwareEsp32EspNativeError, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeStartDeepSleep___STATIC__nanoFrameworkHardwareEsp32EspNativeError, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeGetWakeupCause___STATIC__nanoFrameworkHardwareEsp32SleepWakeupCause, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeGetWakeupGpioPin___STATIC__nanoFrameworkHardwareEsp32SleepWakeupGpioPin, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeGetWakeupTouchpad___STATIC__nanoFrameworkHardwareEsp32SleepTouchPad, + NULL, + NULL, + NULL, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Configuration::NativeSetPinFunction___STATIC__VOID__I4__I4, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Configuration::NativeGetPinFunction___STATIC__I4__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimer::NativeEspTimerCreate___I4, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimer::NativeEspTimerDispose___VOID, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimer::NativeStop___VOID, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimer::NativeStartOneShot___VOID__U8, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimer::NativeStartPeriodic___VOID__U8, + NULL, + Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimer::NativeGetCurrent___STATIC__U8, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Hardware_Esp32 = +{ + "nanoFramework.Hardware.Esp32", + 0xC16385A2, + method_lookup, + { 100, 0, 7, 0 } +}; diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.h new file mode 100644 index 00000000..802bb31c --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native.h @@ -0,0 +1,89 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _NANOFRAMEWORK_HARDWARE_ESP32_NATIVE_H_ +#define _NANOFRAMEWORK_HARDWARE_ESP32_NATIVE_H_ + +#include +#include +#include +#include + +struct Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Logging +{ + NANOCLR_NATIVE_DECLARE(NativeSetLogLevel___STATIC__VOID__STRING__I4); + + //--// + +}; + +struct Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep +{ + NANOCLR_NATIVE_DECLARE(NativeEnableWakeupByTimer___STATIC__nanoFrameworkHardwareEsp32EspNativeError__U8); + NANOCLR_NATIVE_DECLARE(NativeEnableWakeupByPin___STATIC__nanoFrameworkHardwareEsp32EspNativeError__nanoFrameworkHardwareEsp32SleepWakeupGpioPin__I4); + NANOCLR_NATIVE_DECLARE(NativeEnableWakeupByMultiPins___STATIC__nanoFrameworkHardwareEsp32EspNativeError__nanoFrameworkHardwareEsp32SleepWakeupGpioPin__nanoFrameworkHardwareEsp32SleepWakeupMode); + NANOCLR_NATIVE_DECLARE(NativeEnableWakeupByTouchPad___STATIC__nanoFrameworkHardwareEsp32EspNativeError); + NANOCLR_NATIVE_DECLARE(NativeStartLightSleep___STATIC__nanoFrameworkHardwareEsp32EspNativeError); + NANOCLR_NATIVE_DECLARE(NativeStartDeepSleep___STATIC__nanoFrameworkHardwareEsp32EspNativeError); + NANOCLR_NATIVE_DECLARE(NativeGetWakeupCause___STATIC__nanoFrameworkHardwareEsp32SleepWakeupCause); + NANOCLR_NATIVE_DECLARE(NativeGetWakeupGpioPin___STATIC__nanoFrameworkHardwareEsp32SleepWakeupGpioPin); + NANOCLR_NATIVE_DECLARE(NativeGetWakeupTouchpad___STATIC__nanoFrameworkHardwareEsp32SleepTouchPad); + + //--// + +}; + +struct Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Configuration +{ + NANOCLR_NATIVE_DECLARE(NativeSetPinFunction___STATIC__VOID__I4__I4); + NANOCLR_NATIVE_DECLARE(NativeGetPinFunction___STATIC__I4__I4); + + //--// + +}; + +struct Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResEventListener +{ + static const int FIELD__HighResTimers = 1; + + + //--// + +}; + +struct Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimer +{ + static const int FIELD_STATIC__s_eventListener = 0; + + static const int FIELD___timerHandle = 1; + static const int FIELD___disposedValue = 2; + static const int FIELD___syncLock = 3; + static const int FIELD__OnHighResTimerExpired = 4; + + NANOCLR_NATIVE_DECLARE(NativeEspTimerCreate___I4); + NANOCLR_NATIVE_DECLARE(NativeEspTimerDispose___VOID); + NANOCLR_NATIVE_DECLARE(NativeStop___VOID); + NANOCLR_NATIVE_DECLARE(NativeStartOneShot___VOID__U8); + NANOCLR_NATIVE_DECLARE(NativeStartPeriodic___VOID__U8); + NANOCLR_NATIVE_DECLARE(NativeGetCurrent___STATIC__U8); + + //--// + +}; + +struct Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_HighResTimerEvent +{ + static const int FIELD__EventType = 3; + static const int FIELD__TimerHandle = 4; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Hardware_Esp32; + +#endif //_NANOFRAMEWORK_HARDWARE_ESP32_NATIVE_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_Configuration.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_Configuration.cpp new file mode 100644 index 00000000..df996b8b --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_Configuration.cpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nanoFramework_hardware_esp32_native.h" + +#include +#include "Esp32_DeviceMapping.h" + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Configuration::NativeSetPinFunction___STATIC__VOID__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + uint32_t pin = (int32_t)stack.Arg0().NumericByRef().s4; + int32_t function = (int32_t)stack.Arg1().NumericByRef().s4; + + Esp32_SetMappedDevicePins(pin, function); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Configuration::NativeGetPinFunction___STATIC__I4__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + int32_t function = (int32_t)stack.Arg0().NumericByRef().s4; + + // Return current pin used for function + int32_t pin = (int32_t)Esp32_GetMappedDevicePinsWithFunction(function); + stack.SetResult_I4(pin); + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_HighResTimer.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_HighResTimer.cpp new file mode 100644 index 00000000..c13242f9 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Hardware.ESP32/nanoFramework_hardware_esp32_native_Hardware_Esp32_HighResTimer.cpp @@ -0,0 +1,145 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "nanoFramework_hardware_esp32_native.h" + +#define MAX_HRTIMERS 10 + +esp_timer_handle_t hrtimers[MAX_HRTIMERS] = {}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Hardware.Esp32.HighResTimerEventType (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +enum HighResTimerEventType +{ + TimerExpired = 101 +}; + +static int FindNextTimerIndex() +{ + for( int index=0; index +#include +#include + +#include "nanoFramework_hardware_esp32_native.h" + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByTimer___STATIC__nanoFrameworkHardwareEsp32EspNativeError__U8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uint64_t time_us = (uint64_t)stack.Arg0().NumericByRef().s8; + + esp_err_t err = esp_sleep_enable_timer_wakeup(time_us); + + // Return err to the managed application + stack.SetResult_I4( (int)err ) ; + + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByPin___STATIC__nanoFrameworkHardwareEsp32EspNativeError__nanoFrameworkHardwareEsp32SleepWakeupGpioPin__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + gpio_num_t gpio_num = (gpio_num_t)stack.Arg0().NumericByRef().s4; + int level = stack.Arg1().NumericByRef().s4; + + esp_err_t err = esp_sleep_enable_ext0_wakeup( gpio_num, level); + + // Return err to the managed application + stack.SetResult_I4( (int)err ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByMultiPins___STATIC__nanoFrameworkHardwareEsp32EspNativeError__nanoFrameworkHardwareEsp32SleepWakeupGpioPin__nanoFrameworkHardwareEsp32SleepWakeupMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uint64_t mask = (uint64_t)stack.Arg0().NumericByRef().s8; + esp_sleep_ext1_wakeup_mode_t mode = (esp_sleep_ext1_wakeup_mode_t)stack.Arg1().NumericByRef().s4; + + esp_err_t err = esp_sleep_enable_ext1_wakeup(mask, mode); + + // Return err to the managed application + stack.SetResult_I4( (int)err ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeEnableWakeupByTouchPad___STATIC__nanoFrameworkHardwareEsp32EspNativeError( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + esp_err_t err = esp_sleep_enable_touchpad_wakeup(); + + // Return err to the managed application + stack.SetResult_I4( (int)err ) ; + + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeStartLightSleep___STATIC__nanoFrameworkHardwareEsp32EspNativeError( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + esp_err_t err = esp_light_sleep_start(); + + // Return err to the managed application + stack.SetResult_I4( (int)err ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeStartDeepSleep___STATIC__nanoFrameworkHardwareEsp32EspNativeError( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // set flags to stop debug... + CLR_EE_DBG_SET( RebootPending ); + // ... reboot CLR so execution ends gracefully ... + CLR_EE_REBOOT_CLR; + // ... and set power level to OFF + g_CLR_HW_Hardware.m_powerLevel = PowerLevel__Off; + + // no error here, always OK + stack.SetResult_I4( 0 ) ; + + ////////////////////////////////////////////////////////// + // developer notes: + // - the "goto sleep" is actually handled in ClrStartup() loop when calling CPU_SetPowerMode() + // - the execution engine has to exit the current thread execution to be able to check the reboot flags set above and shutdown gracefully + // - a clean approach to accomplish this is to add a Thread.Sleep(Inifinite) in the caller + ////////////////////////////////////////////////////////// + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeGetWakeupCause___STATIC__nanoFrameworkHardwareEsp32SleepWakeupCause( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + + // Return value to the managed application + stack.SetResult_I4( (int32_t)cause ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeGetWakeupGpioPin___STATIC__nanoFrameworkHardwareEsp32SleepWakeupGpioPin( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int64_t pin = (int64_t)esp_sleep_get_ext1_wakeup_status(); + + // Return value to the managed application + stack.SetResult_I8( pin ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_nanoFramework_hardware_esp32_native_nanoFramework_Hardware_Esp32_Sleep::NativeGetWakeupTouchpad___STATIC__nanoFrameworkHardwareEsp32SleepTouchPad( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + touch_pad_t touch_pad = esp_sleep_get_touchpad_wakeup_status(); + + // Return value to the managed application + stack.SetResult_I4( (int)touch_pad ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp new file mode 100644 index 00000000..e1056671 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "nf_rt_native.h" + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// these functions are the real implementation of the 'weak' ones declared at src\CLR\Runtime.Native\nf_rt_native_nanoFramework_Runtime_Native_Rtc_stubs.cpp // +// the stubs for this class are generated by nanoFramework.Runtime.Native // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +HRESULT Library_nf_rt_native_nanoFramework_Runtime_Native_Rtc::Native_RTC_SetSystemTime___STATIC__BOOLEAN__I4__U1__U1__U1__U1__U1__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + struct tm newTime; + + newTime.tm_year = stack.Arg0().NumericByRef().s4 - 1900; // years since 1900 + newTime.tm_mon = (uint8_t)stack.Arg1().NumericByRef().u1 - 1; // months since January 0-11 + newTime.tm_mday = stack.Arg2().NumericByRef().u1; // day of the month 1-31 + newTime.tm_wday = stack.Arg3().NumericByRef().u1; // days since Sunday 0-6 + newTime.tm_hour = (uint32_t)stack.Arg4().NumericByRef().u1; // hours since midnight 0-23 + newTime.tm_min = (uint32_t)stack.Arg5().NumericByRef().u1; // minutes after the hour 0-59 + newTime.tm_sec = (uint32_t)stack.Arg6().NumericByRef().u1; // seconds after the minute 0-59 + + time_t t = mktime(&newTime); + struct timeval now = { .tv_sec = t, .tv_usec = 0 }; + settimeofday(&now, NULL); + + // Return value to the managed application + stack.SetResult_Boolean(true); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..175e9e31 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL.cpp new file mode 100644 index 00000000..06278a2a --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL.cpp @@ -0,0 +1,180 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include + +void Storage_Initialize(); +void Storage_Uninitialize(); + + +extern "C" void FixUpHalSystemConfig(); +extern "C" void FixUpBlockRegionInfo(); + + +// +// Reboot handlers clean up on reboot +// +static ON_SOFT_REBOOT_HANDLER s_rebootHandlers[16] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + +void HAL_AddSoftRebootHandler(ON_SOFT_REBOOT_HANDLER handler) +{ + for(unsigned int i=0; i 0) ? true : false; +} + +void SystemState_Set(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + SystemState_SetNoLock(state); + + GLOBAL_UNLOCK(); +} + +void SystemState_Clear(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + SystemState_ClearNoLock(state ); + + GLOBAL_UNLOCK(); +} + +bool SystemState_Query(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + bool systemStateCopy = SystemState_QueryNoLock(state); + + GLOBAL_UNLOCK(); + + return systemStateCopy; +} + + +// Just in case storage is not configured +__nfweak void Storage_Initialize() {}; +__nfweak void Storage_Uninitialize() {}; \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorage.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorage.h new file mode 100644 index 00000000..1b15a7eb --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorage.h @@ -0,0 +1,93 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include "Esp32_os.h" + +#define CONFIG_ERROR 0xffffffff + +#define CONFIG_TYPE_NETWORK 'C' +#define CONFIG_TYPE_WIRELESS 'W' +#define CONFIG_TYPE_WIRELESSAP 'A' +#define CONFIG_TYPE_CERTIFICATE 'X' + + +// Config_Initialise +// +// Initialise underlying filesystem +// +void Config_Initialise(); + +// +// Config_OpenFile - +// +// Open file for configuration / index +// For the case of NVS we just open the NVS partition, save file details, handle +// +// Parameters:- +// configuration : Type of configuration block to open +// configurationIndex : Index of type to open +// write : True to create/overwrite file +// +// Return :- +// true : returns handle +// false -1 +// +uint32_t Config_OpenFile( DeviceConfigurationOption configuration, uint32_t configurationIndex, bool write ); + +// +// Config_CloseFile - Close opened file / NVS system +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// true - File closed ok +// false- Error/File not open/Invalid handle +// +bool Config_CloseFile( uint32_t handle ); + +// +// Config_FileSize - Return size of file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// File size +// -1 = Error/Not found/Invalid handle +// +int32_t Config_FileSize( uint32_t handle ); + +// +// Config_WriteFile - Write data to file system +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Pointer data to write +// writeSize : Size of data to write +// +// return:- +// true - OK +// false- Error/Not found +// +bool Config_WriteFile(uint32_t handle, uint8_t * pData, int32_t writeSize ); + + +// +// Config_ReadFile - Read the data from opened file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Ponter to where data is to be stored +// +// return:- +// true - read length +// false- -1 , Error/Not found/Invalid handle +// +int32_t Config_ReadFile( uint32_t handle, uint8_t * pData, int32_t maxSizeData ); + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageFatfs.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageFatfs.cpp new file mode 100644 index 00000000..a9569403 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageFatfs.cpp @@ -0,0 +1,249 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// Allocate a FATFS for config +// +// minimum size is 528K wih 4096 allocation unit size +// minimum size is 128K wih 512 allocation unit size +// CONFIG_WL_SECTOR_SIZE +// +#include +#include +#include +#include "Esp32_os.h" +#include "targetHAL_ConfigStorage.h" + +#include "esp_vfs.h" +#include "esp_vfs_fat.h" + +// FATFS config +#define FATFS_Base_Path "/I" +#define FATFS_Base_Config_Name "con_" +#define FATFS_Partition_Label "config" +#define FATFS_MaxFileNameLen 30 + +static const char *TAG = "Config"; + +enum ConfigIoType { Read, Write, GetSize }; + +// Handle of the wear levelling library instance +static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; + +// Initialise SPIFFS +void Config_Initialise() +{ + esp_err_t ret; + + esp_vfs_fat_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE + }; + + ret = esp_vfs_fat_spiflash_mount(FATFS_Base_Path, FATFS_Partition_Label, &mount_config, &s_wl_handle); + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount or format filesystem"); + } else if (ret == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to find config FATFS partition"); + } else if (ret == ESP_ERR_NO_MEM) { + ESP_LOGE(TAG, "Failed to mount FATFS partition as no memory"); + } + else { + ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); + } + } +} + +// Create config name in NVS from option/index +// return name in configName +// +// Return filename +// "/config/" +void Config_GetConfigFileName(DeviceConfigurationOption configuration, uint32_t configurationIndex, char * configName) +{ + char * startName = configName; + + // Add filesystem name + hal_strcpy_s(configName, FATFS_MaxFileNameLen, FATFS_Base_Path ); + configName += hal_strlen_s(configName); + + *configName++ = '/'; + + // Add basename + hal_strcpy_s( configName, FATFS_MaxFileNameLen - (int)(configName-startName), FATFS_Base_Config_Name ); + configName += hal_strlen_s(configName); + + switch (configuration) + { + case DeviceConfigurationOption_Network: + *configName++ = CONFIG_TYPE_NETWORK; + break; + + case DeviceConfigurationOption_Wireless80211Network: + *configName++ = CONFIG_TYPE_WIRELESS; + break; + + case DeviceConfigurationOption_WirelessNetworkAP: + *configName++ = CONFIG_TYPE_WIRELESSAP; + break; + + case DeviceConfigurationOption_X509CaRootBundle: + *configName++ = CONFIG_TYPE_CERTIFICATE; + break; + + default: + *configName++ = '?'; + break; + } + + itoa(configurationIndex, configName, 10); +} + +// +// Config_OpenFile - +// +// Open file for configuration / index +// For the case of NVS we just open the NVS partition, save file details, handle +// +// Parameters:- +// configuration : Type of configuration block to open +// configurationIndex : Index of type to open +// +// Return :- +// true : returns handle +// false -1 +// +uint32_t Config_OpenFile(DeviceConfigurationOption configuration, uint32_t configurationIndex, bool write) +{ + char FileName[FATFS_MaxFileNameLen + 1] = { 0 }; + + Config_GetConfigFileName(configuration, configurationIndex, FileName); + + // Open FATFS config storage + FILE * file = fopen(FileName, write ? "wb" : "rb"); + if (file != NULL) + { + return (uint32_t)file; + } + + ESP_LOGE(TAG, "Failed to open file (%s) %d", FileName, errno); + return CONFIG_ERROR; +} + + +// +// Config_CloseFile - Close opened file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// true - File closed ok +// false- Error/File not open/Invalid handle +// +bool Config_CloseFile( uint32_t handle ) +{ + fclose( (FILE *)handle); + return true; +} + +// +// Shared IO +// +uint32_t Config_IO(uint32_t handle, ConfigIoType ioType, uint8_t * pData, int32_t size ) +{ + FILE * file = (FILE *)handle; + int32_t result = CONFIG_ERROR; + size_t ret; + long blobSize; + + while(true) + { + if ( ioType == GetSize || ioType == Read ) + { + // Get size of blob before we read it + fseek(file, 0, SEEK_END); + blobSize = ftell(file); + + result = (int32_t)blobSize; + + // If GetSize then finnish + if ( ioType == GetSize) break; + + // Do read + // Check room in buffer + if ( (int32_t)blobSize > size ) break; // error + + // Read blob into pData + fseek(file, 0, SEEK_SET); + ret = fread( (void *)pData, 1, (size_t)blobSize, file); + if (ret != (size_t)blobSize) + result = CONFIG_ERROR; + + break; + } + else if ( ioType == Write ) + { + ret = fwrite( (const void *)pData, 1, (size_t)size, file); + if ( ret == (size_t)size ) result = 0; + break; + } + else + break; + + } // while + + return result; +} + +// +// Config_FileSize - Return size of file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// File size +// -1 = Error/Not found/Invalid handle +// +int32_t Config_FileSize( uint32_t handle ) +{ + return Config_IO( handle, GetSize, 0, 0); +} + +// +// Config_WriteFile - Write data to file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Pointer data to write +// writeSize : Size of data to write +// +// return:- +// true - OK +// false- Error/Not found +// +bool Config_WriteFile(uint32_t handle, uint8_t * pData, int32_t writeSize ) +{ + return ( Config_IO( handle, Write, pData, writeSize) != CONFIG_ERROR); +} + +// +// Config_ReadFile - Read the data from file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Ponter to where data is to be stored +// +// return:- +// Read size +// -1 = Error/Not found/Invalid handle +// +int32_t Config_ReadFile( uint32_t handle, uint8_t * pData, int32_t maxSizeData ) +{ + return Config_IO( handle, Read, pData, maxSizeData); +} + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageNVS.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageNVS.cpp new file mode 100644 index 00000000..6f756370 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageNVS.cpp @@ -0,0 +1,216 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include "Esp32_os.h" +#include "targetHAL_ConfigStorage.h" + +// NVS parameters for Interface config +#define NVS_NAMESPACE "nanoF" + + +// Save File details +static nvs_handle configHandle = -1; +static DeviceConfigurationOption configType; +static uint32_t configIndex; + +enum ConfigIoType { Read, Write, GetSize }; + +void Config_Initialise() +{ + +} + + +// Create config name in NVS from option/index +// return name in configName +void Config_GetConfigFileName(DeviceConfigurationOption configuration, uint32_t configurationIndex, char * configName) +{ + switch (configuration) + { + case DeviceConfigurationOption_Network: + *configName++ = CONFIG_TYPE_NETWORK; + break; + + case DeviceConfigurationOption_Wireless80211Network: + *configName++ = CONFIG_TYPE_WIRELESS; + break; + + case DeviceConfigurationOption_WirelessNetworkAP: + *configName++ = CONFIG_TYPE_WIRELESSAP; + break; + + case DeviceConfigurationOption_X509CaRootBundle: + *configName++ = CONFIG_TYPE_CERTIFICATE; + break; + + default: + *configName++ = '?'; + break; + } + + itoa(configurationIndex, configName, 10); +} + +// +// Config_OpenFile - +// +// Open file for configuration / index +// For the case of NVS we just open the NVS partition, save file details, handle +// +// Parameters:- +// configuration : Type of configuration block to open +// configurationIndex : Index of type to open +// +// Return :- +// true : returns handle +// false -1 +// +uint32_t Config_OpenFile( DeviceConfigurationOption configuration, uint32_t configurationIndex ) +{ + // Open NVS storage using NanoFramework namespace + esp_err_t ret = nvs_open( NVS_NAMESPACE, NVS_READWRITE, &configHandle); + if ( ret == ESP_OK ) + { + configType = configuration; + configIndex = configurationIndex; + return configHandle; + } + + return CONFIG_ERROR; +} + + +// +// Config_CloseFile - Close opened file / NVS system +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// true - File closed ok +// false- Error/File not open/Invalid handle +// +bool Config_CloseFile( uint32_t handle ) +{ + // Check valid handle + if ( handle != configHandle) return false; + + nvs_close(configHandle); + configHandle = CONFIG_ERROR; + return true; +} + +// +// Shared IO +// +uint32_t Config_IO(uint32_t handle, ConfigIoType ioType, uint8_t * pData, int32_t size ) +{ + int32_t result = CONFIG_ERROR; + char configName[10]; + esp_err_t ret; + size_t blobSize; + + // Check valid handle + if ( handle != configHandle) return CONFIG_ERROR; + + // Build file system name + Config_GetConfigFileName( configType, configIndex, configName); + + while(true) + { + if ( ioType == GetSize || ioType == Read ) + { + // Get size of blob before we read it + ret = nvs_get_blob(configHandle, configName, (void *)0, &blobSize); + if (ret != ESP_OK) break; + result = (int32_t)blobSize; + + // If GetSize then finnish + if ( ioType == GetSize) break; + + // Do read + // Check room in buffer + if ( (int32_t)blobSize > size ) break; // error + + // Read blob into pData + + ret = nvs_get_blob(configHandle, configName, (void *)pData, &blobSize); + if (ret == ESP_OK) + result = (int32_t)blobSize; + else + result = CONFIG_ERROR; + + break; + } + else if ( ioType == Write ) + { + ret = nvs_set_blob(configHandle, configName, (const void *)pData, (size_t)size); + if ( ret == ESP_OK ) + { + // Write OK so commit it + ret = nvs_commit(configHandle); + if (ret == ESP_OK) result = 0; + } + break; + } + else + break; + + } // while + + return result; +} + +// +// Config_FileSize - Return size of file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// File size +// -1 = Error/Not found/Invalid handle +// +int32_t Config_FileSize( uint32_t handle ) +{ + return Config_IO( handle, GetSize, 0, 0); +} + +// +// Config_WriteFile - Write data to NVS system +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Pointer data to write +// writeSize : Size of data to write +// +// return:- +// true - OK +// false- Error/Not found +// +bool Config_WriteFile(uint32_t handle, uint8_t * pData, int32_t writeSize ) +{ + return ( Config_IO( handle, Write, pData, writeSize) != CONFIG_ERROR); +} + +// +// Config_ReadFile - Read the data from file opened in NVS +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Ponter to where data is to be stored +// +// return:- +// Read size +// -1 = Error/Not found/Invalid handle +// +int32_t Config_ReadFile( uint32_t handle, uint8_t * pData, int32_t maxSizeData ) +{ + return Config_IO( handle, Read, pData, maxSizeData); +} + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageSPIFFS.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageSPIFFS.cpp new file mode 100644 index 00000000..d1c2e4b5 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigStorageSPIFFS.cpp @@ -0,0 +1,243 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include "Esp32_os.h" +#include "targetHAL_ConfigStorage.h" + +// SPIFFS config +#define SPIFFS_Base_Path "/I" +//#define SPIFFS_Base_Path "/config" +#define SPIFFS_Base_Config_Name "con_" +#define SPIFFS_Partition_Label "config" +#define SPIFFS_MaxFileNameLen 20 + +static const char *TAG = "Config"; + +enum ConfigIoType { Read, Write, GetSize }; + +// Initialise SPIFFS +void Config_Initialise() +{ + esp_err_t ret; + + esp_vfs_spiffs_conf_t conf = { + .base_path = SPIFFS_Base_Path, + .partition_label = SPIFFS_Partition_Label, + .max_files = 5, + .format_if_mount_failed = true + }; + + ret = esp_vfs_spiffs_register(&conf); + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount or format filesystem"); + } else if (ret == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to find SPIFFS partition"); + } else { + ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); + } + } + + size_t total = 0, used = 0; + ret = esp_spiffs_info(SPIFFS_Partition_Label, &total, &used); + if (ret == ESP_OK) + { + ESP_LOGI(TAG, "SPIFFS Partition size: total: %d, used: %d", total, used); + } +} + +// Create config name in NVS from option/index +// return name in configName +// +// Return filename +// "/config/" +void Config_GetConfigFileName(DeviceConfigurationOption configuration, uint32_t configurationIndex, char * configName) +{ + char * startName = configName; + + // Add filesystem name + hal_strcpy_s(configName, SPIFFS_MaxFileNameLen, SPIFFS_Base_Path ); + configName += hal_strlen_s(configName); + + *configName++ = '/'; + + // Add basename + hal_strcpy_s( configName, SPIFFS_MaxFileNameLen - (int)(configName-startName), SPIFFS_Base_Config_Name ); + configName += hal_strlen_s(configName); + + switch (configuration) + { + case DeviceConfigurationOption_Network: + *configName++ = CONFIG_TYPE_NETWORK; + break; + + case DeviceConfigurationOption_Wireless80211Network: + *configName++ = CONFIG_TYPE_WIRELESS; + break; + + case DeviceConfigurationOption_WirelessNetworkAP: + *configName++ = CONFIG_TYPE_WIRELESSAP; + break; + + case DeviceConfigurationOption_X509CaRootBundle: + *configName++ = CONFIG_TYPE_CERTIFICATE; + break; + + default: + *configName++ = '?'; + break; + } + + itoa(configurationIndex, configName, 10); +} + +// +// Config_OpenFile - +// +// Open file for configuration / index +// For the case of NVS we just open the NVS partition, save file details, handle +// +// Parameters:- +// configuration : Type of configuration block to open +// configurationIndex : Index of type to open +// +// Return :- +// true : returns handle +// false -1 +// +uint32_t Config_OpenFile( DeviceConfigurationOption configuration, uint32_t configurationIndex, bool write ) +{ + char FileName[SPIFFS_MaxFileNameLen+1] = {0}; + + Config_GetConfigFileName( configuration, configurationIndex, FileName); + + // Open SPIFFS config storage + FILE * file = fopen( FileName, write?"wb":"rb" ); + if ( file != NULL ) + { + return (uint32_t)file; + } + + ESP_LOGE(TAG, "Failed to open file (%s)", FileName ); + return CONFIG_ERROR; +} + + +// +// Config_CloseFile - Close opened file / NVS system +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// true - File closed ok +// false- Error/File not open/Invalid handle +// +bool Config_CloseFile( uint32_t handle ) +{ + fclose( (FILE *)handle); + return true; +} + +// +// Shared IO +// +uint32_t Config_IO(uint32_t handle, ConfigIoType ioType, uint8_t * pData, int32_t size ) +{ + FILE * file = (FILE *)handle; + int32_t result = CONFIG_ERROR; + size_t ret; + long blobSize; + + while(true) + { + if ( ioType == GetSize || ioType == Read ) + { + // Get size of blob before we read it + fseek(file, 0, SEEK_END); + blobSize = ftell(file); + + result = (int32_t)blobSize; + + // If GetSize then finnish + if ( ioType == GetSize) break; + + // Do read + // Check room in buffer + if ( (int32_t)blobSize > size ) break; // error + + // Read blob into pData + fseek(file, 0, SEEK_SET); + ret = fread( (void *)pData, 1, (size_t)blobSize, file); + if (ret != (size_t)blobSize) + result = CONFIG_ERROR; + + break; + } + else if ( ioType == Write ) + { + ret = fwrite( (const void *)pData, 1, (size_t)size, file); + if ( ret == (size_t)size ) result = 0; + break; + } + else + break; + + } // while + + return result; +} + +// +// Config_FileSize - Return size of file +// +// Parameters:- +// handle : Handle returned from Config_openFile +// +// return:- +// File size +// -1 = Error/Not found/Invalid handle +// +int32_t Config_FileSize( uint32_t handle ) +{ + return Config_IO( handle, GetSize, 0, 0); +} + +// +// Config_WriteFile - Write data to NVS system +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Pointer data to write +// writeSize : Size of data to write +// +// return:- +// true - OK +// false- Error/Not found +// +bool Config_WriteFile(uint32_t handle, uint8_t * pData, int32_t writeSize ) +{ + return ( Config_IO( handle, Write, pData, writeSize) != CONFIG_ERROR); +} + +// +// Config_ReadFile - Read the data from file opened in NVS +// +// Parameters:- +// handle : Handle returned from Config_openFile +// pData : Ponter to where data is to be stored +// +// return:- +// Read size +// -1 = Error/Not found/Invalid handle +// +int32_t Config_ReadFile( uint32_t handle, uint8_t * pData, int32_t maxSizeData ) +{ + return Config_IO( handle, Read, pData, maxSizeData); +} + diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigurationManager.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigurationManager.cpp new file mode 100644 index 00000000..a04458d1 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_ConfigurationManager.cpp @@ -0,0 +1,749 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include "Esp32_os.h" +#include "targetHAL_ConfigStorage.h" +#include + +// NVS parameters for Interface config +#define NVS_NAMESPACE "nanoF" + + +// #define DEBUG_CONFIG 1 + +// Saves the remaining bundle size for multiple block cert configs +static int32_t savedBundleSize; +static int32_t remainingBundleSize; +static int32_t savedBundleOffset; + +#ifdef DEBUG_CONFIG +void PrintBlock(char * pBlock, int bsize) +{ + char * pCurrStart; + char * pCurrPos; + char * pCurrEnd; + char * pCurrEndBlock = pBlock + bsize; + + pCurrStart = pBlock; + + while (pCurrStart <= pCurrEndBlock) + { + pCurrPos = pCurrStart; + pCurrEnd = pCurrStart + 32; + + while (pCurrPos < pCurrEnd && pCurrPos <= pCurrEndBlock) + { + ets_printf("%02X ", *pCurrPos); + pCurrPos++; + } + + ets_printf(" "); + + pCurrPos = pCurrStart; + while (pCurrPos < pCurrEnd && pCurrPos <= pCurrEndBlock) + { + if (*pCurrPos < 32) + ets_printf("."); + else + ets_printf("%c", *pCurrPos); + pCurrPos++; + } + ets_printf("\n"); + + pCurrStart = pCurrEnd; + } +} +#endif + +// initialization of configuration manager +// provided as weak so it can be replaced at target level, if required because of the target implementing the storage with a mechanism other then saving to flash +void ConfigurationManager_Initialize() +{ + memset((void*)&g_TargetConfiguration, 0, sizeof(g_TargetConfiguration)); + + Config_Initialise(); + + // enumerate the blocks + ConfigurationManager_EnumerateConfigurationBlocks(); +}; + + +int32_t ConfigurationManager_FindConfigurationBlockSize(DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + uint32_t handle; + int32_t configSize = 0; + + handle = Config_OpenFile(configuration, configurationIndex, false); + if (handle != CONFIG_ERROR) + { + configSize = Config_FileSize(handle); +#ifdef DEBUG_CONFIG + ets_printf("Find type %d index %d, length %d\n", (int)configuration, configurationIndex, configSize); +#endif + Config_CloseFile(handle); + } + + return configSize; +} + +bool ConfigurationManager_GetConfigurationBlockFromStorage(DeviceConfigurationOption configuration, uint32_t configurationIndex, void* configurationBlock, int32_t maxBlockSize) +{ + uint32_t handle; + uint32_t readSize = CONFIG_ERROR; + +#ifdef DEBUG_CONFIG + ets_printf("GetConfigFromStorage %d, %d\n", (int)configuration, configurationIndex); +#endif + + handle = Config_OpenFile(configuration, configurationIndex, false); + if (handle != CONFIG_ERROR) + { + readSize = Config_ReadFile(handle, (uint8_t *)configurationBlock, maxBlockSize); + +#ifdef DEBUG_CONFIG + ets_printf("GetConfigFromStorage read %d, %d size %d\n", (int)configuration, configurationIndex, readSize); +#endif + + Config_CloseFile(handle); + } + + return (readSize != CONFIG_ERROR); +} + + + +// Allocate HAL_CONFIGURATION_NETWORK block if required +void ConfigurationManager_allocate_network(uint32_t configCount) +{ + if (g_TargetConfiguration.NetworkInterfaceConfigs == 0) + { + uint32_t sizeOfNetworkInterfaceConfigs = offsetof(HAL_CONFIGURATION_NETWORK, Configs) + configCount * sizeof(HAL_Configuration_NetworkInterface *); + g_TargetConfiguration.NetworkInterfaceConfigs = (HAL_CONFIGURATION_NETWORK*)platform_malloc(sizeOfNetworkInterfaceConfigs); + memset((void *)g_TargetConfiguration.NetworkInterfaceConfigs, 0, sizeOfNetworkInterfaceConfigs); + } +} + +// Allocate HAL_CONFIGURATION_WIRELESS80211 block if required +void ConfigurationManager_allocate_wireless(uint32_t configCount) +{ + if (g_TargetConfiguration.Wireless80211Configs == 0) + { + uint32_t sizeOfWireless80211Configs = offsetof(HAL_CONFIGURATION_NETWORK_WIRELESS80211, Configs) + configCount * sizeof(HAL_Configuration_Wireless80211 *); + g_TargetConfiguration.Wireless80211Configs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211*)platform_malloc(sizeOfWireless80211Configs); + memset((void *)g_TargetConfiguration.Wireless80211Configs, 0, sizeOfWireless80211Configs); + } +} + +void ConfigurationManager_allocate_wirelessAP(uint32_t configCount) +{ + if (g_TargetConfiguration.WirelessAPConfigs == 0) + { + uint32_t sizeOfWirelessAPConfigs = offsetof(HAL_CONFIGURATION_NETWORK_WIRELESSAP, Configs) + configCount * sizeof(HAL_Configuration_WirelessAP *); + g_TargetConfiguration.WirelessAPConfigs = (HAL_CONFIGURATION_NETWORK_WIRELESSAP*)platform_malloc(sizeOfWirelessAPConfigs); + memset((void *)g_TargetConfiguration.WirelessAPConfigs, 0, sizeOfWirelessAPConfigs); + } +} + +// Allocate HAL_CONFIGURATION_X509_CERTIFICATE block if required +void ConfigurationManager_allocate_certificates(uint32_t certificateCount) +{ + if (g_TargetConfiguration.CertificateStore == 0) + { + uint32_t sizeOfX509CertificateStore = offsetof(HAL_CONFIGURATION_X509_CERTIFICATE, Certificates) + certificateCount * sizeof(g_TargetConfiguration.CertificateStore->Certificates[0]); + g_TargetConfiguration.CertificateStore = (HAL_CONFIGURATION_X509_CERTIFICATE*)platform_malloc(sizeOfX509CertificateStore); + memset((void *)g_TargetConfiguration.CertificateStore, 0, sizeOfX509CertificateStore); + } + + // Init pointers to cert bundles to 0 ( not allocated ) + for (uint32_t index = 0; index < certificateCount; index++) + g_TargetConfiguration.CertificateStore->Certificates[index] = 0; +} + +bool StoreConfigBlock(DeviceConfigurationOption configType, uint32_t configurationIndex, void * pConfigBlock, size_t writeSize) +{ + bool result = false; + uint32_t fileHandle; + + fileHandle = Config_OpenFile(configType, configurationIndex, true); + if (fileHandle != CONFIG_ERROR) + { + result = Config_WriteFile(fileHandle, (uint8_t*)pConfigBlock, writeSize); +#ifdef DEBUG_CONFIG + ets_printf("store type %d index %d, length %d result %d\n", (int)configType, configurationIndex, writeSize, (int)result); +#endif + Config_CloseFile(fileHandle); + } + + return result; +} + +// Enumerates the configuration blocks from the configuration flash sector +// it's implemented with 'weak' attribute so it can be replaced at target level if a different persistance mechanism is used +void ConfigurationManager_EnumerateConfigurationBlocks() +{ + // Fix adapter counts - will get these from NVS + // Still need to do wireless AP + int networkCount = 3; // Esp32 has 3 network interfaces, Ethernet, Wireless Station & Wireless APn + int wirelessCount = 1; + int wirelessAPCount = 1; + int certificateCount = 1; + + // Allocate main structures for each type + ConfigurationManager_allocate_network(networkCount); + ConfigurationManager_allocate_wireless(wirelessCount); + ConfigurationManager_allocate_wirelessAP(wirelessAPCount); + ConfigurationManager_allocate_certificates(certificateCount); + + // For each network interface allocate Network config if required and load from storage + for (int configIndex = 0; configIndex < networkCount; configIndex++) + { + if (g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configIndex] == 0) + { + g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configIndex] = (HAL_Configuration_NetworkInterface*)platform_malloc(sizeof(HAL_Configuration_NetworkInterface)); + } + + if (ConfigurationManager_GetConfigurationBlockFromStorage( + DeviceConfigurationOption_Network, + configIndex, + g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configIndex], + sizeof(HAL_Configuration_NetworkInterface) + ) == false) + { + // No config saved so init default block + HAL_Configuration_NetworkInterface* configPtr = g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configIndex]; + InitialiseNetworkDefaultConfig(configPtr, configIndex); + StoreConfigBlock(DeviceConfigurationOption_Network, configIndex, configPtr, sizeof(HAL_Configuration_NetworkInterface)); + } + } + + g_TargetConfiguration.NetworkInterfaceConfigs->Count = networkCount; + + // For each Wireless interface allocate Wireless config if required and load from storage + for (int configIndex = 0; configIndex < wirelessCount; configIndex++) + { + if (g_TargetConfiguration.Wireless80211Configs->Configs[configIndex] == 0) + { + g_TargetConfiguration.Wireless80211Configs->Configs[configIndex] = (HAL_Configuration_Wireless80211*)platform_malloc(sizeof(HAL_Configuration_Wireless80211)); + } + if (ConfigurationManager_GetConfigurationBlockFromStorage( + DeviceConfigurationOption_Wireless80211Network, + configIndex, + g_TargetConfiguration.Wireless80211Configs->Configs[configIndex], + sizeof(HAL_Configuration_Wireless80211) + ) == false) + { + HAL_Configuration_Wireless80211* configPtr = g_TargetConfiguration.Wireless80211Configs->Configs[configIndex]; + InitialiseWirelessDefaultConfig(configPtr, configIndex); + StoreConfigBlock(DeviceConfigurationOption_Wireless80211Network, configIndex, configPtr, sizeof(HAL_Configuration_Wireless80211)); + } + } + g_TargetConfiguration.Wireless80211Configs->Count = wirelessCount; + + + // For each Wireless AP interface allocate Wireless AP config if required and load from storage + for (int configIndex = 0; configIndex < wirelessAPCount; configIndex++) + { + if (g_TargetConfiguration.WirelessAPConfigs->Configs[configIndex] == 0) + { + g_TargetConfiguration.WirelessAPConfigs->Configs[configIndex] = (HAL_Configuration_WirelessAP*)platform_malloc(sizeof(HAL_Configuration_WirelessAP)); + } + if (ConfigurationManager_GetConfigurationBlockFromStorage( + DeviceConfigurationOption_WirelessNetworkAP, + configIndex, + g_TargetConfiguration.WirelessAPConfigs->Configs[configIndex], + sizeof(HAL_Configuration_WirelessAP) + ) == false) + { + HAL_Configuration_WirelessAP* configPtr = g_TargetConfiguration.WirelessAPConfigs->Configs[configIndex]; + InitialiseWirelessAPDefaultConfig(configPtr, configIndex); + StoreConfigBlock(DeviceConfigurationOption_WirelessNetworkAP, configIndex, configPtr, sizeof(HAL_Configuration_WirelessAP)); + } + } + g_TargetConfiguration.WirelessAPConfigs->Count = wirelessCount; + + // For each Certificate bundle allocate memory and load from storage + for (int certificateIndex = 0; certificateIndex < certificateCount; certificateIndex++) + { + // Free any existing bundles first, we need to reallocate as bundles are variable size + if (g_TargetConfiguration.CertificateStore->Certificates[certificateIndex] != 0) + { + platform_free(g_TargetConfiguration.CertificateStore->Certificates[certificateIndex]); + g_TargetConfiguration.CertificateStore->Certificates[certificateIndex] = 0; + } + + // Find size of saved cert bundle + int32_t bundleSize = ConfigurationManager_FindConfigurationBlockSize(DeviceConfigurationOption_X509CaRootBundle, certificateIndex); + if (bundleSize > 0) + { + // Bundle exits + g_TargetConfiguration.CertificateStore->Count = certificateIndex + 1; + g_TargetConfiguration.CertificateStore->Certificates[certificateIndex] = (HAL_Configuration_X509CaRootBundle*)platform_malloc(bundleSize); + ConfigurationManager_GetConfigurationBlockFromStorage(DeviceConfigurationOption_X509CaRootBundle, certificateIndex, g_TargetConfiguration.CertificateStore->Certificates[certificateIndex], bundleSize); + } + } +} + +// Build AP default ssid based on last 3 bytes of MAC addr +// nano_xxxxxx +// +void CreateDefaultApSSID(HAL_Configuration_WirelessAP * pconfig) +{ + uint8_t mac[6]; + esp_efuse_mac_get_default(mac); + + hal_strcpy_s((char *)pconfig->Ssid, sizeof(pconfig->Ssid), "nano_"); + char * pMac = (char*)pconfig->Ssid + 5; + // Last 3 bytes of MAC address + for (int index = 3; index < 6; index++) + { + sprintf(pMac, "%02X", (int)mac[index]); + pMac += 2; + } +} + +// Default initialisation of wireless config blocks for ESP32 targets +void InitialiseWirelessDefaultConfig(HAL_Configuration_Wireless80211 * pconfig, uint32_t configurationIndex) +{ + memset(pconfig, 0, sizeof(HAL_Configuration_Wireless80211)); + + // Wireless station + pconfig->Id = configurationIndex; + + // test default data for AP + // hal_strcpy_s( (char*)pconfig->Ssid, sizeof(pconfig->Ssid), "MySSID" ); + // hal_strcpy_s( (char*)pconfig->Password, sizeof(pconfig->Password), "MyPassword" ); + + // Set default to Auto Connect + Enable + WirelessFlags_SmartConfig so station can be started by default + // Once smart config has run will start up automatically and reconnect of disconnected + // Application will have to disable wifi to save power etc + pconfig->Flags = (WirelessFlags)(WirelessFlags_Auto | WirelessFlags_Enable | WirelessFlags_SmartConfig); +} + +// Default initialisation of wireless config blocks for ESP32 targets +void InitialiseWirelessAPDefaultConfig(HAL_Configuration_WirelessAP * pconfig, uint32_t configurationIndex) +{ + memset(pconfig, 0, sizeof(HAL_Configuration_WirelessAP)); + + pconfig->Id = configurationIndex; + + // Build AP default ssid/password based on MAC addr + // but don't enable by default + CreateDefaultApSSID(pconfig); + + hal_strcpy_s((char *)pconfig->Password, sizeof(pconfig->Password), "nanoframework"); + + pconfig->Authentication = AuthenticationType_WPA2; + pconfig->Encryption = EncryptionType_WPA2; + pconfig->Radio = RadioType_802_11n; + pconfig->Channel = 11; + pconfig->MaxConnections = 4; + + // Disable Soft AP (default) + pconfig->Flags = WirelessAPFlags_None; +} + +// Default initialisation of Network interface config blocks for ESP32 targets +bool InitialiseNetworkDefaultConfig(HAL_Configuration_NetworkInterface * pconfig, uint32_t configurationIndex) +{ + memset(pconfig, 0, sizeof(HAL_Configuration_NetworkInterface)); + + // make sure the config block marker is set + memcpy(pconfig->Marker, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + switch (configurationIndex) + { + case 0: // Wireless Station + pconfig->InterfaceType = NetworkInterfaceType_Wireless80211; + pconfig->StartupAddressMode = AddressMode_DHCP; + pconfig->AutomaticDNS = 1; + pconfig->SpecificConfigId = 0; + break; + + case 1: // Wireless AP + pconfig->InterfaceType = NetworkInterfaceType_WirelessAP; + pconfig->StartupAddressMode = AddressMode_Static; + pconfig->SpecificConfigId = 0; + // Set default address 192.168.1.1 + //pconfig->IPv4Address + //pconfig->IPv4NetMask + // pconfig->IPv4GatewayAddress + break; + + case 2: // Ethernet + pconfig->InterfaceType = NetworkInterfaceType_Ethernet; + pconfig->StartupAddressMode = AddressMode_DHCP; + pconfig->AutomaticDNS = 1; + break; + } + + // get default MAC + esp_efuse_mac_get_default(pconfig->MacAddress); + + // always good + return TRUE; +} + + +// +// Get the specified configuration block from global memory ( g_TargetConfiguration ) +// +// Parameters:- +// configurationBlock : Destination to copy configuration data +// configuration : Type of configuration block to copy +// configurationIndex : Index of type to copy +// +// return:- +// true - OK +// false- Error/Not found +// +bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + int sizeOfBlock = 0; + uint8_t* blockAddress = NULL; + +#ifdef DEBUG_CONFIG + ets_printf("GetConfig %d, %d\n", (int)configuration, configurationIndex); +#endif + + // validate if the requested block exists + if (configuration == DeviceConfigurationOption_Network) + { + if (g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count) + { + // there is no network config blocks, init one with default settings +#ifdef DEBUG_CONFIG + ets_printf("GetConfig CN exit false\n"); +#endif + return FALSE; + } + + // set block size + sizeOfBlock = sizeof(HAL_Configuration_NetworkInterface); + + // get block address + blockAddress = (uint8_t*)g_TargetConfiguration.NetworkInterfaceConfigs->Configs[configurationIndex]; + } + else if (configuration == DeviceConfigurationOption_Wireless80211Network) + { + if (g_TargetConfiguration.Wireless80211Configs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count) + { +#ifdef DEBUG_CONFIG + ets_printf("GetConfig WN exit false\n"); +#endif + return FALSE; + } + + // set block size + sizeOfBlock = sizeof(HAL_Configuration_Wireless80211); + + // get block address + blockAddress = (uint8_t*)g_TargetConfiguration.Wireless80211Configs->Configs[configurationIndex]; + } + else if (configuration == DeviceConfigurationOption_WirelessNetworkAP) + { + if (g_TargetConfiguration.WirelessAPConfigs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.WirelessAPConfigs->Count) + { +#ifdef DEBUG_CONFIG + ets_printf("GetConfig AP exit false\n"); +#endif + return FALSE; + } + + // set block size + sizeOfBlock = sizeof(HAL_Configuration_WirelessAP); + + // get block address + blockAddress = (uint8_t*)g_TargetConfiguration.WirelessAPConfigs->Configs[configurationIndex]; + } + else if (configuration == DeviceConfigurationOption_X509CaRootBundle) + { + if (g_TargetConfiguration.CertificateStore->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.CertificateStore->Count) + { +#ifdef DEBUG_CONFIG + ets_printf("GetConfig XC exit false\n"); +#endif + return FALSE; + } + + // get block address + blockAddress = (uint8_t*)g_TargetConfiguration.CertificateStore->Certificates[configurationIndex]; + + // set block size + // because X509 certificate has a variable length need to compute the block size in two steps + sizeOfBlock = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + sizeOfBlock += ((HAL_Configuration_X509CaRootBundle*)blockAddress)->CertificateSize; + } + + // copy the config block content to the pointer in the argument + memcpy(configurationBlock, blockAddress, sizeOfBlock); + + return TRUE; +} + + + + +DeviceConfigurationOption GetConfigOption(char * pConfig) +{ + switch (*pConfig) + { + case CONFIG_TYPE_NETWORK: return DeviceConfigurationOption::DeviceConfigurationOption_Network; + case CONFIG_TYPE_WIRELESS: return DeviceConfigurationOption::DeviceConfigurationOption_Wireless80211Network; + case CONFIG_TYPE_WIRELESSAP: return DeviceConfigurationOption::DeviceConfigurationOption_WirelessNetworkAP; + case CONFIG_TYPE_CERTIFICATE: return DeviceConfigurationOption::DeviceConfigurationOption_X509CaRootBundle; + } + return DeviceConfigurationOption_Network; +} + +bool ConfigurationManager_StoreConfigurationBlockAll(void* configurationBlock, uint32_t blockSize, uint32_t offset) +{ + size_t chunkSize = 0; + uint32_t certificateIndex = 0; + bool result = false; + uint32_t configurationIndex = 0; + + // All configuration blocks in one block + // Separate and update + +#ifdef DEBUG_CONFIG + ets_printf("Block size %d\n", blockSize); + + ets_printf("sizeof HAL_Configuration_NetworkInterface %d\n", sizeof(HAL_Configuration_NetworkInterface)); + ets_printf("sizeof HAL_Configuration_Wireless80211 %d\n", sizeof(HAL_Configuration_Wireless80211)); + ets_printf("sizeof of X509Certificate varies\n"); +#endif + + configurationIndex = 0; + + char * pConfig = (char *)configurationBlock; + char * pEndConfig = (pConfig + blockSize); + DeviceConfigurationOption currentConfigType; + + while (pConfig < pEndConfig) + { + int remainingBlockSize = pEndConfig - pConfig; + +#ifdef DEBUG_CONFIG + ets_printf("Parse block %d:%d\n", pConfig, pEndConfig); + PrintBlock((char *)pConfig, 16); +#endif + currentConfigType = GetConfigOption(pConfig); + + // X509 certificate block ? + if (currentConfigType == DeviceConfigurationOption_X509CaRootBundle || offset > 0) + { + if (offset == 0) + { + HAL_Configuration_X509CaRootBundle * pX509Certificate = (HAL_Configuration_X509CaRootBundle*)pConfig; + + // First block of certificate bundle + // set total bundle size including header + // because X509 certificate has a variable length need to compute the block size in two steps + savedBundleSize = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + savedBundleSize += pX509Certificate->CertificateSize; + remainingBundleSize = savedBundleSize; + savedBundleOffset = 0; + + // Free if already allocated ( could be different size ) + if (g_TargetConfiguration.CertificateStore->Certificates[certificateIndex] != 0) + platform_free((void*)g_TargetConfiguration.CertificateStore->Certificates); + + g_TargetConfiguration.CertificateStore->Certificates[certificateIndex] = (HAL_Configuration_X509CaRootBundle *)platform_malloc(savedBundleSize); + +#ifdef DEBUG_CONFIG + ets_printf("X509 certificate block total size:%d\n", pX509Certificate->CertificateSize); +#endif + } + + // The current chunk size is what remains in current block + // we can't use offset as it relates to flash memory offset, not useful + chunkSize = remainingBlockSize; + + // Copy into correct position in memory + memcpy((void *)(g_TargetConfiguration.CertificateStore->Certificates[0] + savedBundleOffset), + (const void *)pConfig, + chunkSize); +#ifdef DEBUG_CONFIG + ets_printf("X509 certificate chunksize:%d reminaing:%d\n", chunkSize, savedBundleSize); + PrintBlock((char *)pConfig, 32); +#endif + pConfig += chunkSize; + remainingBundleSize -= chunkSize; + savedBundleOffset += chunkSize; + // Return true for partial blocks + result = true; + + if (remainingBundleSize <= 0) + { + // Save Certificate Bundle to storage + result = StoreConfigBlock(DeviceConfigurationOption_X509CaRootBundle, + certificateIndex, + (void*)g_TargetConfiguration.CertificateStore->Certificates[certificateIndex], + savedBundleSize); + certificateIndex++; +#ifdef DEBUG_CONFIG + ets_printf("X509 certificate complete, saving\n"); +#endif + } + +#ifdef DEBUG_CONFIG + ets_printf("X509 certificate block ret:%d\n", result); +#endif + } + // Network interface block ? + else if (currentConfigType == DeviceConfigurationOption_Network) + { + HAL_Configuration_NetworkInterface * pNetConfig = (HAL_Configuration_NetworkInterface*)pConfig; + pConfig += sizeof(HAL_Configuration_NetworkInterface); + + result = StoreConfigBlock(currentConfigType, configurationIndex, (void*)pNetConfig, sizeof(HAL_Configuration_NetworkInterface)); + configurationIndex++; + +#ifdef DEBUG_CONFIG + ets_printf("Network block %X %X ret:%d\n", pNetConfig->InterfaceType, pNetConfig->SpecificConfigId, result); + PrintBlock((char *)pNetConfig, sizeof(HAL_Configuration_NetworkInterface)); +#endif + } + // Wireless block ? + else if (currentConfigType == DeviceConfigurationOption_Wireless80211Network) + { + HAL_Configuration_Wireless80211 * pWirelessConfig = (HAL_Configuration_Wireless80211*)pConfig; + pConfig += sizeof(HAL_Configuration_Wireless80211); + + result = StoreConfigBlock(currentConfigType, pWirelessConfig->Id, (void*)pWirelessConfig, sizeof(HAL_Configuration_Wireless80211)); + +#ifdef DEBUG_CONFIG + ets_printf("Wireless block %d ssid:%s password:%s ret:%d\n", pWirelessConfig->Id, pWirelessConfig->Ssid, pWirelessConfig->Password, result); + PrintBlock((char *)pWirelessConfig, sizeof(HAL_Configuration_Wireless80211)); +#endif + } + else + break; + } // while + +#ifdef DEBUG_CONFIG + ets_printf("StoreConfig ALL exit %d\n", (int)result); +#endif + return result; +} + + +// +// Stores the configuration block to the storage +// +// Parameters:- +// configurationBlock : Pointer to block to store +// configuration : Type of configuration block to store or All for block with multiple types +// configurationIndex : Index of type to store ( not used for All ) +// blockSize : Size of data pointed to by configurationBlock +// offset : Offset of data when multiple blocks ( currently Certificate Bundles only ), For single type this is offset withing the type +// For ALL type blocks this is the offset in the total data of multiple types. +// Return:- +// true - OK +// false- Error/Not found +// +bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize, uint32_t offset) +{ + bool result = false; + bool requiresEnumeration = false; + size_t blobSize = 0; + +#ifdef DEBUG_CONFIG + ets_printf("StoreConfig config:%d, index:%d size:%d offset:%d\n", (int)configuration, configurationIndex, blockSize, offset); +#endif + + if (configuration == DeviceConfigurationOption_All) + return ConfigurationManager_StoreConfigurationBlockAll(configurationBlock, blockSize, offset); + + if (configuration == DeviceConfigurationOption_Network) + { + // set blob size + blobSize = sizeof(HAL_Configuration_NetworkInterface); + } + else if (configuration == DeviceConfigurationOption_Wireless80211Network) + { + // set blob size + blobSize = sizeof(HAL_Configuration_Wireless80211); + } + else if (configuration == DeviceConfigurationOption_WirelessNetworkAP) + { + // set blob size + blobSize = sizeof(HAL_Configuration_WirelessAP); + } + else if (configuration == DeviceConfigurationOption_X509CaRootBundle) + { + // set blob size ( Total size of X509 certificate ) + // because X509 certificate has a variable length need to compute the block size in two steps + blobSize = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + blobSize += ((HAL_Configuration_X509CaRootBundle*)configurationBlock)->CertificateSize; + +#ifdef DEBUG_CONFIG + ets_printf("StoreConfig x509 blobSize:%d, certsize:%d", blobSize, ((HAL_Configuration_X509CaRootBundle*)configurationBlock)->CertificateSize); +#endif + } + else + { + // Invalid Config + return false; + } + + // Anything to save + if (blobSize != 0) + { + result = StoreConfigBlock(configuration, configurationIndex, configurationBlock, blobSize); + } + + if (requiresEnumeration) + { + // perform enumeration of configuration blocks + ConfigurationManager_EnumerateConfigurationBlocks(); + } + +#ifdef DEBUG_CONFIG + ets_printf("StoreConfig exit %d", result); +#endif + + return result; +} + +// Updates a configuration block in the configuration storage +bool ConfigurationManager_UpdateConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + // figure out the block size first + uint32_t blockSize = 0; + + switch (configuration) + { + case DeviceConfigurationOption_Network: + blockSize = sizeof(HAL_Configuration_NetworkInterface); + break; + + case DeviceConfigurationOption_Wireless80211Network: + blockSize = sizeof(HAL_Configuration_Wireless80211); + break; + + case DeviceConfigurationOption_WirelessNetworkAP: + blockSize = sizeof(HAL_Configuration_WirelessAP); + break; + + case DeviceConfigurationOption_X509CaRootBundle: + blockSize = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + blockSize += ((HAL_Configuration_X509CaRootBundle*)configurationBlock)->CertificateSize; + break; + + default: + // shouldn't ever reach here + return FALSE; + } + + return ConfigurationManager_StoreConfigurationBlock(configurationBlock, configuration, configurationIndex, blockSize, 0); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Power.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Power.c new file mode 100644 index 00000000..a0ff214e --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Power.c @@ -0,0 +1,43 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +inline void CPU_Reset() +{ + esp_restart(); +}; + +// CPU sleep is not currently implemented in this target +inline void CPU_Sleep(SLEEP_LEVEL_type level, uint64_t wakeEvents) +{ + (void)level; + (void)wakeEvents; + +}; + +inline bool CPU_IsSoftRebootSupported() +{ + return true; +}; + +void CPU_SetPowerMode(PowerLevel_type powerLevel) +{ + switch(powerLevel) + { + case PowerLevel__Off: + // gracefully shutdown everything + nanoHAL_Uninitialize_C(); + + esp_deep_sleep_start(); + + break; + + default: + // all the other power modes are unsupported here + break; + } +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Time.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Time.cpp new file mode 100644 index 00000000..b631c7fa --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetHAL_Time.cpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include + +#define TIME_CONVERSION__TO_USECS 10 + +// Returns the current date time from the RTC +uint64_t HAL_Time_CurrentDateTime(bool datePartOnly) +{ + SYSTEMTIME st; + + struct timeval tv; + + gettimeofday(&tv, NULL); + + // Convert from Unix time(year since 1900) to SYSTEMTIME(Years since 1601) + int64_t time = ((int64_t)tv.tv_sec * (int64_t)TIME_CONVERSION__TO_SECONDS) + ((int64_t)tv.tv_usec * (int64_t)TIME_CONVERSION__TO_USECS) + TIME_UNIX_EPOCH_AS_TICKS; + + // zero 'time' fields if date part only is required + if(datePartOnly) + { + HAL_Time_ToSystemTime(time, &st); + + st.wMilliseconds = 0; + st.wSecond = 0; + st.wMinute = 0; + st.wHour = 0; + + time = HAL_Time_ConvertFromSystemTime(&st); + } + + return time; +}; + +void HAL_Time_SetUtcTime(uint64_t utcTime) +{ + SYSTEMTIME systemTime; + + HAL_Time_ToSystemTime(utcTime, &systemTime); + + struct tm newTime; + + newTime.tm_year = systemTime.wYear - 1900; // years since 1900 + newTime.tm_mon = systemTime.wMonth - 1; // months since January 0-11 + newTime.tm_mday = systemTime.wDay; // day of the month 1-31 + newTime.tm_wday = systemTime.wDayOfWeek; // days since Sunday 0-6 + newTime.tm_hour = (uint32_t)systemTime.wHour; // hours since midnight 0-23 + newTime.tm_min = (uint32_t)systemTime.wMinute; // minutes after the hour 0-59 + newTime.tm_sec = (uint32_t)systemTime.wSecond; // seconds after the minute 0-59 + + time_t t = mktime(&newTime); + struct timeval now = { .tv_sec = t, .tv_usec = 0 }; + settimeofday(&now, NULL); +} + +bool HAL_Time_TimeSpanToStringEx( const int64_t& ticks, char*& buf, size_t& len ) +{ + uint64_t ticksAbs; + uint64_t rest; + + if(ticks < 0) + { + ticksAbs = -ticks; + + CLR_SafeSprintf( buf, len, "-" ); + } + else + { + ticksAbs = ticks; + } + + rest = ticksAbs % ( 1000 * TIME_CONVERSION__TICKUNITS); + ticksAbs = ticksAbs / ( 1000 * TIME_CONVERSION__TICKUNITS); // Convert to seconds. + + if(ticksAbs > TIME_CONVERSION__ONEDAY) // More than one day. + { + CLR_SafeSprintf( buf, len, "%d.", (int32_t)(ticksAbs / TIME_CONVERSION__ONEDAY) ); ticksAbs %= TIME_CONVERSION__ONEDAY; + } + + CLR_SafeSprintf( buf, len, "%02d:", (int32_t)(ticksAbs / TIME_CONVERSION__ONEHOUR) ); ticksAbs %= TIME_CONVERSION__ONEHOUR ; + CLR_SafeSprintf( buf, len, "%02d:", (int32_t)(ticksAbs / TIME_CONVERSION__ONEMINUTE)); ticksAbs %= TIME_CONVERSION__ONEMINUTE; + CLR_SafeSprintf( buf, len, "%02d" , (int32_t)(ticksAbs / TIME_CONVERSION__ONESECOND)); ticksAbs %= TIME_CONVERSION__ONESECOND; + + ticksAbs = (uint32_t)rest; + if(ticksAbs) + { + CLR_SafeSprintf( buf, len, ".%07d", (uint32_t)ticksAbs ); + } + + return len != 0; +} + +bool DateTimeToString(const int64_t& time, char*& buf, size_t& len ) +{ + SYSTEMTIME st; + + HAL_Time_ToSystemTime( time, &st ); + + return CLR_SafeSprintf(buf, len, "%4d/%02d/%02d %02d:%02d:%02d.%03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ); +} + +char* DateTimeToString(const int64_t& time) +{ + static char rgBuffer[128]; + char* szBuffer = rgBuffer; + size_t iBuffer = ARRAYSIZE(rgBuffer); + + DateTimeToString( time, szBuffer, iBuffer ); + + return rgBuffer; +} + +const char* HAL_Time_CurrentDateTimeToString() +{ + return DateTimeToString(HAL_Time_CurrentDateTime(false)); +} + +uint64_t CPU_MillisecondsToTicks(uint64_t ticks) +{ + return ESP32_TICKS_PER_MS(ticks); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL.c new file mode 100644 index 00000000..973fe28c --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL.c @@ -0,0 +1,10 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp new file mode 100644 index 00000000..c83b1736 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp @@ -0,0 +1,178 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +uint64_t CPU_MillisecondsToTicks(uint64_t ticks); + +// timer for bool events +static TimerHandle_t boolEventsTimer; + +volatile uint32_t systemEvents; + +static void local_Events_SetBoolTimer_Callback( TimerHandle_t xTimer ); + +set_Event_Callback g_Event_Callback = NULL; +void* g_Event_Callback_Arg = NULL; + +bool Events_Initialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // init events + GLOBAL_LOCK(); + systemEvents = 0; + GLOBAL_UNLOCK(); + + boolEventsTimer = xTimerCreate( "boolEventsTimer", 10, pdFALSE, (void *)0, local_Events_SetBoolTimer_Callback); + + return true; +} + +bool Events_Uninitialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + xTimerDelete(boolEventsTimer,0); + + return true; +} + +void Events_Set( uint32_t events ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // set events + GLOBAL_LOCK(); + systemEvents |= events; + GLOBAL_UNLOCK(); + + if( g_Event_Callback != NULL ) + { + g_Event_Callback( g_Event_Callback_Arg ); + } +} + +uint32_t Events_Get( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // get the requested flags from system events state and... + uint32_t returnEvents = (systemEvents & eventsOfInterest); + + // ... clear the requested flags atomically + GLOBAL_LOCK(); + systemEvents &= ~eventsOfInterest; + GLOBAL_UNLOCK(); + + // give the caller notice of just the events they asked for ( and were cleared already ) + return returnEvents; +} + +uint32_t Events_MaskedRead( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + return (systemEvents & eventsOfInterest); +} + +static void local_Events_SetBoolTimer_Callback( TimerHandle_t xTimer ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + bool* timerCompleteFlag = (bool*)pvTimerGetTimerID( xTimer ); + *timerCompleteFlag = true; +} + +void Events_SetCallback( set_Event_Callback pfn, void* arg ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + g_Event_Callback = pfn; + g_Event_Callback_Arg = arg; +} + +void Events_SetBoolTimer( bool* timerCompleteFlag, uint32_t millisecondsFromNow ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // we assume only 1 can be active, abort previous just in case + xTimerStop( boolEventsTimer, 0 ); + + if(timerCompleteFlag != NULL) + { + vTimerSetTimerID( boolEventsTimer, (void*) timerCompleteFlag ); + xTimerChangePeriod( boolEventsTimer, millisecondsFromNow / portTICK_PERIOD_MS, 0 ); + } +} + +uint32_t Events_WaitForEvents( uint32_t powerLevel, uint32_t wakeupSystemEvents, uint32_t timeoutMilliseconds ) +{ + // schedule an interrupt for this far in the future + // timeout is in milliseconds, need to convert to ticks + uint64_t countsRemaining = CPU_MillisecondsToTicks(timeoutMilliseconds); + + #if defined(HAL_PROFILE_ENABLED) + Events_WaitForEvents_Calls++; + #endif + + uint64_t expireTimeInTicks = HAL_Time_CurrentTime() + countsRemaining; + bool runContinuations = true; + + while(true) + { + EVENTS_HEART_BEAT; + + uint32_t events = Events_MaskedRead( wakeupSystemEvents ); + if(events) + { + return events; + } + + if(expireTimeInTicks <= HAL_Time_CurrentTime()) + { + break; + } + + // first check and possibly run any continuations + // but only if we have slept after stalling + if(runContinuations && !SystemState_QueryNoLock(SYSTEM_STATE_NO_CONTINUATIONS)) + { + // if we stall on time, don't check again until after we sleep + runContinuations = HAL_CONTINUATION::Dequeue_And_Execute(); + } + else + { + // try stalled continuations again after sleeping + runContinuations = true; + + HAL_COMPLETION::WaitForInterrupts(expireTimeInTicks, powerLevel, wakeupSystemEvents ); + } + + // no events, pass control to the OS + taskYIELD(); + + // check if reboot or exit flags were set when the other OS threads executed + if(CLR_EE_DBG_IS(RebootPending) || CLR_EE_DBG_IS(ExitPending)) + { + break; + } + } + + return 0; +} + +void FreeManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2) +{ + (void)category; + (void)subCategory; + (void)data1; + (void)data2; + + NATIVE_PROFILE_PAL_EVENTS(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp.groups.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp.groups.cpp new file mode 100644 index 00000000..4594c310 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Events.cpp.groups.cpp @@ -0,0 +1,146 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +#define ESP32_AVAILABLE_EVENTBITS 0x00ffffff + +static void local_Events_SetBoolTimer_Callback( TimerHandle_t xTimer ); + +// events timer +static TimerHandle_t boolEventsTimer; +static bool* saveTimerCompleteFlag = 0; + +EventGroupHandle_t systemEventsHigh; +EventGroupHandle_t systemEventsLow; + +set_Event_Callback g_Event_Callback = NULL; +void* g_Event_Callback_Arg = NULL; + +bool Events_Initialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // init events + // The Eps32 Event group is 24 bits, top 8 bits used by system + // Currently Nanoframework only uses 21 bits, see nanoHal.h + systemEventsHigh = xEventGroupCreate(); + systemEventsLow = xEventGroupCreate(); + + boolEventsTimer = xTimerCreate( "boolEventsTimer", 10, pdFALSE, (void *)0, local_Events_SetBoolTimer_Callback); + + return true; +} + +bool Events_Uninitialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + vEventGroupDelete( systemEventsHigh ); + vEventGroupDelete( systemEventsLow); + + return true; +} + +void Events_Set( uint32_t events ) +{ + NATIVE_PROFILE_PAL_EVENTS(); +ets_printf( "Events_set %X\n", events); + // set events + xEventGroupSetBits( systemEventsHigh, events >> 16 ); + xEventGroupSetBits( systemEventsLow, events & 0x00ffff ); + + if( g_Event_Callback != NULL ) + { + g_Event_Callback( g_Event_Callback_Arg ); + } +} + +uint32_t Events_Get( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // get the requested flags from system events state and... + + uint32_t returnEvents = (xEventGroupGetBits(systemEventsHigh) << 16) & xEventGroupGetBits(systemEventsLow) + + // Make off top 8 bits otherwise get exception when calling xEventGroupClearBits + uint32_t eventstoClear = ~eventsOfInterest; + + // ... clear the requested flags atomically + xEventGroupClearBits(systemEventsHigh, eventstoClear >> 16 ); + xEventGroupClearBits(systemEventsLow, eventstoClear & 0x00ffff ); + + // give the caller notice of just the events they asked for ( and were cleared already ) + return returnEvents; +} + +uint32_t Events_MaskedRead( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + uint32_t returnEvents = (xEventGroupGetBits(systemEventsHigh) << 16) & xEventGroupGetBits(systemEventsLow) + + return ( returnEvents & eventsOfInterest); +} + +static void local_Events_SetBoolTimer_Callback( TimerHandle_t xTimer ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + *saveTimerCompleteFlag = true; +} + +void Events_SetCallback( set_Event_Callback pfn, void* arg ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + g_Event_Callback = pfn; + g_Event_Callback_Arg = arg; +} + +void Events_SetBoolTimer( bool* timerCompleteFlag, uint32_t millisecondsFromNow ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // we assume only 1 can be active, abort previous just in case + xTimerStop( boolEventsTimer, 0 ); + + if(timerCompleteFlag != NULL) + { + + xTimerChangePeriod( boolEventsTimer, millisecondsFromNow / portTICK_PERIOD_MS, 0 ); + +// Was going to just change existing timer but vTimerSetTimerID() does not exist in this version of FreeRTOS +// As only one timer running at a time we will just save it in global memory + saveTimerCompleteFlag = timerCompleteFlag; + // vTimerSetTimerID( boolEventsTimer, (void *)timerCompleteFlag ); + xTimerStart(boolEventsTimer, 0); + } +} + +uint32_t Events_WaitForEvents( uint32_t powerLevel, uint32_t wakeupSystemEvents, uint32_t timeoutMilliseconds ) +{ + +#if defined(HAL_PROFILE_ENABLED) + Events_WaitForEvents_Calls++; +#endif + + EventBits_t events = (xEventGroupGetBits(systemEventsHigh) << 16) & xEventGroupGetBits(systemEventsLow) + if( events == 0) { + // no events, wait for timeoutMilliseconds + vTaskDelay( timeoutMilliseconds / portTICK_PERIOD_MS ); + } + + return (uint32_t)events; +} + +void FreeManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2) +{ + NATIVE_PROFILE_PAL_EVENTS(); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Time.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Time.cpp new file mode 100644 index 00000000..30ec2936 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetPAL_Time.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +static TimerHandle_t nextEventTimer; + +static void NextEventTimer_Callback( TimerHandle_t xTimer ) +{ + (void)xTimer; + + // this call also schedules the next one, if there is one + HAL_COMPLETION::DequeueAndExec(); +} + +HRESULT Time_Initialize() +{ + nextEventTimer = xTimerCreate( "NextEventTimer", 10, pdFALSE, (void *)0, NextEventTimer_Callback); + + return S_OK; +} + +HRESULT Time_Uninitialize() +{ + xTimerDelete(nextEventTimer, 0); + + return S_OK; +} + +void Time_SetCompare ( uint64_t compareValueTicks ) +{ + if(compareValueTicks == 0) + { + // compare value is 0 so dequeue and schedule immediately + HAL_COMPLETION::DequeueAndExec(); + } + else if(compareValueTicks == HAL_COMPLETION_IDLE_VALUE) + { + // wait for infinity, don't need to do anything here + return; + } + else + { + if (HAL_Time_CurrentTime() >= compareValueTicks) + { + // already missed the event, dequeue and execute immediately + HAL_COMPLETION::DequeueAndExec(); + } + else + { + xTimerStop( nextEventTimer, 0 ); + + // compareValueTicks is the time (in sys ticks) that is being requested to fire an HAL_COMPLETION::DequeueAndExec() + // need to subtract the current system time to set when the timer will fire + compareValueTicks -= HAL_Time_CurrentTime(); + + // no need to stop the timer even if it's running because the API does it anyway + // need to convert from nF ticks to milliseconds and then to FreeRTOS sys ticks to load the timer + xTimerChangePeriod(nextEventTimer, compareValueTicks, 0); + } + } +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetRandom.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetRandom.cpp new file mode 100644 index 00000000..061993b0 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/targetRandom.cpp @@ -0,0 +1,35 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +void CLR_RT_Random::Initialize() +{ +} + +void CLR_RT_Random::Initialize( int seed ) +{ + (void)seed; +} + +uint32_t CLR_RT_Random::Next() +{ + return esp_random(); +} + +double CLR_RT_Random::NextDouble() +{ + // the hardware generator returns a value between 0 - 0xFFFFFFFF + return ((double)esp_random()) / ((double)0xFFFFFFFF); +} + +void CLR_RT_Random::NextBytes(unsigned char* buffer, unsigned int count) +{ + unsigned int i; + + for(i = 0; i < count; i++) + { + buffer[i] = (unsigned char)esp_random(); + } +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_board.h.in new file mode 100644 index 00000000..825bc90d --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_board.h.in @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include + +#define OEMSYSTEMINFOSTRING "nanoFramework running ESP32 built with IDF v3.3" + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_platform.h.in b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_platform.h.in new file mode 100644 index 00000000..a495f6da --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/nanoCLR/target_platform.h.in @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_ESP32_NANOCLR_H_ +#define _TARGET_ESP32_NANOCLR_H_ + + +// set when SD card is enabled +#define HAL_USE_SDC @HAL_USE_SDC_OPTION@ +#if defined(HAL_USE_SDC) + +#define SDC_MAX_OPEN_FILES 5 + + + +#endif + + + +#endif /* _TARGET_ESP32_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.h new file mode 100644 index 00000000..3156288d --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.h @@ -0,0 +1,297 @@ +/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL 3 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB" +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_MONITOR_BAUD_115200B 1 +#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED 1 +#define CONFIG_STACK_CHECK_NONE 1 +#define CONFIG_ESP32_APPTRACE_DEST_NONE 1 +#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF 0 +#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE 0 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_ADC2_DISABLE_DAC 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_SPIRAM_SUPPORT 1 +#define CONFIG_SPIRAM_BOOT_INIT 1 +#define CONFIG_SPIRAM_IGNORE_NOTFOUND 1 +#define CONFIG_SPIRAM_USE_MALLOC 1 +#define CONFIG_SPIRAM_TYPE_AUTO 1 +#define CONFIG_SPIRAM_SIZE -1 +#define CONFIG_SPIRAM_SPEED_40M 1 +#define CONFIG_SPIRAM_MEMTEST 1 +#define CONFIG_SPIRAM_CACHE_WORKAROUND 1 +#define CONFIG_SPIRAM_BANKSWITCH_ENABLE 1 +#define CONFIG_SPIRAM_BANKSWITCH_RESERVE 8 +#define CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL 16384 +#define CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL 32768 +#define CONFIG_D0WD_PSRAM_CLK_IO 17 +#define CONFIG_D0WD_PSRAM_CS_IO 16 +#define CONFIG_D2WD_PSRAM_CLK_IO 9 +#define CONFIG_D2WD_PSRAM_CS_IO 10 +#define CONFIG_PICO_PSRAM_CS_IO 10 +#define CONFIG_SPIRAM_SPIWP_SD3_PIN 7 +#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 +#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_CONSOLE_UART_DEFAULT 1 +#define CONFIG_CONSOLE_UART_NUM 0 +#define CONFIG_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_ESP32_DEBUG_STUBS_ENABLE 1 +#define CONFIG_INT_WDT 1 +#define CONFIG_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_INT_WDT_CHECK_CPU1 1 +#define CONFIG_TASK_WDT 1 +#define CONFIG_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_BROWNOUT_DET 1 +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_BROWNOUT_DET_LVL 0 +#define CONFIG_REDUCE_PHY_TX_POWER 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_STATIC_TX_BUFFER 1 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 0 +#define CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM 16 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_PM_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_DMA_RX_BUF_NUM 10 +#define CONFIG_DMA_TX_BUF_NUM 10 +#define CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE 1 +#define CONFIG_EMAC_CHECK_LINK_PERIOD_MS 2000 +#define CONFIG_EMAC_TASK_PRIORITY 20 +#define CONFIG_EMAC_TASK_STACK_SIZE 3072 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FATFS_ALLOC_PREFER_EXTRAM 1 +#define CONFIG_MB_QUEUE_LENGTH 20 +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_MB_SERIAL_BUF_SIZE 256 +#define CONFIG_MB_SERIAL_TASK_PRIO 10 +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_MB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_MB_TIMER_PORT_ENABLED 1 +#define CONFIG_MB_TIMER_GROUP 0 +#define CONFIG_MB_TIMER_INDEX 0 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_SUPPORT_STATIC_ALLOCATION 1 +#define CONFIG_TIMER_TASK_PRIORITY 1 +#define CONFIG_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_LWIP_MAX_SOCKETS 16 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_ESP_GRATUITOUS_ARP 1 +#define CONFIG_GARP_TMR_INTERVAL 60 +#define CONFIG_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_TCP_MAXRTX 12 +#define CONFIG_TCP_SYNMAXRTX 6 +#define CONFIG_TCP_MSS 1436 +#define CONFIG_TCP_MSL 60000 +#define CONFIG_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_TCP_WND_DEFAULT 5744 +#define CONFIG_TCP_RECVMBOX_SIZE 6 +#define CONFIG_TCP_QUEUE_OOSEQ 1 +#define CONFIG_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_UDP_RECVMBOX_SIZE 6 +#define CONFIG_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_MULTICAST_PING 1 +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1 +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY 1 +#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_TCPIP_LWIP 1 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_SUPPORT_TERMIOS 1 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.txt b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.txt new file mode 100644 index 00000000..3c4da6c8 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/sdkconfig.txt @@ -0,0 +1,737 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_TARGET="esp32" + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT_ENABLED is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_STACK_CHECK is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +# CONFIG_ESP32_APPTRACE_ENABLE is not set +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_AWS_IOT_SDK is not set +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y +# CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY is not set +# CONFIG_BTDM_CONTROLLER_MODE_BTDM is not set +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y +# CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1 is not set +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y +# CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4 is not set +CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=y +CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y +# CONFIG_BTDM_MODEM_SLEEP_MODE_EVED is not set +CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y +CONFIG_BLE_SCAN_DUPLICATE=y +CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR=y +# CONFIG_SCAN_DUPLICATE_BY_ADV_DATA is not set +# CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR is not set +CONFIG_SCAN_DUPLICATE_TYPE=0 +CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200 +# CONFIG_BLE_MESH_SCAN_DUPLICATE_EN is not set +# CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED is not set +CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED=y +CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM=100 +CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BLUEDROID_ENABLED=y +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +# CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTC_TASK_STACK_SIZE=3072 +CONFIG_BTU_TASK_STACK_SIZE=4096 +# CONFIG_BLUEDROID_MEM_DEBUG is not set +# CONFIG_CLASSIC_BT_ENABLED is not set +CONFIG_GATTS_ENABLE=y +# CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set +CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 +CONFIG_GATTC_ENABLE=y +# CONFIG_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BLE_SMP_ENABLE=y +# CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_BT_STACK_NO_LOG is not set +# CONFIG_HCI_TRACE_LEVEL_NONE is not set +# CONFIG_HCI_TRACE_LEVEL_ERROR is not set +CONFIG_HCI_TRACE_LEVEL_WARNING=y +# CONFIG_HCI_TRACE_LEVEL_API is not set +# CONFIG_HCI_TRACE_LEVEL_EVENT is not set +# CONFIG_HCI_TRACE_LEVEL_DEBUG is not set +# CONFIG_HCI_TRACE_LEVEL_VERBOSE is not set +CONFIG_HCI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTM_TRACE_LEVEL_NONE is not set +# CONFIG_BTM_TRACE_LEVEL_ERROR is not set +CONFIG_BTM_TRACE_LEVEL_WARNING=y +# CONFIG_BTM_TRACE_LEVEL_API is not set +# CONFIG_BTM_TRACE_LEVEL_EVENT is not set +# CONFIG_BTM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTM_INITIAL_TRACE_LEVEL=2 +# CONFIG_L2CAP_TRACE_LEVEL_NONE is not set +# CONFIG_L2CAP_TRACE_LEVEL_ERROR is not set +CONFIG_L2CAP_TRACE_LEVEL_WARNING=y +# CONFIG_L2CAP_TRACE_LEVEL_API is not set +# CONFIG_L2CAP_TRACE_LEVEL_EVENT is not set +# CONFIG_L2CAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_L2CAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 +# CONFIG_RFCOMM_TRACE_LEVEL_NONE is not set +# CONFIG_RFCOMM_TRACE_LEVEL_ERROR is not set +CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y +# CONFIG_RFCOMM_TRACE_LEVEL_API is not set +# CONFIG_RFCOMM_TRACE_LEVEL_EVENT is not set +# CONFIG_RFCOMM_TRACE_LEVEL_DEBUG is not set +# CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE is not set +CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 +# CONFIG_SDP_TRACE_LEVEL_NONE is not set +# CONFIG_SDP_TRACE_LEVEL_ERROR is not set +CONFIG_SDP_TRACE_LEVEL_WARNING=y +# CONFIG_SDP_TRACE_LEVEL_API is not set +# CONFIG_SDP_TRACE_LEVEL_EVENT is not set +# CONFIG_SDP_TRACE_LEVEL_DEBUG is not set +# CONFIG_SDP_TRACE_LEVEL_VERBOSE is not set +CONFIG_SDP_INITIAL_TRACE_LEVEL=2 +# CONFIG_GAP_TRACE_LEVEL_NONE is not set +# CONFIG_GAP_TRACE_LEVEL_ERROR is not set +CONFIG_GAP_TRACE_LEVEL_WARNING=y +# CONFIG_GAP_TRACE_LEVEL_API is not set +# CONFIG_GAP_TRACE_LEVEL_EVENT is not set +# CONFIG_GAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_GAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_GAP_INITIAL_TRACE_LEVEL=2 +# CONFIG_BNEP_TRACE_LEVEL_NONE is not set +# CONFIG_BNEP_TRACE_LEVEL_ERROR is not set +CONFIG_BNEP_TRACE_LEVEL_WARNING=y +# CONFIG_BNEP_TRACE_LEVEL_API is not set +# CONFIG_BNEP_TRACE_LEVEL_EVENT is not set +# CONFIG_BNEP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BNEP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 +# CONFIG_PAN_TRACE_LEVEL_NONE is not set +# CONFIG_PAN_TRACE_LEVEL_ERROR is not set +CONFIG_PAN_TRACE_LEVEL_WARNING=y +# CONFIG_PAN_TRACE_LEVEL_API is not set +# CONFIG_PAN_TRACE_LEVEL_EVENT is not set +# CONFIG_PAN_TRACE_LEVEL_DEBUG is not set +# CONFIG_PAN_TRACE_LEVEL_VERBOSE is not set +CONFIG_PAN_INITIAL_TRACE_LEVEL=2 +# CONFIG_A2D_TRACE_LEVEL_NONE is not set +# CONFIG_A2D_TRACE_LEVEL_ERROR is not set +CONFIG_A2D_TRACE_LEVEL_WARNING=y +# CONFIG_A2D_TRACE_LEVEL_API is not set +# CONFIG_A2D_TRACE_LEVEL_EVENT is not set +# CONFIG_A2D_TRACE_LEVEL_DEBUG is not set +# CONFIG_A2D_TRACE_LEVEL_VERBOSE is not set +CONFIG_A2D_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVDT_TRACE_LEVEL_NONE is not set +# CONFIG_AVDT_TRACE_LEVEL_ERROR is not set +CONFIG_AVDT_TRACE_LEVEL_WARNING=y +# CONFIG_AVDT_TRACE_LEVEL_API is not set +# CONFIG_AVDT_TRACE_LEVEL_EVENT is not set +# CONFIG_AVDT_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVDT_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVCT_TRACE_LEVEL_NONE is not set +# CONFIG_AVCT_TRACE_LEVEL_ERROR is not set +CONFIG_AVCT_TRACE_LEVEL_WARNING=y +# CONFIG_AVCT_TRACE_LEVEL_API is not set +# CONFIG_AVCT_TRACE_LEVEL_EVENT is not set +# CONFIG_AVCT_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVCT_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 +# CONFIG_AVRC_TRACE_LEVEL_NONE is not set +# CONFIG_AVRC_TRACE_LEVEL_ERROR is not set +CONFIG_AVRC_TRACE_LEVEL_WARNING=y +# CONFIG_AVRC_TRACE_LEVEL_API is not set +# CONFIG_AVRC_TRACE_LEVEL_EVENT is not set +# CONFIG_AVRC_TRACE_LEVEL_DEBUG is not set +# CONFIG_AVRC_TRACE_LEVEL_VERBOSE is not set +CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 +# CONFIG_MCA_TRACE_LEVEL_NONE is not set +# CONFIG_MCA_TRACE_LEVEL_ERROR is not set +CONFIG_MCA_TRACE_LEVEL_WARNING=y +# CONFIG_MCA_TRACE_LEVEL_API is not set +# CONFIG_MCA_TRACE_LEVEL_EVENT is not set +# CONFIG_MCA_TRACE_LEVEL_DEBUG is not set +# CONFIG_MCA_TRACE_LEVEL_VERBOSE is not set +CONFIG_MCA_INITIAL_TRACE_LEVEL=2 +# CONFIG_HID_TRACE_LEVEL_NONE is not set +# CONFIG_HID_TRACE_LEVEL_ERROR is not set +CONFIG_HID_TRACE_LEVEL_WARNING=y +# CONFIG_HID_TRACE_LEVEL_API is not set +# CONFIG_HID_TRACE_LEVEL_EVENT is not set +# CONFIG_HID_TRACE_LEVEL_DEBUG is not set +# CONFIG_HID_TRACE_LEVEL_VERBOSE is not set +CONFIG_HID_INITIAL_TRACE_LEVEL=2 +# CONFIG_APPL_TRACE_LEVEL_NONE is not set +# CONFIG_APPL_TRACE_LEVEL_ERROR is not set +CONFIG_APPL_TRACE_LEVEL_WARNING=y +# CONFIG_APPL_TRACE_LEVEL_API is not set +# CONFIG_APPL_TRACE_LEVEL_EVENT is not set +# CONFIG_APPL_TRACE_LEVEL_DEBUG is not set +# CONFIG_APPL_TRACE_LEVEL_VERBOSE is not set +CONFIG_APPL_INITIAL_TRACE_LEVEL=2 +# CONFIG_GATT_TRACE_LEVEL_NONE is not set +# CONFIG_GATT_TRACE_LEVEL_ERROR is not set +CONFIG_GATT_TRACE_LEVEL_WARNING=y +# CONFIG_GATT_TRACE_LEVEL_API is not set +# CONFIG_GATT_TRACE_LEVEL_EVENT is not set +# CONFIG_GATT_TRACE_LEVEL_DEBUG is not set +# CONFIG_GATT_TRACE_LEVEL_VERBOSE is not set +CONFIG_GATT_INITIAL_TRACE_LEVEL=2 +# CONFIG_SMP_TRACE_LEVEL_NONE is not set +# CONFIG_SMP_TRACE_LEVEL_ERROR is not set +CONFIG_SMP_TRACE_LEVEL_WARNING=y +# CONFIG_SMP_TRACE_LEVEL_API is not set +# CONFIG_SMP_TRACE_LEVEL_EVENT is not set +# CONFIG_SMP_TRACE_LEVEL_DEBUG is not set +# CONFIG_SMP_TRACE_LEVEL_VERBOSE is not set +CONFIG_SMP_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTIF_TRACE_LEVEL_NONE is not set +# CONFIG_BTIF_TRACE_LEVEL_ERROR is not set +CONFIG_BTIF_TRACE_LEVEL_WARNING=y +# CONFIG_BTIF_TRACE_LEVEL_API is not set +# CONFIG_BTIF_TRACE_LEVEL_EVENT is not set +# CONFIG_BTIF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTIF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 +# CONFIG_BTC_TRACE_LEVEL_NONE is not set +# CONFIG_BTC_TRACE_LEVEL_ERROR is not set +CONFIG_BTC_TRACE_LEVEL_WARNING=y +# CONFIG_BTC_TRACE_LEVEL_API is not set +# CONFIG_BTC_TRACE_LEVEL_EVENT is not set +# CONFIG_BTC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BTC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BTC_INITIAL_TRACE_LEVEL=2 +# CONFIG_OSI_TRACE_LEVEL_NONE is not set +# CONFIG_OSI_TRACE_LEVEL_ERROR is not set +CONFIG_OSI_TRACE_LEVEL_WARNING=y +# CONFIG_OSI_TRACE_LEVEL_API is not set +# CONFIG_OSI_TRACE_LEVEL_EVENT is not set +# CONFIG_OSI_TRACE_LEVEL_DEBUG is not set +# CONFIG_OSI_TRACE_LEVEL_VERBOSE is not set +CONFIG_OSI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BLUFI_TRACE_LEVEL_NONE is not set +# CONFIG_BLUFI_TRACE_LEVEL_ERROR is not set +CONFIG_BLUFI_TRACE_LEVEL_WARNING=y +# CONFIG_BLUFI_TRACE_LEVEL_API is not set +# CONFIG_BLUFI_TRACE_LEVEL_EVENT is not set +# CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 +CONFIG_BT_ACL_CONNECTIONS=4 +# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set +# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set +# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set +CONFIG_SMP_ENABLE=y +# CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 +CONFIG_BT_RESERVE_DRAM=0xdb5c +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC2_DISABLE_DAC=y +CONFIG_SPI_MASTER_IN_IRAM=y +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set +CONFIG_EFUSE_MAX_BLK_LEN=192 +CONFIG_IDF_TARGET_ESP32=y +# CONFIG_ESP32_REV_MIN_0 is not set +CONFIG_ESP32_REV_MIN_1=y +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=1 +CONFIG_ESP32_DPORT_WORKAROUND=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +CONFIG_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_SIZE=-1 +CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_CACHE_WORKAROUND=y +CONFIG_SPIRAM_BANKSWITCH_ENABLE=y +CONFIG_SPIRAM_BANKSWITCH_RESERVE=8 +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 +# CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is not set +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 +# CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY is not set +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +CONFIG_D0WD_PSRAM_CLK_IO=17 +CONFIG_D0WD_PSRAM_CS_IO=16 +CONFIG_D2WD_PSRAM_CLK_IO=9 +CONFIG_D2WD_PSRAM_CS_IO=10 +CONFIG_PICO_PSRAM_CS_IO=10 +CONFIG_SPIRAM_SPIWP_SD3_PIN=7 +# CONFIG_MEMMAP_TRACEMEM is not set +# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +# CONFIG_ESP32_PANIC_PRINT_HALT is not set +CONFIG_ESP32_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32_PANIC_GDBSTUB is not set +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +# CONFIG_TASK_WDT is not set +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +# CONFIG_ESP32_XTAL_FREQ_26 is not set +# CONFIG_ESP32_XTAL_FREQ_AUTO is not set +CONFIG_ESP32_XTAL_FREQ=40 +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_ESP_TIMER_PROFILING is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_SW_COEXIST_ENABLE=y +# CONFIG_SW_COEXIST_PREFERENCE_WIFI is not set +# CONFIG_SW_COEXIST_PREFERENCE_BT is not set +CONFIG_SW_COEXIST_PREFERENCE_BALANCE=y +CONFIG_SW_COEXIST_PREFERENCE_VALUE=2 +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +CONFIG_PM_ENABLE=y +# CONFIG_PM_DFS_INIT_AUTO is not set +# CONFIG_PM_USE_RTC_TIMER_REF is not set +# CONFIG_PM_PROFILING is not set +# CONFIG_PM_TRACE is not set +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_OTA_ALLOW_HTTP is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# CONFIG_ESP32_ENABLE_COREDUMP is not set +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE=y +CONFIG_EMAC_CHECK_LINK_PERIOD_MS=2000 +CONFIG_EMAC_TASK_PRIORITY=20 +CONFIG_EMAC_TASK_STACK_SIZE=3072 +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +# CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_USE_TICKLESS_IDLE is not set +# CONFIG_FREERTOS_DEBUG_INTERNALS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +# CONFIG_HEAP_TRACING is not set +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_MAX_SOCKETS=16 +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +# CONFIG_LWIP_IP_FRAG is not set +# CONFIG_LWIP_IP_REASSEMBLY is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_LWIP_MULTICAST_PING=y +# CONFIG_LWIP_BROADCAST_PING is not set +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +# CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN is not set +# CONFIG_MBEDTLS_DEBUG is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +# CONFIG_MBEDTLS_HARDWARE_MPI is not set +# CONFIG_MBEDTLS_HARDWARE_SHA is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_RIPEMD160_C is not set +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +# CONFIG_OPENSSL_ASSERT_EXIT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPIFFS_MAX_PARTITIONS=3 +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +CONFIG_IP_LOST_TIMER_INTERVAL=120 +CONFIG_TCPIP_LWIP=y +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.c new file mode 100644 index 00000000..6b185982 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.c @@ -0,0 +1,19 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice ESP32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + // add device AND request initialization + // required to setup flash partitions memory mapping + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &ESP32Flash_BlockStorageInterface, &Device_BlockStorageConfig, true); +} diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.c b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.c new file mode 100644 index 00000000..022af372 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.c @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +#include + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; + + +void FixUpHalSystemConfig() +{ + HalSystemConfig.FLASH1.Size = g_rom_flashchip.chip_size; +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.h.in b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.h.in new file mode 100644 index 00000000..74d44824 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_common.h.in @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress (0x200000C0) +// RAM size +#define RAM1_MEMORY_Size (0x00020000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress (0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size (0x00080000) + +///////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////// +#define TARGETNAMESTRING "ESP32_WROOM_32" +#define PLATFORMNAMESTRING "ESP32" +////////////////////////////////////////////// + +///////////////////////////////////// +// #define EVENTS_HEART_BEAT +///////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_lwip_sntp_opts.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_lwip_sntp_opts.h new file mode 100644 index 00000000..30007664 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_lwip_sntp_opts.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#define SNTP_SERVER_DEFAULT_ADDRESS "0.pool.ntp.org" + +// update delay (default 1 hour) +// (value in milliseconds) +#define SNTP_UPDATE_DELAY 3600000 + +// better have a startup delay because we can have DHCP enabled, value in milliseconds. +// As we automatically start SNTP when we get the IP address then only a small delay +#define SNTP_STARTUP_DELAY 1000 + +// retry timeout (15 minutes) +// value in milliseconds +#define SNTP_RETRY_TIMEOUT 900000 diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.h new file mode 100644 index 00000000..33de9b0a --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_nf_devices_onewire_config.h @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// use UART 2 for the 1-wire interface +#define NF_ONEWIRE_ESP32_UART_NUM UART_NUM_2 +// use GPIO port 16 for RX and 17 for TX +#define NF_ONEWIRE_ESP32_UART_RX_PIN UART_NUM_2_RXD_DIRECT_GPIO_NUM +#define NF_ONEWIRE_ESP32_UART_TX_PIN UART_NUM_2_TXD_DIRECT_GPIO_NUM diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..d7b7376b --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_system_devices_dac_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_adc_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_i2c_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..4845bf12 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_devices_spi_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_storage_config.h b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_storage_config.h new file mode 100644 index 00000000..4fe92098 --- /dev/null +++ b/source/native/nf-interpreter/targets/FreeRTOS_ESP32/ESP32_WROOM_32/target_windows_storage_config.h @@ -0,0 +1,5 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/CMakeLists.txt b/source/native/nf-interpreter/targets/TI-SimpleLink/CMakeLists.txt new file mode 100644 index 00000000..504dbd22 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/CMakeLists.txt @@ -0,0 +1,233 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# set target base location +# this has to be set before the class library modules are pulled in +if(EXISTS ${PROJECT_SOURCE_DIR}/targets/TI-SimpleLink/${TI_BOARD}) + # set target base location + set(TARGET_BASE_LOCATION "${PROJECT_SOURCE_DIR}/targets/TI-SimpleLink/${TI_BOARD}") + message(STATUS "Support for target board '${TI_BOARD}' found") +else() + # board NOT found + # can't continue + message(FATAL_ERROR "\n\nSorry but support for ${TI_BOARD} target is not available...\n\nYou can wait for that to be added or you might want to contribute and start working on a PR for that.\n\n") +endif() + +# Define base path for the class libraries +set(BASE_PATH_FOR_CLASS_LIBRARIES_MODULES "${PROJECT_SOURCE_DIR}/targets/TI-SimpleLink/nanoCLR") + +# add target TI SimpleLink dirs +add_subdirectory(common) +add_subdirectory(Include) +add_subdirectory(nanoCLR) + +if("${TARGET_SERIES}" STREQUAL "CC32xx") + + # CC32xx series is using TI SimpleLink CC32xx SDK and FreeRTOS + + # check if TI_SL_CC32xx_SDK_SOURCE was specified or if it's empty (default is empty) + set(NO_TI_SL_CC32xx_SDK_SOURCE TRUE) + if(TI_SL_CC32xx_SDK_SOURCE) + if(NOT "${TI_SL_CC32xx_SDK_SOURCE}" STREQUAL "") + set(NO_TI_SL_CC32xx_SDK_SOURCE FALSE) + endif() + endif() + + if(NO_TI_SL_CC32xx_SDK_SOURCE) + # no TI SimpleLink CC32xx SDK source specified, download it from our repo + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + message(STATUS "TI SimpleLink CC32xx SDK (latest available code from v3.10.00.04") + set(TI_SL_CC32xx_SDK_TAG "3.10.00.04") + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/SimpleLinkCC32xxSdk.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdk_Download/CMakeLists.txt") + + # setup CMake project for TI SimpleLink CC32xx SDK download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdk_Download") + + # run build on TI SimpleLink CC32xx SDK download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdk_Download") + + # add TI SimpleLink CC32xx SDK as external project + ExternalProject_Add( + SimpleLinkCC32xxSDK + PREFIX SimpleLinkCC32xxSdk + SOURCE_DIR ${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdk_Source + GIT_REPOSITORY https://github.com/nanoframework/SimpleLink_CC32xx_SDK + GIT_TAG ${TI_SL_CC32xx_SDK_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for TI SimpleLink CC32xx SDK CMake project + ExternalProject_Get_Property(SimpleLinkCC32xxSDK SOURCE_DIR) + + else() + # TI SimpleLink CC32xx SDK source was specified + + # sanity check is source path exists + if(EXISTS "${TI_SL_CC32xx_SDK_SOURCE}/") + message(STATUS "TI SimpleLink CC32xx SDK source from: ${TI_SL_CC32xx_SDK_SOURCE}") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/TI_SL_CC32xx_SDK_SOURCE") + file(COPY "${TI_SL_CC32xx_SDK_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdk_Source") + else() + message(STATUS "Using local cache of TI SimpleLink CC32xx SDK source from ${TI_SL_CC32xx_SDK_SOURCE}") + endif() + + set(SimpleLinkCC32xxSDK_INCLUDE_DIR ${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdkS_Source/ti/devices/cc32xx) + else() + message(FATAL_ERROR "Couldn't find TI SimpleLink CC32xx SDK source at ${TI_SL_CC32xx_SDK_SOURCE}/") + endif() + + # add TI SimpleLink CC32xx SDK as external project + ExternalProject_Add( + SimpleLinkCC32xxSDK + PREFIX SimpleLinkCC32xxSdk + SOURCE_DIR ${CMAKE_BINARY_DIR}/SimpleLinkCC32xxSdk_Source + + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for TI SimpleLink CC32xx SDK CMake project + ExternalProject_Get_Property(SimpleLinkCC32xxSDK SOURCE_DIR) + endif() + + # check if FREERTOS_SOURCE was specified or if it's empty (default is empty) + set(NO_FREERTOS_SOURCE TRUE) + if(FREERTOS_SOURCE) + if(NOT "${FREERTOS_SOURCE}" STREQUAL "") + set(NO_FREERTOS_SOURCE FALSE) + endif() + endif() + + if(NO_FREERTOS_SOURCE) + # no FreeRTOS source specified, download it from it's repo + + # check for Git (needed here for advanced warning to user if it's not installed) + find_package(Git) + + # check if Git was found, if not report to user and abort + if(NOT GIT_EXECUTABLE) + message(FATAL_ERROR "error: could not find Git, make sure you have it installed.") + endif() + + # FreeRTOS version + set(FREERTOS_VERSION_EMPTY TRUE) + + # check if build was requested with a specifc FreeRTOS version + if(DEFINED FREERTOS_VERSION) + if(NOT "${FREERTOS_VERSION}" STREQUAL "") + set(FREERTOS_VERSION_EMPTY FALSE) + endif() + endif() + + # FreeRTOS version + set(FREERTOS_VERSION_EMPTY TRUE) + + # check if build was requested with a specifc FreeRTOS version + if(FREERTOS_VERSION_EMPTY) + # no FreeRTOS version actualy specified, must be empty which is fine, we'll default to a known good version + set(FREERTOS_VERSION_TAG "v1.4.8") + else() + # set SVN tag + set(FREERTOS_VERSION_TAG "${FREERTOS_VERSION}") + endif() + + message(STATUS "RTOS is: FreeRTOS ${FREERTOS_VERSION} from GitHub repo") + + # need to setup a separate CMake project to download the code from the GitHub repository + # otherwise it won't be available before the actual build step + configure_file("${PROJECT_SOURCE_DIR}/CMake/FreeRTOS.CMakeLists.cmake.in" + "${CMAKE_BINARY_DIR}/FreeRTOS_Download/CMakeLists.txt") + + # setup CMake project for FreeRTOS download + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/FreeRTOS_Download") + + # run build on FreeRTOS download CMake project to perform the download + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/FreeRTOS_Download") + + # add FreeRTOS as external project + ExternalProject_Add( + FreeRTOS + PREFIX FreeRTOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/FreeRTOS_Source + GIT_REPOSITORY https://github.com/aws/amazon-freertos.git + GIT_TAG ${FREERTOS_VERSION_TAG} # target specified branch + GIT_SHALLOW 1 # download only the tip of the branch, not the complete history + TIMEOUT 10 + LOG_DOWNLOAD 1 + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + else() + # FreeRTOS source was specified + + # sanity check is source path exists + if(EXISTS "${FREERTOS_SOURCE}/") + message(STATUS "RTOS is: FreeRTOS (source from: ${FREERTOS_SOURCE})") + + # check if we already have the sources, no need to copy again + if(NOT EXISTS "${CMAKE_BINARY_DIR}/FreeRTOS_Source") + file(COPY "${FREERTOS_SOURCE}/" DESTINATION "${CMAKE_BINARY_DIR}/FreeRTOS_Source") + else() + message(STATUS "Using local cache of FreeRTOS source from ${FREERTOS_SOURCE}") + endif() + + set(FREERTOS_INCLUDE_DIR ${CMAKE_BINARY_DIR}/FreeRTOS_Source/include) + else() + message(FATAL_ERROR "Couldn't find FreeRTOS source at ${FREERTOS_SOURCE}/") + endif() + + # add FreeRTOS as external project + ExternalProject_Add( + FreeRTOS + PREFIX FreeRTOS + SOURCE_DIR ${CMAKE_BINARY_DIR}/FreeRTOS_Source + # Disable all other steps + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + ) + + # get source dir for FreeRTOS CMake project + ExternalProject_Get_Property(FreeRTOS SOURCE_DIR) + + endif() + + add_subdirectory(${TI_BOARD}) + +endif() diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/CLR_Startup_Thread.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/CLR_Startup_Thread.h new file mode 100644 index 00000000..3c394ef4 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/CLR_Startup_Thread.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _CLRSTARTUPTHREAD_ +#define _CLRSTARTUPTHREAD_ + +// declaration of RTOS thread +void CLRStartupThread(void const * argument); + +#endif //_CLRSTARTUPTHREAD_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/CMakeLists.txt b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/CMakeLists.txt new file mode 100644 index 00000000..38729eda --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append include directory for target TI SimpleLink +list(APPEND TARGET_TI_SimpleLink_COMMON_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") + +# make var global +set(TARGET_TI_SimpleLink_COMMON_INCLUDE_DIRS ${TARGET_TI_SimpleLink_COMMON_INCLUDE_DIRS} CACHE INTERNAL "make global") + +# add header with target platform definitions +configure_file("${CMAKE_SOURCE_DIR}/CMake/TI_SimpleLink_target_os.h.in" + "${CMAKE_BINARY_DIR}/targets/TI-SimpleLink/${TI_BOARD}/target_os.h" @ONLY) diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/TargetPAL_BlockStorage.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/TargetPAL_BlockStorage.h new file mode 100644 index 00000000..1828f750 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/TargetPAL_BlockStorage.h @@ -0,0 +1,11 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_BLOCKSTORAGE_H_ +#define _TARGET_PAL_BLOCKSTORAGE_H_ 1 + +#include + +#endif // _TARGET_PAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_BlockStorage_CC32xxFlashDriver.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_BlockStorage_CC32xxFlashDriver.h new file mode 100644 index 00000000..7097fd80 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_BlockStorage_CC32xxFlashDriver.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_CC32XXFLASH_DRIVER_H_ +#define _TARGET_CC32XXFLASH_DRIVER_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool CC32xxFlashDriver_InitializeDevice(void*); +bool CC32xxFlashDriver_UninitializeDevice(void*); +DeviceBlockInfo* CC32xxFlashDriver_GetDeviceInfo(void*); +bool CC32xxFlashDriver_Read(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer); +bool CC32xxFlashDriver_Write(void*, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite); +bool CC32xxFlashDriver_IsBlockErased(void*, ByteAddress blockAddress, unsigned int length); +bool CC32xxFlashDriver_EraseBlock(void*, ByteAddress address); +void CC32xxFlashDriver_SetPowerState(void*, unsigned int state); + +#ifdef __cplusplus +} +#endif + +#endif //_TARGET_CC32XXFLASH_DRIVER_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_Windows_Storage.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_Windows_Storage.h new file mode 100644 index 00000000..888c34fe --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/Target_Windows_Storage.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_WINDOWS_STORAGE_H_ +#define _TARGET_WINDOWS_STORAGE_H_ 1 + +#endif //_TARGET_WINDOWS_STORAGE_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/WireProtocol_ReceiverThread.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/WireProtocol_ReceiverThread.h new file mode 100644 index 00000000..2ab358a6 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/WireProtocol_ReceiverThread.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_RECEIVERTHREAD_H_ +#define _WIREPROTOCOL_RECEIVERTHREAD_H_ + +// declaration of RTOS thread +void* ReceiverThread(void* argument); + +#endif //_WIREPROTOCOL_RECEIVERTHREAD_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/platform_target_capabilities.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/platform_target_capabilities.h new file mode 100644 index 00000000..b44fe07a --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/platform_target_capabilities.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _PLATFORM_TARGET_CAPABILITIES_H_ +#define _PLATFORM_TARGET_CAPABILITIES_H_ 1 + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.TiCc32xx.TargetCapabilities (in managed code) !!! // +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +// this platform doesn't have any declared capabilities + +// the targets of this platform don't have any declared capabilities + +#ifdef __cplusplus +} +#endif + +#endif //_PLATFORM_TARGET_CAPABILITIES_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/ssl_simplelink.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/ssl_simplelink.h new file mode 100644 index 00000000..063d426c --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/ssl_simplelink.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _SSL_SIMPLELINK_H_ +#define _SSL_SIMPLELINK_H_ 1 + +#include + +struct SlSSL_Context +{ + SlNetSockSecAttrib_t* SecurityAttributes; + uint32_t SocketFd; + bool IsServer; +}; + +#endif //_SSL_SIMPLELINK_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL.h new file mode 100644 index 00000000..7d5746e5 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL.h @@ -0,0 +1,103 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_H_ +#define _TARGET_HAL_H_ + +#include +#include +#include +#include + +#define GLOBAL_LOCK() vPortEnterCritical(); +#define GLOBAL_UNLOCK() vPortExitCritical(); + +// platform dependent delay +#define PLATFORM_DELAY(milliSecs) ClockP_usleep(milliSecs * 1000); + +// Definitions for Sockets/Network +#define GLOBAL_LOCK_SOCKETS(x) + +#define PLATFORM_DEPENDENT__SOCKETS_MAX_COUNT 16 + +#define LPCSTR const char* + +// these macros are to be used at entry/exit of native interrupt handlers +#define NATIVE_INTERRUPT_START SystemState_SetNoLock( SYSTEM_STATE_ISR ); \ + SystemState_SetNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); +#define NATIVE_INTERRUPT_END SystemState_ClearNoLock( SYSTEM_STATE_NO_CONTINUATIONS ); \ + SystemState_ClearNoLock( SYSTEM_STATE_ISR ); + +#define TRUE true +#define FALSE false + +#if !defined(BUILD_RTM) + +#define HARD_BREAKPOINT() HARD_Breakpoint() + +// #if defined(_DEBUG) +// #define DEBUG_HARD_BREAKPOINT() HARD_Breakpoint() +// #else +// #define DEBUG_HARD_BREAKPOINT() +// #endif + +// #else + +// #define HARD_BREAKPOINT() +// #define DEBUG_HARD_BREAKPOINT() + +#endif // !defined(BUILD_RTM) + +// map TI SimpleLink calls to UART output to nanoFramework API +// this is valid only for debug buils +// release and RTM build don't call these +#if defined(BUILD_RTM) + +#define UART_PRINT(x,...) +#define INFO_PRINT(x,...) + +#else + +#if defined(DEBUG) || defined(_DEBUG) + +#define UART_PRINT DebuggerPort_WriteProxy +#define INFO_PRINT DebuggerPort_WriteProxy + +#else + +#define UART_PRINT(x,...) +#define INFO_PRINT(x,...) + +#endif // DEBUG + +#endif // defined(BUILD_RTM) + +#define NANOCLR_STOP() HARD_BREAKPOINT() + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// DEBUGGER HELPER // +// The line below is meant to be used as helper on checking that the execution engine is running. // +// This can be inferred by checking if Events_WaitForEvents loop is running. // +// The implementation should is to be provided by each target at target_common.h.in // +//////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(BUILD_RTM) + #define EVENTS_HEART_BEAT +#else + #ifndef EVENTS_HEART_BEAT + #define EVENTS_HEART_BEAT __asm__ __volatile__ ("nop") + #endif // EVENTS_HEART_BEAT +#endif + +extern int HeapBegin; +extern int HeapEnd; + +extern uint32_t __nanoImage_start__; +extern uint32_t __nanoImage_end__; +extern uint32_t __nanoConfig_start__; +extern uint32_t __nanoConfig_end__; +extern uint32_t __deployment_start__; +extern uint32_t __deployment_end__; + +#endif //_TARGET_HAL_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_ConfigurationManager_CC32xx.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_ConfigurationManager_CC32xx.h new file mode 100644 index 00000000..4a931362 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_ConfigurationManager_CC32xx.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_CONFIGURATIONMANAGER_CC32XX_H_ +#define _TARGET_CONFIGURATIONMANAGER_CC32XX_H_ 1 + +// we'll store up to 4 network configuration blocks +#define NETWORK_CONFIG_MAX_COUNT (4) +// files with network configuration have this namming patter "network-config-N.bin" +#define NETWORK_CONFIG_FILE_NAME "nf/network-config0.bin" +// position of the index in the file name above (that's the 0) +#define NETWORK_CONFIG_FILE_INDEX_POSITION (17) + +// CA (Certificate Authority) root file name +#define CA_ROOT_CERT_FILE_NAME "ca-cert.pem" + +#endif //_TARGET_CONFIGURATIONMANAGER_CC32XX_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_Time.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_Time.h new file mode 100644 index 00000000..a456444d --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetHAL_Time.h @@ -0,0 +1,14 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_TIME_H_ +#define _TARGET_HAL_TIME_H_ 1 + +#include +#include + +#define HAL_Time_CurrentSysTicks xTaskGetTickCount + +#endif //_TARGET_HAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetPAL_Time.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetPAL_Time.h new file mode 100644 index 00000000..815979a7 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetPAL_Time.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_TIME_H_ +#define _TARGET_PAL_TIME_H_ 1 + +#endif //_TARGET_PAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_LinkLocalTask.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_LinkLocalTask.h new file mode 100644 index 00000000..f799a3b1 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_LinkLocalTask.h @@ -0,0 +1,239 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _SIMPLELINK_CC32XX_LINKLOCAL_TASK_H_ +#define _SIMPLELINK_CC32XX_LINKLOCAL_TASK_H_ + +/* TI-DRIVERS Header files */ +#include + +/* POSIX Header files */ +#include +#include + +#define OOB_IS_NETAPP_MORE_DATA(flags) ((flags & \ + SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION) \ + == \ + SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION) +#define OOB_IS_NETAPP_ERROR(flags) ((flags & \ + SL_NETAPP_REQUEST_RESPONSE_FLAGS_ERROR) \ + == \ + SL_NETAPP_REQUEST_RESPONSE_FLAGS_ERROR) + +/* header fields definitions */ +#define WEB_SERVER_VERSION "HTTP Version:" +#define WEB_SERVER_REQUEST_URI "Request URI:" +#define WEB_SERVER_QUERY_STRING "Query String:" +#define WEB_SERVER_HEADER_CONTENT_TYPE "Content-Type: " +#define WEB_SERVER_HEADER_CONTENT_LEN "Content-Length: " +#define WEB_SERVER_HEADER_LOCATION "Location: " +#define WEB_SERVER_HEADER_SERVER "Server: " +#define WEB_SERVER_HEADER_USER_AGENT "User-Agent: " +#define WEB_SERVER_HEADER_COOKIE "Cookie:" +#define WEB_SERVER_HEADER_SET_COOKIE "Set-Cookie: " +#define WEB_SERVER_HEADER_UPGRADE "Upgrade: " +#define WEB_SERVER_HEADER_REFERER "Referer: " +#define WEB_SERVER_HEADER_ACCEPT "Accept: " +#define WEB_SERVER_HEADER_CONTENT_ENCODING "Content-Encoding: " +#define WEB_SERVER_HEADER_CONTENT_DISPOSITION "Content-Disposition: " +#define WEB_SERVER_HEADER_CONNECTION "Connection: " +#define WEB_SERVER_HEADER_ETAG "Etag: " +#define WEB_SERVER_HEADER_DATE "Date: " +#define WEB_SERVER_HEADER_HOST "Host: " +#define WEB_SERVER_HEADER_ACCEPT_ENCODING "Accept-Encoding: " +#define WEB_SERVER_HEADER_ACCEPT_LANGUAGE "Accept-Language: " +#define WEB_SERVER_HEADER_CONTENT_LANGUAGE "Content-Language: " + +/* Content types list */ +#define TEXT_HTML "text/html" +#define TEXT_CSS "text/css" +#define TEXT_XML "text/xml" +#define APPLICATION_JSON "application/json" +#define IMAGE_PNG "image/png" +#define IMAGE_GIF "image/gif" +#define TEXT_PLAIN "text/plain" +#define TEXT_CSV "text/csv" +#define APPLICATION_JAVASCRIPT "application/javascript" +#define IMAGE_JPEG "image/jpeg" +#define APPLICATION_PDF "application/pdf" +#define APPLICATION_ZIP "application/zip" +#define SHOCKWAVE_FLASH "application/x-shockwave-flash" +#define AUDIO_X_AAC "audio/x-aac" +#define IMAGE_X_ICON "image/x-icon" +#define TEXT_VCARD "text/vcard" +#define APPLICATION_OCTEC_STREAM "application/octet-stream" +#define VIDEO_AVI "video/avi" +#define VIDEO_MPEG "video/mpeg" +#define VIDEO_MP4 "video/mp4" +#define FORM_URLENCODED "application/x-www-form-urlencoded" + +/* MIME types list */ +#define TEXT_HTML_MIME ".html" +#define TEXT_CSS_MIME ".css" +#define TEXT_XML_MIME ".xml" +#define APPLICATION_JSON_MIME ".json" +#define IMAGE_PNG_MIME ".png" +#define IMAGE_GIF_MIME ".gif" +#define TEXT_PLAIN_MIME ".txt" +#define TEXT_CSV_MIME ".csv" +#define APPLICATION_JAVASCRIPT_MIME ".js" +#define IMAGE_JPEG_MIME ".jpg" +#define APPLICATION_PDF_MIME ".pdf" +#define APPLICATION_ZIP_MIME ".zip" +#define SHOCKWAVE_FLASH_MIME ".swf" +#define AUDIO_X_AAC_MIME ".aac" +#define IMAGE_X_ICON_MIME ".ico" +#define TEXT_VCARD_MIME ".vcf" +#define APPLICATION_OCTEC_STREAM_MIME ".bin" +#define VIDEO_AVI_MIME ".avi" +#define VIDEO_MPEG_MIME ".mpeg" +#define VIDEO_MP4_MIME ".mp4" +/* dummy - no such extension */ + +#define URL_ENCODED_MIME ".form" +typedef enum +{ +/* Content types list */ + HttpContentTypeList_TextHtml, + HttpContentTypeList_TextCSS, + HttpContentTypeList_TextXML, + HttpContentTypeList_ApplicationJson, + HttpContentTypeList_ImagePNG, + HttpContentTypeList_ImageGIF, + HttpContentTypeList_TextPlain, + HttpContentTypeList_TextCSV, + HttpContentTypeList_ApplicationJavascript, + HttpContentTypeList_ImageJPEG, + HttpContentTypeList_ApplicationPDF, + HttpContentTypeList_ApplicationZIP, + HttpContentTypeList_ShokewaveFlash, + HttpContentTypeList_AudioXAAC, + HttpContentTypeList_ImageXIcon, + HttpContentTypeList_TextVcard, + HttpContentTypeList_ApplicationOctecStream, + HttpContentTypeList_VideoAVI, + HttpContentTypeList_VideoMPEG, + HttpContentTypeList_VideoMP4, + HttpContentTypeList_UrlEncoded, +}HttpContentTypeList; + +#define CONTENT_LEN_TYPE 0xFF + +/* offsets of TLV structure of parameters parsed in NetApp request */ +#define ARGV_TYPE_OFFSET 0 +#define ARGV_LEN_OFFSET 2 +#define ARGV_VALUE_OFFSET 3 + +typedef struct _http_headerFieldType_t_ +{ + SlNetAppMetadataHTTPTypes_e headerType; + char * headerText; +}http_headerFieldType_t; + +typedef struct _http_contentTypeMapping_t_ +{ + HttpContentTypeList contentType; + char *contentTypeText; + char *mimeExt; +}http_contentTypeMapping_t; + +typedef struct _http_charValuesPair_t_ +{ + char *characteristic; + char *value[5]; +}http_charValuesPair_t; + +typedef struct _http_RequestObj_t_ +{ + uint8_t requestIdx; + uint8_t httpMethod; + char *service; + http_charValuesPair_t charValues[10]; + int32_t (*serviceCallback)(uint8_t, + uint8_t *, + uint8_t **, + SlNetAppRequest_t *); +}http_RequestObj_t; + +typedef enum +{ + LedIdx_RedLed, + LedIdx_OrangeLed, + LedIdx_GreenLed, + LedIdx_MaxLed, +}LedIdx; + +typedef enum +{ + LedValues_Off, + LedValues_On, + LedValues_Toggle, + LedValues_MaxLed, +}LedValues; + +typedef enum +{ + SensorIdx_XAxis, + SensorIdx_YAxis, + SensorIdx_ZAxis, + SensorIdx_FarnTemp, + SensorIdx_MaxSensor, +}SensorIdx; + +typedef enum +{ + DeviceIdx_Ssid, + DeviceIdx_IpAddress, + DeviceIdx_MacAddress, + DeviceIdx_AppID, + DeviceIdx_MaxDevice, +}DeviceIdx; + +typedef enum +{ + OtaIdx_Version, + OtaIdx_MaxOTA, +}OtaIdx; + +typedef struct LinkLocal_ControlBlock_t +{ + sem_t otaReportServerStartSignal; + sem_t otaReportServerStopSignal; + mqd_t reportServerMQueue; +}LinkLocal_CB; + +/**************************************************************************** + GLOBAL VARIABLES +****************************************************************************/ +extern LinkLocal_CB LinkLocal_ControlBlock; + +//**************************************************************************** +// FUNCTION PROTOTYPES +//**************************************************************************** + +//***************************************************************************** +// +//! \brief This function fetches the device type and prints it +//! +//! \param[in] None +//! +//! \return device type +//! +//**************************************************************************** +uint32_t getDeviceType(); + +//***************************************************************************** +// +//! \brief This task handles LinkLocal transactions with the client +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void * linkLocalTask(void *pvParameters); + +#endif //_SIMPLELINK_CC32XX_LINKLOCAL_TASK_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_ProvisioningTask.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_ProvisioningTask.h new file mode 100644 index 00000000..3b13f6ee --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_ProvisioningTask.h @@ -0,0 +1,145 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _SIMPLELINK_CC32XX_PROVISIONING_TASK_H_ +#define _SIMPLELINK_CC32XX_PROVISIONING_TASK_H_ + +#include + +/* POSIX Header files */ +#include +#include +#include + +#include +// #include +// #include + +/*! + * \brief Provisioning events + */ +typedef enum +{ + PrvnEvent_Triggered, + PrvnEvent_Started, + PrvnEvent_StartFailed, + PrvnEvent_ConfirmationSuccess, + PrvnEvent_ConfirmationFailed, + PrvnEvent_Stopped, + PrvnEvent_WaitForConn, + PrvnEvent_Timeout, + PrvnEvent_Error, + PrvnEvent_Max, +}PrvnEvent; + +/*! + * \brief Provisioning states + */ +typedef enum +{ + PrvnState_Init, + PrvnState_Idle, + PrvnState_WaitForConfirmation, + PrvnState_Completed, + PrvnState_Error, + PrvnState_Max +}PrvnState; + +typedef struct Provisioning_ControlBlock_t +{ + sem_t connectionAsyncEvent; + sem_t provisioningDoneSignal; + sem_t provisioningConnDoneToOtaServerSignal; +}Provisioning_CB; + + +/**************************************************************************** + GLOBAL VARIABLES +****************************************************************************/ +extern Provisioning_CB Provisioning_ControlBlock; + +//**************************************************************************** +// FUNCTION PROTOTYPES +//**************************************************************************** + +//***************************************************************************** +// +//! \brief This function signals the application events +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +_i16 SignalProvisioningEvent(PrvnEvent event); + +//***************************************************************************** +// +//! \brief This function gets the current provisioning state +//! +//! \param[in] None +//! +//! \return provisioning state +//! +//**************************************************************************** +PrvnState GetProvisioningState(); + +//***************************************************************************** +// +//! \brief The interrupt handler for the LED timer +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void LedTimerIntHandler(sigval val); + +//***************************************************************************** +// +//! \brief This function starts the led toggling timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +int32_t StartLedEvtTimer(uint32_t timeout); + +//***************************************************************************** +// +//! \brief This function stops the led toggling timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +int32_t StopLedEvtTimer(void); + +//***************************************************************************** +// +//! \brief This function stops provisioning process +//! +//! \param[in] None +//! +//! \return SL_RET_CODE_PROVISIONING_IN_PROGRESS if provisioning was running, otherwise 0 +//! +//**************************************************************************** +int32_t provisioningStop(void); + +//***************************************************************************** +// +//! \brief This is the main provisioning task +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void * provisioningTask(void *pvParameters); + +#endif //_SIMPLELINK_CC32XX_PROVISIONING_TASK_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Sntp.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Sntp.h new file mode 100644 index 00000000..29ee5425 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Sntp.h @@ -0,0 +1,153 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_SNTP_H_ +#define _TARGET_SNTP_H_ 1 + +#include +#include +#include + +#include +#include + +// default SNTP server address +#ifndef SNTP_SERVER_DEFAULT_ADDRESS +#define SNTP_SERVER_DEFAULT_ADDRESS "0.pool.ntp.org" +#endif + +// Must wait at least 15 sec to retry NTP server (RFC 4330) +#ifndef SNTP_UPDATE_DELAY +#define SNTP_UPDATE_DELAY (15) +#endif + +// better have a startup delay because we can have DHCP enabled (default 30 seconds) +// value in seconds +#ifndef SNTP_STARTUP_DELAY +#define SNTP_STARTUP_DELAY (30) +#endif + +// retry timeout (15 minutes) +// value in seconds +#ifndef SNTP_RETRY_TIMEOUT +#define SNTP_RETRY_TIMEOUT (15 * 60) +#endif + +#define NTP_SERVERS 1 +#define NTP_SERVER_PORT 123 + +// Time to wait for reply from server (seconds) +#define NTP_REPLY_WAIT_TIME 5 + +#define TIME_BASEDIFF ((((uint32_t)70 * 365 + 17) * 24 * 3600)) +#define TIME_NTP_TO_LOCAL(t) ((t) - TIME_BASEDIFF) + +// SNTP Error Codes +// Failed to resolve Host address +#define SNTP_EGETHOSTBYNAMEFAIL (-100) + +// Input arguments are invalid +#define SNTP_EINVALIDARGS (-101) + +// Failed to create a socket +#define SNTP_ESOCKCREATEFAIL (-102) + +// The input socket address is not of AF_INET (IPv4) or AF_INET6 +// (IPv6) family type +#define SNTP_EINVALIDFAMILY (-103) + +// Failed to set receive timeout on socket +#define SNTP_ESOCKOPTFAIL (-104) + +// Failed to connect to the NTP server +#define SNTP_ECONNECTFAIL (-105) + +// Failed to send a time request to the NTP server +#define SNTP_ESENDFAIL (-106) + +// Failed to recieve the new time from the NTP server +#define SNTP_ERECVFAIL (-107) + +// NTP Server requests to reduce the update rate (RFC 5905 kiss code RATE) + +#define SNTP_ERATEBACKOFF (-108) + +// NTP Server invalid or server requests to end all communications (RFC +// 5905 kiss code DENY or RSTR) +#define SNTP_EFATALNORETRY (-109) + +// Server response with stratum == 0, with no kiss code +#define SNTP_EINVALIDRESP (-110) + +// KOD error code: rate exceeded, server requesting NTP client to back off +#define SNTP_KOD_RATE_STR "RATE" +#define SNTP_KOD_RATE_CODE 3 + +// KOD error code: access denied, server requests client to end all comm +#define SNTP_KOD_DENY_STR "DENY" +#define SNTP_KOD_DENY_CODE 2 + +// KOD error code: access denied, server requests client to end all comm +#define SNTP_KOD_RSTR_STR "RSTR" +#define SNTP_KOD_RSTR_CODE 1 + +// Size of KOD error codes +#define SNTP_KOD_ERROR_CODE_SIZE 4 + +// Use NTP version 4 +#define SNTP_VERSION 4 + +// Flag value for unsync'ed leap indicator field, signifying server error +#define SNTP_NOSYNC 3 + +// NTP mode defined in RFC 4330 +#define SNTP_MODE_CLIENT 3 + +// SNTP Header (as specified in RFC 4330) +typedef struct _SNTP_Header_t_ +{ + // + // 'flags' stores three values: + // + // - 2 bit Leap Indicator (LI) + // - 3 bit Version Number (VN) + // - 3 bit Mode. + + uint8_t flags; + uint8_t stratum; + uint8_t poll; + int8_t precision; + int32_t rootDelay; + uint32_t rootDispersion; + uint32_t referenceID; + + // NTP time stamps + uint32_t referenceTS[2]; + uint32_t originateTS[2]; + uint32_t receiveTS[2]; + uint32_t transmitTS[2]; +} SNTP_Header_t; + +struct sntp_server +{ + char* name; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void sntp_init(void); +void sntp_stop(void); +bool sntp_enabled(void); +char* sntp_getservername(int index); +void sntp_setservername(int index, char* server); + +#ifdef __cplusplus +} +#endif + +#endif //_TARGET_SNTP_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Threads.h b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Threads.h new file mode 100644 index 00000000..28f1f622 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/Include/targetSimpleLinkCC32xx_Threads.h @@ -0,0 +1,127 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _SIMPLELINK_CC32XX_THREADS_H_ +#define _SIMPLELINK_CC32XX_THREADS_H_ + +#include + +/* POSIX Header files */ +#include +#include +#include +#include + +#include +// #include +// #include + + +#define SL_STOP_TIMEOUT (200) +#define NF_TASK_PRIORITY (5) + + +#define ERR_PRINT(x) + +/* check the error code and handle it */ +#define ASSERT_ON_ERROR(error_code) \ + { \ + if(error_code < 0) \ + { \ + ERR_PRINT(error_code); \ + return error_code; \ + } \ + } + +#define SET_STATUS_BIT(status_variable, bit) status_variable |= (1 << (bit)) + +#define CLR_STATUS_BIT(status_variable, bit) status_variable &= ~(1 << (bit)) + +#define GET_STATUS_BIT(status_variable, bit) \ + (0 != (status_variable & (1 << (bit)))) + +#define APPS_WDT_START_KEY 0xAE42DB15 +#define HWREG(x) (*((volatile unsigned long *)(x))) + +#define IS_CONNECTED(status_variable) \ + GET_STATUS_BIT(status_variable, AppStatusBits_Connection) + +#define IS_IP_ACQUIRED(status_variable) \ + GET_STATUS_BIT(status_variable, AppStatusBits_IpAcquired) + +#define IS_IPV6L_ACQUIRED(status_variable) \ + GET_STATUS_BIT(status_variable, AppStatusBits_Ipv6lAcquired) + +#define IS_IPV6G_ACQUIRED(status_variable) \ + GET_STATUS_BIT(status_variable, AppStatusBits_Ipv6gAcquired) + +typedef struct +{ + _u8 Sd; + _u8 Type; +} nFSlSocketAsyncEvent_t; + +typedef enum +{ + /* If this bit is set: Network Processor is powered up */ + AppStatusBits_NwpInit = 0, + /* If this bit is set: the device is connected to + the AP or client is connected to device (AP) */ + AppStatusBits_Connection = 1, + /* If this bit is set: the device has leased IP to + any connected client */ + AppStatusBits_IpLeased = 2, + /* If this bit is set: the device has acquired an IP */ + AppStatusBits_IpAcquired = 3, + /* If this bit is set: the SmartConfiguration process is + started from SmartConfig app */ + AppStatusBits_SmartconfigStart = 4, + /* If this bit is set: the device (P2P mode) found any + p2p-device in scan */ + AppStatusBits_P2pDevFound = 5, + /* If this bit is set: the device (P2P mode) found any + p2p-negotiation request */ + AppStatusBits_P2pReqReceived = 6, + /* If this bit is set: the device(P2P mode) + connection to client(or reverse way) is failed */ + AppStatusBits_ConnectionFailed = 7, + /* If this bit is set: the device has completed the ping operation */ + AppStatusBits_PingDone = 8, + /* If this bit is set: the device has acquired an IPv6 address */ + AppStatusBits_Ipv6lAcquired = 9, + /* If this bit is set: the device has acquired an IPv6 address */ + AppStatusBits_Ipv6gAcquired = 10, + + AppStatusBits_AuthenticationFailed = 11, + AppStatusBits_ResetRequired = 12, +}AppStatusBits; + +// nF Control block for SimpleLink +typedef struct nanoFramework_ControlBlock_t +{ + // This bit-wise status variable shows the state of the NWP + uint32_t Status; + // This field keeps the device's role (STA, P2P or AP) + uint32_t Role; + + uint8_t configurationDone; + + mqd_t socketAsyncEvent; + + // uint32_t gatewayIP;/* Network Gateway IP address */ + + // uint8_t connectionSSID[SL_WLAN_SSID_MAX_LENGTH + 1];/* Connection SSID */ + + // uint8_t ssidLen;/* Connection SSID */ + + // uint8_t connectionBSSID[SL_WLAN_BSSID_LENGTH];/* Connection BSSID */ + +}nanoFramework_CB; + +extern nanoFramework_CB nF_ControlBlock; + + +#endif //_SIMPLELINK_CC32XX_THREADS_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/Board.h b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/Board.h new file mode 100644 index 00000000..0866af85 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/Board.h @@ -0,0 +1,81 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef __BOARD_H +#define __BOARD_H + +#define Board_CC3220SF_LAUNCHXL + +#ifdef __cplusplus +extern "C" { +#endif + +#include "CC3220SF_LAUNCHXL.h" + +#define Board_init CC3220SF_LAUNCHXL_initGeneral +#define Board_initGeneral CC3220SF_LAUNCHXL_initGeneral + +#define Board_ADC0 CC3220SF_LAUNCHXL_ADC0 +#define Board_ADC1 CC3220SF_LAUNCHXL_ADC1 + +#define Board_CAPTURE0 CC3220SF_LAUNCHXL_CAPTURE0 +#define Board_CAPTURE1 CC3220SF_LAUNCHXL_CAPTURE1 + +#define Board_CRYPTO0 CC3220SF_LAUNCHXL_CRYPTO0 + +#define Board_GPIO_LED_ON CC3220SF_LAUNCHXL_GPIO_LED_ON +#define Board_GPIO_LED_OFF CC3220SF_LAUNCHXL_GPIO_LED_OFF +#define Board_GPIO_LED0 CC3220SF_LAUNCHXL_GPIO_LED_D10 +/* + * CC3220SF_LAUNCHXL_GPIO_LED_D8 and CC3220SF_LAUNCHXL_GPIO_LED_D9 are shared with the I2C + * and PWM peripherals. In order for those examples to work, these LEDs are + * taken out of gpioPinCOnfig[] + */ +#define Board_GPIO_LED1 CC3220SF_LAUNCHXL_GPIO_LED_D10 +#define Board_GPIO_LED2 CC3220SF_LAUNCHXL_GPIO_LED_D10 + +#define Board_GPIO_BUTTON0 CC3220SF_LAUNCHXL_GPIO_SW2 +#define Board_GPIO_BUTTON1 CC3220SF_LAUNCHXL_GPIO_SW3 + +#define Board_GPIO_TMP116_EN CC3220SF_LAUNCHXL_GPIO_TMP116_EN + +#define Board_I2C0 CC3220SF_LAUNCHXL_I2C0 +#define Board_I2C_TMP CC3220SF_LAUNCHXL_I2C0 + +#define Board_I2S0 CC3220SF_LAUNCHXL_I2S0 + +#define Board_PWM0 CC3220SF_LAUNCHXL_PWM6 +#define Board_PWM1 CC3220SF_LAUNCHXL_PWM7 + +#define Board_SD0 CC3220SF_LAUNCHXL_SD0 + +#define Board_SDFatFS0 CC3220SF_LAUNCHXL_SD0 + +/* CC3220SF_LAUNCHXL_SPI0 is reserved for the NWP */ +#define Board_SPI0 CC3220SF_LAUNCHXL_SPI1 +#define Board_SPI_MASTER CC3220SF_LAUNCHXL_SPI1 +#define Board_SPI_SLAVE CC3220SF_LAUNCHXL_SPI1 +#define Board_SPI_MASTER_READY CC3220SF_LAUNCHXL_SPI_MASTER_READY +#define Board_SPI_SLAVE_READY CC3220SF_LAUNCHXL_SPI_SLAVE_READY + +#define Board_TIMER0 CC3220SF_LAUNCHXL_TIMER0 +#define Board_TIMER1 CC3220SF_LAUNCHXL_TIMER1 +#define Board_TIMER2 CC3220SF_LAUNCHXL_TIMER2 + +#define Board_UART0 CC3220SF_LAUNCHXL_UART0 +#define Board_UART1 CC3220SF_LAUNCHXL_UART1 + +#define Board_WATCHDOG0 CC3220SF_LAUNCHXL_WATCHDOG0 + +/* Board specific I2C address */ +#define Board_TMP006_ADDR (0x41) +#define Board_I2C_TMP006_ADDR Board_TMP006_ADDR + +#ifdef __cplusplus +} +#endif + +#endif /* __BOARD_H */ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.c b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.c new file mode 100644 index 00000000..8c9e9c29 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.c @@ -0,0 +1,831 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// This file is responsible for setting up the board specific items for the +// CC3220SF_LAUNCHXL board + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "CC3220SF_LAUNCHXL.h" + +/* + * This define determines whether to use the UARTCC32XXDMA driver + * or the UARTCC32XX (no DMA) driver. Set to 1 to use the UARTCC32XXDMA + * driver. + */ +#ifndef TI_DRIVERS_UART_DMA +#define TI_DRIVERS_UART_DMA 0 +#endif + +/* + * =============================== ADC =============================== + */ +#include +#include + +ADCCC32XX_Object adcCC3220SObjects[CC3220SF_LAUNCHXL_ADCCOUNT]; + +const ADCCC32XX_HWAttrsV1 adcCC3220SHWAttrs[CC3220SF_LAUNCHXL_ADCCOUNT] = { + { + .adcPin = ADCCC32XX_PIN_59_CH_2 + }, + { + .adcPin = ADCCC32XX_PIN_60_CH_3 + } +}; + +const ADC_Config ADC_config[CC3220SF_LAUNCHXL_ADCCOUNT] = { + { + .fxnTablePtr = &ADCCC32XX_fxnTable, + .object = &adcCC3220SObjects[CC3220SF_LAUNCHXL_ADC0], + .hwAttrs = &adcCC3220SHWAttrs[CC3220SF_LAUNCHXL_ADC0] + }, + { + .fxnTablePtr = &ADCCC32XX_fxnTable, + .object = &adcCC3220SObjects[CC3220SF_LAUNCHXL_ADC1], + .hwAttrs = &adcCC3220SHWAttrs[CC3220SF_LAUNCHXL_ADC1] + } +}; + +const uint_least8_t ADC_count = CC3220SF_LAUNCHXL_ADCCOUNT; + +/* + * =============================== Capture =============================== + */ +#include +#include + +CaptureCC32XX_Object captureCC3220SFObjects[CC3220SF_LAUNCHXL_CAPTURECOUNT]; + +const CaptureCC32XX_HWAttrs captureCC3220SFHWAttrs[CC3220SF_LAUNCHXL_CAPTURECOUNT] = +{ + { + .capturePin = CaptureCC32XX_PIN_04, + .intPriority = ~0 + }, + { + .capturePin = CaptureCC32XX_PIN_05, + .intPriority = ~0 + }, +}; + +const Capture_Config Capture_config[CC3220SF_LAUNCHXL_CAPTURECOUNT] = { + { + .fxnTablePtr = &CaptureCC32XX_fxnTable, + .object = &captureCC3220SFObjects[CC3220SF_LAUNCHXL_CAPTURE0], + .hwAttrs = &captureCC3220SFHWAttrs[CC3220SF_LAUNCHXL_CAPTURE0] + }, + { + .fxnTablePtr = &CaptureCC32XX_fxnTable, + .object = &captureCC3220SFObjects[CC3220SF_LAUNCHXL_CAPTURE1], + .hwAttrs = &captureCC3220SFHWAttrs[CC3220SF_LAUNCHXL_CAPTURE1] + } +}; + +const uint_least8_t Capture_count = CC3220SF_LAUNCHXL_CAPTURECOUNT; + +/* + * =============================== Crypto =============================== + */ +#include + +CryptoCC32XX_Object cryptoCC3220SObjects[CC3220SF_LAUNCHXL_CRYPTOCOUNT]; + +const CryptoCC32XX_Config CryptoCC32XX_config[CC3220SF_LAUNCHXL_CRYPTOCOUNT] = { + { + .object = &cryptoCC3220SObjects[CC3220SF_LAUNCHXL_CRYPTO0] + } +}; + +const uint_least8_t CryptoCC32XX_count = CC3220SF_LAUNCHXL_CRYPTOCOUNT; + +/* + * =============================== DMA =============================== + */ +#include + +static tDMAControlTable dmaControlTable[64] __attribute__ ((aligned (1024))); + +/* + * ======== dmaErrorFxn ======== + * This is the handler for the uDMA error interrupt. + */ +static void dmaErrorFxn(uintptr_t arg) +{ + int status = MAP_uDMAErrorStatusGet(); + MAP_uDMAErrorStatusClear(); + + /* Suppress unused variable warning */ + (void)status; + + while (1); +} + +UDMACC32XX_Object udmaCC3220SObject; + +const UDMACC32XX_HWAttrs udmaCC3220SHWAttrs = { + .controlBaseAddr = (void *)dmaControlTable, + .dmaErrorFxn = (UDMACC32XX_ErrorFxn)dmaErrorFxn, + .intNum = INT_UDMAERR, + .intPriority = (~0) +}; + +const UDMACC32XX_Config UDMACC32XX_config = { + .object = &udmaCC3220SObject, + .hwAttrs = &udmaCC3220SHWAttrs +}; + +/* + * =============================== General =============================== + */ +/* + * ======== CC3220SF_LAUNCHXL_initGeneral ======== + */ +void CC3220SF_LAUNCHXL_initGeneral(void) +{ + PRCMCC3200MCUInit(); + Power_init(); + + // enable clock on the DTHE + MAP_PRCMPeripheralClkEnable(PRCM_DTHE, PRCM_RUN_MODE_CLK); + + // init CRC engine + MAP_CRCConfigSet(DTHE_BASE, (CRC_CFG_INIT_SEED | CRC_CFG_SIZE_8BIT | CRC_CFG_TYPE_P4C11DB7) ); + + // Mux Pin62 to mode 1 for outputing NWP logs + //MAP_PinTypeUART(PIN_62, PIN_MODE_1); +} + +/* + * =============================== GPIO =============================== + */ +#include +#include + +/* + * Array of Pin configurations + * NOTE: The order of the pin configurations must coincide with what was + * defined in CC3220SF_LAUNCHXL.h + * NOTE: Pins not used for interrupts should be placed at the end of the + * array. Callback entries can be omitted from callbacks array to + * reduce memory usage. + */ +GPIO_PinConfig gpioPinConfigs[] = { + /* input pins with callbacks */ + /* CC3220SF_LAUNCHXL_GPIO_SW2 */ + GPIOCC32XX_GPIO_13 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING, + /* CC3220SF_LAUNCHXL_GPIO_SW3 */ + GPIOCC32XX_GPIO_22 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING, + + /* CC3220SF_LAUNCHXL_SPI_MASTER_READY */ + GPIOCC32XX_GPIO_28 | GPIO_DO_NOT_CONFIG, + /* CC3220SF_LAUNCHXL_SPI_SLAVE_READY */ + GPIOCC32XX_GPIO_12 | GPIO_DO_NOT_CONFIG, + + /* output pins */ + /* CC3220SF_LAUNCHXL_GPIO_LED_D10 */ + GPIOCC32XX_GPIO_09 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW, + + /* + * CC3220SF_LAUNCHXL_GPIO_LED_D8 and CC3220SF_LAUNCHXL_GPIO_LED_D9 are shared with the + * I2C and PWM peripherals. In order for those examples to work, these + * LEDs are taken out of gpioPinConfig[] + */ + /* CC3220SF_LAUNCHXL_GPIO_LED_D9 */ + GPIOCC32XX_GPIO_10 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW, + /* CC3220SF_LAUNCHXL_GPIO_LED_D8 */ + GPIOCC32XX_GPIO_11 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW, + + GPIOCC32XX_GPIO_30 | GPIO_DO_NOT_CONFIG, /* TMP116 EN */ + + /* Sharp Display - GPIO configurations will be done in the Display files */ + GPIOCC32XX_GPIO_12 | GPIO_DO_NOT_CONFIG, /* SPI chip select */ + GPIOCC32XX_GPIO_06 | GPIO_DO_NOT_CONFIG, /* LCD power control */ + GPIOCC32XX_GPIO_03 | GPIO_DO_NOT_CONFIG, /*LCD enable */ +}; + +/* + * Array of callback function pointers + * NOTE: The order of the pin configurations must coincide with what was + * defined in CC3220SF_LAUNCHXL.h + * NOTE: Pins not used for interrupts can be omitted from callbacks array to + * reduce memory usage (if placed at end of gpioPinConfigs array). + */ +GPIO_CallbackFxn gpioCallbackFunctions[] = { + NULL, /* CC3220SF_LAUNCHXL_GPIO_SW2 */ + NULL, /* CC3220SF_LAUNCHXL_GPIO_SW3 */ + NULL, /* CC3220SF_LAUNCHXL_SPI_MASTER_READY */ + NULL /* CC3220SF_LAUNCHXL_SPI_SLAVE_READY */ +}; + +/* The device-specific GPIO_config structure */ +const GPIOCC32XX_Config GPIOCC32XX_config = { + .pinConfigs = (GPIO_PinConfig *)gpioPinConfigs, + .callbacks = (GPIO_CallbackFxn *)gpioCallbackFunctions, + .numberOfPinConfigs = sizeof(gpioPinConfigs)/sizeof(GPIO_PinConfig), + .numberOfCallbacks = sizeof(gpioCallbackFunctions)/sizeof(GPIO_CallbackFxn), + .intPriority = (~0) +}; + +/* + * ============================= Display ============================= + */ +#include +#include +#include +#define MAXPRINTLEN 1024 + +/* This value can be changed to 96 for use with the 430BOOST-SHARP96 BoosterPack. */ +#define BOARD_DISPLAY_SHARP_SIZE 128 + +DisplayUart_Object displayUartObject; +DisplaySharp_Object displaySharpObject; + +static char displayBuf[MAXPRINTLEN]; +static uint_least8_t sharpDisplayBuf[BOARD_DISPLAY_SHARP_SIZE * BOARD_DISPLAY_SHARP_SIZE / 8]; + +const DisplayUart_HWAttrs displayUartHWAttrs = { + .uartIdx = 0, + .baudRate = 921600, + .mutexTimeout = (unsigned int)(-1), + .strBuf = displayBuf, + .strBufLen = MAXPRINTLEN +}; + +const DisplaySharp_HWAttrsV1 displaySharpHWattrs = { + .spiIndex = CC3220SF_LAUNCHXL_SPI1, + .csPin = CC3220SF_LAUNCHXL_LCD_CS, + .powerPin = CC3220SF_LAUNCHXL_LCD_POWER, + .enablePin = CC3220SF_LAUNCHXL_LCD_ENABLE, + .pixelWidth = BOARD_DISPLAY_SHARP_SIZE, + .pixelHeight = BOARD_DISPLAY_SHARP_SIZE, + .displayBuf = sharpDisplayBuf, +}; + +#ifndef BOARD_DISPLAY_USE_UART +#define BOARD_DISPLAY_USE_UART 1 +#endif +#ifndef BOARD_DISPLAY_USE_UART_ANSI +#define BOARD_DISPLAY_USE_UART_ANSI 0 +#endif +#ifndef BOARD_DISPLAY_USE_LCD +#define BOARD_DISPLAY_USE_LCD 0 +#endif + +const Display_Config Display_config[] = { + { +# if (BOARD_DISPLAY_USE_UART_ANSI) + .fxnTablePtr = &DisplayUartAnsi_fxnTable, +# else /* Default to minimal UART with no cursor placement */ + .fxnTablePtr = &DisplayUartMin_fxnTable, +# endif + .object = &displayUartObject, + .hwAttrs = &displayUartHWAttrs + }, +#if (BOARD_DISPLAY_USE_LCD) + { + .fxnTablePtr = &DisplaySharp_fxnTable, + .object = &displaySharpObject, + .hwAttrs = &displaySharpHWattrs + }, +#endif +}; + +const uint_least8_t Display_count = sizeof(Display_config) / sizeof(Display_Config); + + + +/* + * =============================== I2C =============================== + */ +#include +#include + +I2CCC32XX_Object i2cCC3220SObjects[CC3220SF_LAUNCHXL_I2CCOUNT]; + +const I2CCC32XX_HWAttrsV1 i2cCC3220SHWAttrs[CC3220SF_LAUNCHXL_I2CCOUNT] = { + { + .baseAddr = I2CA0_BASE, + .intNum = INT_I2CA0, + .intPriority = (~0), + .clkPin = I2CCC32XX_PIN_01_I2C_SCL, + .dataPin = I2CCC32XX_PIN_02_I2C_SDA + } +}; + +const I2C_Config I2C_config[CC3220SF_LAUNCHXL_I2CCOUNT] = { + { + .fxnTablePtr = &I2CCC32XX_fxnTable, + .object = &i2cCC3220SObjects[CC3220SF_LAUNCHXL_I2C0], + .hwAttrs = &i2cCC3220SHWAttrs[CC3220SF_LAUNCHXL_I2C0] + } +}; + +const uint_least8_t I2C_count = CC3220SF_LAUNCHXL_I2CCOUNT; + +/* + * =============================== I2S =============================== + */ +#include +#include + +I2SCC32XX_Object i2sCC3220SObjects[CC3220S_LAUNCHXL_I2SCOUNT]; + +const I2SCC32XX_HWAttrs i2sCC3220SHWAttrs[CC3220S_LAUNCHXL_I2SCOUNT] = { + { + .pinSD1 = I2SCC32XX_PIN_50_SD1, + .pinSD0 = I2SCC32XX_PIN_64_SD0, + .pinSCK = I2SCC32XX_PIN_53_SCK, + .pinSCKX = I2SCC32XX_PIN_UNUSED, + .pinWS = I2SCC32XX_PIN_63_WS, + .rxChannelIndex = UDMA_CH4_I2S_RX, + .txChannelIndex = UDMA_CH5_I2S_TX, + .intPriority = 0x40, + } +}; + +const I2S_Config I2S_config[CC3220S_LAUNCHXL_I2SCOUNT] = { + { + .object = &i2sCC3220SObjects[CC3220S_LAUNCHXL_I2S0], + .hwAttrs = &i2sCC3220SHWAttrs[CC3220S_LAUNCHXL_I2S0] + } +}; + +const uint_least8_t I2S_count = CC3220S_LAUNCHXL_I2SCOUNT; + +/* + * =============================== Power =============================== + */ +/* + * This table defines the parking state to be set for each parkable pin + * during LPDS. (Device pins must be parked during LPDS to achieve maximum + * power savings.) If the pin should be left unparked, specify the state + * PowerCC32XX_DONT_PARK. For example, for a UART TX pin, the device + * will automatically park the pin in a high state during transition to LPDS, + * so the Power Manager does not need to explictly park the pin. So the + * corresponding entries in this table should indicate PowerCC32XX_DONT_PARK. + */ +PowerCC32XX_ParkInfo parkInfo[] = { +/* PIN PARK STATE PIN ALIAS (FUNCTION) + ----------------- ------------------------------ -------------------- */ + {PowerCC32XX_PIN01, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO10 */ + {PowerCC32XX_PIN02, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO11 */ + {PowerCC32XX_PIN03, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO12 */ + {PowerCC32XX_PIN04, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO13 */ + {PowerCC32XX_PIN05, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO14 */ + {PowerCC32XX_PIN06, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO15 */ + {PowerCC32XX_PIN07, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO16 */ + {PowerCC32XX_PIN08, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO17 */ + {PowerCC32XX_PIN13, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* FLASH_SPI_DIN */ + {PowerCC32XX_PIN15, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO22 */ + {PowerCC32XX_PIN16, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* TDI (JTAG DEBUG) */ + {PowerCC32XX_PIN17, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* TDO (JTAG DEBUG) */ + {PowerCC32XX_PIN19, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* TCK (JTAG DEBUG) */ + {PowerCC32XX_PIN20, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* TMS (JTAG DEBUG) */ + {PowerCC32XX_PIN18, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO28 */ + {PowerCC32XX_PIN21, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* SOP2 */ + {PowerCC32XX_PIN29, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* ANTSEL1 */ + {PowerCC32XX_PIN30, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* ANTSEL2 */ + {PowerCC32XX_PIN45, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* DCDC_ANA2_SW_P */ + {PowerCC32XX_PIN50, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO0 */ + {PowerCC32XX_PIN52, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* RTC_XTAL_N */ + {PowerCC32XX_PIN53, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO30 */ + {PowerCC32XX_PIN55, PowerCC32XX_WEAK_PULL_UP_STD}, /* GPIO1 (XDS_UART_RX) */ + {PowerCC32XX_PIN57, PowerCC32XX_WEAK_PULL_UP_STD}, /* GPIO2 (XDS_UART_TX) */ + {PowerCC32XX_PIN58, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO3 */ + {PowerCC32XX_PIN59, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO4 */ + {PowerCC32XX_PIN60, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO5 */ + {PowerCC32XX_PIN61, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO6 */ + {PowerCC32XX_PIN62, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO7 */ + {PowerCC32XX_PIN63, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO8 */ + {PowerCC32XX_PIN64, PowerCC32XX_WEAK_PULL_DOWN_STD}, /* GPIO9 */ +}; + +/* + * This structure defines the configuration for the Power Manager. + * + * In this configuration the Power policy is disabled by default (because + * enablePolicy is set to false). The Power policy can be enabled dynamically + * at runtime by calling Power_enablePolicy(), or at build time, by changing + * enablePolicy to true in this structure. + */ +const PowerCC32XX_ConfigV1 PowerCC32XX_config = { + .policyInitFxn = &PowerCC32XX_initPolicy, + .policyFxn = &PowerCC32XX_sleepPolicy, + .enterLPDSHookFxn = NULL, + .resumeLPDSHookFxn = NULL, + .enablePolicy = false, + .enableGPIOWakeupLPDS = true, + .enableGPIOWakeupShutdown = true, + .enableNetworkWakeupLPDS = true, + .wakeupGPIOSourceLPDS = PRCM_LPDS_GPIO13, + .wakeupGPIOTypeLPDS = PRCM_LPDS_FALL_EDGE, + .wakeupGPIOFxnLPDS = NULL, + .wakeupGPIOFxnLPDSArg = 0, + .wakeupGPIOSourceShutdown = PRCM_HIB_GPIO13, + .wakeupGPIOTypeShutdown = PRCM_HIB_RISE_EDGE, + .ramRetentionMaskLPDS = PRCM_SRAM_COL_1 | PRCM_SRAM_COL_2 | + PRCM_SRAM_COL_3 | PRCM_SRAM_COL_4, + .keepDebugActiveDuringLPDS = false, + .ioRetentionShutdown = PRCM_IO_RET_GRP_1, + .pinParkDefs = parkInfo, + .numPins = sizeof(parkInfo) / sizeof(PowerCC32XX_ParkInfo) +}; + +/* + * =============================== PWM =============================== + */ +#include +#include + +PWMTimerCC32XX_Object pwmTimerCC3220SObjects[CC3220SF_LAUNCHXL_PWMCOUNT]; + +const PWMTimerCC32XX_HWAttrsV2 pwmTimerCC3220SHWAttrs[CC3220SF_LAUNCHXL_PWMCOUNT] = { + { /* CC3220SF_LAUNCHXL_PWM6 */ + .pwmPin = PWMTimerCC32XX_PIN_01 + }, + { /* CC3220SF_LAUNCHXL_PWM7 */ + .pwmPin = PWMTimerCC32XX_PIN_02 + } +}; + +const PWM_Config PWM_config[CC3220SF_LAUNCHXL_PWMCOUNT] = { + { + .fxnTablePtr = &PWMTimerCC32XX_fxnTable, + .object = &pwmTimerCC3220SObjects[CC3220SF_LAUNCHXL_PWM6], + .hwAttrs = &pwmTimerCC3220SHWAttrs[CC3220SF_LAUNCHXL_PWM6] + }, + { + .fxnTablePtr = &PWMTimerCC32XX_fxnTable, + .object = &pwmTimerCC3220SObjects[CC3220SF_LAUNCHXL_PWM7], + .hwAttrs = &pwmTimerCC3220SHWAttrs[CC3220SF_LAUNCHXL_PWM7] + } +}; + +const uint_least8_t PWM_count = CC3220SF_LAUNCHXL_PWMCOUNT; + +/* + * =============================== SDFatFS =============================== + */ +#include +#include + +/* + * Note: The SDFatFS driver provides interface functions to enable FatFs + * but relies on the SD driver to communicate with SD cards. Opening a + * SDFatFs driver instance will internally try to open a SD driver instance + * reusing the same index number (opening SDFatFs driver at index 0 will try to + * open SD driver at index 0). This requires that all SDFatFs driver instances + * have an accompanying SD driver instance defined with the same index. It is + * acceptable to have more SD driver instances than SDFatFs driver instances + * but the opposite is not supported & the SDFatFs will fail to open. + */ +SDFatFS_Object sdfatfsObjects[CC3220SF_LAUNCHXL_SDFatFSCOUNT]; + +const SDFatFS_Config SDFatFS_config[CC3220SF_LAUNCHXL_SDFatFSCOUNT] = { + { + .object = &sdfatfsObjects[CC3220SF_LAUNCHXL_SDFatFS0] + } +}; + +const uint_least8_t SDFatFS_count = CC3220SF_LAUNCHXL_SDFatFSCOUNT; + +/* + * =============================== SD =============================== + */ +#include +#include + +SDHostCC32XX_Object sdhostCC3220SObjects[CC3220SF_LAUNCHXL_SDCOUNT]; + +/* SDHost configuration structure, describing which pins are to be used */ +const SDHostCC32XX_HWAttrsV1 sdhostCC3220SHWattrs[CC3220SF_LAUNCHXL_SDCOUNT] = { + { + .clkRate = 8000000, + .intPriority = ~0, + .baseAddr = SDHOST_BASE, + .rxChIdx = UDMA_CH23_SDHOST_RX, + .txChIdx = UDMA_CH24_SDHOST_TX, + .dataPin = SDHostCC32XX_PIN_06_SDCARD_DATA, + .cmdPin = SDHostCC32XX_PIN_08_SDCARD_CMD, + .clkPin = SDHostCC32XX_PIN_07_SDCARD_CLK + } +}; + +const SD_Config SD_config[CC3220SF_LAUNCHXL_SDCOUNT] = { + { + .fxnTablePtr = &sdHostCC32XX_fxnTable, + .object = &sdhostCC3220SObjects[CC3220SF_LAUNCHXL_SD0], + .hwAttrs = &sdhostCC3220SHWattrs[CC3220SF_LAUNCHXL_SD0] + }, +}; + +const uint_least8_t SD_count = CC3220SF_LAUNCHXL_SDCOUNT; + +/* + * =============================== SPI =============================== + */ +#include +#include + +SPICC32XXDMA_Object spiCC3220SDMAObjects[CC3220SF_LAUNCHXL_SPICOUNT]; + +uint32_t spiCC3220SDMAscratchBuf[CC3220SF_LAUNCHXL_SPICOUNT]; + +const SPICC32XXDMA_HWAttrsV1 spiCC3220SDMAHWAttrs[CC3220SF_LAUNCHXL_SPICOUNT] = { + /* index 0 is reserved for LSPI that links to the NWP */ + { + .baseAddr = LSPI_BASE, + .intNum = INT_LSPI, + .intPriority = (~0), + .spiPRCM = PRCM_LSPI, + .csControl = SPI_SW_CTRL_CS, + .csPolarity = SPI_CS_ACTIVEHIGH, + .pinMode = SPI_4PIN_MODE, + .turboMode = SPI_TURBO_OFF, + .scratchBufPtr = &spiCC3220SDMAscratchBuf[CC3220SF_LAUNCHXL_SPI0], + .defaultTxBufValue = 0, + .rxChannelIndex = UDMA_CH12_LSPI_RX, + .txChannelIndex = UDMA_CH13_LSPI_TX, + .minDmaTransferSize = 100, + .mosiPin = SPICC32XXDMA_PIN_NO_CONFIG, + .misoPin = SPICC32XXDMA_PIN_NO_CONFIG, + .clkPin = SPICC32XXDMA_PIN_NO_CONFIG, + .csPin = SPICC32XXDMA_PIN_NO_CONFIG + }, + { + .baseAddr = GSPI_BASE, + .intNum = INT_GSPI, + .intPriority = (~0), + .spiPRCM = PRCM_GSPI, + .csControl = SPI_HW_CTRL_CS, + .csPolarity = SPI_CS_ACTIVELOW, + .pinMode = SPI_4PIN_MODE, + .turboMode = SPI_TURBO_OFF, + .scratchBufPtr = &spiCC3220SDMAscratchBuf[CC3220SF_LAUNCHXL_SPI1], + .defaultTxBufValue = 0, + .rxChannelIndex = UDMA_CH6_GSPI_RX, + .txChannelIndex = UDMA_CH7_GSPI_TX, + .minDmaTransferSize = 10, + .mosiPin = SPICC32XXDMA_PIN_07_MOSI, + .misoPin = SPICC32XXDMA_PIN_06_MISO, + .clkPin = SPICC32XXDMA_PIN_05_CLK, + .csPin = SPICC32XXDMA_PIN_08_CS + } +}; + +const SPI_Config SPI_config[CC3220SF_LAUNCHXL_SPICOUNT] = { + { + .fxnTablePtr = &SPICC32XXDMA_fxnTable, + .object = &spiCC3220SDMAObjects[CC3220SF_LAUNCHXL_SPI0], + .hwAttrs = &spiCC3220SDMAHWAttrs[CC3220SF_LAUNCHXL_SPI0] + }, + { + .fxnTablePtr = &SPICC32XXDMA_fxnTable, + .object = &spiCC3220SDMAObjects[CC3220SF_LAUNCHXL_SPI1], + .hwAttrs = &spiCC3220SDMAHWAttrs[CC3220SF_LAUNCHXL_SPI1] + } +}; + +const uint_least8_t SPI_count = CC3220SF_LAUNCHXL_SPICOUNT; + +/* + * =============================== Timer =============================== + */ +#include +#include + +TimerCC32XX_Object timerCC3220SFObjects[CC3220SF_LAUNCHXL_TIMERCOUNT]; + +const TimerCC32XX_HWAttrs timerCC3220SFHWAttrs[CC3220SF_LAUNCHXL_TIMERCOUNT] = { + { + .baseAddress = TIMERA0_BASE, + .subTimer = TimerCC32XX_timer32, + .intNum = INT_TIMERA0A, + .intPriority = ~0 + }, + { + .baseAddress = TIMERA1_BASE, + .subTimer = TimerCC32XX_timer16A, + .intNum = INT_TIMERA1A, + .intPriority = ~0 + }, + { + .baseAddress = TIMERA1_BASE, + .subTimer = TimerCC32XX_timer16B, + .intNum = INT_TIMERA1B, + .intPriority = ~0 + }, +}; + +const Timer_Config Timer_config[CC3220SF_LAUNCHXL_TIMERCOUNT] = { + { + .fxnTablePtr = &TimerCC32XX_fxnTable, + .object = &timerCC3220SFObjects[CC3220SF_LAUNCHXL_TIMER0], + .hwAttrs = &timerCC3220SFHWAttrs[CC3220SF_LAUNCHXL_TIMER0] + }, + { + .fxnTablePtr = &TimerCC32XX_fxnTable, + .object = &timerCC3220SFObjects[CC3220SF_LAUNCHXL_TIMER1], + .hwAttrs = &timerCC3220SFHWAttrs[CC3220SF_LAUNCHXL_TIMER1] + }, + { + .fxnTablePtr = &TimerCC32XX_fxnTable, + .object = &timerCC3220SFObjects[CC3220SF_LAUNCHXL_TIMER2], + .hwAttrs = &timerCC3220SFHWAttrs[CC3220SF_LAUNCHXL_TIMER2] + }, +}; + +const uint_least8_t Timer_count = CC3220SF_LAUNCHXL_TIMERCOUNT; + +/* + * =============================== UART =============================== + */ +#include +#if TI_DRIVERS_UART_DMA +#include + +UARTCC32XXDMA_Object uartCC3220SDmaObjects[CC3220SF_LAUNCHXL_UARTCOUNT]; + +/* UART configuration structure */ +const UARTCC32XXDMA_HWAttrsV1 uartCC3220SDmaHWAttrs[CC3220SF_LAUNCHXL_UARTCOUNT] = { + { + .baseAddr = UARTA0_BASE, + .intNum = INT_UARTA0, + .intPriority = (~0), + .flowControl = UARTCC32XXDMA_FLOWCTRL_NONE, + .rxChannelIndex = UDMA_CH8_UARTA0_RX, + .txChannelIndex = UDMA_CH9_UARTA0_TX, + .rxPin = UARTCC32XXDMA_PIN_57_UART0_RX, + .txPin = UARTCC32XXDMA_PIN_55_UART0_TX, + .ctsPin = UARTCC32XXDMA_PIN_UNASSIGNED, + .rtsPin = UARTCC32XXDMA_PIN_UNASSIGNED, + .errorFxn = NULL + }, + { + .baseAddr = UARTA1_BASE, + .intNum = INT_UARTA1, + .intPriority = (~0), + .flowControl = UARTCC32XXDMA_FLOWCTRL_NONE, + .rxChannelIndex = UDMA_CH10_UARTA1_RX, + .txChannelIndex = UDMA_CH11_UARTA1_TX, + .rxPin = UARTCC32XXDMA_PIN_08_UART1_RX, + .txPin = UARTCC32XXDMA_PIN_07_UART1_TX, + .ctsPin = UARTCC32XXDMA_PIN_UNASSIGNED, + .rtsPin = UARTCC32XXDMA_PIN_UNASSIGNED, + .errorFxn = NULL + } +}; + +const UART_Config UART_config[CC3220SF_LAUNCHXL_UARTCOUNT] = { + { + .fxnTablePtr = &UARTCC32XXDMA_fxnTable, + .object = &uartCC3220SDmaObjects[CC3220SF_LAUNCHXL_UART0], + .hwAttrs = &uartCC3220SDmaHWAttrs[CC3220SF_LAUNCHXL_UART0] + }, + { + .fxnTablePtr = &UARTCC32XXDMA_fxnTable, + .object = &uartCC3220SDmaObjects[CC3220SF_LAUNCHXL_UART1], + .hwAttrs = &uartCC3220SDmaHWAttrs[CC3220SF_LAUNCHXL_UART1] + } +}; + +#else +#include + +UARTCC32XX_Object uartCC3220SObjects[CC3220SF_LAUNCHXL_UARTCOUNT]; +unsigned char uartCC3220SRingBuffer[CC3220SF_LAUNCHXL_UARTCOUNT][32]; + +/* UART configuration structure */ +const UARTCC32XX_HWAttrsV1 uartCC3220SHWAttrs[CC3220SF_LAUNCHXL_UARTCOUNT] = { + { + .baseAddr = UARTA0_BASE, + .intNum = INT_UARTA0, + .intPriority = (~0), + .flowControl = UARTCC32XX_FLOWCTRL_NONE, + .ringBufPtr = uartCC3220SRingBuffer[CC3220SF_LAUNCHXL_UART0], + .ringBufSize = sizeof(uartCC3220SRingBuffer[CC3220SF_LAUNCHXL_UART0]), + .rxPin = UARTCC32XX_PIN_57_UART0_RX, + .txPin = UARTCC32XX_PIN_55_UART0_TX, + .ctsPin = UARTCC32XX_PIN_UNASSIGNED, + .rtsPin = UARTCC32XX_PIN_UNASSIGNED, + .errorFxn = NULL + }, + { + .baseAddr = UARTA1_BASE, + .intNum = INT_UARTA1, + .intPriority = (~0), + .flowControl = UARTCC32XX_FLOWCTRL_NONE, + .ringBufPtr = uartCC3220SRingBuffer[CC3220SF_LAUNCHXL_UART1], + .ringBufSize = sizeof(uartCC3220SRingBuffer[CC3220SF_LAUNCHXL_UART1]), + .rxPin = UARTCC32XX_PIN_08_UART1_RX, + .txPin = UARTCC32XX_PIN_07_UART1_TX, + .ctsPin = UARTCC32XX_PIN_UNASSIGNED, + .rtsPin = UARTCC32XX_PIN_UNASSIGNED, + .errorFxn = NULL + } +}; + +const UART_Config UART_config[CC3220SF_LAUNCHXL_UARTCOUNT] = { + { + .fxnTablePtr = &UARTCC32XX_fxnTable, + .object = &uartCC3220SObjects[CC3220SF_LAUNCHXL_UART0], + .hwAttrs = &uartCC3220SHWAttrs[CC3220SF_LAUNCHXL_UART0] + }, + { + .fxnTablePtr = &UARTCC32XX_fxnTable, + .object = &uartCC3220SObjects[CC3220SF_LAUNCHXL_UART1], + .hwAttrs = &uartCC3220SHWAttrs[CC3220SF_LAUNCHXL_UART1] + } +}; +#endif /* TI_DRIVERS_UART_DMA */ + +const uint_least8_t UART_count = CC3220SF_LAUNCHXL_UARTCOUNT; + +/* + * =============================== Watchdog =============================== + */ +#include +#include + +WatchdogCC32XX_Object watchdogCC3220SObjects[CC3220SF_LAUNCHXL_WATCHDOGCOUNT]; + +const WatchdogCC32XX_HWAttrs watchdogCC3220SHWAttrs[CC3220SF_LAUNCHXL_WATCHDOGCOUNT] = { + { + .baseAddr = WDT_BASE, + .intNum = INT_WDT, + .intPriority = (~0), + .reloadValue = 80000000 /* 1 second period at default CPU clock freq */ + } +}; + +const Watchdog_Config Watchdog_config[CC3220SF_LAUNCHXL_WATCHDOGCOUNT] = { + { + .fxnTablePtr = &WatchdogCC32XX_fxnTable, + .object = &watchdogCC3220SObjects[CC3220SF_LAUNCHXL_WATCHDOG0], + .hwAttrs = &watchdogCC3220SHWAttrs[CC3220SF_LAUNCHXL_WATCHDOG0] + } +}; + +const uint_least8_t Watchdog_count = CC3220SF_LAUNCHXL_WATCHDOGCOUNT; + +/* + * ======== Board_debugHeader ======== + * This structure prevents the CC32XXSF bootloader from overwriting the + * internal FLASH; this allows us to flash a program that will not be + * overwritten by the bootloader with the encrypted program saved in + * "secure/serial flash". + * + * This structure must be placed at the beginning of internal FLASH (so + * the bootloader is able to recognize that it should not overwrite + * internal FLASH). + */ +#if defined (__SF_DEBUG__) || defined(__SF_NODEBUG__) +#if defined(__TI_COMPILER_VERSION__) +#pragma DATA_SECTION(Board_debugHeader, ".dbghdr") +#pragma RETAIN(Board_debugHeader) +#elif defined(__IAR_SYSTEMS_ICC__) +#pragma location=".dbghdr" +#elif defined(__GNUC__) +__attribute__ ((section (".dbghdr"))) +#endif +#if defined(__SF_DEBUG__) +const uint32_t Board_debugHeader[] = { + 0x5AA5A55A, + 0x000FF800, + 0xEFA3247D +}; +#elif defined (__SF_NODEBUG__) +const uint32_t Board_debugHeader[] = { + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF +}; +#endif +#endif diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.h b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.h new file mode 100644 index 00000000..c107c3e6 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CC3220SF_LAUNCHXL.h @@ -0,0 +1,186 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// CC3220 Board Specific APIs + +#ifndef __CC3220SF_LAUNCHXL_H +#define __CC3220SF_LAUNCHXL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define CC3220SF_LAUNCHXL_GPIO_LED_OFF (0) +#define CC3220SF_LAUNCHXL_GPIO_LED_ON (1) + +/*! + * @def CC3220SF_LAUNCHXL_ADCName + * @brief Enum of ADC names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_ADCName { + CC3220SF_LAUNCHXL_ADC0 = 0, + CC3220SF_LAUNCHXL_ADC1, + + CC3220SF_LAUNCHXL_ADCCOUNT +} CC3220SF_LAUNCHXL_ADCName; + +/*! + * @def CC3220SF_LAUNCHXL_CaptureName + * @brief Enum of Capture names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_CaptureName { + CC3220SF_LAUNCHXL_CAPTURE0 = 0, + CC3220SF_LAUNCHXL_CAPTURE1, + + CC3220SF_LAUNCHXL_CAPTURECOUNT +} CC3220SF_LAUNCHXL_CaptureName; + +/*! + * @def CC3220SF_LAUNCHXL_CryptoName + * @brief Enum of Crypto names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_CryptoName { + CC3220SF_LAUNCHXL_CRYPTO0 = 0, + + CC3220SF_LAUNCHXL_CRYPTOCOUNT +} CC3220SF_LAUNCHXL_CryptoName; + +/*! + * @def CC3220SF_LAUNCHXL_GPIOName + * @brief Enum of GPIO names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_GPIOName { + CC3220SF_LAUNCHXL_GPIO_SW2 = 0, + CC3220SF_LAUNCHXL_GPIO_SW3, + CC3220SF_LAUNCHXL_SPI_MASTER_READY, + CC3220SF_LAUNCHXL_SPI_SLAVE_READY, + CC3220SF_LAUNCHXL_GPIO_LED_D10, + + /* + * CC3220SF_LAUNCHXL_GPIO_LED_D8 and CC3220SF_LAUNCHXL_GPIO_LED_D9 are shared with the + * I2C and PWM peripherals. In order for those examples to work, these + * LEDs are taken out of gpioPinCOnfig[] + */ + CC3220SF_LAUNCHXL_GPIO_LED_D9, + CC3220SF_LAUNCHXL_GPIO_LED_D8, + + CC3220SF_LAUNCHXL_GPIO_TMP116_EN, + + /* Sharp LCD Pins */ + CC3220SF_LAUNCHXL_LCD_CS, + CC3220SF_LAUNCHXL_LCD_POWER, + CC3220SF_LAUNCHXL_LCD_ENABLE, + + CC3220SF_LAUNCHXL_GPIOCOUNT +} CC3220SF_LAUNCHXL_GPIOName; + +/*! + * @def CC3220SF_LAUNCHXL_I2CName + * @brief Enum of I2C names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_I2CName { + CC3220SF_LAUNCHXL_I2C0 = 0, + + CC3220SF_LAUNCHXL_I2CCOUNT +} CC3220SF_LAUNCHXL_I2CName; + +/*! + * @def CC3220S_LAUNCHXL_I2SName + * @brief Enum of I2S names on the CC3220S_LAUNCHXL dev board + */ +typedef enum CC3220S_LAUNCHXL_I2SName { + CC3220S_LAUNCHXL_I2S0 = 0, + + CC3220S_LAUNCHXL_I2SCOUNT +} CC3220S_LAUNCHXL_I2SName; + +/*! + * @def CC3220SF_LAUNCHXL_PWMName + * @brief Enum of PWM names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_PWMName { + CC3220SF_LAUNCHXL_PWM6 = 0, + CC3220SF_LAUNCHXL_PWM7, + + CC3220SF_LAUNCHXL_PWMCOUNT +} CC3220SF_LAUNCHXL_PWMName; + +/*! + * @def CC3220SF_LAUNCHXL_SDFatFSName + * @brief Enum of SDFatFS names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_SDFatFSName { + CC3220SF_LAUNCHXL_SDFatFS0 = 0, + + CC3220SF_LAUNCHXL_SDFatFSCOUNT +} CC3220SF_LAUNCHXL_SDFatFSName; + +/*! + * @def CC3220SF_LAUNCHXL_SDName + * @brief Enum of SD names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_SDName { + CC3220SF_LAUNCHXL_SD0 = 0, + + CC3220SF_LAUNCHXL_SDCOUNT +} CC3220SF_LAUNCHXL_SDName; + +/*! + * @def CC3220SF_LAUNCHXL_SPIName + * @brief Enum of SPI names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_SPIName { + CC3220SF_LAUNCHXL_SPI0 = 0, + CC3220SF_LAUNCHXL_SPI1, + + CC3220SF_LAUNCHXL_SPICOUNT +} CC3220SF_LAUNCHXL_SPIName; + +/*! + * @def CC3220SF_LAUNCHXL_TimerName + * @brief Enum of Timer names on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_TimerName { + CC3220SF_LAUNCHXL_TIMER0 = 0, + CC3220SF_LAUNCHXL_TIMER1, + CC3220SF_LAUNCHXL_TIMER2, + + CC3220SF_LAUNCHXL_TIMERCOUNT +} CC3220SF_LAUNCHXL_TimerName; + +/*! + * @def CC3220SF_LAUNCHXL_UARTName + * @brief Enum of UARTs on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_UARTName { + CC3220SF_LAUNCHXL_UART0 = 0, + CC3220SF_LAUNCHXL_UART1, + + CC3220SF_LAUNCHXL_UARTCOUNT +} CC3220SF_LAUNCHXL_UARTName; + +/*! + * @def CC3220SF_LAUNCHXL_WatchdogName + * @brief Enum of Watchdogs on the CC3220SF_LAUNCHXL dev board + */ +typedef enum CC3220SF_LAUNCHXL_WatchdogName { + CC3220SF_LAUNCHXL_WATCHDOG0 = 0, + + CC3220SF_LAUNCHXL_WATCHDOGCOUNT +} CC3220SF_LAUNCHXL_WatchdogName; + +/*! + * @brief Initialize the general board specific settings + * + * This function initializes the general board specific settings. + */ +extern void CC3220SF_LAUNCHXL_initGeneral(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __CC3220SF_LAUNCHXL_H */ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CMakeLists.txt b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CMakeLists.txt new file mode 100644 index 00000000..fd38d737 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/CMakeLists.txt @@ -0,0 +1,131 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(TI_SimpleLink REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoCLR") + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/CC3220SF_LAUNCHXL.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_TI_SimpleLink_COMMON_SOURCES} + + ${TARGET_TI_SimpleLink_NANOCLR_SOURCES} + + ${TI_SimpleLink_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from TI SimpleLink CC32xx SDK and FreeRTOS (this is required to make sure that those repos are downloaded before the build starts) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf FreeRTOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf SimpleLinkCC32xxSDK) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/common" + "${PROJECT_SOURCE_DIR}/src/CLR/Core" + "${PROJECT_SOURCE_DIR}/src/CLR/Include" + "${PROJECT_SOURCE_DIR}/src/HAL/Include" + "${PROJECT_SOURCE_DIR}/src/PAL/Include" + + "${WireProtocol_INCLUDE_DIRS}" + "${TI_SimpleLink_INCLUDE_DIRS}" + + "${TARGET_TI_SimpleLink_COMMON_INCLUDE_DIRS}" +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + "${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR" + + "${TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS}" + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} +) + +# set compiler options +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +############################################### +# add -DUSE_CC3220_ROM_DRV_API to use ROM API # +############################################### +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf -DDeviceFamily_CC3220) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/CC3220SF_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/CC3220SF_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the size of CRT heap stacks is defined here +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__crt_heap_size__=0x0") + +# generate output files +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/FreeRTOSConfig.h b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/FreeRTOSConfig.h new file mode 100644 index 00000000..6e7fc379 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/FreeRTOSConfig.h @@ -0,0 +1,207 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +/****************************************************************************** + See http://www.freertos.org/a00110.html for an explanation of the + definitions contained in this file. +******************************************************************************/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* Constants related to the behaviour or the scheduler. */ +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) +#define configUSE_PREEMPTION 1 +#define configUSE_TIME_SLICING 0 +#define configMAX_PRIORITIES ( 10UL ) +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_16_BIT_TICKS 0 /* Only for 8 and 16-bit hardware. */ + +/* Constants used to specify if only static allocation is to be supported (in +which case a heap_n.c file is not required), only dynamic allocation is to be +supported, or if both static and dynamic allocation are supported. */ +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Constants that describe the hardware and memory usage. */ +#define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 ) +#define configMAX_TASK_NAME_LEN ( 12 ) + +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x8000 ) ) + +/* Default stack size for TI-POSIX threads (in words) */ +#define configPOSIX_STACK_SIZE ( ( unsigned short ) 512 ) + +/* Constants that build features in or out. */ +#define configUSE_MUTEXES 1 +#define configUSE_TICKLESS_IDLE 1 +#define configUSE_APPLICATION_TASK_TAG 1 /* Need by POSIX/pthread */ +#define configUSE_CO_ROUTINES 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TASK_NOTIFICATIONS 1 + +/* Constants that define which hook (callback) functions should be used. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 1 + +/* Constants provided for debugging and optimisation assistance. */ +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } +#define configQUEUE_REGISTRY_SIZE 0 + +/* + * Minimum number of full tick periods of idle time required to run Power + * sleep policy function. + */ +#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 5 + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (5) +#define configTIMER_QUEUE_LENGTH (20) +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +#define configENABLE_BACKWARD_COMPATIBILITY 0 + +#if defined(__TI_COMPILER_VERSION__) +#include +#define traceTASK_DELETE( pxTCB ) PTLS_taskDeleteHook( pxTCB ) +#elif defined(__IAR_SYSTEMS_ICC__) +#ifndef __IAR_SYSTEMS_ASM__ +#include +#define traceTASK_DELETE( pxTCB ) Mtx_taskDeleteHook( pxTCB ) +#endif +#endif + +/* + * Enable thread local storage + * + * Assign TLS array index ownership here to avoid collisions. + * TLS storage is needed to implement thread-safe errno with + * TI and IAR compilers. With GNU compiler, we enable newlib. + */ +#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) + +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1 + +#if defined(__TI_COMPILER_VERSION__) +#define PTLS_TLS_INDEX 0 /* ti.posix.freertos.PTLS */ +#elif defined(__IAR_SYSTEMS_ICC__) +#define MTX_TLS_INDEX 0 /* ti.posix.freertos.Mtx */ +#endif + +#elif defined(__GNUC__) +/* note: system locks required by newlib are not implemented */ +#define configUSE_NEWLIB_REENTRANT 1 +#endif + +/* + * Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. NOTE: Setting an INCLUDE_ parameter to 0 is only + * necessary if the linker does not automatically remove functions that are not + * referenced anyway. + */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskResumeFromISR 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xSemaphoreGetMutexHolder 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Cortex-M3/4 interrupt priority configuration follows...................... */ + +/* Use the system definition, if there is one. */ +#ifdef __NVIC_PRIO_BITS + #define configPRIO_BITS __NVIC_PRIO_BITS +#else + #define configPRIO_BITS 3 /* 8 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07 + +/* + * The highest interrupt priority that can be used by any interrupt service + * routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL + * INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER + * PRIORITY THAN THIS! (higher priorities are lower numeric values. + */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1 + +/* + * Priority 7 (shifted 5 since only the top 3 bits are implemented). + * Priority 7 is the lowest priority. + */ +#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* + * Priority 1 (shifted 5 since only the top 3 bits are implemented). + * Priority 1 is the second highest priority. + * Priority 0 is the highest priority. + * !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! + * See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. + */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* The trace facility is turned on to make some functions available for use in +CLI commands. */ +#define configUSE_TRACE_FACILITY 1 + +/* Constants related to the generation of run time stats. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#define portGET_RUN_TIME_COUNTER_VALUE() 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/README.md b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/README.md new file mode 100644 index 00000000..79a98a08 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/README.md @@ -0,0 +1,74 @@ +# TI CC3220SF LAUNCHXL + +The CC3220SF LAUNCHXL board contains a TI CC3220SF device. + +## Jumper Settings + +* Set __RX__ and __TX__ to provide UART communications via the onboard USB debugger. + +## Board Resources + +The following table lists the Board names of the resources and their corresponding pins. + + |Board Resource|Pins| + |--------------|:---| + |`Board_ADC0`|P59 (Connect to analog signal)| + |`Board_ADC1`|P60 (Connect to analog signal)| + |`Board_CAPTURE0`|P04 | + |`Board_CAPTURE1`|P05 | + |`Board_GPIO_LED0`|P64 (__LED EN__ must be jumpered)| + |`Board_GPIO_LED1`|P01 (__LED EN__ must be jumpered)| + |`Board_GPIO_LED2`|P02 (__LED EN__ must be jumpered)| + |`Board_GPIO_BUTTON0`|P04 (`SW2`)| + |`Board_GPIO_BUTTON1`|P15 (`SW3`)| + |`Board_I2C0`|P01 - `SCL`, P02 - `SDA`| + |`Board_I2C_TMP`|P01 - `SCL`, P02 - `SDA` (__SCL__ and __SDA__ must be jumpered)| + |`Board_I2S0`|P50 - `XR1`, P53 - `CLK`, P62 - `CLKX`, P63 - `FSX`, P64 - `XR0`| + |`Board_PWM0`|P01 (__LED EN__ must be jumpered)| + |`Board_PWM1`|P02 (__LED EN__ must be jumpered)| + |`Board_SD0`|P06 - `DATA`, P07 - `CLK`, P08 - `CMD`| + |`Board_SDFatFS0`|P06 - `DATA`, P07 - `CLK`, P08 - `CMD`| + |`Board_SPI0`|P05 - `CLK`, P06 - `MISO`, P07 - `MOSI`, P08 - `CS`| + |`Board_SPI_MASTER`|P05 - `CLK`, P06 - `MISO`, P07 - `MOSI`, P08 - `CS`| + |`Board_SPI_SLAVE`|P05 - `CLK`, P06 - `MISO`, P07 - `MOSI`, P08 - `CS`| + |`Board_SPI_MASTER_READY`|P18| + |`Board_SPI_SLAVE_READY`|P03| + |`Board_UART0`|P57 - `RX`, P55 - `TX` (UART provided through emulation, __RX__ and __TX__ must be jumpered)| + |`Board_UART1`|P08 - `RX`, P07 - `TX`| + +## ADC Examples Pin Connections + +>__Important:__ The inputs to the ADC are required to be well within 1.4 VDC to avoid clipping, which will cause distortion. +The ADC inputs can be damaged if an input voltage higher than 1.8 VDC is applied to these pin. The 1.8 VDC hard limit must be considered from both the SW and HW points of view. +Always add a resistor divider/buffer to bring down the measurement signal voltage to within the ADC limits. See the [CC32xx ADC Appnote](http://processors.wiki.ti.com/index.php/CC32xx_ADC_Appnote) +for more details. + +The __CC3220SF LAUNCHXL__ has a protective circuit to allow an input of 3.3 VDC. +The `5V` should NOT be used for this may damage the ADC inputs. For testing, the following jumpers must be present: +`J5` = `OPAMP EN`, `J10` = `GND`, `J13` = `BRD`. + +>__Note:__ There are duplicate pins P59 and P60 on the board. Choose the ones connected to the BoosterPack headers (the pins not connected to the BoosterPack headers have an asterisk next to them). + +## Reset Behavior + +By default, the application is not retained after a power reset. To enable +retention of the application for debug purposes, the application should +add the following pre-defined symbol: `__SF_DEBUG__`. This will place a header, +`Board_debugHeader`, into flash. This header is defined in the Board.c file. + +>__Note:__ The user should ensure the `Board_debugHeader` is erased if +retention of the application is no longer desired. The Board.c file +will erase the `Board_debugHeader` if `__SF_NODEBUG__` is defined. + +## Floating point + +The current build is set to add support for single-precision floating point. +Meaning that `System.Math` API supports only the `float` overloads. The `double` ones will throw a `NotImplementedException`. + +## nanoBooter + +Because this CPU uses a proprietary boot mechanism that copies the application from the SPI flash memory to the Cortex-M application core, it does not use nanoBooter. + +## Flashing nanoCLR + +Follow the instructions [here](http://docs.nanoframework.net/articles/ti-cc32xx/flash-nanoclr.html) on how to flash nanoCLR image in the board. diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/CMakeLists.txt b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/CMakeLists.txt new file mode 100644 index 00000000..42be0d5f --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..b3904523 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 2k blocks +const BlockRange BlockRange1[] = +{ + // the 1st block is reserved for the flash header + // so we don't take it into account for the map + { BlockRange_BLOCKTYPE_CODE , 0 , 125 }, // 0x01000800 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT , 126, 510 }, // 0x0103F000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x01000800, // start address for block region + 511, // total number of blocks in this region + 0x800, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + } +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage.c new file mode 100644 index 00000000..acdd399c --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/common/Device_BlockStorage.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 2k blocks +const BlockRange BlockRange1[] = +{ + // the 1st block is reserved for the flash header + // so we don't take it into account for the map + { BlockRange_BLOCKTYPE_CODE , 0 , 93 }, // 0x01000800 nanoCLR + { BlockRange_BLOCKTYPE_DEPLOYMENT , 94, 510 }, // 0x0102F800 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x01000800, // start address for block region + 511, // total number of blocks in this region + 0x800, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + } +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00200000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/README.md b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/README.md new file mode 100644 index 00000000..3fedf328 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/README.md @@ -0,0 +1,5 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](TI_CC3220SF_LAUNCHXL.Adc.cs) diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/TI_CC3220SF_LAUNCHXL.Gpio.cs b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/TI_CC3220SF_LAUNCHXL.Gpio.cs new file mode 100644 index 00000000..1a9adc02 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/TI_CC3220SF_LAUNCHXL.Gpio.cs @@ -0,0 +1,38 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.TI_CC3220SF_LAUNCHXL +{ + /// + /// Enumeration of GPIO pins in TI_CC3220SF_LAUNCHXL + /// + public static class GpioPins + { + /// + /// Switch 2, connected to CC32XX GPIO 13 + /// + public const int SW2 = 0; + + /// + /// Switch 3, connected to CC32XX GPIO 22 + /// + public const int SW3 = 1; + + /// + /// LED D10, connected to CC32XX GPIO 09 + /// + public const int LED_D10 = 4; + + /// + /// LED D9, connected to CC32XX GPIO 10 + /// + public const int LED_D9 = 5; + + /// + /// LED D8, connected to CC32XX GPIO 11 + /// + public const int LED_D8 = 6; + } +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/package.nuspec b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/package.nuspec new file mode 100644 index 00000000..8553a224 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/managed_helpers/package.nuspec @@ -0,0 +1,28 @@ + + + + nanoFramework.Targets.TI_CC3220SF_LAUNCHXL + nanoFramework.Targets.TI_CC3220SF_LAUNCHXL + 1.0.0 + nanoFramework project contributors + nanoFramework project contributors + false + + Helper classes to use TI_CC3220SF_LAUNCHXL target in C# applications. + + + + + This is an extension for .NET nanoFramework providing the GPIO pins when coding for the TI_CC3220SF_LAUNCHXL. + + https://github.com/nanoframework + https://secure.gravatar.com/avatar/97d0e092247f0716db6d4b47b7d1d1ad + https://github.com/nanoframework/nf-interpreter/blob/develop/LICENSE.md + Copyright (c) 2019 The nanoFramework project contributors + + nanoFramework, nano Framework, NETNF, NETMF, Micro Framework,.net + + + + + diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR-DEBUG.ld b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR-DEBUG.ld new file mode 100644 index 00000000..5987d6c5 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR-DEBUG.ld @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016-2017, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +STACKSIZE = 0x800; + +MEMORY +{ + FLASH_HDR (RX) : ORIGIN = 0x01000000, LENGTH = 0x7FF + FLASH (RX) : ORIGIN = 0x01000800, LENGTH = 0x03F000 + SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00040000 +} + +REGION_ALIAS("REGION_HDR", FLASH_HDR); +REGION_ALIAS("REGION_TEXT", FLASH); +REGION_ALIAS("REGION_BSS", SRAM); +REGION_ALIAS("REGION_DATA", SRAM); +REGION_ALIAS("REGION_STACK", SRAM); +REGION_ALIAS("REGION_HEAP", SRAM); +REGION_ALIAS("REGION_ARM_EXIDX", FLASH); +REGION_ALIAS("REGION_ARM_EXTAB", FLASH); + +SECTIONS { + + .dbghdr : ALIGN (2048) { + KEEP (*(.dbghdr)) + } > REGION_HDR + + PROVIDE (_resetVecs_base_address = + DEFINED(_resetVecs_base_address) ? _resetVecs_base_address : 0x01000800); + + .resetVecs (_resetVecs_base_address) : AT (_resetVecs_base_address) { + KEEP (*(.resetVecs)) + } > REGION_TEXT + + .ramVecs (NOLOAD) : ALIGN(1024) { + KEEP (*(.ramVecs)) + } > REGION_DATA + + .text : { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + *(.init) + *(.fini*) + } > REGION_TEXT AT> REGION_TEXT + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : { + *(.rodata) + *(.rodata*) + } > REGION_TEXT AT> REGION_TEXT + + .data : ALIGN (4) { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + *(.data) + *(.data*) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + .bss : { + __bss_start__ = .; + *(.shbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP(*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + __stack = .; + KEEP(*(.stack)) + . += STACKSIZE; + _stack_end = .; + __stack_end = .; + } > REGION_STACK AT> REGION_STACK +} + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", SRAM); + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld + +ENTRY(resetISR) diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR.ld b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR.ld new file mode 100644 index 00000000..88f978a6 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CC3220SF_CLR.ld @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016-2017, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +STACKSIZE = 0x800; + +MEMORY +{ + FLASH_HDR (RX) : ORIGIN = 0x01000000, LENGTH = 0x7FF + FLASH (RX) : ORIGIN = 0x01000800, LENGTH = 0x02F000 + SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00040000 +} + +REGION_ALIAS("REGION_HDR", FLASH_HDR); +REGION_ALIAS("REGION_TEXT", FLASH); +REGION_ALIAS("REGION_BSS", SRAM); +REGION_ALIAS("REGION_DATA", SRAM); +REGION_ALIAS("REGION_STACK", SRAM); +REGION_ALIAS("REGION_HEAP", SRAM); +REGION_ALIAS("REGION_ARM_EXIDX", FLASH); +REGION_ALIAS("REGION_ARM_EXTAB", FLASH); + +SECTIONS { + + .dbghdr : ALIGN (2048) { + KEEP (*(.dbghdr)) + } > REGION_HDR + + PROVIDE (_resetVecs_base_address = + DEFINED(_resetVecs_base_address) ? _resetVecs_base_address : 0x01000800); + + .resetVecs (_resetVecs_base_address) : AT (_resetVecs_base_address) { + KEEP (*(.resetVecs)) + } > REGION_TEXT + + .ramVecs (NOLOAD) : ALIGN(1024) { + KEEP (*(.ramVecs)) + } > REGION_DATA + + .text : { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + *(.init) + *(.fini*) + } > REGION_TEXT AT> REGION_TEXT + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : { + *(.rodata) + *(.rodata*) + } > REGION_TEXT AT> REGION_TEXT + + .data : ALIGN (4) { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + *(.data) + *(.data*) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + .bss : { + __bss_start__ = .; + *(.shbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP(*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + __stack = .; + KEEP(*(.stack)) + . += STACKSIZE; + _stack_end = .; + __stack_end = .; + } > REGION_STACK AT> REGION_STACK +} + +/* RAM region to be used for the nanoFramework CLR managed heap.*/ +REGION_ALIAS("CLR_MANAGED_HEAP_RAM", SRAM); + +/* nanoCLR rules inclusion.*/ +INCLUDE rules_clr.ld + +ENTRY(resetISR) diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..605070bb --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append nanoCLR source files +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.c") +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoHAL.cpp") + +# default Wi-Fi configuration for this target +list(APPEND NANOCLR_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/ti_drivers_net_wifi_Config.c") + +# make var global +set(NANOCLR_PROJECT_SOURCES ${NANOCLR_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/main.c b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/main.c new file mode 100644 index 00000000..9283109b --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/main.c @@ -0,0 +1,67 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +// POSIX Header files +#include +#include + +// RTOS header files +#include "FreeRTOS.h" +#include "task.h" + +// board Header files +#include "Board.h" + +////////////////////////////// + +// Stack size in bytes +#define THREADSTACKSIZE 2024 + +extern void * mainThread(void *arg0); + +int main(void) +{ + pthread_t thread; + pthread_attr_t threadAttributes; + struct sched_param priorityParameters; + + int retc; + + // Call board init functions + Board_initGeneral(); + + // CLR settings to launch CLR thread + CLR_SETTINGS clrSettings; + (void)memset(&clrSettings, 0, sizeof(CLR_SETTINGS)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + // Set priority and stack size attributes + pthread_attr_init(&threadAttributes); + priorityParameters.sched_priority = 1; + + retc = pthread_attr_setdetachstate(&threadAttributes, PTHREAD_CREATE_DETACHED); + + pthread_attr_setschedparam(&threadAttributes, &priorityParameters); + retc |= pthread_attr_setstacksize(&threadAttributes, THREADSTACKSIZE); + retc |= pthread_create(&thread, &threadAttributes, mainThread, &clrSettings); + if(retc != 0) + { + // pthread_create() + while(1) + { + ; + } + } + + // Start the FreeRTOS scheduler + vTaskStartScheduler(); + + return (0); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/nanoHAL.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/nanoHAL.cpp new file mode 100644 index 00000000..076a50fc --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/nanoHAL.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void HAL_EnterBooterMode() +{ +} + +bool g_fDoNotUninitializeDebuggerPort = false; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/target_board.h.in b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/target_board.h.in new file mode 100644 index 00000000..25bf6abd --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/target_board.h.in @@ -0,0 +1,16 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_BOARD_NANOCLR_H_ +#define _TARGET_BOARD_NANOCLR_H_ + +#include + +#endif /* _TARGET_BOARD_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/ti_drivers_net_wifi_Config.c b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/ti_drivers_net_wifi_Config.c new file mode 100644 index 00000000..8806c8f0 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/nanoCLR/ti_drivers_net_wifi_Config.c @@ -0,0 +1,31 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +// TI-DRIVERS Header files +#include + + +///////////////////////////////////////////////// +// Default Wi-Fi configuration for this target // +///////////////////////////////////////////////// + +const SlWifiCC32XXConfig_t SimpleLinkWifiCC32XX_config = { + + .Mode = ROLE_STA, + .Ipv4Mode = SL_NETCFG_IPV4_STA_ADDR_MODE, + .ConnectionPolicy = SL_WLAN_CONNECTION_POLICY(1,0,0,1), + .PMPolicy = SL_WLAN_ALWAYS_ON_POLICY,//SL_WLAN_NORMAL_POLICY, + .MaxSleepTimeMS = 0, + .ScanPolicy = SL_WLAN_SCAN_POLICY(0,0), + .ScanIntervalInSeconds = 0, + .Ipv4Config = SL_NETCFG_ADDR_DHCP, + .Ipv4 = 0, + .IpMask = 0, + .IpGateway = 0, + .IpDnsServer = 0, + .ProvisioningStop = 0, + .DeleteAllProfile = 0 +}; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.c b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.c new file mode 100644 index 00000000..ab075246 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.c @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice CC32xxFlash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &CC32xxFlash_BlockStorageInterface, &Device_BlockStorageConfig, true); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.h b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.h new file mode 100644 index 00000000..74d115d3 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 2 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 2 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.c b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.c new file mode 100644 index 00000000..7aabc922 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.c @@ -0,0 +1,28 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0,//ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; + +// these addresses are the start and end address of flash region FLASH +uint32_t __nanoImage_start__ = FLASH1_MEMORY_StartAddress; +uint32_t __nanoImage_end__ = (FLASH1_MEMORY_StartAddress + FLASH1_MEMORY_Size); diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.h.in b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.h.in new file mode 100644 index 00000000..fd6f12cf --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_common.h.in @@ -0,0 +1,53 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00040000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x01000800) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x000FF800) + +///////////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////// +#define PLATFORM_HAS_RNG TRUE +///////////////////////////////////// + +////////////////////////////////////////////// +#define OEMSYSTEMINFOSTRING "nanoCLR running @ @TI_BOARD@ built with TI SL CC32xx SDK v3.10.00.04" +#define TARGETNAMESTRING "@TI_BOARD@" +#define PLATFORMNAMESTRING "TI_SL_CC32xx" +////////////////////////////////////////////// + +////////////////////////////////////////////// +// set Wire Protocol packet size +// valid sizes are 1024, 512, 256, 128 +// check Monitor_Ping_Source_Flags enum +#define WP_PACKET_SIZE 256U +////////////////////////////////////////////// + +///////////////////////////////////// +//#define EVENTS_HEART_BEAT GPIO_toggle(Board_GPIO_LED0) +///////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_sntp_opts.h b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_sntp_opts.h new file mode 100644 index 00000000..ecd95c61 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_sntp_opts.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_SNTP_OPTS_H_ +#define _TARGET_SNTP_OPTS_H_ 1 + +#define SNTP_SERVER_DEFAULT_ADDRESS "0.pool.ntp.org" + +// update delay (default 1 hour) +// (value in seconds) +// Must wait at least 15 sec to retry NTP server (RFC 4330) +#define SNTP_UPDATE_DELAY (60 * 60) + +// no startup delay for SNTP +// value in seconds +#define SNTP_STARTUP_DELAY (0) + +// retry timeout +// value in seconds +#define SNTP_RETRY_TIMEOUT (10) + +#endif // _TARGET_SNTP_OPTS_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..d7b7376b --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_adc_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_i2c_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_pwm_config.h b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_pwm_config.h new file mode 100644 index 00000000..e3c11018 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_pwm_config.h @@ -0,0 +1,7 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// number of PWM pins available in this target +#define PWM_PIN_COUNT (2) diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..76238dbe --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/TI_CC3220SF_LAUNCHXL/target_windows_devices_spi_config.cpp @@ -0,0 +1,8 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/CMakeLists.txt b/source/native/nf-interpreter/targets/TI-SimpleLink/common/CMakeLists.txt new file mode 100644 index 00000000..f8696b1a --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/CMakeLists.txt @@ -0,0 +1,37 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append target TI SimpleLink common source files +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platform_heap.c") + +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_ReceiverThread.c") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_HAL_Interface.c") + +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Target_BlockStorage_CC32xxFlashDriver.c") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platform_BlockStorage.c") + +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/FreeRTOS-openocd.c") + +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/GenericPort.cpp") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/syscalls.c") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoSupport_CRC32.c") + +# append nanoHAL +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platformHAL.c") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/platformHAL_Time.cpp") + +# append configuration manager according to target +if("${TARGET_SERIES}" STREQUAL "CC32xx") + list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigurationManager_CC32xx.cpp") +endif() + +# append sockets and SSL driver +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/simplelink_sockets_functions.cpp") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/simplelink_sockets.cpp") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/sockets_simplelink.cpp") +list(APPEND TARGET_TI_SimpleLink_COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/ssl_simplelink.cpp") + +# make var global +set(TARGET_TI_SimpleLink_COMMON_SOURCES ${TARGET_TI_SimpleLink_COMMON_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/FreeRTOS-openocd.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/FreeRTOS-openocd.c new file mode 100644 index 00000000..81a3ab77 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/FreeRTOS-openocd.c @@ -0,0 +1,20 @@ +/* + * Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer + * present in the kernel, so it has to be supplied by other means for + * OpenOCD's threads awareness. + * + * Add this file to your project, and, if you're using --gc-sections, + * ``--undefined=uxTopUsedPriority'' (or + * ``-Wl,--undefined=uxTopUsedPriority'' when using gcc for final + * linking) to your LDFLAGS; same with all the other symbols you need. + */ + +#include "FreeRTOS.h" + +#ifdef __GNUC__ +#define USED __attribute__((used)) +#else +#define USED +#endif + +const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/GenericPort.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/common/GenericPort.cpp new file mode 100644 index 00000000..5629083b --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/GenericPort.cpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +extern UART_Handle uart; +extern SemaphoreP_Handle uartMutex; + +// developer note: +// Outputing to board UART can be done only if there is no debugger attached, because it uses the same UART. + +extern "C" uint32_t DebuggerPort_WriteProxy(const char *format, ...) +{ + va_list arg; + uint32_t chars = 0; + + if( CLR_EE_DBG_IS_NOT( Enabled ) ) + { + if(SemaphoreP_pend(uartMutex, UART_WAIT_FOREVER) == SemaphoreP_OK) + { + va_start( arg, format ); + + chars = CLR_Debug::PrintfV( format, arg ); + + va_end( arg ); + + SemaphoreP_post(uartMutex); + } + } + + return chars; +} + +uint32_t GenericPort_Write( int portNum, const char* data, size_t size ) +{ + (void)portNum; + + if( CLR_EE_DBG_IS_NOT( Enabled ) ) + { + // debugger port is NOT in use, OK to output to UART + // send characters directly to the UART port + UART_write(uart, data, size); + + return size; + } + + return (uint32_t)size; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/Target_BlockStorage_CC32xxFlashDriver.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/Target_BlockStorage_CC32xxFlashDriver.c new file mode 100644 index 00000000..41f07d89 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/Target_BlockStorage_CC32xxFlashDriver.c @@ -0,0 +1,91 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +// includes from SimpleLink +#include "inc/hw_types.h" +#include + +// local defines +#define FLASH_ERASED_WORD 0x0FFFFFFFFU + +bool CC32xxFlashDriver_InitializeDevice(void* context) +{ + (void)context; + + // SimpleLink driver takes care of this, so always true + return true; +} + +bool CC32xxFlashDriver_UninitializeDevice(void* context) +{ + (void)context; + + // SimpleLink driver takes care of this, so always true + return true; +} + +DeviceBlockInfo* CC32xxFlashDriver_GetDeviceInfo(void* context) +{ + MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = context; + + return config->BlockConfig.BlockDeviceInformation; +} + +bool CC32xxFlashDriver_Read(void* context, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer) +{ + (void)context; + + // ... and always return true + return true; +} + +bool CC32xxFlashDriver_Write(void* context, ByteAddress startAddress, unsigned int numBytes, unsigned char* buffer, bool readModifyWrite) +{ + (void)context; + (void)readModifyWrite; + + if(FlashProgram((unsigned long*)buffer, (unsigned long) startAddress, (unsigned long) numBytes) == 0) + { + return true; + } + + return false; +} + +bool CC32xxFlashDriver_IsBlockErased(void* context, ByteAddress blockAddress, unsigned int length) +{ + (void)context; + + unsigned long* cursor = (unsigned long *)blockAddress; + unsigned long* endAddress = (unsigned long *)(blockAddress + length); + + // an erased flash address has to read FLASH_ERASED_WORD + // OK to check by word (32 bits) because the erase is performed by 'block' whose size is word multiple + while(cursor < endAddress) + { + if(*cursor++ != FLASH_ERASED_WORD) + { + // found an address with something other than FLASH_ERASED_WORD!! + return false; + } + } + + // reached here so the block must be erased + return true; +} + +bool CC32xxFlashDriver_EraseBlock(void* context, ByteAddress address) +{ + (void)context; + + if(FlashErase((unsigned long) address) == 0) + { + return true; + } + + return false; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_HAL_Interface.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_HAL_Interface.c new file mode 100644 index 00000000..5e5904a3 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_HAL_Interface.c @@ -0,0 +1,104 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include + +UART_Handle uart = NULL; + +WP_Message inboundMessage; + +//////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////// +// The functions below are the ones that need to be ported to new channels/HALs when required +// These are to be considered as a reference implementations when working on new ports +// +// This reference implementation provides communication through: +// - serial port (UART/USART) +// +//////////////////////////////////////////////////////////////////////////////////////////////// + +int WP_ReceiveBytes(uint8_t* ptr, uint16_t* size) +{ + // save for latter comparison + uint16_t requestedSize = *size; + + //int readData = 0; + // sanity check for request of 0 size + if(*size) + { + ////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + ////////////////////////////////////////////////////////// + // change here to read (size) bytes from the input stream + // preferably with read timeout and being able to check + // if the requested number of bytes was actually read + ////////////////////////////////////////////////////////// + + // non blocking read from serial port with 500ms timeout + size_t read = UART_read(uart, ptr, requestedSize); + + ptr += read; + *size -= read; + + // check if the requested read matches the actual read count + return (requestedSize == read); + } + + return true; +} + +int WP_TransmitMessage(WP_Message* message) +{ + uint32_t writeResult; + bool operationResult = false; + + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // change here to write (size) bytes to the output stream + // preferably with timeout and being able to check + // if the write was successfull or at least buffered + ////////////////////////////////////////////////////////// + + TRACE( TRACE_HEADERS, "TXMSG: 0x%08X, 0x%08X, 0x%08X\n", message->m_header.m_cmd, message->m_header.m_flags, message->m_header.m_size ); + + // write header to uart + writeResult = UART_write(uart, (const void *)&message->m_header, sizeof(message->m_header)); + + if(writeResult == sizeof(message->m_header)) + { + operationResult = true; + + // if there is anything on the payload send it to the output stream + if(message->m_header.m_size && message->m_payload) + { + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // see description above + ////////////////////////////////////////////////////////// + + // reset flag + operationResult = false; + + writeResult = UART_write(uart, (const void *)message->m_payload, message->m_header.m_size); + + if(writeResult == message->m_header.m_size) + { + operationResult = true; + + TRACE0( TRACE_ERRORS, "TXMSG: OK\n"); + } + } + } + + return operationResult; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_ReceiverThread.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_ReceiverThread.c new file mode 100644 index 00000000..8943333d --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/WireProtocol_ReceiverThread.c @@ -0,0 +1,31 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "WireProtocol_HAL_Interface.h" +#include +#include + +extern WP_Message inboundMessage; + +void WP_Message_Initialize(WP_Message* a); +void WP_Message_PrepareReception(WP_Message* a); +void WP_Message_Process(WP_Message* a); + +void* ReceiverThread(void* argument) +{ + (void)argument; + + // loop forever + while (1) + { + WP_Message_Initialize(&inboundMessage); + WP_Message_PrepareReception(&inboundMessage); + + WP_Message_Process(&inboundMessage); + + // Allow other tasks a chance to run + taskYIELD(); + } +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/nanoSupport_CRC32.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/nanoSupport_CRC32.c new file mode 100644 index 00000000..0f7b0e60 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/nanoSupport_CRC32.c @@ -0,0 +1,21 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +// strong implementation of this function specific to the TI Simple Link targets +unsigned int SUPPORT_ComputeCRC(const void* rgBlock, int nLength, unsigned int crc) +{ + MAP_CRCSeedSet(DTHE_BASE, crc); + + crc = MAP_CRCDataProcess(DTHE_BASE, rgBlock, nLength, CRC_CFG_SIZE_8BIT); + + return crc; +}; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL.c new file mode 100644 index 00000000..92fc4de2 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL.c @@ -0,0 +1,51 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +void HAL_AssertEx() +{ + __asm__("BKPT"); + while(true) { /*nop*/ } +} + +#if !defined(BUILD_RTM) + +void HARD_Breakpoint() +{ + __asm__("BKPT"); + while(true) { /*nop*/ } +}; + +#endif // !defined(BUILD_RTM) + + +// Provides information whether the configuration block storage requires erase command before sending the update command +// The 'weak' implementation for TI SimpleLink targets is false +// If a target implements the store differently it has to provide a 'strong' implementation of this. +__nfweak bool Target_ConfigUpdateRequiresErase() +{ + return false; +}; + +bool Target_HasNanoBooter() +{ + return false; +}; + +// declarations of platform capabilities +uint32_t GetPlatformCapabilities() +{ + return 0; +}; + +// declarations of target capabilities +// If a target has something to declare it has to provide a 'strong' implementation of this. +__nfweak uint32_t GetTargetCapabilities() +{ + return 0; +}; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL_Time.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL_Time.cpp new file mode 100644 index 00000000..bcb18568 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platformHAL_Time.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +// Converts FreeRTOS Tickcount to .NET ticks (100 nanoseconds) +uint64_t HAL_Time_SysTicksToTime(unsigned int sysTicks) +{ + return (((int64_t)sysTicks * (int64_t)1000000 + (int64_t)configTICK_RATE_HZ - 1) / (int64_t)configTICK_RATE_HZ) * 10; +} + +// because HAL_Time_SysTicksToTime needs to be called from C we need a proxy to allow it to be called from 'C' code +extern "C" { + + uint64_t HAL_Time_SysTicksToTime_C(unsigned int sysTicks) + { + return HAL_Time_SysTicksToTime(sysTicks); + } +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_BlockStorage.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_BlockStorage.c new file mode 100644 index 00000000..0af51e54 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_BlockStorage.c @@ -0,0 +1,22 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// map here the Block Storage Interface to the CC32xx driver +IBlockStorageDevice CC32xxFlash_BlockStorageInterface = +{ + &CC32xxFlashDriver_InitializeDevice, + &CC32xxFlashDriver_UninitializeDevice, + &CC32xxFlashDriver_GetDeviceInfo, + &CC32xxFlashDriver_Read, + &CC32xxFlashDriver_Write, + NULL, + &CC32xxFlashDriver_IsBlockErased, + &CC32xxFlashDriver_EraseBlock, + NULL, + NULL +}; diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_heap.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_heap.c new file mode 100644 index 00000000..d2507def --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/platform_heap.c @@ -0,0 +1,18 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +void* platform_malloc(size_t size) { + return malloc(size); +} + +void platform_free(void* ptr) { + free(ptr); +} + +void* platform_realloc(void* ptr, size_t size) { + return realloc(ptr, size); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/rules_clr.ld b/source/native/nf-interpreter/targets/TI-SimpleLink/common/rules_clr.ld new file mode 100644 index 00000000..e9359385 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/rules_clr.ld @@ -0,0 +1,15 @@ + SECTIONS +{ + + /* nanoFramework CLR managed heap section at the specified RAM section.*/ + .clr_managed_heap (NOLOAD) : + { + . = ALIGN(8); + __clr_managed_heap_base__ = .; + PROVIDE(HeapBegin = LOADADDR(.clr_managed_heap)); + . = ORIGIN(CLR_MANAGED_HEAP_RAM) + LENGTH(CLR_MANAGED_HEAP_RAM); + . = ALIGN(8); + __clr_managed_heap_end__ = .; + PROVIDE(HeapEnd = .); + } > CLR_MANAGED_HEAP_RAM +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.cpp new file mode 100644 index 00000000..57704aa7 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.cpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "simplelink_sockets.h" + +//--// + +#if defined(DEBUG) +#define DEBUG_HANDLE_SOCKET_ERROR(t,a) +// assume there is something to add in later?? +#else +#define DEBUG_HANDLE_SOCKET_ERROR(t,a) +#endif + +//--// + +//--// +static HAL_CONTINUATION PostAddressChangedContinuation; +static HAL_CONTINUATION PostAvailabilityOnContinuation; +static HAL_CONTINUATION PostAvailabilityOffContinuation; + +void PostAddressChanged(void* arg) +{ + (void)arg; + + Network_PostEvent(NetworkEventType_AddressChanged, 0, 0); +} + +void PostAvailabilityOn(void* arg) +{ + (void)arg; + + Network_PostEvent(NetworkEventType_AvailabilityChanged, NetworkEventFlags_NetworkAvailable, 0); +} + +void PostAvailabilityOff(void* arg) +{ + (void)arg; + + Network_PostEvent(NetworkEventType_AvailabilityChanged, NetworkEventFlags_NetworkNOTAvailable, 0); +} + +void Link_callback(bool linkUp) +{ + if (linkUp) + { + if (!PostAvailabilityOnContinuation.IsLinked()) + PostAvailabilityOnContinuation.Enqueue(); + } + else + { + if (!PostAvailabilityOffContinuation.IsLinked()) + PostAvailabilityOffContinuation.Enqueue(); + } + + Events_Set(SYSTEM_EVENT_FLAG_SOCKET); + Events_Set(SYSTEM_EVENT_FLAG_NETWORK); +} + +void Status_callback() +{ + if (!PostAddressChangedContinuation.IsLinked()) + PostAddressChangedContinuation.Enqueue(); + +#if !defined(BUILD_RTM) + // lcd_printf("\f\n\n\n\n\n\nLink Update: %s\n", (netif_is_up(netif) ? "UP " : "DOWN")); + // lcd_printf(" IP: %d.%d.%d.%d\n", (netif->ip_addr.addr >> 0) & 0xFF, + // (netif->ip_addr.addr >> 8) & 0xFF, + // (netif->ip_addr.addr >> 16) & 0xFF, + // (netif->ip_addr.addr >> 24) & 0xFF); + // lcd_printf(" SM: %d.%d.%d.%d\n", (netif->netmask.addr >> 0) & 0xFF, + // (netif->netmask.addr >> 8) & 0xFF, + // (netif->netmask.addr >> 16) & 0xFF, + // (netif->netmask.addr >> 24) & 0xFF); + // lcd_printf(" GW: %d.%d.%d.%d\n", (netif->gw.addr >> 0) & 0xFF, + // (netif->gw.addr >> 8) & 0xFF, + // (netif->gw.addr >> 16) & 0xFF, + // (netif->gw.addr >> 24) & 0xFF); + +//FIXME debug_printf("IP Address: %d.%d.%d.%d\n", (netif->ip_addr.u_addr.ip4.addr >> 0) & 0xFF, +// (netif->ip_addr.u_addr.ip4.addr >> 8) & 0xFF, +// (netif->ip_addr.u_addr.ip4.addr >> 16) & 0xFF, +// (netif->ip_addr.u_addr.ip4.addr >> 24) & 0xFF); +#if LWIP_DNS + if (netif->flags & NETIF_FLAG_ETHARP) + { + //ip_addr_t * dns1 = dns_getserver(0); + //ip_addr_t * dns2 = dns_getserver(1); + + // lcd_printf(" dns1: %d.%d.%d.%d\n", (dns1.addr >> 0) & 0xFF, + // (dns1.addr >> 8) & 0xFF, + // (dns1.addr >> 16) & 0xFF, + // (dns1.addr >> 24) & 0xFF); + + // lcd_printf(" dns2: %d.%d.%d.%d\n", (dns2.addr >> 0) & 0xFF, + // (dns2.addr >> 8) & 0xFF, + // (dns2.addr >> 16) & 0xFF, + // (dns2.addr >> 24) & 0xFF); + } +#endif + Events_Set(SYSTEM_EVENT_FLAG_SOCKET); + Events_Set(SYSTEM_EVENT_FLAG_NETWORK); +} +#endif + +bool SimpleLink_SOCKETS_Initialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + + PostAddressChangedContinuation.InitializeCallback(PostAddressChanged, NULL); + PostAvailabilityOnContinuation.InitializeCallback(PostAvailabilityOn, NULL); + PostAvailabilityOffContinuation.InitializeCallback(PostAvailabilityOff, NULL); + + return true; +} + +bool SimpleLink_SOCKETS_Uninitialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + + PostAddressChangedContinuation.Abort(); + PostAvailabilityOnContinuation.Abort(); + PostAvailabilityOffContinuation.Abort(); + + return true; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.h b/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.h new file mode 100644 index 00000000..d7cf7465 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _SIMPLELINK_SOCKETS_H_ +#define _SIMPLELINK_SOCKETS_H_ + +#include +#include + +#define NATIVE_PROFILE_PAL_NETWORK() + +#ifdef __cplusplus +extern "C" { +#endif + +bool SimpleLink_SOCKETS_Initialize(); +bool SimpleLink_SOCKETS_Uninitialize(); + +void Status_callback(); +void Link_callback(bool linkUp); +// void PostAddressChanged(void* arg); +// void PostAvailabilityOn(void* arg); +// void PostAvailabilityOff(void* arg); + +#ifdef __cplusplus +} +#endif + +#endif // _SIMPLELINK_SOCKETS_H_ 1 diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets_functions.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets_functions.cpp new file mode 100644 index 00000000..9f8dbcb9 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/simplelink_sockets_functions.cpp @@ -0,0 +1,178 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include "simplelink_sockets.h" + +#include + +#define NATIVE_PROFILE_PAL_NETWORK() + +bool HAL_SOCK_Initialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + return SimpleLink_SOCKETS_Initialize(); +} + +bool HAL_SOCK_Uninitialize() +{ + NATIVE_PROFILE_PAL_NETWORK(); + return SimpleLink_SOCKETS_Uninitialize(); +} + +HRESULT HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + uint16_t configOptions; + uint16_t ipLen = sizeof(SlNetCfgIpV4Args_t); + SlNetCfgIpV4Args_t ipV4 = {0}; + + if(config->StartupAddressMode == AddressMode_DHCP) + { + // if this is on DHCP we need to load whatever we have on top of the stored configuration +#if LWIP_IPV6 + { + // FIXME IPV6 + // config->IPv6Address = networkInterface->ip_addr.u_addr.ip6.addr; + // config->IPv6NetMask = networkInterface->netmask.u_addr.ip6.addr; + // config->IPv6GatewayAddress = networkInterface->gw.u_addr.ip6.addr; + } +#else + if (sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE, &configOptions, &ipLen, (uint8_t *)&ipV4) >= 0) + { + config->IPv4Address = sl_Ntohl(ipV4.Ip); + config->IPv4NetMask = sl_Ntohl(ipV4.IpMask); + config->IPv4GatewayAddress = sl_Ntohl(ipV4.IpGateway); + config->IPv4DNSAddress1 = sl_Ntohl(ipV4.IpDnsServer); + config->IPv4DNSAddress2 = 0; + } + else + { + config->IPv4Address = 0; + config->IPv4NetMask = 0; + config->IPv4GatewayAddress = 0; + config->IPv4DNSAddress1 = 0; + config->IPv4DNSAddress2 = 0; + } +#endif + } + + return S_OK; +} + +HRESULT HAL_SOCK_CONFIGURATION_UpdateAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex, uint32_t updateFlags) +{ + NATIVE_PROFILE_PAL_NETWORK(); + + uint16_t configOptions; + uint16_t ipLen = sizeof(SlNetCfgIpV4Args_t); + SlNetCfgIpV4Args_t ipV4 = {0}; + + bool enableDHCP = (config->StartupAddressMode == AddressMode_DHCP); + + if (sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE, &configOptions, &ipLen, (uint8_t *)&ipV4) >= 0) + { + // when using DHCP do not use the static settings + if(0 != (updateFlags & UpdateOperation_Dns)) + { + // FIXME IPV6 + if(config->AutomaticDNS == 0) + { + // user defined DNS addresses + if(config->IPv4DNSAddress1 != 0) + { + ipV4.IpDnsServer = sl_Htonl(config->IPv4DNSAddress1); + } + + // this interface doesn't have a secondary DNS + + // update configuration + if(sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE, SL_NETCFG_ADDR_STATIC, sizeof(SlNetCfgIpV4Args_t), (uint8_t*)&ipV4) < 0) + { + return CLR_E_FAIL; + } + } + } + + if(0 != (updateFlags & UpdateOperation_Dhcp)) + { + if(enableDHCP) + { + // need to start DHCP + if(sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE, SL_NETCFG_ADDR_DHCP ,0 ,0 ) < 0) + { + return CLR_E_FAIL; + } + } + else + { + // we should be polite and let the DHCP server that we are now using a static IP + sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE, SL_NETCFG_ADDR_RELEASE_IP_SET, 0, 0); + + ipV4.Ip = sl_Htonl(config->IPv4Address); + ipV4.IpMask = sl_Htonl(config->IPv4NetMask); + ipV4.IpGateway = sl_Htonl(config->IPv4GatewayAddress); + ipV4.IpDnsServer = sl_Htonl(config->IPv4DNSAddress1); + + if(sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE, SL_NETCFG_ADDR_STATIC, sizeof(SlNetCfgIpV4Args_t), (uint8_t*)&ipV4) < 0) + { + return CLR_E_FAIL; + } + + } + } + + if(enableDHCP) + { + if(0 != (updateFlags & UpdateOperation_DhcpRelease)) + { + sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE, SL_NETCFG_ADDR_RELEASE_IP_SET, 0, 0); + } + else if(0 != (updateFlags & UpdateOperation_DhcpRenew)) + { + //dhcp_renew(networkInterface); + } + else if(0 != (updateFlags & (UpdateOperation_DhcpRelease | UpdateOperation_DhcpRenew)) ) + { + return CLR_E_INVALID_PARAMETER; + } + } + + if(0 != (updateFlags & UpdateOperation_Mac)) + { + uint8_t macAddress[SL_MAC_ADDR_LEN]; + + memcpy(macAddress, config->MacAddress, SL_MAC_ADDR_LEN); + + if(sl_NetCfgSet(SL_NETCFG_MAC_ADDRESS_SET, 1, SL_MAC_ADDR_LEN, (uint8_t*)macAddress) < 0) + { + return CLR_E_FAIL; + } + } + } + + // all changes require SL reinit + sl_Stop(0); + sl_Start(NULL,NULL,NULL); + + return S_OK; +} + +void HAL_SOCK_EventsSet( uint32_t events ) +{ + NATIVE_PROFILE_PAL_NETWORK(); + ASSERT( (events == SOCKET_EVENT_FLAG_SOCKET) || (events == SOCKET_EVENT_FLAG_SOCKETS_READY)); + + Events_Set( SYSTEM_EVENT_FLAG_SOCKET ); +} + +void * HAL_SOCK_GlobalLockContext() +{ + NATIVE_PROFILE_PAL_NETWORK(); + return NULL; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/sockets_simplelink.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/common/sockets_simplelink.cpp new file mode 100644 index 00000000..6d7ad04c --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/sockets_simplelink.cpp @@ -0,0 +1,900 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "simplelink_sockets.h" + +#include +#include +#include + +//--// + +// this is to store the return value of the calls to sockets APIs +int socketErrorCode; + +static int MARSHAL_SOCK_FDSET_TO_SL_SDSET(SOCK_fd_set* sf, SlNetSock_SdSet_t* f) +{ + if(f != NULL && sf != NULL) + { + SlNetSock_sdsClrAll(f); + + for(unsigned int i=0; i < sf->fd_count; i++) + { + SlNetSock_sdsSet(sf->fd_array[i], f); + } + + return sf->fd_count; + } + + return 0; +} + +static void MARSHAL_SL_SDSET_TO_SOCK_FDSET(SOCK_fd_set* sf, SlNetSock_SdSet_t* f) +{ + if(sf != NULL && f != NULL) + { + int cnt = sf->fd_count; + sf->fd_count = 0; + + for(int i=0; ifd_array[i], f)) + { + sf->fd_array[sf->fd_count] = sf->fd_array[i]; + sf->fd_count++; + } + } + } +} + +int GetNativeTcpOption (int optname) +{ + int nativeOptionName = 0; + + switch(optname) + { + case SOCK_TCP_NODELAY: + nativeOptionName = SLNETSOCK_TCP_NODELAY; + break; + + // case SOCK_SOCKO_KEEPALIVE: + // nativeOptionName = TCP_KEEPALIVE; + // break; + + // allow the C# user to specify LWIP options that our managed enum + // doesn't support + default: + nativeOptionName = optname; + break; + } + return nativeOptionName; +} + +int GetNativeSockOption (int optname) +{ + int nativeOptionName = 0; + + switch(optname) + { + case SOCK_SOCKO_DONTLINGER: + case SOCK_SOCKO_LINGER: + nativeOptionName = SLNETSOCK_OPSOCK_LINGER; + break; + // case SOCK_SOCKO_SENDTIMEOUT: + // nativeOptionName = SO_SNDTIMEO; + // break; + case SOCK_SOCKO_RECEIVETIMEOUT: + nativeOptionName = SLNETSOCK_OPSOCK_RCV_TIMEO; + break; + // case SOCK_SOCKO_EXCLUSIVEADDRESSUSE: + // case SOCK_SOCKO_REUSEADDRESS: + // nativeOptionName = SO_REUSEADDR; + // break; + case SOCK_SOCKO_KEEPALIVE: + nativeOptionName = SLNETSOCK_OPSOCK_KEEPALIVE; + break; + case SOCK_SOCKO_ERROR: + nativeOptionName = SLNETSOCK_OPSOCK_ERROR; + break; + case SOCK_SOCKO_BROADCAST: + nativeOptionName = SLNETSOCK_OPSOCK_BROADCAST; + break; + case SOCK_SOCKO_RECEIVEBUFFER: + nativeOptionName = SLNETSOCK_OPSOCK_RCV_BUF; + break; + // case SOCK_SOCKO_SENDBUFFER: + // nativeOptionName = SO_SNDBUF; + // break; + // case SOCK_SOCKO_ACCEPTCONNECTION: + // nativeOptionName = SO_ACCEPTCONN; + // break; + // case SOCK_SOCKO_USELOOPBACK: + // nativeOptionName = SO_USELOOPBACK; + // break; + // case SOCK_SOCKO_DONTROUTE: + // nativeOptionName = SO_DONTROUTE; + // break; + // case SOCK_SOCKO_OUTOFBANDINLINE: + // nativeOptionName = SO_OOBINLINE; + // break; + + // case SOCK_SOCKO_DEBUG: + // nativeOptionName = SO_DEBUG; + // break; + + // case SOCK_SOCKO_SENDLOWWATER: + // nativeOptionName = SO_SNDLOWAT; + // break; + + // case SOCK_SOCKO_RECEIVELOWWATER: + // nativeOptionName = SO_RCVLOWAT; + // break; + + // case SOCK_SOCKO_MAXCONNECTIONS: //don't support + // case SOCK_SOCKO_UPDATE_ACCEPT_CTX: + // case SOCK_SOCKO_UPDATE_CONNECT_CTX: + // nativeOptionName = 0; + // break; + + // allow the C# user to specify LWIP options that our managed enum + // doesn't support + default: + nativeOptionName = optname; + break; + + } + + return nativeOptionName; +} + +int GetNativeIPOption (int optname) +{ + int nativeOptionName = 0; + + switch(optname) + { + // case SOCK_IPO_TTL: + // nativeOptionName = IP_TTL; + // break; + // case SOCK_IPO_TOS: + // nativeOptionName = IP_TOS; + // break; + + // case SOCK_IPO_MULTICAST_IF: + // nativeOptionName = IP_MULTICAST_IF; + // break; + // case SOCK_IPO_MULTICAST_TTL: + // nativeOptionName = SLNETSOCK_OPIP_MULTICAST_TTL; + // break; + // case SOCK_IPO_MULTICAST_LOOP: + // nativeOptionName = IP_MULTICAST_LOOP; + // break; + case SOCK_IPO_ADD_MEMBERSHIP: + nativeOptionName = SLNETSOCK_OPIP_ADD_MEMBERSHIP; + break; + case SOCK_IPO_DROP_MEMBERSHIP: + nativeOptionName = SLNETSOCK_OPIP_DROP_MEMBERSHIP; + break; + + // case SOCK_IPO_ADD_SOURCE_MEMBERSHIP: + // case SOCK_IPO_DROP_SOURCE_MEMBERSHIP: + // case SOCK_IPO_OPTIONS: + // case SOCK_IPO_HDRINCL: + // case SOCK_IPO_IP_DONTFRAGMENT: + // case SOCK_IPO_BLOCK_SOURCE: + // case SOCK_IPO_UBLOCK_SOURCE: + // case SOCK_IPO_PACKET_INFO: + // nativeOptionName = 0; + // break; + + // allow the C# user to specify LWIP options that our managed enum + // doesn't support + default: + nativeOptionName = optname; + break; + } + + return nativeOptionName; +} + +SOCK_SOCKET SOCK_socket( int family, int type, int protocol ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_create(family, type, protocol, 0, 0); + + return socketErrorCode; +} + +int SOCK_bind( SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int addressLen ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_bind( socket, (const SlNetSock_Addr_t*)address, addressLen ); + + return socketErrorCode; +} + +int SOCK_connect(SOCK_SOCKET socket, const struct SOCK_sockaddr* address, int addressLen) +{ + NATIVE_PROFILE_PAL_COM(); + + // Simple Link connect API requires it to be called over and over until connection is established (or fails!) + // See chapter 6.7.1 of CC3X20 Programmer's Guide (doc SWRU455G). + // Our current sockets implementation handles this as blocking connect, so we have to deal with it here + // it's not optimal because it prevents the execution engine from performing task switching + // this should be addressed at the caller level be implementing a timeout execution within the connect code. + + socketErrorCode = -1; + + // loop until socket is connected (or error is returned) + while(socketErrorCode < 0) + { + socketErrorCode = SlNetSock_connect(socket, (const SlNetSock_Addr_t*)address, addressLen); + + if( socketErrorCode == SL_ERROR_BSD_EALREADY ) + { + ClockP_usleep(10*1000); + continue; + } + else if(socketErrorCode < 0) + { + sl_Close(socket); + } + break; + } + + return socketErrorCode; +} + +int SOCK_send(SOCK_SOCKET socket, const char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_send(socket, buf, len, flags); + + return socketErrorCode; +} + +int SOCK_recv(SOCK_SOCKET socket, char* buf, int len, int flags) +{ + NATIVE_PROFILE_PAL_COM(); + + // check for SOCKET_READ_PEEK_OPTION because Simple Link doesn't support this flag + if(flags == SOCKET_READ_PEEK_OPTION) + { + socketErrorCode = SLNETERR_BSD_EINVAL; + } + else + { + socketErrorCode = SlNetSock_recv(socket, buf, len, flags); + } + + return socketErrorCode; +} + +int SOCK_close(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_close(socket); + + return socketErrorCode; +} + +int SOCK_listen( SOCK_SOCKET socket, int backlog ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_listen( socket, backlog ); + + return socketErrorCode; +} + +SOCK_SOCKET SOCK_accept( SOCK_SOCKET socket, struct SOCK_sockaddr* address, int* addressLen ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_accept( socket, (SlNetSock_Addr_t*)address, (SlNetSocklen_t*)addressLen ); + + return socketErrorCode; +} + +int SOCK_shutdown( SOCK_SOCKET socket, int how ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_shutdown( socket, how ); + + return socketErrorCode; +} + +int SOCK_getaddrinfo( const char* nodename, char* servname, const struct SOCK_addrinfo* hints, struct SOCK_addrinfo** res ) +{ + NATIVE_PROFILE_PAL_COM(); + + SOCK_addrinfo *ai; + SOCK_sockaddr_in *sa = NULL; + int total_size = sizeof(SOCK_addrinfo) + sizeof(SOCK_sockaddr_in); + struct SlNetUtil_addrInfo_t* addrInfo = NULL; + + if(res == NULL) return SOCK_SOCKET_ERROR; + + *res = NULL; + + // if the nodename == "" then return the IP address of this device + if(nodename[0] == 0 && servname == NULL) + { + uint16_t configOptions; + uint16_t ipLen = sizeof(SlNetCfgIpV4Args_t); + SlNetCfgIpV4Args_t ipV4 = {0}; + + if (sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE, &configOptions, &ipLen, (uint8_t *)&ipV4) >= 0) + { + ai = (SOCK_addrinfo*)platform_malloc(total_size); + + if (ai != NULL) + { + memset(ai, 0, total_size); + sa = (SOCK_sockaddr_in*)((uint8_t*)ai + sizeof(SOCK_addrinfo)); + + /* set up sockaddr */ + #if LWIP_IPV6 + // TODO + //sa->sin_addr.S_un.S_addr = networkInterface->ip_addr.u_addr.ip4.addr; + #else + sa->sin_addr.S_un.S_addr = sl_Ntohl(ipV4.Ip); + #endif + + sa->sin_family = SL_AF_INET; + sa->sin_port = 0; + + // set up addrinfo + ai->ai_family = SL_AF_INET; + if (hints != NULL) + { + // copy socktype & protocol from hints if specified + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + + ai->ai_addrlen = sizeof(SOCK_sockaddr_in); + ai->ai_addr = (SOCK_sockaddr*)sa; + + *res = ai; + + return 0; + } + } + } + else + { + int err = SlNetUtil_getAddrInfo(0, nodename, servname, (SlNetUtil_addrInfo_t*)hints, &addrInfo ); + socketErrorCode = err; + + if(err >= 0) + { + /// + /// Marshal addrinfo data + /// + SlNetSock_AddrIn_t* sockaddr_in; + + ai = (SOCK_addrinfo*)platform_malloc(total_size); + if (ai == NULL) + { + SlNetUtil_freeAddrInfo(addrInfo); + } + else + { + memset(ai, 0, total_size); + + sockaddr_in = (SlNetSock_AddrIn_t*)addrInfo->ai_addr; + + sa = (SOCK_sockaddr_in*)((uint8_t*)ai + sizeof(SOCK_addrinfo)); + /* set up sockaddr */ + sa->sin_addr.S_un.S_addr = sockaddr_in->sin_addr.s_addr; + sa->sin_family = sockaddr_in->sin_family; + sa->sin_port = sockaddr_in->sin_port; + + /* set up addrinfo */ + ai->ai_family = addrInfo->ai_family; + if (hints != NULL) + { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + + ai->ai_addrlen = sizeof(SOCK_sockaddr_in); + ai->ai_addr = (SOCK_sockaddr*)sa; + + *res = ai; + + // free marshalled addrinfo + SlNetUtil_freeAddrInfo(addrInfo); + + return 0; + } + } + } + + return SOCK_SOCKET_ERROR; +} + +void SOCK_freeaddrinfo( struct SOCK_addrinfo* ai ) +{ + NATIVE_PROFILE_PAL_COM(); + SlNetUtil_freeAddrInfo( (SlNetUtil_addrInfo_t*)ai ); +} + +int SOCK_ioctl( SOCK_SOCKET socket, int cmd, int* data ) +{ + NATIVE_PROFILE_PAL_COM(); + + if(cmd == SOCK_FIONBIO) + { + // adjust setting for socket blocking/non-blocking + SlNetSock_Nonblocking_t enableOption; + enableOption.nonBlockingEnabled = *data; + + socketErrorCode = SlNetSock_setOpt(socket, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_NON_BLOCKING, (uint8_t *)&enableOption, sizeof(enableOption)); + + return socketErrorCode; + } + else if(cmd == SOCK_IPPROTO_TCP) + { + // TODO + HAL_AssertEx(); + } + else if(cmd == SOCK_SOL_SOCKET) + { + // TODO + HAL_AssertEx(); + } + + // unknown command + return -1; +} + +int SOCK_getlasterror() +{ + NATIVE_PROFILE_PAL_COM(); + // FIXME + return 0;//SlNetSock_getlasterror(); +} + +int SOCK_getsocklasterror(SOCK_SOCKET socket) +{ + NATIVE_PROFILE_PAL_COM(); + + int errorNo; + + if(socketErrorCode >= 0) + { + return socketErrorCode; + } + + /* This switch case block is necessary for translating the SlNetSock error codes + * to BSD ones. The #ifdef in each case are made in order to reduce code footprint: + * This cases are compiled if and only if there's a discrepancy between the BSD error + * number and the error code returned by the SlNetSock layer. + */ + switch(socketErrorCode) + { +#if EBADF != SLNETERR_BSD_EBADF + case SLNETERR_BSD_EBADF: + errorNo = EBADF; + break; +#endif +#if ENFILE != SLNETERR_BSD_ENSOCK + case SLNETERR_BSD_ENSOCK: + errorNo = ENFILE; + break; +#endif +#if EAGAIN != SLNETERR_BSD_EAGAIN + case SLNETERR_BSD_EAGAIN: + errorNo = EAGAIN; + break; +#endif +#if ENOMEM != SLNETERR_BSD_ENOMEM + case SLNETERR_BSD_ENOMEM: + errorNo = ENOMEM; + break; +#endif +#if EACCES != SLNETERR_BSD_EACCES + case SLNETERR_BSD_EACCES: + errorNo = EACCES; + break; +#endif +#if EFAULT != SLNETERR_BSD_EFAULT + case SLNETERR_BSD_EFAULT: + errorNo = EFAULT; + break; +#endif +#if EINVAL != SLNETERR_BSD_EINVAL + case SLNETERR_BSD_EINVAL: + errorNo = EINVAL; + break; +#endif +#if EDESTADDRREQ != SLNETERR_BSD_EDESTADDRREQ + case SLNETERR_BSD_EDESTADDRREQ: + errorNo = EDESTADDRREQ; + break; +#endif +#if EPROTOTYPE != SLNETERR_BSD_EPROTOTYPE + case SLNETERR_BSD_EPROTOTYPE: + errorNo = EPROTOTYPE; + break; +#endif +#if ENOPROTOOPT != SLNETERR_BSD_ENOPROTOOPT + case SLNETERR_BSD_ENOPROTOOPT: + errorNo = ENOPROTOOPT; + break; +#endif +#if EPROTONOSUPPORT != SLNETERR_BSD_EPROTONOSUPPORT + case SLNETERR_BSD_EPROTONOSUPPORT: + errorNo = EPROTONOSUPPORT; + break; +#endif +#if EOPNOTSUPP != SLNETERR_BSD_EOPNOTSUPP + case SLNETERR_BSD_EOPNOTSUPP: + errorNo = EOPNOTSUPP; + break; +#endif +#if EAFNOSUPPORT != SLNETERR_BSD_EAFNOSUPPORT + case SLNETERR_BSD_EAFNOSUPPORT: + errorNo = EAFNOSUPPORT; + break; +#endif +#if EADDRINUSE != SLNETERR_BSD_EADDRINUSE + case SLNETERR_BSD_EADDRINUSE: + errorNo = EADDRINUSE; + break; +#endif +#if EADDRNOTAVAIL != SLNETERR_BSD_EADDRNOTAVAIL + case SLNETERR_BSD_EADDRNOTAVAIL: + errorNo = EADDRNOTAVAIL; + break; +#endif +#if ENETDOWN != SLNETERR_BSD_ENETDOWN + case SLNETERR_BSD_ENETDOWN: + errorNo = ENETDOWN; + break; +#endif +#if ENETUNREACH != SLNETERR_BSD_ENETUNREACH + case SLNETERR_BSD_ENETUNREACH: + errorNo = ENETUNREACH; + break; +#endif +#if ENOBUFS != SLNETERR_BSD_ENOBUFS + case SLNETERR_BSD_ENOBUFS: + errorNo = ENOBUFS; + break; +#endif +#if EISCONN != SLNETERR_BSD_EISCONN + case SLNETERR_BSD_EISCONN: + errorNo = EISCONN; + break; +#endif +#if ENOTCONN != SLNETERR_BSD_ENOTCONN + case SLNETERR_BSD_ENOTCONN: + errorNo = ENOTCONN; + break; +#endif +#if ETIMEDOUT != SLNETERR_BSD_ETIMEDOUT + case SLNETERR_BSD_ETIMEDOUT: + errorNo = ETIMEDOUT; + break; +#endif +#if ECONNREFUSED != SLNETERR_BSD_ECONNREFUSED + case SLNETERR_BSD_ECONNREFUSED: + errorNo = ECONNREFUSED; + break; +#endif + case SL_ERROR_BSD_EALREADY: + errorNo = SOCK_EWOULDBLOCK; + break; + + /* The cases below are propriety driver errors, which can + * be returned by the SimpleLink Driver, in various cases of failure. + * Each is mapped to the corresponding BSD error. + */ + case SLNETERR_POOL_IS_EMPTY: + case SLNETERR_RET_CODE_NO_FREE_SPACE: + case SLNETERR_RET_CODE_MUTEX_CREATION_FAILED: + case SLNETERR_RET_CODE_MALLOC_ERROR: + errorNo = ENOMEM; + break; + case SLNETERR_RET_CODE_INVALID_INPUT: + case SLNETERR_EZEROLEN: + case SLNETERR_ESMALLBUF: + case SLNETERR_INVALPARAM: + errorNo = EINVAL; + break; + case SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN: + errorNo = EOPNOTSUPP; + break; + case SLNETERR_RET_CODE_COULDNT_FIND_RESOURCE: + errorNo = EBADF; + break; + default: + /* Do nothing .. + * If no case is true, that means that the BSD error + * code and the code returned by the NWP are either identical, + * or no propriety error has occurred. + */ + break; + } + + return errorNo; +} + +int SOCK_select( int nfds, SOCK_fd_set* readfds, SOCK_fd_set* writefds, SOCK_fd_set* exceptfds, const struct SOCK_timeval* timeout ) +{ + NATIVE_PROFILE_PAL_COM(); + + int ret = 0; + uint32_t networkInterfaceID; + + // If the network goes down then we should alert any pending socket actions + if(exceptfds != NULL && exceptfds->fd_count > 0) + { + // find the network interface for this socket + // the socket handle is "burried" inside the exceptfds struct (see the caller code in Helper__SelectSocket) + networkInterfaceID = SlNetSock_getIfID(exceptfds->fd_array[0]); + if ( networkInterfaceID == SLNETERR_RET_CODE_INVALID_INPUT ) + { + socketErrorCode = ENOTSOCK; + + return SOCK_SOCKET_ERROR; + } + + if ( SlNetIf_getConnectionStatus(networkInterfaceID) == SLNETIF_STATUS_DISCONNECTED ) + { + if(readfds != NULL) + { + readfds->fd_count = 0; + } + if(writefds != NULL) + { + writefds->fd_count = 0; + } + + socketErrorCode = ENETDOWN; + + return exceptfds->fd_count; + } + } + + // developer note: + // The original code, being lwIP based, uses the convention that 0 is infinite timeout + // Because SimpleLink infinite timeout is negative or NULL we need to translate it. + SlNetSock_Timeval_t timeoutCopy; + bool isInfiniteTimeout = false; + + if(timeout->tv_sec > 0 || timeout->tv_usec > 0) + { + timeoutCopy.tv_sec = timeout->tv_sec; + timeoutCopy.tv_usec = timeout->tv_usec; + } + else + { + isInfiniteTimeout = true; + } + + ret = SlNetSock_select( + SLNETSOCK_MAX_CONCURRENT_SOCKETS, + (SlNetSock_SdSet_t*)readfds, + (SlNetSock_SdSet_t*)writefds, + (SlNetSock_SdSet_t*)exceptfds, + isInfiniteTimeout ? NULL : &timeoutCopy ); + + socketErrorCode = ret; + + // developer notes: + // SlNetSock_select() call doesn't touch the exception SDSET. + // In SimpleLink socket exceptions are handled differently. + // We need to clear that one here because the way the caller is implemented it will think there is an exception + // because it has forced it. + SlNetSock_sdsClrAll((SlNetSock_SdSet_t*)exceptfds); + + return ret; +} + +int SOCK_setsockopt( SOCK_SOCKET socket, int level, int optname, const char* optval, int optlen ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_setOpt( socket, level, optname, (void *) optval, optlen ); + + return socketErrorCode; +} + +int SOCK_getsockopt( SOCK_SOCKET socket, int level, int optname, char* optval, int* optlen ) +{ + NATIVE_PROFILE_PAL_COM(); + + int nativeLevel; + int nativeOptionName; + char* pNativeOptval = optval; + int ret; + + switch(level) + { + case SOCK_IPPROTO_IP: + nativeLevel = SLNETSOCK_LVL_PHY; + nativeOptionName = GetNativeIPOption(optname); + break; + case SOCK_IPPROTO_TCP: + nativeLevel = SLNETSOCK_PROTO_TCP; + nativeOptionName = GetNativeTcpOption(optname); + break; + case SOCK_IPPROTO_UDP: + case SOCK_IPPROTO_ICMP: + case SOCK_IPPROTO_IGMP: + case SOCK_IPPROTO_IPV4: + case SOCK_SOL_SOCKET: + nativeLevel = SLNETSOCK_LVL_SOCKET; + nativeOptionName = GetNativeSockOption(optname); + break; + default: + nativeLevel = level; + nativeOptionName = optname; + break; + } + + socketErrorCode = SlNetSock_getOpt( socket, nativeLevel, nativeOptionName, (void *)pNativeOptval, (SlNetSocklen_t *)optlen ); + + if(socketErrorCode == 0) + { + switch(level) + { + case SOCK_SOL_SOCKET: + switch(optname) + { + case SOCK_SOCKO_EXCLUSIVEADDRESSUSE: + case SOCK_SOCKO_DONTLINGER: + *optval = !(*(int*)optval != 0); + break; + + case SOCK_SOCKO_ACCEPTCONNECTION: + case SOCK_SOCKO_BROADCAST: + case SOCK_SOCKO_KEEPALIVE: + *optval = (*(int*)optval != 0); + break; + } + break; + } + } + + return socketErrorCode; +} + +int SOCK_getpeername( SOCK_SOCKET socket, struct SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_getPeerName( socket, (SlNetSock_Addr_t*)name, (SlNetSocklen_t*)namelen ); + + return socketErrorCode; +} + +int SOCK_getsockname( SOCK_SOCKET socket, struct SOCK_sockaddr* name, int* namelen ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_getSockName( socket, (SlNetSock_Addr_t*)name, (SlNetSocklen_t*)namelen ); + + return socketErrorCode; +} + +int SOCK_recvfrom( SOCK_SOCKET s, char* buf, int len, int flags, struct SOCK_sockaddr* from, int* fromlen ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_recvFrom( s, buf, len, flags, (SlNetSock_Addr_t*)from, (SlSocklen_t*)fromlen ); + + return socketErrorCode; +} + +int SOCK_sendto( SOCK_SOCKET s, const char* buf, int len, int flags, const struct SOCK_sockaddr* to, int tolen ) +{ + NATIVE_PROFILE_PAL_COM(); + + socketErrorCode = SlNetSock_sendTo( s, buf, len, flags, (SlNetSock_Addr_t*)to, (SlSocklen_t)tolen ); + + return socketErrorCode; +} + +bool Network_Initialize() +{ + NATIVE_PROFILE_PAL_COM(); + + // call our equivalent to lwIP driver + return SimpleLink_SOCKETS_Initialize(); + + // network initialization is taken care of by SimpleLink + return true; +} + +bool Network_Uninitialize() +{ + NATIVE_PROFILE_PAL_COM(); + + // not required SimpleLink + return true; +} + +void SOCKETS_CloseConnections() +{ + NATIVE_PROFILE_PAL_COM(); + // FIXME + //Sockets_SimpleLink_Driver::CloseConnections(FALSE); +} + +HRESULT SOCK_CONFIGURATION_LoadAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex) +{ + NATIVE_PROFILE_PAL_COM(); + return HAL_SOCK_CONFIGURATION_LoadAdapterConfiguration(config, interfaceIndex); +} + +HRESULT SOCK_CONFIGURATION_UpdateAdapterConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex, uint32_t updateFlags) +{ + NATIVE_PROFILE_PAL_COM(); + HRESULT hr = S_OK; + bool success = FALSE; + + const uint32_t c_reInitFlag = UpdateOperation_Dhcp | + UpdateOperation_DhcpRenew | + UpdateOperation_Mac; + + const uint32_t c_uninitFlag = c_reInitFlag | UpdateOperation_DhcpRelease; + + if(0 != (updateFlags & c_uninitFlag)) + { + success = SOCKETS_DbgUninitialize(COM_SOCKET_DBG); + } + + hr = HAL_SOCK_CONFIGURATION_UpdateAdapterConfiguration(config, interfaceIndex, updateFlags); + + if(!SUCCEEDED(hr)) + { + return S_FALSE; + } + + if(0 != (updateFlags & c_reInitFlag)) + { + if(success) SOCKETS_DbgInitialize(COM_SOCKET_DBG); + } + + return hr; +} + +HRESULT SOCK_CONFIGURATION_LoadConfiguration(HAL_Configuration_NetworkInterface* config, uint32_t interfaceIndex) +{ + NATIVE_PROFILE_PAL_COM(); + HRESULT hr = S_OK; + + // load current DCHP settings + hr = SOCK_CONFIGURATION_LoadAdapterConfiguration(config, interfaceIndex); + + return hr; +} + +bool SOCKETS_DbgInitialize( int ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + + return true; +} + +bool SOCKETS_DbgUninitialize( int ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + + return true; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/ssl_simplelink.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/common/ssl_simplelink.cpp new file mode 100644 index 00000000..8b2935df --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/ssl_simplelink.cpp @@ -0,0 +1,416 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include + +#include +#include +#include + +//--// + +// need to declare this here because the SimpleLink header doesn't have the appropriate C++ wrappers +extern "C" +{ + int32_t ClockSync_convert(uint32_t gmTime, struct tm *localTime); +} + +// TODO +bool ssl_parse_certificate_internal( + void* buf, + size_t size, + void* pwd, + void* x509 ) +{ + (void)buf; + (void)size; + (void)pwd; + (void)x509; +} + +int ssl_decode_private_key_internal( + const unsigned char *key, + size_t keyLength, + const unsigned char *password, + size_t passwordLength) +{ + (void)key; + (void)keyLength; + (void)password; + (void)passwordLength; + + return 0; +} + +int ssl_accept_internal( + int socket, + int contextHandle ) +{ + (void)socket; + (void)contextHandle; +} + +bool ssl_add_cert_auth_internal( + int contextHandle, + const char* certificate, + int certLength, + const char* certPassword ) +{ + (void)contextHandle; + (void)certificate; + (void)certLength; + (void)certPassword; + +} + +// declared at sockets_simplelink +extern int socketErrorCode; + +extern "C" +{ +void ssl_rand_seed( + const void *seed, + int length) +{ + (void)seed; + (void)length; +} +} + +bool ssl_initialize_internal() +{ + memset(&g_SSL_Driver, 0, sizeof(g_SSL_Driver)); + + return true; +} + +bool ssl_generic_init_internal( + int sslMode, + int sslVerify, + const char* certificate, + int certLength, + const uint8_t* privateKey, + int privateKeyLength, + const char* password, + int passwordLength, + int& contextHandle, + bool isServer ) +{ + (void)password; + (void)passwordLength; + (void)privateKey; + (void)privateKeyLength; + + int sslContexIndex = -1; + + SlSSL_Context* context; + SlNetSockSecAttrib_e attribName; + int32_t status; + uint32_t dummyVal = 1; + uint8_t securityMethod; + uint32_t securityCypher = SLNETSOCK_SEC_CIPHER_FULL_LIST; + + // we only have one CA root bundle, so this is fixed to 0 + uint32_t configIndex = 0; + + /////////////////////// + for(uint32_t i=0; iSecurityAttributes = SlNetSock_secAttribCreate(); + if (context->SecurityAttributes == NULL) + { + goto error; + } + + context->IsServer = isServer; + + // configure protocol + switch((SslProtocols)sslMode) + { + case SslProtocols_TLSv1: + securityMethod = SLNETSOCK_SEC_METHOD_TLSV1; + break; + + case SslProtocols_TLSv11: + securityMethod = SLNETSOCK_SEC_METHOD_TLSV1_1; + break; + + case SslProtocols_TLSv12: + securityMethod = SLNETSOCK_SEC_METHOD_TLSV1_2; + break; + + default: + // shouldn't reach here! + goto error; + } + + status = SlNetSock_secAttribSet(context->SecurityAttributes, SLNETSOCK_SEC_ATTRIB_METHOD, (void *)&(securityMethod), sizeof(securityMethod)); + if (status < 0) + { + goto error; + } + + // enable all cyphers (this is Simple Link default, so nothing to do about this) + + // CA root certs are taken from Simple Link trusted root-certificate catalog, so nothing to do here + + // // parse "own" certificate if passed + // if(certificate != NULL && certLength > 0) + // { + // // TODO + // // this isn't required for client authentication + + // // mbedtls_x509_crt_init( &clicert ); + + // // ///////////////////////////////////////////////////////////////////////////////////////////////// + // // // developer notes: // + // // // this call parses certificates in both string and binary formats // + // // // when the formart is a string it has to include the terminator otherwise the parse will fail // + // // ///////////////////////////////////////////////////////////////////////////////////////////////// + // // if(mbedtls_x509_crt_parse( &clicert, (const unsigned char*)certificate, certLength ) != 0) + // // { + // // // x509_crt_parse_failed + // // goto error; + // // } + + // // if( mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key, mbedtls_test_cli_key_len, NULL, 0 ) != 0) + // // { + // // // failed parsing the + // // } + + // // if( mbedtls_tls_conf_own_cert( &conf, &clicert, &pkey ) != 0 ) + // // { + // // // configuring own certificate failed + // // goto error; + // // } + // } + + // set certificate verification + // the current options provided by Simple Link API are only verify or don't verify + if((SslVerification)sslVerify == SslVerification_NoVerification) + { + status = SlNetSock_secAttribSet(context->SecurityAttributes, SLNETSOCK_SEC_ATTRIB_DISABLE_CERT_STORE, (void *)&dummyVal, sizeof(dummyVal)); + if (status < 0) + { + goto error; + } + } + + ////////////////////////////////////// + + // the equivalent of SSL contex in Simple Link is the Security Attribute that we've been building + g_SSL_Driver.ContextArray[sslContexIndex].Context = context; + g_SSL_Driver.ContextCount++; + + contextHandle = sslContexIndex; + + return true; + + error: + + // check for any memory allocation that needs to be freed before exiting + if(context != NULL) + { + platform_free(context); + } + + if(context->SecurityAttributes != NULL) + { + SlNetSock_secAttribDelete(context->SecurityAttributes); + } + + return false; +} + +bool ssl_exit_context_internal(int contextHandle) +{ + SlSSL_Context* context = NULL; + + // Check contextHandle range + if((contextHandle >= (int)ARRAYSIZE(g_SSL_Driver.ContextArray)) || (contextHandle < 0) || (g_SSL_Driver.ContextArray[contextHandle].Context == NULL)) + { + return false; + } + + context = (SlSSL_Context*)g_SSL_Driver.ContextArray[contextHandle].Context; + if (context == NULL) + { + return false; + } + + SlNetSock_secAttribDelete(context->SecurityAttributes); + + platform_free(context); + + memset(&g_SSL_Driver.ContextArray[contextHandle], 0, sizeof(g_SSL_Driver.ContextArray[contextHandle])); + + g_SSL_Driver.ContextCount --; + + return true; +} + +int ssl_connect_internal( + int sd, + const char* szTargetHost, + int contextHandle) +{ + SlSSL_Context* context; + int32_t status; + struct timespec ts; + struct tm rtcTime; + + // Check contextHandle range + if((contextHandle >= (int)ARRAYSIZE(g_SSL_Driver.ContextArray)) || (contextHandle < 0)) + { + return SOCK_SOCKET_ERROR; + } + + // Retrieve SSL context from g_SSL_Driver + // sd should already have been created + // Now do the SSL negotiation + context = (SlSSL_Context*)g_SSL_Driver.ContextArray[contextHandle].Context; + if (context == NULL) + { + return SOCK_SOCKET_ERROR; + } + + // set socket in network context + context->SocketFd = sd; + + if(szTargetHost != NULL && szTargetHost[0] != 0) + { + status = SlNetSock_secAttribSet( + context->SecurityAttributes, + SLNETSOCK_SEC_ATTRIB_DOMAIN_NAME, + (void *)szTargetHost, + hal_strlen_s(szTargetHost)); + if (status < 0) + { + // hostname_failed + return status; + } + } + + // in order to validate certificates, the device has to have it's date/time set + // get current time + clock_gettime(CLOCK_REALTIME, &ts); + + // need to convert between structs + ClockSync_convert(ts.tv_sec, &rtcTime); + + SlDateTime_t dateTime; + dateTime.tm_sec = rtcTime.tm_sec; + dateTime.tm_min = rtcTime.tm_min; + dateTime.tm_hour = rtcTime.tm_hour; + dateTime.tm_day = rtcTime.tm_mday; + // tm_mon starts month 0 + dateTime.tm_mon = rtcTime.tm_mon + 1; + // tm_year starts in 1970 + dateTime.tm_year = rtcTime.tm_year + 1970; + + sl_DeviceSet( + SL_DEVICE_GENERAL, + SL_DEVICE_GENERAL_DATE_TIME, + sizeof(SlDateTime_t), + (uint8_t *)(&dateTime)); + + // DON'T setup socket for blocking operation + + // start security context on socket + status = SlNetSock_startSec( + context->SocketFd, + context->SecurityAttributes, context->IsServer ? + (SLNETSOCK_SEC_START_SECURITY_SESSION_ONLY | SLNETSOCK_SEC_IS_SERVER) : + (SLNETSOCK_SEC_START_SECURITY_SESSION_ONLY | SLNETSOCK_SEC_BIND_CONTEXT_ONLY)); + + if ( (status < 0) && + (status != SLNETERR_ESEC_UNKNOWN_ROOT_CA) && + (status != SLNETERR_ESEC_HAND_SHAKE_TIMED_OUT) && + (status != SLNETERR_ESEC_DATE_ERROR) && + (status != SLNETERR_ESEC_SNO_VERIFY)) + { + return status; + } + + // got here, handshake is completed + + return 0; +} + +int ssl_pending_internal( int sd ) +{ + // Simple Link doesn't have an API to check for pending data + // just return 0 + return 0; +} + +int ssl_write_internal( + int sd, + const char* data, + size_t req_len) +{ + int32_t status; + + socketErrorCode = SlNetSock_send( + sd, + (const void*)data, + req_len, + 0); + + // anything below 0 is considered an error, so we have to report that no bytes were sent + if (socketErrorCode < 0) + { + return 0; + } + + return req_len; +} + +int ssl_read_internal( + int sd, + char* data, + size_t size ) +{ + socketErrorCode = SlNetSock_recv( + sd, + (unsigned char *)(data), + size, + 0); + + return socketErrorCode; +} + +int ssl_close_socket_internal( int sd ) +{ + // Simple Link takes care of everything for us, just call close socket + SOCK_close( sd ); + + return true; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/syscalls.c b/source/native/nf-interpreter/targets/TI-SimpleLink/common/syscalls.c new file mode 100644 index 00000000..e56deb95 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/syscalls.c @@ -0,0 +1,45 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// these are stubs to keep the linker happy when these are pulled in + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * _gettimeofday primitive (Stub function) + * */ + +/* + * Structure used in select() call, taken from the BSD file sys/time.h. + */ +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int _gettimeofday (struct timeval * tp, struct timezone * tzp) +{ + (void)tp; + + /* Return fixed data for the timezone. */ + if (tzp) + { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/common/targetHAL_ConfigurationManager_CC32xx.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/common/targetHAL_ConfigurationManager_CC32xx.cpp new file mode 100644 index 00000000..15808c7e --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/common/targetHAL_ConfigurationManager_CC32xx.cpp @@ -0,0 +1,512 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include +#include + +typedef struct +{ + SlFileAttributes_t attribute; + char fileName[SL_FS_MAX_FILE_NAME_LENGTH]; +}slGetfileList_t; + +// This configuration manager implementation is valid for CC32xx devices. +// Because everything that is meant to be stored in the configure block is handled by the SimpleLink +// persistent storage, this code is either empty or acts as a proxy to the SimpleLink API + +// network configuration blocks are stored as files in file storage +void* ConfigurationManagerCC32xx_FindNetworkConfigurationBlocks() +{ + int32_t ret = 1; + int32_t retGetFileList = 1; + slGetfileList_t* fileList; + int32_t index = -1; + + int32_t i; + uint32_t fileCount = 0; + + // allocate memory for file list buffer + fileList = (slGetfileList_t*)platform_malloc(sizeof(slGetfileList_t) * NETWORK_CONFIG_MAX_COUNT); + + // check succesfull malloc + if (fileList == NULL) + { + return NULL; + } + + // clear memory + memset(fileList, 0x0, sizeof(sizeof(SlFileAttributes_t) * NETWORK_CONFIG_MAX_COUNT)); + + // first pass: find out how many files of this type we have + while(retGetFileList > 0) + { + retGetFileList = sl_FsGetFileList( &index, NETWORK_CONFIG_MAX_COUNT, + (uint8_t)(SL_FS_MAX_FILE_NAME_LENGTH + sizeof(SlFileAttributes_t)), + (unsigned char*)fileList, SL_FS_GET_FILE_ATTRIBUTES); + if (retGetFileList < 0) + { + // error getting file list, or no more files + break; + } + + for (i = 0; i < retGetFileList; i++) + { + // check file name + if(memcmp(fileList[i].fileName, NETWORK_CONFIG_FILE_NAME, sizeof(NETWORK_CONFIG_FILE_NAME)) == 0) + { + fileCount++; + } + } + } + + // allocate config struct + HAL_CONFIGURATION_NETWORK *networkConfigs = (HAL_CONFIGURATION_NETWORK *)platform_malloc(offsetof(HAL_CONFIGURATION_NETWORK, Configs) + fileCount * sizeof(networkConfigs->Configs[0])); + // set collection count + networkConfigs->Count = fileCount; + + // clear memory for file list + platform_free(fileList); + + return networkConfigs; +} + +// wireless profiles are stored as SimpleLink WLAN profile +void* ConfigurationManagerCC32xx_FindNetworkWireless80211ConfigurationBlocks() +{ + int16_t index, status; + signed char name[32]; + int16_t nameLength; + unsigned char macAddr[6]; + SlWlanSecParams_t secParams; + SlWlanGetSecParamsExt_t secExtParams; + uint32_t priority; + uint16_t profileCount = 0; + + // first pass: find out how many profiles are stored + for(index = 0; index < SL_WLAN_MAX_PROFILES; index++) + { + status = sl_WlanProfileGet(index, name, &nameLength, macAddr, &secParams, &secExtParams, &priority); + if( status >= 0) + { + profileCount++; + } + } + + // allocate config struct + HAL_CONFIGURATION_NETWORK_WIRELESS80211 *networkWirelessConfigs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211 *)platform_malloc(offsetof(HAL_CONFIGURATION_NETWORK_WIRELESS80211, Configs) + profileCount * sizeof(networkWirelessConfigs->Configs[0])); + + // set collection count + networkWirelessConfigs->Count = profileCount; + + return networkWirelessConfigs; +} + +// initialization of configuration manager +void ConfigurationManager_Initialize() +{ + memset( (void*)&g_TargetConfiguration, 0, sizeof(g_TargetConfiguration)); + + // enumerate the blocks + ConfigurationManager_EnumerateConfigurationBlocks(); +}; + +// Enumerates the configuration blocks from the configuration flash sector +void ConfigurationManager_EnumerateConfigurationBlocks() +{ + // find network configuration blocks + HAL_CONFIGURATION_NETWORK* networkConfigs = (HAL_CONFIGURATION_NETWORK*)ConfigurationManagerCC32xx_FindNetworkConfigurationBlocks(); + + // check network configs count + if(networkConfigs->Count == 0) + { + // there is no network config block available, get a default + HAL_Configuration_NetworkInterface* networkConfig = (HAL_Configuration_NetworkInterface*)platform_malloc(sizeof(HAL_Configuration_NetworkInterface)); + if(InitialiseNetworkDefaultConfig(networkConfig, 0)) + { + // config block created, store it + ConfigurationManager_StoreConfigurationBlock(networkConfig, DeviceConfigurationOption_Network, 0, sizeof(HAL_Configuration_NetworkInterface), 0); + + // have to enumerate again to pick it up + networkConfigs = (HAL_CONFIGURATION_NETWORK*)ConfigurationManagerCC32xx_FindNetworkConfigurationBlocks(); + } + + platform_free(networkConfig); + } + + // find wireless 80211 network configuration blocks + HAL_CONFIGURATION_NETWORK_WIRELESS80211* networkWirelessConfigs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211*)ConfigurationManagerCC32xx_FindNetworkWireless80211ConfigurationBlocks(); + + // // find X509 certificate blocks + // HAL_CONFIGURATION_X509_CERTIFICATE* certificateStore = (HAL_CONFIGURATION_X509_CERTIFICATE*)ConfigurationManager_FindX509CertificateConfigurationBlocks((uint32_t)&__nanoConfig_start__, (uint32_t)&__nanoConfig_end__); + + // alloc memory for g_TargetConfiguration + // because this is a struct of structs that use flexible members the memory has to be allocated from the heap + // the malloc size for each struct is computed separately + uint32_t sizeOfNetworkInterfaceConfigs = offsetof(HAL_CONFIGURATION_NETWORK, Configs) + networkConfigs->Count * sizeof(networkConfigs->Configs[0]); + uint32_t sizeOfWireless80211Configs = offsetof(HAL_CONFIGURATION_NETWORK_WIRELESS80211, Configs) + networkWirelessConfigs->Count * sizeof(networkWirelessConfigs->Configs[0]); + // uint32_t sizeOfX509CertificateStore = offsetof(HAL_CONFIGURATION_X509_CERTIFICATE, Certificates) + certificateStore->Count * sizeof(certificateStore->Certificates[0]); + + g_TargetConfiguration.NetworkInterfaceConfigs = (HAL_CONFIGURATION_NETWORK*)platform_malloc(sizeOfNetworkInterfaceConfigs); + g_TargetConfiguration.Wireless80211Configs = (HAL_CONFIGURATION_NETWORK_WIRELESS80211*)platform_malloc(sizeOfWireless80211Configs); + // g_TargetConfiguration.CertificateStore = (HAL_CONFIGURATION_X509_CERTIFICATE*)platform_malloc(sizeOfX509CertificateStore); + + // copy structs to g_TargetConfiguration + memcpy((HAL_CONFIGURATION_NETWORK*)g_TargetConfiguration.NetworkInterfaceConfigs, networkConfigs, sizeOfNetworkInterfaceConfigs); + memcpy((HAL_CONFIGURATION_NETWORK_WIRELESS80211*)g_TargetConfiguration.Wireless80211Configs, networkWirelessConfigs, sizeOfWireless80211Configs); + // memcpy((HAL_CONFIGURATION_X509_CERTIFICATE*)g_TargetConfiguration.CertificateStore, certificateStore, sizeOfX509CertificateStore); + + // now free the memory of the original structs + platform_free(networkConfigs); + platform_free(networkWirelessConfigs); + // platform_free(certificateStore); +} + +EncryptionType GetEncryption(SlWlanSecParams_t secParams) +{ + switch (secParams.Type) + { + case SL_WLAN_SEC_TYPE_WEP: + return EncryptionType_WEP; + + // deprecated + // case SL_WLAN_SEC_TYPE_WPA: + // return EncryptionType_WPA; + + case SL_WLAN_SEC_TYPE_WPA_WPA2: + return EncryptionType_WPA2; + + default: + return EncryptionType_None; + } +} + +AuthenticationType GetAuthentication(SlWlanSecParams_t secParams) +{ + switch (secParams.Type) + { + case SL_WLAN_SEC_TYPE_OPEN: + return AuthenticationType_Open; + + case SL_WLAN_SEC_TYPE_WEP: + return AuthenticationType_WEP; + + // deprecated + // case SL_WLAN_SEC_TYPE_WPA: + // return AuthenticationType_WPA; + + case SL_WLAN_SEC_TYPE_WPA_WPA2: + return AuthenticationType_WPA2; + + case SL_WLAN_SEC_TYPE_WEP_SHARED: + return AuthenticationType_Shared; + + default: + return AuthenticationType_None; + } +} + +// Gets the network configuration block from the configuration flash sector +bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + unsigned char* fileName = NULL; + + int32_t fileHandle; + uint32_t token = 0; + int32_t retVal; + SlWlanSecParams_t secParams; + int16_t dummyNameLen; + uint8_t dummyMAC[SL_MAC_ADDR_LEN]; + uint32_t dummyPriority; + + HAL_Configuration_Wireless80211* wirelessConfigBlock = NULL; + + + // validate if the requested block exists + // Count has to be non zero + // requested Index has to exist (array index starts at zero, so need to add one) + if(configuration == DeviceConfigurationOption_Network) + { + if( g_TargetConfiguration.NetworkInterfaceConfigs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.NetworkInterfaceConfigs->Count) + { + // the requested config block is beyond the available count + return false; + } + } + else if(configuration == DeviceConfigurationOption_Wireless80211Network) + { + if(g_TargetConfiguration.Wireless80211Configs->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.Wireless80211Configs->Count) + { + return false; + } + } + else if(configuration == DeviceConfigurationOption_X509CaRootBundle) + { + if(g_TargetConfiguration.CertificateStore->Count == 0 || + (configurationIndex + 1) > g_TargetConfiguration.CertificateStore->Count) + { + return false; + } + + // // get block address + // blockAddress = (uint8_t*)g_TargetConfiguration.CertificateStore->Certificates[configurationIndex]; + + // // set block size + // // because X509 certificate has a variable length need to compute the block size in two steps + // sizeOfBlock = offsetof(HAL_Configuration_X509CaRootBundle, Certificate); + // sizeOfBlock += ((HAL_Configuration_X509CaRootBundle*)blockAddress)->CertificateSize; + } + + if(configuration == DeviceConfigurationOption_Network) + { + // network config blocks are stored as files + + // compose file name + fileName = (unsigned char*)platform_malloc(sizeof(NETWORK_CONFIG_FILE_NAME)); + memcpy(fileName, NETWORK_CONFIG_FILE_NAME, sizeof(NETWORK_CONFIG_FILE_NAME)); + // insert index number at position N as char + fileName[NETWORK_CONFIG_FILE_INDEX_POSITION] = '0' + configurationIndex; + + fileHandle = sl_FsOpen( fileName, + SL_FS_READ, + (uint32_t *)&token); + + // on error there is no file handle, rather a negative error code + if(fileHandle > 0) + { + retVal = sl_FsRead(fileHandle, 0, (unsigned char*)configurationBlock, sizeof(HAL_Configuration_NetworkInterface)); + + // on success the return value is the amount of bytes written + if(retVal == sizeof(HAL_Configuration_NetworkInterface)) + { + retVal = sl_FsClose(fileHandle, 0, 0, 0); + + if( retVal < 0 ) + { + // error closing file, API ceremony suggests calling "abort" operation + uint8_t signature = 'A'; + sl_FsClose(fileHandle, 0, &signature, 1); + } + } + } + + if(fileName != NULL) + { + platform_free(fileName); + } + + // done! + return true; + } + else if(configuration == DeviceConfigurationOption_Wireless80211Network) + { + wirelessConfigBlock = (HAL_Configuration_Wireless80211*)configurationBlock; + + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_WIRELESS80211_V1, sizeof(c_MARKER_CONFIGURATION_WIRELESS80211_V1)); + + // get profile from SimpleLink + retVal = sl_WlanProfileGet(configurationIndex, (signed char *)wirelessConfigBlock->Ssid, &dummyNameLen, &dummyMAC[0], &secParams, NULL, &dummyPriority); + if(retVal == SL_ERROR_WLAN_GET_PROFILE_INVALID_INDEX) + { + return false; + } + + // fill struct fields + wirelessConfigBlock->Id = configurationIndex; + wirelessConfigBlock->Authentication = GetAuthentication(secParams); + wirelessConfigBlock->Encryption = GetEncryption(secParams); + + // password is hidden, NULL the string + memset(wirelessConfigBlock->Password, 0, sizeof(wirelessConfigBlock->Password)); + //wirelessConfigBlock->Radio + + + // done + return true; + } + + return false; +} + +uint8_t GetSecurityType(AuthenticationType authentication) +{ + switch (authentication) + { + case AuthenticationType_Open: + return SL_WLAN_SEC_TYPE_OPEN; + + case AuthenticationType_WEP: + return SL_WLAN_SEC_TYPE_WEP; + + case AuthenticationType_WPA: + case AuthenticationType_WPA2: + return SL_WLAN_SEC_TYPE_WPA_WPA2; + + case AuthenticationType_Shared: + return SL_WLAN_SEC_TYPE_WEP_SHARED; + + default: + return SL_WLAN_SEC_TYPE_OPEN; + } +} + +// Stores the configuration block to the file system +bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize, uint32_t offset) +{ + bool requiresEnumeration = false; + bool success = false; + + unsigned char* fileName = NULL; + + int32_t fileHandle; + uint32_t token = 0; + int32_t retVal; + SlWlanSecParams_t secParams; + + if(configuration == DeviceConfigurationOption_Network) + { + // network config blocks are stored as files + + // compose file name + fileName = (unsigned char*)platform_malloc(sizeof(NETWORK_CONFIG_FILE_NAME)); + memcpy(fileName, NETWORK_CONFIG_FILE_NAME, sizeof(NETWORK_CONFIG_FILE_NAME)); + // insert index number at position N as char + fileName[NETWORK_CONFIG_FILE_INDEX_POSITION] = '0' + configurationIndex; + + fileHandle = sl_FsOpen( fileName, + SL_FS_CREATE | SL_FS_OVERWRITE | + SL_FS_CREATE_MAX_SIZE(sizeof(HAL_Configuration_NetworkInterface)) | + SL_FS_CREATE_PUBLIC_WRITE | SL_FS_CREATE_NOSIGNATURE, + (uint32_t *)&token); + + // on error there is no file handle, rather a negative error code + if(fileHandle > 0) + { + // make sure the config block marker is set + memcpy(configurationBlock, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + retVal = sl_FsWrite(fileHandle, 0, (unsigned char*)configurationBlock, sizeof(HAL_Configuration_NetworkInterface)); + + // on success the return value is the amount of bytes written + if(retVal == sizeof(HAL_Configuration_NetworkInterface)) + { + retVal = sl_FsClose(fileHandle, 0, 0, 0); + + if( retVal < 0 ) + { + // error closing file, API ceremony suggests calling "abort" operation + uint8_t signature = 'A'; + sl_FsClose(fileHandle, 0, &signature, 1); + } + else + { + // configuration stored + success = true; + requiresEnumeration = true; + } + } + } + + if(fileName != NULL) + { + platform_free(fileName); + } + } + else if(configuration == DeviceConfigurationOption_Wireless80211Network) + { + HAL_Configuration_Wireless80211* wirelessConfigBlock = (HAL_Configuration_Wireless80211*)configurationBlock; + + secParams.Type = GetSecurityType(wirelessConfigBlock->Authentication); + secParams.Key = (signed char *)wirelessConfigBlock->Password; + secParams.KeyLen = hal_strlen_s((const char *)secParams.Key); + + // add profile to SimpleLink + // TODO - default priority is 0 + retVal = sl_WlanProfileAdd((const signed char *)wirelessConfigBlock->Ssid, hal_strlen_s((const char *)(wirelessConfigBlock->Ssid)), NULL, &secParams, NULL, 0, 0); + if(retVal < 0) + { + return false; + } + + // done + success = true; + requiresEnumeration = true; + } + else if(configuration == DeviceConfigurationOption_X509CaRootBundle) + { + // CA root certificate bundle is stored as a file /sys/certstore.lst + // currently we don't support updating this + success = false; + } + + if(success == true && requiresEnumeration) + { + // free the current allocation(s) + platform_free(g_TargetConfiguration.NetworkInterfaceConfigs); + platform_free(g_TargetConfiguration.Wireless80211Configs); + platform_free(g_TargetConfiguration.CertificateStore); + + // perform enumeration of configuration blocks + ConfigurationManager_EnumerateConfigurationBlocks(); + } + + return success; +} + +// Updates a configuration block +bool ConfigurationManager_UpdateConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + // CC32xx stores the config blocks on the file system so we don't care about sizes + + switch(configuration) + { + case DeviceConfigurationOption_Network: + case DeviceConfigurationOption_Wireless80211Network: + return ConfigurationManager_StoreConfigurationBlock(configurationBlock, configuration, configurationIndex, 0, 0); + + // this configuration option is not supported + case DeviceConfigurationOption_X509CaRootBundle: + default: + // shouldn't ever reach here + return FALSE; + } +} + +// Default initialisation for wireless config block +void InitialiseWirelessDefaultConfig(HAL_Configuration_Wireless80211 * pconfig, uint32_t configurationIndex) +{ + (void)pconfig; + (void)configurationIndex; + + // TODO +} + +// Default initialisation for Network interface config blocks +bool InitialiseNetworkDefaultConfig(HAL_Configuration_NetworkInterface * pconfig, uint32_t configurationIndex) +{ + (void)configurationIndex; + + uint16_t macAddressLen = SL_MAC_ADDR_LEN; + + memset(pconfig, 0, sizeof(HAL_Configuration_NetworkInterface)); + + // make sure the config block marker is set + memcpy(pconfig->Marker, c_MARKER_CONFIGURATION_NETWORK_V1, sizeof(c_MARKER_CONFIGURATION_NETWORK_V1)); + + pconfig->InterfaceType = NetworkInterfaceType_Wireless80211; + pconfig->StartupAddressMode = AddressMode_DHCP; + pconfig->AutomaticDNS = 1; + pconfig->SpecificConfigId = 0; + + sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET, 0, &macAddressLen, pconfig->MacAddress); + + return true; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CLR_Startup_Thread.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CLR_Startup_Thread.c new file mode 100644 index 00000000..fa09cebf --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CLR_Startup_Thread.c @@ -0,0 +1,19 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +void* CLRStartupThread(void* argument) +{ + CLR_SETTINGS* clrSettings = (CLR_SETTINGS*)argument; + + nanoHAL_Initialize_C(); + + ClrStartup(*clrSettings); + + // nothing to deinitialize or cleanup, so it's safe to return +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CMakeLists.txt b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CMakeLists.txt new file mode 100644 index 00000000..fbb86360 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/CMakeLists.txt @@ -0,0 +1,91 @@ +# +# Copyright (c) 2019 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +include(NF_NativeAssemblies) + +# add header file with common target definitions +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_platform.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_platform.h" @ONLY) + +# append nanoHAL +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL.cpp") + +# append target nanoCLR source files +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_App_Interface.c) +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WireProtocol_MonitorCommands.c) +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/CLR_Startup_Thread.c") +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL.c") + +# append target HAL source files +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Power.c") +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Time.cpp") + +# append watchdog only if option is ON +# if(HAL_USE_WDG_OPTION) +# list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Watchdog.c") +# endif() + +# append SNTP only if option is ON +if(NF_NETWORKING_SNTP) + list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetSimpleLinkCC32xx_Sntp.c") +endif() + +# append target PAL source files +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL_Events.cpp") +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetPAL_Time.cpp") + +# append other CLR core files +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Memory.cpp") + +# append nanoCRT +list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoCRT.cpp") + +# append SimpleLink target specific files +if("${TARGET_SERIES}" STREQUAL "CC32xx") + list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetSimpleLinkCC32xx_Threads.c") + list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetSimpleLinkCC32xx_LinkLocalTask.c") + list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetSimpleLinkCC32xx_ProvisioningTask.c") +endif() + +# append files from Runtime.Native +# list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/nanoFramework.Runtime.Native/nf_rt_native_nanoFramework_Runtime_Native_Rtc.cpp") + +# append TRNG only if option is ON +if(USE_RNG) + + # # append random implementation for all series, except F0 + # if( ${TARGET_SERIES} STREQUAL "STM32L0xx" OR + # ${TARGET_SERIES} STREQUAL "STM32F4xx" OR + # ${TARGET_SERIES} STREQUAL "STM32F7xx" OR + # ${TARGET_SERIES} STREQUAL "STM32H7xx") + + # list(APPEND TARGET_TI_SimpleLink_NANOCLR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/targetRandom.cpp") + + # else() + # # this series doesn't feature hardware TRNG, report + # message(ERROR "This CPU doesn't have a Random Number Generation. Please change USE_RNG option to OFF.") + # endif() + +endif() + +# add native assemblies +ParseNativeAssemblies() + +# make var global +set(TARGET_TI_SimpleLink_NANOCLR_SOURCES ${TARGET_TI_SimpleLink_NANOCLR_SOURCES} CACHE INTERNAL "make global") + +# append target ChibiOS nanoCLR include directory +list(APPEND TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) +list(APPEND TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) +list(APPEND TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core) + +# append PAL include directory +list(APPEND TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include) + +# append Runtime.Native include directory +list(APPEND TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Runtime.Native) + +# make var global +set(TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS ${TARGET_TI_SimpleLink_NANOCLR_INCLUDE_DIRS} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Memory.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Memory.cpp new file mode 100644 index 00000000..e488b377 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Memory.cpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +// void HeapLocation(unsigned char*& baseAddress, unsigned int& sizeInBytes) +// { +// NATIVE_PROFILE_PAL_HEAP(); + +// baseAddress = (unsigned char*) &HeapBegin; +// sizeInBytes = (unsigned int)((size_t)&HeapEnd - (size_t)&HeapBegin); +// } + +// Define an area for the CLR managed heap +#if !defined(MANAGED_HEAP_SIZE) +#define MANAGED_HEAP_SIZE (64*1024) +#endif + +uint32_t managedHeap[MANAGED_HEAP_SIZE/ sizeof(uint32_t)]; + +void HeapLocation(unsigned char*& baseAddress, unsigned int& sizeInBytes) +{ + NATIVE_PROFILE_PAL_HEAP(); + + baseAddress = (unsigned char*)&managedHeap; + sizeInBytes = sizeof(managedHeap); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp new file mode 100644 index 00000000..85b09785 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcChannel.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +// // this has to be an array because ChibiOS ADC API expects that +// static adcsample_t sampleBuffer[1 * 1]; + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +// // not used, just left here if needed for debugging purposes +// static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) +// { +// (void)adcp; +// (void)err; +// } + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeReadValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get channel from _channelNumber field + int channelNumber = pThis[FIELD___channelNumber].NumericByRef().s4; + + uint16_t adcValue0; + uint32_t adcValue0MicroVolt; + + ADC_Params params; + ADC_Params_init(¶ms); + ADC_Handle adcHandler = ADC_open(channelNumber, ¶ms); FAULT_ON_NULL(adcHandler); + + int_fast16_t res = ADC_convert(adcHandler, &adcValue0); + + if (res == ADC_STATUS_SUCCESS) + { + adcValue0MicroVolt = ADC_convertRawToMicroVolts(adcHandler, adcValue0); + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + + ADC_close(adcHandler); + + stack.SetResult_I4(adcValue0MicroVolt); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcChannel::NativeDisposeChannel___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // left empty on purpose, nothing to do here + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp new file mode 100644 index 00000000..de4b4c17 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_Windows_Devices_Adc_AdcController.cpp @@ -0,0 +1,124 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + +extern const uint_least8_t ADC_count; + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeOpenChannel___VOID__I4( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // left empty on purpose, nothing to do here + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetChannelCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int channelCount; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + int controllerId = pThis[ FIELD___controllerId ].NumericByRefConst().s4; + + switch(controllerId) + { + case 1: + channelCount = ADC_count; + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Return value to the managed application + stack.SetResult_I4(channelCount); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMaxValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Currently fixed at 12 bit so return 4095 = ((2^12) - 1) + stack.SetResult_I4(4095); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetMinValue___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + stack.SetResult_I4(0); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeIsChannelModeSupported___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int mode = stack.Arg1().NumericByRef().s4; + + // Only support Single ended mode for now + stack.SetResult_Boolean( (mode == (int)AdcChannelMode::SingleEnded) ) ; + } + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeGetResolutionInBits___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // Fixed at 12 bit + stack.SetResult_I4(12); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + int controllerId; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get pointer to _controllerId field in AdcController + controllerId = pThis[FIELD___controllerId].NumericByRef().s4; + + switch(controllerId) + { + case 1: + ADC_init(); + break; + + default: + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_adc_native_Windows_Devices_Adc_AdcController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String("ADC1"); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h new file mode 100644 index 00000000..6aaa808f --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Adc/win_dev_adc_native_target.h @@ -0,0 +1,14 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_ADC_NATIVE_TARGET_H_ +#define _WIN_DEV_ADC_NATIVE_TARGET_H_ + +#include "Board.h" +#include +#include + +#endif //_WIN_DEV_ADC_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp new file mode 100644 index 00000000..87c7fcd4 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter.cpp @@ -0,0 +1,86 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_gpio_native.h" + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeInit___VOID(CLR_RT_StackFrame& stack) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int16_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + //bool InputMode = (bool)pThis[FIELD___inputMode].NumericByRefConst().u1; + + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeRead___U8__BOOLEAN(CLR_RT_StackFrame& stack) +{ + (void)stack; + + NANOCLR_HEADER(); + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStart___VOID(CLR_RT_StackFrame& stack) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + //GpioChangePolarity polarity = (GpioChangePolarity)pThis[ FIELD___Polarity ].NumericByRefConst().s4; + + + // TODO + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeStop___VOID(CLR_RT_StackFrame& stack) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioChangeCounter::NativeDispose___VOID(CLR_RT_StackFrame& stack) +{ + (void)stack; + + NANOCLR_HEADER(); + { + //CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + //int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp new file mode 100644 index 00000000..c1ed62f8 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_gpio_native_target.h" + + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController::get_PinCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // return count ot available GPIO pins + stack.SetResult_I4( 256 ); // Fixme: temporary arbitrary value + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp new file mode 100644 index 00000000..e79db908 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp @@ -0,0 +1,418 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_gpio_native_target.h" +#include "nf_rt_events_native.h" + +#include + +// this array points to the GPIO managed object that has interrupt active +CLR_RT_HeapBlock* indexPinMapping[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +// this array points to the active debounce timers +TimerHandle_t debounceTimerMapping[ARRAYSIZE_CONST_EXPR(indexPinMapping)]; + +// this arrays points to the last read value to be used by the debounce timers +uint_fast8_t lastReadValueMapping[ARRAYSIZE_CONST_EXPR(indexPinMapping)]; + +static void debounceTimer_Callback(TimerHandle_t xTimer) +{ + (void)xTimer; + + int16_t index; + + // loop through timers to find the index for this + for(index = 0; index < ARRAYSIZE_CONST_EXPR(indexPinMapping); index++) + { + if(debounceTimerMapping[index] == xTimer) + { + // found it! + + // get current value + uint_fast8_t currentValue = GPIO_read(index); + + // get last read value + uint_fast8_t lastRead = (uint_fast8_t) pvTimerGetTimerID( xTimer ); + + if(lastRead == currentValue) + { + // value hasn't change during debounce interval so this is a valid change + + // get managed GPIO object + CLR_RT_HeapBlock* pThis = (CLR_RT_HeapBlock*)indexPinMapping[index]; + + // flag to determine if there are any callbacks registered in managed code + bool callbacksRegistered = (pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___callbacks ].Dereference() != NULL); + + // post a managed event with the current pin value, only if there is anyone listening otherwise don't bother + if(callbacksRegistered) + { + PostManagedEvent( EVENT_GPIO, 0, index, currentValue ); + } + } + + xTimerDelete(xTimer, 0); + } + } +} + +static void GpioEventCallback(uint_least8_t index) +{ + NATIVE_INTERRUPT_START + + CLR_RT_HeapBlock* pThis = indexPinMapping[index]; + + if(pThis == NULL) + { + // no Gpio pin here, leave now + NATIVE_INTERRUPT_END + return; + } + + // check if object has been disposed + if( pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + // object has been disposed, leave now + NATIVE_INTERRUPT_END + return; + } + + // check if there is a debounce time set + int64_t debounceTimeoutMilsec = (CLR_INT64_TEMP_CAST) pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___debounceTimeout ].NumericByRefConst().s8 / TIME_CONVERSION__TO_MILLISECONDS; + + // store current value + uint_fast8_t lastRead = GPIO_read(index); + + if(debounceTimeoutMilsec > 0) + { + // debounce set, need to handle it + + if(debounceTimerMapping[index] != NULL) + { + // there is a debounce timer already running so this change in pin value should be discarded + NATIVE_INTERRUPT_END + return; + } + + // setup timer + debounceTimerMapping[index] = xTimerCreate( NULL, (debounceTimeoutMilsec / portTICK_PERIOD_MS), pdFALSE, (void*)lastRead, debounceTimer_Callback); + xTimerStart(debounceTimerMapping[index], 0); + } + else + { + // read pin + pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___lastInputValue ].NumericByRef().s4 = lastRead; + + // flag to determine if there are any callbacks registered in managed code + bool callbacksRegistered = (pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___callbacks ].Dereference() != NULL); + + // post a managed event with the current pin reading, only if there is anyone listening otherwise don't bother + if(callbacksRegistered) + { + PostManagedEvent( EVENT_GPIO, 0, index, lastRead ); + } + } + + NATIVE_INTERRUPT_END +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Read___WindowsDevicesGpioGpioPinValue( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int32_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + stack.SetResult_I4(GPIO_read(pinNumber)); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Toggle___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int32_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[ FIELD___driveMode ].NumericByRefConst().s4; + + // sanity check for drive mode set to output so we don't mess up writing to an input pin + if ((driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + GPIO_toggle(pinNumber); + + // store new state + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = (GpioPinValue)(GpioPinValue_High ^ (GpioPinValue)pThis[ FIELD___lastOutputValue ].NumericByRef().s4); + } + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + int32_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + // it's OK to do always this, no matter if interrupts are enabled or not + // disable interrupts + GPIO_disableInt(pinNumber); + + // clear assignment + indexPinMapping[pinNumber] = NULL; + + // set pin to input to save power + GPIO_setConfig(pinNumber, GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_NONE); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + GpioPinDriveMode driveMode = (GpioPinDriveMode)stack.Arg1().NumericByRef().s4; + + bool driveModeSupported = false; + + // check if the requested drive mode is supported by SimpleLink + if ((driveMode == GpioPinDriveMode_Input) || + (driveMode == GpioPinDriveMode_InputPullDown) || + (driveMode == GpioPinDriveMode_InputPullUp) || + (driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + driveModeSupported = true; + } + + // Return value to the managed application + stack.SetResult_Boolean( driveModeSupported ) ; + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + // get pin number + int32_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + // it's better cast this this to the appropriate enum + GpioPinDriveMode driveMode = (GpioPinDriveMode)stack.Arg1().NumericByRef().s4; + + // check if drive mode is input + bool driveModeIsInput = false; + + if( driveMode == GpioPinDriveMode_Input || + driveMode == GpioPinDriveMode_InputPullDown || + driveMode == GpioPinDriveMode_InputPullUp) + { + driveModeIsInput = true; + } + + // flag to signal that interrupts need to be setup + bool setupInterrupt = false; + + // flag to determine if there are any callbacks registered in managed code + bool callbacksRegistered = (pThis[ FIELD___callbacks ].Dereference() != NULL); + + // disable interrupt as default + GPIO_disableInt(pinNumber); + + switch (driveMode) + { + case GpioPinDriveMode_Input: + GPIO_setConfig(pinNumber, GPIO_CFG_IN_NOPULL); + setupInterrupt = true; + break; + + case GpioPinDriveMode_InputPullDown: + GPIO_setConfig(pinNumber, GPIO_CFG_IN_PD); + setupInterrupt = true; + break; + + case GpioPinDriveMode_InputPullUp: + GPIO_setConfig(pinNumber, GPIO_CFG_IN_PU); + setupInterrupt = true; + break; + + case GpioPinDriveMode_Output: + GPIO_setConfig(pinNumber, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); + break; + + case GpioPinDriveMode_OutputOpenDrain: + GPIO_setConfig(pinNumber, GPIO_CFG_OUT_OD_NOPULL); + break; + + case GpioPinDriveMode_OutputOpenDrainPullUp: + GPIO_setConfig(pinNumber, GPIO_CFG_OUT_OD_PU); + break; + + case GpioPinDriveMode_OutputOpenSourcePullDown: + GPIO_setConfig(pinNumber, GPIO_CFG_OUT_OD_PD); + break; + + default: + // all other modes are NOT supported + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // if drive mode is output, read the pad to update the managed field _lastOutputValue + if(!driveModeIsInput) + { + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = GPIO_read(pinNumber); + } + + if(callbacksRegistered && setupInterrupt) + { + // there are callbacks registered and... + // the drive mode is input so need to setup the interrupt + + // save pin + indexPinMapping[pinNumber] = pThis; + + // get current config + GPIO_PinConfig currentPinConfig; + GPIO_getConfig(pinNumber, ¤tPinConfig); + + // set interrupt on both edges + GPIO_setConfig(pinNumber, currentPinConfig | GPIO_CFG_IN_INT_BOTH_EDGES); + GPIO_setCallback(pinNumber, GpioEventCallback); + + GPIO_enableInt(pinNumber); + + // protect this from GC so that the callback is where it's supposed to + CLR_RT_ProtectFromGC gc( *pThis ); + } + else + { + // clear assignment + indexPinMapping[pinNumber] = NULL; + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeInit___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + int16_t pinNumber = stack.Arg1().NumericByRef().s4; + + // TODO is probably a good idea keep track of the used pins, so we can check that here + // TODO is probably a good idea to check if this pin exists + + // clear assignment, to make sure it's empty + indexPinMapping[pinNumber] = NULL; + + // Return value to the managed application + stack.SetResult_Boolean(true ); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDebounceTimeout___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + // nothing to do here as the debounce timeout is grabbed from the managed object when required + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::WriteNative___VOID__WindowsDevicesGpioGpioPinValue( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int32_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[ FIELD___driveMode ].NumericByRefConst().s4; + + GpioPinValue state = (GpioPinValue)stack.Arg1().NumericByRef().s4; + + // sanity check for drive mode set to output so we don't mess up writing to an input pin + if ((driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + GPIO_write(pinNumber, state); + + // store new state + pThis[ FIELD___lastOutputValue ].NumericByRef().s4 = state; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetAlternateFunction___VOID__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // check if object has been disposed + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + int32_t pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + // get alternate function argument + int32_t alternateFunction = stack.Arg1().NumericByRef().s4; + + GPIO_setConfig(pinNumber, alternateFunction); + + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h new file mode 100644 index 00000000..311d0569 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_target.h @@ -0,0 +1,22 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_GPIO_NATIVE_TARGET_H_ +#define _WIN_DEV_GPIO_NATIVE_TARGET_H_ + +#include + +#include "rom.h" +#include "rom_map.h" +#include +#include +#include +#include +#include +#include + +#endif //_WIN_DEV_GPIO_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp new file mode 100644 index 00000000..99ec20d4 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2C_I2cDevice.cpp @@ -0,0 +1,244 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "win_dev_i2c_native_target.h" + +typedef Library_win_dev_i2c_native_Windows_Devices_I2c_I2cConnectionSettings I2cConnectionSettings; + +///////////////////////////////////////////////////// +// I2C PAL strucs declared in win_dev_i2c_native.h // +///////////////////////////////////////////////////// +NF_PAL_I2C I2C1_PAL; + +void HostI2C_CallbackFxn(I2C_Handle handle, I2C_Transaction *transaction, bool transferStatus) +{ + NATIVE_INTERRUPT_START + + // fire event for I2C transaction complete + Events_Set(SYSTEM_EVENT_FLAG_I2C_MASTER); + + NATIVE_INTERRUPT_END +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + NF_PAL_I2C* palI2c = NULL; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed I2C connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the I2cDevice() constructor in managed code for details + uint8_t busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // config GPIO pins used by the I2C peripheral + // init the PAL struct for this I2C bus and assign the respective driver + // all this occurs if not already done + // why do we need to check if this is already done? because several I2cDevice objects can be created associated to the same bus just using different addresses + switch (busIndex) + { + case 1: + if(I2C1_PAL.i2c == NULL) + { + palI2c = &I2C1_PAL; + } + break; + + default: + // this I2C bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // Create I2C for usage + I2C_Params_init(&palI2c->i2cParams); + palI2c->i2cParams.bitRate = (I2cBusSpeed)pConfig[ I2cConnectionSettings::FIELD___busSpeed ].NumericByRef().s4 == I2cBusSpeed_StandardMode ? I2C_100kHz : I2C_400kHz; + palI2c->i2cParams.transferMode = I2C_MODE_CALLBACK; + palI2c->i2cParams.transferCallbackFxn = HostI2C_CallbackFxn; + palI2c->i2c = I2C_open(Board_I2C0, &palI2c->i2cParams); FAULT_ON_NULL(palI2c->i2c); + palI2c->i2cTransaction.slaveAddress = (I2cBusSpeed)pConfig[ I2cConnectionSettings::FIELD___slaveAddress ].NumericByRef().s4; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeDispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + uint8_t busIndex; + NF_PAL_I2C* palI2c = NULL; + bool disposeController = false; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get disposeController + disposeController = (bool)stack.Arg0().NumericByRef().u1; + + if(disposeController) + { + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the I2cDevice() constructor in managed code for details + busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // get the driver for the I2C bus + switch (busIndex) + { + case 1: + // deactivates the I2C peripheral + I2C_close(palI2c->i2c); + I2C1_PAL.i2c == NULL; + break; + + default: + // this I2C bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cDevice::NativeTransmit___WindowsDevicesI2cI2cTransferResult__SZARRAY_U1__SZARRAY_U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + uint8_t busIndex; + NF_PAL_I2C* palI2c = NULL; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + uint32_t estimatedDurationMiliseconds; + + CLR_RT_HeapBlock_Array* writeBuffer; + CLR_RT_HeapBlock_Array* readBuffer; + CLR_RT_HeapBlock* result; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // // get pointer to connection settings field + // CLR_RT_HeapBlock* connectionSettings = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the I2cDevice() constructor in managed code for details + busIndex = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // get the driver for the I2C bus + switch (busIndex) + { + case 1 : + palI2c = &I2C1_PAL; + break; + default: + // the requested I2C bus is not valid + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + break; + } + + // dereference the write and read buffers from the arguments + writeBuffer = stack.Arg1().DereferenceArray(); + if (writeBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + palI2c->i2cTransaction.writeCount = writeBuffer->m_numOfElements; + } + else + { + // nothing to write, have to zero this + palI2c->i2cTransaction.writeCount = 0; + } + + readBuffer = stack.Arg2().DereferenceArray(); + if (readBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + palI2c->i2cTransaction.readCount = readBuffer->m_numOfElements; + } + else + { + // nothing to read, have to zero this + palI2c->i2cTransaction.readCount = 0; + } + + // set a timeout to an infinite timeout + // the catch is that the working thread MUST ALWAYS return at some point + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // protect the buffers from GC so DMA can find them where they are supposed to be + CLR_RT_ProtectFromGC gcWriteBuffer( *writeBuffer ); + CLR_RT_ProtectFromGC gcReadBuffer( *readBuffer ); + + if (writeBuffer != NULL) + { + palI2c->i2cTransaction.writeBuf = (uint8_t*)writeBuffer->GetFirstElement(); + } + + if (readBuffer != NULL) + { + palI2c->i2cTransaction.readBuf = (uint8_t*)readBuffer->GetFirstElement(); + } + + // perform I2C transaction using driver's callback which will set the appropriate event on completion + if(stack.m_customState == 1) + { + I2C_transfer(palI2c->i2c, &palI2c->i2cTransaction); + + // bump custom state + stack.m_customState = 2; + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the I2C transaction to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_I2cMaster, eventResult )); + + if(eventResult) + { + // event occurred + + // create the return object (I2cTransferResult) + // only at this point we are sure that there will be a return from this thread so it's OK to use the managed stack + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(top, g_CLR_RT_WellKnownTypes.m_I2cTransferResult)); + result = top.Dereference(); FAULT_ON_NULL(result); + + // successfull transaction + // set the result field + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___status ].SetInteger((CLR_UINT32)I2cTransferStatus_FullTransfer); + + // set the bytes transferred field + result[ Library_win_dev_i2c_native_Windows_Devices_I2c_I2cTransferResult::FIELD___bytesTransferred ].SetInteger((CLR_UINT32)(palI2c->i2cTransaction.writeCount + palI2c->i2cTransaction.readCount)); + + // done here + break; + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp new file mode 100644 index 00000000..c3006aa3 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_Windows_Devices_I2c_I2cController.cpp @@ -0,0 +1,33 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include "win_dev_i2c_native_target.h" + + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + { + + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_i2c_native_Windows_Devices_I2c_I2cController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "I2C1,I2C2,I2C3,I2C4," + terminator and init with the terminator + char deviceSelectorString[] = { "I2C1" }; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h new file mode 100644 index 00000000..853b5523 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.I2c/win_dev_i2c_native_target.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_I2C_NATIVE_TARGET_H_ +#define _WIN_DEV_I2C_NATIVE_TARGET_H_ + +#include +#include "Board.h" +#include + +// struct representing the I2C +struct NF_PAL_I2C +{ + I2C_Handle i2c; + I2C_Params i2cParams; + I2C_Transaction i2cTransaction; +}; + +/////////////////////////////////////////// +// declaration of the the I2C PAL strucs // +/////////////////////////////////////////// +extern NF_PAL_I2C I2C1_PAL; + +#endif //_WIN_DEV_I2C_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp new file mode 100644 index 00000000..9b11039a --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmController.cpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_pwm_native_target.h" + +// PWMConfig _pwmConfig; + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MaxFrequency___R8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // FIXME : how can this value be determined ? + stack.SetResult_R8(1.0); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_MinFrequency___R8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // FIXME : how can this value be determined ? + stack.SetResult_R8(1.0); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::get_PinCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // TODO + // this is now hardcoded to TWO because this is the available PWM outputs in CC3220SF launchpad + // ideally it should come from the PWM config file at target level + stack.SetResult_I4(2); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::NativeSetDesiredFrequency___U4__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // the SimpleLink PWM driver doesn't require any general setting + // so there is nothing to do here, just keeping the ceremony for the managed API + unsigned int desiredFrequency = (unsigned int)stack.Arg1().NumericByRef().u4; + + stack.SetResult_R8(desiredFrequency); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // this is now hardcoded to ONE because there is only one PWM controller in CC3220SF launchpad + // ideally it should come from the PWM config file at target level + char deviceSelectorString[] = "TIM0"; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp new file mode 100644 index 00000000..7c6bf15b --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_Windows_Devices_Pwm_PwmPin.cpp @@ -0,0 +1,120 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_pwm_native_target.h" + +//////////////////////////////////////////////////////////////////// + + +PWM_Handle PwmPins[PWM_PIN_COUNT]; + + +int GetChannel (int pin, int timerId) +{ + // TODO + return -1; +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetActiveDutyCyclePercentage___VOID__U4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + + // Retrieves the needed parameters from method parameters + unsigned int dutyCycle = (unsigned int)stack.Arg1().NumericByRef().u4; + + PWM_setDuty(PwmPins[pinNumber], dutyCycle); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeSetPolarity___VOID__U1( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(stack.NotImplementedStub()); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStart___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + + // get the controller + CLR_RT_HeapBlock* controller = pThis[ FIELD___pwmController ].Dereference(); + + // get the frequency from the controller + double frequency = controller[ Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmController::FIELD___actualFrequency ].NumericByRef().r8; + + PWM_Params params; + PWM_Params_init(¶ms); + params.dutyUnits = PWM_DUTY_US; + params.dutyValue = 0; + params.periodUnits = PWM_PERIOD_HZ; + params.periodValue = frequency; + PwmPins[pinNumber] = PWM_open(pinNumber, ¶ms); + if (PwmPins[pinNumber] == NULL) + { + // Board_PWM did not open + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + PWM_start(PwmPins[pinNumber]); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeStop___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + + // Stops PWM output on the channel associated with this handler + PWM_stop(PwmPins[pinNumber]); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_pwm_native_Windows_Devices_Pwm_PwmPin::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieves the needed parameters from private class properties + int pinNumber = (int)(pThis[ FIELD___pinNumber ].NumericByRef().u4); + + PWM_close(PwmPins[pinNumber]); + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h new file mode 100644 index 00000000..b6f2523a --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Pwm/win_dev_pwm_native_target.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIN_DEV_PWM_NATIVE_TARGET_H_ +#define _WIN_DEV_PWM_NATIVE_TARGET_H_ + +#include "Board.h" +#include + +#include +#include + +///////////////////////////////////// +// Array of PWM handlers // +// these live in the target folder // +///////////////////////////////////// +extern PWM_Handle PwmPins[PWM_PIN_COUNT]; + +#endif //_WIN_DEV_PWM_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp new file mode 100644 index 00000000..7754a7e7 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_spi_native_target.h" + + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MaxClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // return dummy value + stack.SetResult_I4 (0); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MinClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // return dummy value + stack.SetResult_I4 (0); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp new file mode 100644 index 00000000..ba60fb41 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiController.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "win_dev_spi_native_target.h" + + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiController::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "SPI1" + terminator and init with the terminator + char deviceSelectorString[] = { "SPI1" }; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp new file mode 100644 index 00000000..85fdfd46 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp @@ -0,0 +1,262 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include +#include "win_dev_spi_native_target.h" + +// define this type here to make it shorter and improve code readability +typedef Library_win_dev_spi_native_Windows_Devices_Spi_SpiConnectionSettings SpiConnectionSettings; + + +///////////////////////////////////////////////////// +// SPI PAL strucs declared in win_dev_spi_native.h // +///////////////////////////////////////////////////// +NF_PAL_SPI SPI1_PAL; + + +void SpiCallback(SPI_Handle handle, SPI_Transaction *transaction) +{ + NATIVE_INTERRUPT_START + + // are there any other transactions pending? + if(SPI1_PAL.transactionCount) + { + // start transfer of 1st transaction + SPI_transfer(SPI1_PAL.masterSpi, &SPI1_PAL.transactions[SPI1_PAL.transactionCount--]); + } + else + { + // no more transactions + // fire event for SPI transaction complete + Events_Set( SYSTEM_EVENT_FLAG_SPI_MASTER ); + } + + NATIVE_INTERRUPT_END +} + +// Give a complete low-level SPI configuration from user's managed connectionSettings +void GetSPIConfig(int busIndex, CLR_RT_HeapBlock* config, bool bufferIs16bits) +{ + SPI_Params spiParams; + + // Open SPI as slave (default) + SPI_Params_init(&spiParams); + spiParams.frameFormat = (SPI_FrameFormat)config[ SpiConnectionSettings::FIELD___spiMode ].NumericByRef().s4; + spiParams.transferMode = SPI_MODE_CALLBACK; + spiParams.mode = SPI_SLAVE; + spiParams.transferCallbackFxn = SpiCallback; + spiParams.dataSize = bufferIs16bits ? 16 : 8; + spiParams.bitRate = (uint32_t)config[ SpiConnectionSettings::FIELD___clockFrequency ].NumericByRef().s4; + SPI1_PAL.masterSpi = SPI_open(Board_SPI_SLAVE, &spiParams); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + return NativeTransfer( stack, false ); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + return NativeTransfer( stack, true ); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer( CLR_RT_StackFrame& stack, bool bufferIs16bits ) +{ + NANOCLR_HEADER(); + { + bool fullDuplex; + + CLR_RT_HeapBlock hbTimeout; + CLR_INT64* timeout; + bool eventResult = true; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // Are we using SPI full-duplex for transfer? + fullDuplex = (bool)stack.Arg3().NumericByRef().u1; + + // dereference the write and read buffers from the arguments + CLR_RT_HeapBlock_Array* writeBuffer = stack.Arg1().DereferenceArray(); + CLR_RT_HeapBlock_Array* readBuffer = stack.Arg2().DereferenceArray(); + + // set a timeout to an infinite timeout + // the catch is that the working thread MUST ALWAYS return at some point + // !! need to cast to CLR_INT64 otherwise it wont setup a proper timeout infinite + hbTimeout.SetInteger((CLR_INT64)-1); + + NANOCLR_CHECK_HRESULT(stack.SetupTimeoutFromTicks( hbTimeout, timeout )); + + // protect the buffers from GC so DMA can find them where they are supposed to be + CLR_RT_ProtectFromGC gcWriteBuffer( *writeBuffer ); + CLR_RT_ProtectFromGC gcReadBuffer( *readBuffer ); + + // setup the operation and init buffers + if(stack.m_customState == 1) + { + // get the LL SPI configuration, depending on user's managed parameters and buffer element size + GetSPIConfig(0, pConfig, bufferIs16bits); // index '0' in this case is a dummy value... there is only one SPI available + + // alloc mem for transactions + if(fullDuplex) + { + // we'll be doing this on a single transaction + SPI1_PAL.transactions = (SPI_Transaction*)platform_malloc(sizeof(SPI_Transaction)); + SPI1_PAL.transactionCount = 1; + } + else + { + // we need two transactions + SPI1_PAL.transactions = (SPI_Transaction*)platform_malloc(sizeof(SPI_Transaction) * 2); + SPI1_PAL.transactionCount = 2; + } + + // check allocation + if(SPI1_PAL.transactions == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + else + { + if(fullDuplex) + { + if (writeBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + SPI1_PAL.transactions[0].count = writeBuffer->m_numOfElements; + + // set DMA write buffer + if(bufferIs16bits) + { + // buffer data width is 16bits + // get the pointer to the write buffer as UINT16 because it's really an UINT16 (2 bytes) + SPI1_PAL.transactions[0].txBuf = (uint16_t*)writeBuffer->GetFirstElementUInt16(); + } + else + { + // buffer data width is 8bits + // get the pointer to the write buffer as BYTE + SPI1_PAL.transactions[0].txBuf = (uint8_t*)writeBuffer->GetFirstElement(); + } + } + + if (readBuffer != NULL) + { + // we are in full duplex, the count for the SPI transaction was already set on the write + + if(bufferIs16bits) + { + // buffer data width is 16bits + SPI1_PAL.transactions[0].rxBuf = (uint16_t*)readBuffer->GetFirstElementUInt16(); + } + else + { + // buffer data width is 8bits + // get the pointer to the read buffer as BYTE + SPI1_PAL.transactions[0].rxBuf = (uint8_t*)readBuffer->GetFirstElement(); + } + } + } + else + { + // on a sequential transmition we TX first and then RX + + // TX on 1st transaction + if (writeBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + SPI1_PAL.transactions[0].count = writeBuffer->m_numOfElements; + + // set DMA write buffer + if(bufferIs16bits) + { + // buffer data width is 16bits + // get the pointer to the write buffer as UINT16 because it's really an UINT16 (2 bytes) + SPI1_PAL.transactions[0].txBuf = (uint16_t*)writeBuffer->GetFirstElementUInt16(); + } + else + { + // buffer data width is 8bits + // get the pointer to the write buffer as BYTE + SPI1_PAL.transactions[0].txBuf = (uint8_t*)writeBuffer->GetFirstElement(); + } + } + + // RX on 2nd transaction + if (readBuffer != NULL) + { + // get the size of the buffer by reading the number of elements in the CLR_RT_HeapBlock_Array + SPI1_PAL.transactions[1].count = readBuffer->m_numOfElements; + + if(bufferIs16bits) + { + // buffer data width is 16bits + SPI1_PAL.transactions[1].rxBuf = (uint16_t*)readBuffer->GetFirstElementUInt16(); + } + else + { + // buffer data width is 8bits + // get the pointer to the read buffer as BYTE + SPI1_PAL.transactions[1].rxBuf = (uint8_t*)readBuffer->GetFirstElement(); + } + } + } + + // start transfer of 1st transaction + SPI_transfer(SPI1_PAL.masterSpi, &SPI1_PAL.transactions[0]); + + // take one from pending transcations counter + SPI1_PAL.transactionCount--; + + // bump custom state + stack.m_customState = 2; + } + } + + while(eventResult) + { + // non-blocking wait allowing other threads to run while we wait for the Spi transaction to complete + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_SpiMaster, eventResult )); + + if(!eventResult) + { + // timeout occurred + NANOCLR_SET_AND_LEAVE(CLR_E_TIMEOUT); + } + } + + // pop timeout heap block from stack + stack.PopValue(); + + // null pointers and vars + pThis = NULL; + pConfig = NULL; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + (void)stack; + + NANOCLR_HEADER(); + + SPI_close(SPI1_PAL.masterSpi); + + NANOCLR_NOCLEANUP_NOLABEL(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h new file mode 100644 index 00000000..59a2c758 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_target.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_SPI_NATIVE_TARGET_H_ +#define _WIN_DEV_SPI_NATIVE_TARGET_H_ + +#include +#include "Board.h" +#include + +// struct representing the SPI +struct NF_PAL_SPI +{ + SPI_Handle masterSpi; + SPI_Params spiParams; + SPI_Transaction* transactions; + uint8_t transactionCount; +}; + +/////////////////////////////////////////// +// declaration of the the SPI PAL strucs // +/////////////////////////////////////////// +extern NF_PAL_SPI SPI1_PAL; + +#endif //_WIN_DEV_SPI_NATIVE_TARGET_H_ diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_App_Interface.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_App_Interface.c new file mode 100644 index 00000000..21259693 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_App_Interface.c @@ -0,0 +1,30 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +// declaration for wrapper function +extern int CLR_Messaging_ProcessPayload(WP_Message* msg); + +//////////////////////////////////////////////////// + +int WP_App_ProcessHeader(WP_Message* message) +{ + // check for reception buffer overflow + if(message->m_header.m_size > sizeof(receptionBuffer)) + { + return false; + } + + message->m_payload = receptionBuffer; + return true; +} + +int WP_App_ProcessPayload(WP_Message* message) +{ + return CLR_Messaging_ProcessPayload(message); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_MonitorCommands.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_MonitorCommands.c new file mode 100644 index 00000000..74e05b66 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/WireProtocol_MonitorCommands.c @@ -0,0 +1,7 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +// file empty on purpose +// in nanoCLR the MonitorCommands are implemented in Debugger diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/nanoCRT.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/nanoCRT.cpp new file mode 100644 index 00000000..45e1fa3e --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/nanoCRT.cpp @@ -0,0 +1,205 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include + +//--// +/* STDIO stubs */ +//--// + +#if !defined(BUILD_RTM) + +void hal_fprintf_SetLoggingCallback( LOGGING_CALLBACK fpn ) +{ + (void)fpn; + NATIVE_PROFILE_PAL_CRT(); + +} + +#endif + +//--// + +#if defined(PLATFORM_EMULATED_FLOATINGPOINT) + +// no floating point, fixed point + +int hal_snprintf_float( char* buffer, size_t len, const char* format, int32_t f ) +{ + NATIVE_PROFILE_PAL_CRT(); + + uint32_t i ; + uint32_t dec; + + if ( f < 0 ) + { + // negative number + i = (uint32_t) -f ; + dec = i & (( 1<>HAL_FLOAT_SHIFT); + + if (dec !=0) dec = (dec * (uint32_t)HAL_FLOAT_PRECISION + (1<< (HAL_FLOAT_SHIFT-1))) >>HAL_FLOAT_SHIFT; + + return hal_snprintf( buffer, len, "-%d.%03u", i, (uint32_t)dec); + + } + else + { + // positive number + i = (uint32_t) f ; + dec = f & (( 1<>HAL_FLOAT_SHIFT); + + if (dec !=0) dec = (dec * (uint32_t)HAL_FLOAT_PRECISION + (1<< (HAL_FLOAT_SHIFT-1))) >>HAL_FLOAT_SHIFT; + + return hal_snprintf( buffer, len, "%d.%03u", i, (uint32_t)dec); + } +} + +int hal_snprintf_double( char* buffer, size_t len, const char* format, int64_t& d ) +{ + NATIVE_PROFILE_PAL_CRT(); + + uint64_t i; + uint32_t dec; // 32 bit is enough for decimal part + + if ( d < 0 ) + { + // negative number + i = (uint64_t)-d; + + i += ((1 << (HAL_DOUBLE_SHIFT-1)) / HAL_DOUBLE_PRECISION); // add broad part of rounding increment before split + + dec = i & (( 1<> HAL_DOUBLE_SHIFT ; + + if (dec !=0) dec = (dec * HAL_DOUBLE_PRECISION + ((1 << (HAL_DOUBLE_SHIFT-1)) % HAL_DOUBLE_PRECISION)) >> HAL_DOUBLE_SHIFT; + + return hal_snprintf( buffer, len, "-%lld.%04u", (int64_t)i, (uint32_t)dec); + + } + else + { + + // positive number + i = (uint64_t)d; + + i += ((1 << (HAL_DOUBLE_SHIFT-1)) / HAL_DOUBLE_PRECISION); // add broad part of rounding increment before split + + dec = i & (( 1<> HAL_DOUBLE_SHIFT; + + if (dec !=0) dec = (dec * HAL_DOUBLE_PRECISION + ((1 << (HAL_DOUBLE_SHIFT-1)) % HAL_DOUBLE_PRECISION)) >> HAL_DOUBLE_SHIFT; + + return hal_snprintf( buffer, len, "%lld.%04u", (int64_t)i, (uint32_t)dec); + } +} + +#else + +#endif + +// because debug_printf needs to be called in both C and C++ we need a proxy to allow it to be called in 'C' +extern "C" { + +#if !defined(BUILD_RTM) + + void debug_printf(const char* format, ...) + { + char buffer[256]; + va_list arg_ptr; + + va_start( arg_ptr, format ); + + int len = vsnprintf( buffer, sizeof(buffer)-1, format, arg_ptr ); + + DebuggerPort_Write( HalSystemConfig.stdio, buffer, len, 0 ); // skip null terminator + + va_end( arg_ptr ); + } + +#else + __inline void debug_printf( const char *format, ... ) {} +#endif // !defined(BUILD_RTM) +} + +int hal_strcpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strcpy + + size_t len; + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + len = hal_strlen_s(strSrc); + if(sizeInBytes < len + 1) {_ASSERTE(FALSE); return 1;} + + strcpy( strDst, strSrc ); + return 0; + +#define strcpy DoNotUse_*strcpy [] +} + +int hal_strncpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc, size_t count ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strncpy + if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;} + + if (sizeInBytes < count + 1) + { + _ASSERTE(FALSE); + strDst[0] = 0; + return 1; + } + + strDst[count] = 0; + strncpy( strDst, strSrc, count ); + return 0; + +#define strncpy DoNotUse_*strncpy [] +} + +size_t hal_strlen_s (const char * str) +{ + NATIVE_PROFILE_PAL_CRT(); + + const char *eos = str; + while( *eos++ ) ; + return( eos - str - 1 ); +} + +int hal_strncmp_s ( const char* str1, const char* str2, size_t num ) +{ + NATIVE_PROFILE_PAL_CRT(); +#undef strncmp + if(str1 == NULL || str2 == NULL) {_ASSERTE(FALSE); return 1;} + + return strncmp( str1, str2, num ); + +#define strncmp DoNotUse_*strncmp [] +} + +// Compares 2 ASCII strings case insensitive. Does not take locale into account. +int hal_stricmp( const char * dst, const char * src ) +{ + int f = 0, l = 0; + + do + { + if ( ((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z') ) + { + f -= 'A' - 'a'; + } + if ( ((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z') ) + { + l -= 'A' - 'a'; + } + } + while ( f && (f == l) ); + + return(f - l); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL.cpp new file mode 100644 index 00000000..b1d5dd80 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL.cpp @@ -0,0 +1,155 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include + +// +// Reboot handlers clean up on reboot +// +static ON_SOFT_REBOOT_HANDLER s_rebootHandlers[16] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + +void HAL_AddSoftRebootHandler(ON_SOFT_REBOOT_HANDLER handler) +{ + for(unsigned int i=0; i 0) ? true : false; +} + +void SystemState_Set(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + SystemState_SetNoLock(state); + + GLOBAL_UNLOCK(); +} + +void SystemState_Clear(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + SystemState_ClearNoLock(state ); + + GLOBAL_UNLOCK(); +} + +bool SystemState_Query(SYSTEM_STATE_type state) +{ + GLOBAL_LOCK(); + + bool systemStateCopy = SystemState_QueryNoLock(state); + + GLOBAL_UNLOCK(); + + return systemStateCopy; +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Power.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Power.c new file mode 100644 index 00000000..d81f534d --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Power.c @@ -0,0 +1,39 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +#define SL_STOP_TIMEOUT (200) +extern uint16_t sl_Stop(const uint16_t Timeout); + +// FIXME TODO +void CPU_Reset() +{ + // stop network processor activities before reseting the MCU + sl_Stop(SL_STOP_TIMEOUT); + + // Reset the MCU + PRCMHibernateCycleTrigger(); +}; + +// CPU sleep is not currently implemented in this target +inline void CPU_Sleep(SLEEP_LEVEL_type level, uint64_t wakeEvents){ (void)level; (void)wakeEvents; }; + +inline bool CPU_IsSoftRebootSupported() { return true; }; + +void CPU_SetPowerMode(PowerLevel_type powerLevel) +{ + switch(powerLevel) + { + case PowerLevel__Off: + // gracefully shutdown everything + // FIXME TODO + break; + + default: + // all the other power modes are unsupported here + break; + } +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Time.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Time.cpp new file mode 100644 index 00000000..397c0866 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetHAL_Time.cpp @@ -0,0 +1,128 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +// Returns the current date time from the RTC +uint64_t HAL_Time_CurrentDateTime(bool datePartOnly) +{ + SYSTEMTIME st; + struct timespec tspec; + + clock_gettime(CLOCK_REALTIME, &tspec); + + // Convert from Unix time(year since 1900) to SYSTEMTIME(Years since 1601) + int64_t time = ((int64_t)tspec.tv_sec * (int64_t)TIME_CONVERSION__TO_SECONDS) + TIME_UNIX_EPOCH_AS_TICKS; + + HAL_Time_ToSystemTime(time, &st ); + + // zero 'time' fields if date part only is required + if(datePartOnly) + { + st.wMilliseconds = 0; + st.wSecond = 0; + st.wMinute = 0; + st.wHour = 0; + } + + return HAL_Time_ConvertFromSystemTime( &st ); +}; + +void HAL_Time_SetUtcTime(uint64_t utcTime) +{ + SYSTEMTIME systemTime; + struct tm newTime; + struct timespec tspec; + + HAL_Time_ToSystemTime(utcTime, &systemTime); + + newTime.tm_year = systemTime.wYear - 1900; // years since 1900 + newTime.tm_mon = systemTime.wMonth - 1; // months since January 0-11 + newTime.tm_mday = systemTime.wDay; // day of the month 1-31 + newTime.tm_wday = systemTime.wDayOfWeek; // days since Sunday 0-6 + newTime.tm_hour = (uint32_t)systemTime.wHour; // hours since midnight 0-23 + newTime.tm_min = (uint32_t)systemTime.wMinute; // minutes after the hour 0-59 + newTime.tm_sec = (uint32_t)systemTime.wSecond; // seconds after the minute 0-59 + + time_t t = mktime(&newTime); + tspec.tv_sec = t; + tspec.tv_nsec = 0; + + clock_settime(CLOCK_REALTIME, &tspec); +} + +bool HAL_Time_TimeSpanToStringEx( const int64_t& ticks, char*& buf, size_t& len ) +{ + uint64_t ticksAbs; + uint64_t rest; + + if(ticks < 0) + { + ticksAbs = -ticks; + + CLR_SafeSprintf( buf, len, "-" ); + } + else + { + ticksAbs = ticks; + } + + rest = ticksAbs % ( 1000 * TIME_CONVERSION__TICKUNITS); + ticksAbs = ticksAbs / ( 1000 * TIME_CONVERSION__TICKUNITS); // Convert to seconds. + + if(ticksAbs > TIME_CONVERSION__ONEDAY) // More than one day. + { + CLR_SafeSprintf( buf, len, "%d.", (int32_t)(ticksAbs / TIME_CONVERSION__ONEDAY) ); ticksAbs %= TIME_CONVERSION__ONEDAY; + } + + CLR_SafeSprintf( buf, len, "%02d:", (int32_t)(ticksAbs / TIME_CONVERSION__ONEHOUR) ); ticksAbs %= TIME_CONVERSION__ONEHOUR ; + CLR_SafeSprintf( buf, len, "%02d:", (int32_t)(ticksAbs / TIME_CONVERSION__ONEMINUTE)); ticksAbs %= TIME_CONVERSION__ONEMINUTE; + CLR_SafeSprintf( buf, len, "%02d" , (int32_t)(ticksAbs / TIME_CONVERSION__ONESECOND)); ticksAbs %= TIME_CONVERSION__ONESECOND; + + ticksAbs = (uint32_t)rest; + if(ticksAbs) + { + CLR_SafeSprintf( buf, len, ".%07d", (uint32_t)ticksAbs ); + } + + return len != 0; +} + +bool DateTimeToString(const int64_t& time, char*& buf, size_t& len ) +{ + SYSTEMTIME st; + + HAL_Time_ToSystemTime( time, &st ); + + return CLR_SafeSprintf(buf, len, "%4d/%02d/%02d %02d:%02d:%02d.%03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ); +} + +char* DateTimeToString(const int64_t& time) +{ + static char rgBuffer[128]; + char* szBuffer = rgBuffer; + size_t iBuffer = ARRAYSIZE(rgBuffer); + + DateTimeToString( time, szBuffer, iBuffer ); + + return rgBuffer; +} + +const char* HAL_Time_CurrentDateTimeToString() +{ + return DateTimeToString(HAL_Time_CurrentDateTime(false)); +} + +uint64_t CPU_MillisecondsToTicks(uint64_t ticks) +{ + return ((ticks * (uint64_t)configTICK_RATE_HZ) / 1000); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL.c new file mode 100644 index 00000000..a4d0c627 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL.c @@ -0,0 +1,68 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +extern UART_Handle uart; + +SemaphoreP_Handle uartMutex; + +// Need to have calls to these two functions in C code. +// Because they are called only on asm code, GCC linker with LTO option thinks they are not used and just removes them. +// Having them called from a dummy function that is never called it a workaround for this. +// The clean alternative would be to add the GCC attribute used in those functions, but that's not our code to touch. + +void dummyFunction(void) __attribute__((used)); + +// Never called. +void dummyFunction(void) { + vTaskSwitchContext(); + localProgramStart(); +} + +// configure UART +void ConfigUART() +{ + UART_Params uartParams; + + // Create a UART with data processing off + UART_Params_init(&uartParams); + + uartParams.writeDataMode = UART_DATA_BINARY; + uartParams.readDataMode = UART_DATA_BINARY; + uartParams.readReturnMode = UART_RETURN_FULL; + uartParams.readEcho = UART_ECHO_OFF; + uartParams.baudRate = 921600; + uartParams.readTimeout = 500; + + uart = UART_open(Board_UART0, &uartParams); + + if (uart == NULL) + { + // UART_open() failed + while (1); + } + + uartMutex = SemaphoreP_createBinary(1); + if (uartMutex == NULL) + { + // failed to create semaphore + while (1); + } +} + +void __error__(char *pcFilename, unsigned long ulLine) +{ + // + // Something horrible happened! You need to look + // at file "pcFilename" at line "ulLine" to see + // what error is being reported. + // + while(1) + { + } +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Events.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Events.cpp new file mode 100644 index 00000000..702f7fec --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Events.cpp @@ -0,0 +1,179 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include +#include +#include + +uint64_t CPU_MillisecondsToTicks(uint64_t ticks); + +// timer for bool events +static TimerHandle_t boolEventsTimer; + +volatile uint32_t systemEvents; + +static void local_Events_SetBoolTimer_Callback( TimerHandle_t xTimer ); + +set_Event_Callback g_Event_Callback = NULL; +void* g_Event_Callback_Arg = NULL; + +bool Events_Initialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // init events + GLOBAL_LOCK(); + systemEvents = 0; + GLOBAL_UNLOCK(); + + boolEventsTimer = xTimerCreate( "boolEventsTimer", 10, pdFALSE, (void *)0, local_Events_SetBoolTimer_Callback); + + return true; +} + +bool Events_Uninitialize() +{ + NATIVE_PROFILE_PAL_EVENTS(); + + xTimerDelete(boolEventsTimer,0); + + return true; +} + +void Events_Set( uint32_t events ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // set events + GLOBAL_LOCK(); + systemEvents |= events; + GLOBAL_UNLOCK(); + + if( g_Event_Callback != NULL ) + { + g_Event_Callback( g_Event_Callback_Arg ); + } +} + +uint32_t Events_Get( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // get the requested flags from system events state and... + uint32_t returnEvents = (systemEvents & eventsOfInterest); + + // ... clear the requested flags atomically + GLOBAL_LOCK(); + systemEvents &= ~eventsOfInterest; + GLOBAL_UNLOCK(); + + // give the caller notice of just the events they asked for ( and were cleared already ) + return returnEvents; +} + +uint32_t Events_MaskedRead( uint32_t eventsOfInterest ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + return (systemEvents & eventsOfInterest); +} + +static void local_Events_SetBoolTimer_Callback( TimerHandle_t xTimer ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + bool* timerCompleteFlag = (bool*)pvTimerGetTimerID( xTimer ); + *timerCompleteFlag = true; +} + +void Events_SetCallback( set_Event_Callback pfn, void* arg ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + g_Event_Callback = pfn; + g_Event_Callback_Arg = arg; +} + +void Events_SetBoolTimer( bool* timerCompleteFlag, uint32_t millisecondsFromNow ) +{ + NATIVE_PROFILE_PAL_EVENTS(); + + // we assume only 1 can be active, abort previous just in case + xTimerStop( boolEventsTimer, 0 ); + + if(timerCompleteFlag != NULL) + { + vTimerSetTimerID( boolEventsTimer, (void*) timerCompleteFlag ); + xTimerChangePeriod( boolEventsTimer, millisecondsFromNow / portTICK_PERIOD_MS, 0 ); + } +} + +uint32_t Events_WaitForEvents( uint32_t powerLevel, uint32_t wakeupSystemEvents, uint32_t timeoutMilliseconds ) +{ + // schedule an interrupt for this far in the future + // timeout is in milliseconds, need to convert to ticks + uint64_t countsRemaining = CPU_MillisecondsToTicks(timeoutMilliseconds); + + #if defined(HAL_PROFILE_ENABLED) + Events_WaitForEvents_Calls++; + #endif + + uint64_t expireTimeInTicks = HAL_Time_CurrentTime() + countsRemaining; + bool runContinuations = true; + + while(true) + { + EVENTS_HEART_BEAT; + + uint32_t events = Events_MaskedRead( wakeupSystemEvents ); + if(events) + { + return events; + } + + if(expireTimeInTicks <= HAL_Time_CurrentTime()) + { + break; + } + + // first check and possibly run any continuations + // but only if we have slept after stalling + if(runContinuations && !SystemState_QueryNoLock(SYSTEM_STATE_NO_CONTINUATIONS)) + { + // if we stall on time, don't check again until after we sleep + runContinuations = HAL_CONTINUATION::Dequeue_And_Execute(); + } + else + { + // try stalled continuations again after sleeping + runContinuations = true; + + HAL_COMPLETION::WaitForInterrupts(expireTimeInTicks, powerLevel, wakeupSystemEvents ); + } + + // no events, pass control to the OS + taskYIELD(); + + // check if reboot or exit flags were set when the other OS threads executed + if(CLR_EE_DBG_IS(RebootPending) || CLR_EE_DBG_IS(ExitPending)) + { + break; + } + } + + return 0; +} + +void FreeManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2) +{ + (void)category; + (void)subCategory; + (void)data1; + (void)data2; + + NATIVE_PROFILE_PAL_EVENTS(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Time.cpp b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Time.cpp new file mode 100644 index 00000000..283f34ad --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetPAL_Time.cpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +static TimerHandle_t nextEventTimer; + +static void NextEventTimer_Callback( TimerHandle_t xTimer ) +{ + (void)xTimer; + + // this call also schedules the next one, if there is one + HAL_COMPLETION::DequeueAndExec(); +} + +HRESULT Time_Initialize() +{ + nextEventTimer = xTimerCreate( "NextEventTimer", 10, pdFALSE, (void *)0, NextEventTimer_Callback); + + return S_OK; +} + +HRESULT Time_Uninitialize() +{ + xTimerDelete(nextEventTimer, 0); + + return S_OK; +} + +void Time_SetCompare ( uint64_t compareValueTicks ) +{ + if(compareValueTicks == 0) + { + // compare value is 0 so dequeue and schedule immediately + HAL_COMPLETION::DequeueAndExec(); + } + else if(compareValueTicks == HAL_COMPLETION_IDLE_VALUE) + { + // wait for infinity, don't need to do anything here + return; + } + else + { + if (HAL_Time_CurrentTime() >= compareValueTicks) + { + // already missed the event, dequeue and execute immediately + HAL_COMPLETION::DequeueAndExec(); + } + else + { + xTimerStop( nextEventTimer, 0 ); + + // compareValueTicks is the time (in sys ticks) that is being requested to fire an HAL_COMPLETION::DequeueAndExec() + // need to subtract the current system time to set when the timer will fire + compareValueTicks -= HAL_Time_CurrentTime(); + + // no need to stop the timer even if it's running because the API does it anyway + // need to convert from nF ticks to milliseconds and then to FreeRTOS sys ticks to load the timer + xTimerChangePeriod(nextEventTimer, compareValueTicks, 0); + } + } +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_LinkLocalTask.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_LinkLocalTask.c new file mode 100644 index 00000000..58e2f7cb --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_LinkLocalTask.c @@ -0,0 +1,2840 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +/* standard includes */ +#include +#include + +/* TI-DRIVERS Header files */ +#include +#include +#include + +/* Example/Board Header files */ +#include +#include +#include + +/* driverlib Header files */ +#include +#include + +// nanoFramework header files +#include + +#define NETAPP_MAX_RX_FRAGMENT_LEN SL_NETAPP_REQUEST_MAX_DATA_LEN +#define NETAPP_MAX_METADATA_LEN (100) +#define NETAPP_MAX_ARGV_TO_CALLBACK SL_FS_MAX_FILE_NAME_LENGTH + 50 +#define NUMBER_OF_URI_SERVICES (6) + +#define LED_TOGGLE_OTA_PROCESS_TIMEOUT (100) /* In msecs */ + +#define DEV_TYPE_CC3220R (0x010) +#define DEV_TYPE_CC3220RS (0x018) +#define DEV_TYPE_CC3220FS (0x019) +#define DEV_TYPE_CC323XR (0x110) +#define DEV_TYPE_CC323XRS (0x118) +#define DEV_TYPE_CC323XFS (0x119) + +#define MAC_ADDR_STR_LEN (18) +#define IP_ADDR_STR_LEN (16) +#define SENSOR_VALUE_STR_LEN (4) + + +/**************************************************************************** + LOCAL FUNCTION PROTOTYPES +****************************************************************************/ + +//***************************************************************************** +// +//! \brief This function prepare error netapp response in case memory could +//! not be allocated +//! +//! \param[in] pNetAppResponse netapp response structure +//! +//! \return none +//! +//**************************************************************************** +void NetAppRequestErrorResponse(SlNetAppResponse_t *pNetAppResponse); + +//***************************************************************************** +// +//! \brief This function fetches the device MAC address +//! +//! \param[out] buffer to occupy the MAC address in string format +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t getDeviceMacAddress(uint8_t *macAddress); + +//***************************************************************************** +// +//! Function to read accelarometer +//! +//! \param none +//! +//! \return SUCCESS or FAILURE +//! +//***************************************************************************** +uint8_t accelarometerReading(void); + +//***************************************************************************** +// +//! Function to read temperature +//! +//! \param none +//! +//! \return SUCCESS or FAILURE +//! +//***************************************************************************** +uint8_t temperatureReading(void); + +//***************************************************************************** +// +//! \brief this function composes an element type from metadata/payload +//!(TLV structure) +//! +//! \param[in] isAnswer states whether this is a value or a parameter +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] elementVal value of element +//! +//! \return element type +//! +//**************************************************************************** +uint16_t setElementType(uint8_t isValue, + uint8_t requestIdx, + uint8_t elementVal); + +//***************************************************************************** +// +//! \brief This function prepares metadata for HTTP GET requests +//! +//! \param[in] parsingStatus validity of HTTP GET request +//! +//! \param[in] contentLen content length in respond to +//! HTTP GET request +//! +//! \return metadataLen +//! +//**************************************************************************** +uint16_t prepareGetMetadata(int32_t parsingStatus, + uint32_t contentLen, + HttpContentTypeList contentTypeId); + +//***************************************************************************** +// +//! \brief This function prepares metadata for HTTP POST/PUT requests +//! +//! \param[in] parsingStatus validity of HTTP POST/PUT request +//! +//! \return metadataLen +//! +//**************************************************************************** +uint16_t preparePostMetadata(int32_t parsingStatus); + +//***************************************************************************** +// +//! \brief This function fetches the device IP address +//! +//! \param[in] none +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t getDeviceIpAddress(void); + +//***************************************************************************** +// +//! \brief This function fetches the SSID the device is connected to +//! +//! \param[in] none +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t getDeviceSSID(void); + +//***************************************************************************** +// +//! \brief This function flushes the netapp data from the client +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \param[in] flags netapp flags for more data +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t otaFlushNetappReq(SlNetAppRequest_t *netAppRequest, + uint32_t *flags); + +//***************************************************************************** +// +//! \brief This is a filesystem service callback function for HTTP PUT +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t otaPutCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest); + +//***************************************************************************** +// +//! \brief This is the ota service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t otaGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest); + +//***************************************************************************** +// +//! \brief This is a light service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t lightGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest); + +//***************************************************************************** +// +//! \brief This is a light service callback function for HTTP POST +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t lightPostCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest); + +//***************************************************************************** +// +//! \brief This is a sensors service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t sensorGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest); + +//***************************************************************************** +// +//! \brief This is a generic device service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t deviceGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest); + +//***************************************************************************** +// +//! \brief This function create mailbox message queue between linkLocal task +//! and driver task +//! +//! \param[in] None +//! +//! \return 0 on success or -ve on error +//! +//**************************************************************************** +void initLinkLocalDB(void); + +//***************************************************************************** +// +//! \brief This function scan netapp request and parse the payload +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] pPhrase pointer to HTTP metadata payload +//! +//! \param[in] payloadLen HTTP metadata or payload length +//! +//! \param[out] argcCallback count of input params to the service callback +//! +//! \param[out] argvCallback set of input params to the service callback +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t parseUrlEncoded(uint8_t requestIdx, + uint8_t * pPhrase, + uint16_t phraseLen, + uint8_t *argcCallback, + uint8_t **argvCallback); + +//***************************************************************************** +// +//! \brief This function maps header type to its string value +//! +//! \param[in] httpHeaderType http header type +//! +//! \param[out] httpHeaderText http header text +//! +//! \return none +//! +//**************************************************************************** +void convertHeaderType2Text(uint8_t httpHeaderType, + uint8_t **httpHeaderText); + +//***************************************************************************** +// +//! \brief This function scan netapp request and parse the metadata +//! +//! \param[in] requestType HTTP method (GET, POST, PUT or DEL) +//! +//! \param[in] pMetadata pointer to HTTP metadata +//! +//! \param[in] metadataLen HTTP metadata length +//! +//! \param[out] requestIdx request index to indicate the message +//! +//! \param[out] argcCallback count of input params to the service callback +//! +//! \param[out] argvCallback set of input params to the service callback +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t parseHttpRequestMetadata(uint8_t requestType, + uint8_t * pMetadata, + uint16_t metadataLen, + uint8_t *requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback); + +//***************************************************************************** +// +//! \brief This function scan netapp request and parse the payload +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] pPayload pointer to HTTP payload +//! +//! \param[in] payloadLen HTTP payload length +//! +//! \param[out] argcCallback count of input params to the service callback +//! +//! \param[out] argvCallback set of input params to the service callback +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t parseHttpRequestPayload(uint8_t requestIdx, + uint8_t * pPayload, + uint16_t payloadLen, + uint8_t *argcCallback, + uint8_t **argvCallback); + +//***************************************************************************** +// +//! \brief This function checks that the content requested via HTTP message exists +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \param[out] requestIdx request index to indicate the message +//! +//! \param[out] argcCallback count of input params to the service callback +//! +//! \param[out] argvCallback set of input params to the service callback +//! +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t httpCheckContentInDB(SlNetAppRequest_t *netAppRequest, + uint8_t *requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback); + +//***************************************************************************** +// +//! \brief This function parse and execute HTTP GET requests +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return None +//! +//**************************************************************************** +void httpGetHandler(SlNetAppRequest_t *netAppRequest); + +//***************************************************************************** +// +//! \brief This function parse and execute HTTP POST/PUT requests +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return None +//! +//**************************************************************************** +void httpPostHandler(SlNetAppRequest_t *netAppRequest); + +/**************************************************************************** + GLOBAL VARIABLES +****************************************************************************/ + +const uint8_t pageNotFound[] = "404 - Sorry page not found"; + +/* metadata and content buffer are allocated + static as these are shared in all use cases*/ +/* however, it is possible to set those dynamically as well */ +uint8_t gMetadataBuffer[NETAPP_MAX_METADATA_LEN]; +uint8_t gPayloadBuffer[NETAPP_MAX_RX_FRAGMENT_LEN]; +//uint8_t gOtaVersion[VERSION_STR_SIZE + 1]; + +uint8_t gHttpPostBuffer[NETAPP_MAX_ARGV_TO_CALLBACK]; +uint8_t gHttpGetBuffer[NETAPP_MAX_ARGV_TO_CALLBACK]; + +int8_t xVal, yVal, zVal; +float temperatureVal; +I2C_Handle i2cHandle; + +/* database to hold ota archive */ +//OtaArchive_t gOtaArcive; + +/* message queue for http messages between server and client */ +mqd_t linkLocalMQueue; +pthread_mutex_t *sensorLockObj = NULL; /* Lock Object for sensor readings */ + +http_RequestObj_t httpRequest[NUMBER_OF_URI_SERVICES] = +{ + {0, SL_NETAPP_REQUEST_HTTP_GET, "/ota", { + {NULL} + }, NULL}, + {1, SL_NETAPP_REQUEST_HTTP_PUT, "/ota", { + {NULL} + }, NULL}, + {2, SL_NETAPP_REQUEST_HTTP_GET, "/light", { + {NULL} + }, NULL}, + {3, SL_NETAPP_REQUEST_HTTP_POST, "/light", { + {NULL} + }, NULL}, + {4, SL_NETAPP_REQUEST_HTTP_GET, "/sensor", { + {NULL} + }, NULL}, + {5, SL_NETAPP_REQUEST_HTTP_GET, "/device", { + {NULL} + }, NULL}, +}; + +http_headerFieldType_t g_HeaderFields [] = +{ + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_VERSION, WEB_SERVER_VERSION}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_REQUEST_URI, WEB_SERVER_REQUEST_URI}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_QUERY_STRING, + WEB_SERVER_QUERY_STRING}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_TYPE, + WEB_SERVER_HEADER_CONTENT_TYPE}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_LEN, + WEB_SERVER_HEADER_CONTENT_LEN}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_LOCATION, + WEB_SERVER_HEADER_LOCATION}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_SERVER, WEB_SERVER_HEADER_SERVER}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_USER_AGENT, + WEB_SERVER_HEADER_USER_AGENT}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_COOKIE, WEB_SERVER_HEADER_COOKIE}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_SET_COOKIE, + WEB_SERVER_HEADER_SET_COOKIE}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_UPGRADE, WEB_SERVER_HEADER_UPGRADE}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_REFERER, WEB_SERVER_HEADER_REFERER}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_ACCEPT, WEB_SERVER_HEADER_ACCEPT}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_ENCODING, + WEB_SERVER_HEADER_CONTENT_ENCODING}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_DISPOSITION, + WEB_SERVER_HEADER_CONTENT_DISPOSITION}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONNECTION, + WEB_SERVER_HEADER_CONNECTION}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_ETAG, WEB_SERVER_HEADER_ETAG}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_DATE, WEB_SERVER_HEADER_DATE}, + {SL_NETAPP_REQUEST_METADATA_TYPE_HEADER_HOST, WEB_SERVER_HEADER_HOST}, + {SL_NETAPP_REQUEST_METADATA_TYPE_ACCEPT_ENCODING, + WEB_SERVER_HEADER_ACCEPT_ENCODING}, + {SL_NETAPP_REQUEST_METADATA_TYPE_ACCEPT_LANGUAGE, + WEB_SERVER_HEADER_ACCEPT_LANGUAGE}, + {SL_NETAPP_REQUEST_METADATA_TYPE_CONTENT_LANGUAGE, + WEB_SERVER_HEADER_CONTENT_LANGUAGE} +}; + +http_contentTypeMapping_t g_ContentTypes [] = +{ + {HttpContentTypeList_TextHtml, TEXT_HTML, TEXT_HTML_MIME}, + {HttpContentTypeList_TextCSS, TEXT_CSS, TEXT_CSS_MIME}, + {HttpContentTypeList_TextXML, TEXT_XML, TEXT_XML_MIME}, + {HttpContentTypeList_ApplicationJson, APPLICATION_JSON, + APPLICATION_JSON_MIME}, + {HttpContentTypeList_ImagePNG, IMAGE_PNG, IMAGE_PNG_MIME}, + {HttpContentTypeList_ImageGIF, IMAGE_GIF, IMAGE_GIF_MIME}, + {HttpContentTypeList_TextPlain, TEXT_PLAIN, TEXT_PLAIN_MIME}, + {HttpContentTypeList_TextCSV, TEXT_CSV, TEXT_CSV_MIME}, + {HttpContentTypeList_ApplicationJavascript, APPLICATION_JAVASCRIPT, + APPLICATION_JAVASCRIPT_MIME}, + {HttpContentTypeList_ImageJPEG, IMAGE_JPEG, IMAGE_JPEG_MIME}, + {HttpContentTypeList_ApplicationPDF, APPLICATION_PDF, + APPLICATION_PDF_MIME}, + {HttpContentTypeList_ApplicationZIP, APPLICATION_ZIP, + APPLICATION_ZIP_MIME}, + {HttpContentTypeList_ShokewaveFlash, SHOCKWAVE_FLASH, + SHOCKWAVE_FLASH_MIME}, + {HttpContentTypeList_AudioXAAC, AUDIO_X_AAC, AUDIO_X_AAC_MIME}, + {HttpContentTypeList_ImageXIcon, IMAGE_X_ICON, IMAGE_X_ICON_MIME}, + {HttpContentTypeList_TextVcard, TEXT_VCARD, TEXT_VCARD_MIME}, + {HttpContentTypeList_ApplicationOctecStream, APPLICATION_OCTEC_STREAM, + APPLICATION_OCTEC_STREAM_MIME}, + {HttpContentTypeList_VideoAVI, VIDEO_AVI, VIDEO_AVI_MIME}, + {HttpContentTypeList_VideoMPEG, VIDEO_MPEG, VIDEO_MPEG_MIME}, + {HttpContentTypeList_VideoMP4, VIDEO_MP4, VIDEO_MP4_MIME}, + {HttpContentTypeList_UrlEncoded, FORM_URLENCODED, URL_ENCODED_MIME} +}; + +LinkLocal_CB LinkLocal_ControlBlock; + +extern int snprintf(char *_string, + size_t _n, + const char *_format, + ...); + +/***************************************************************************** + Callback Functions +*****************************************************************************/ + +//***************************************************************************** +// +//! \brief This function is registered as netapp request callback +//! +//! \param[in] pNetAppRequest netapp request structure +//! +//! \param[out] pNetAppResponse netapp response structure +//! +//! \return none +//! +//**************************************************************************** +void SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t *pNetAppRequest, + SlNetAppResponse_t *pNetAppResponse) +{ + SlNetAppRequest_t *netAppRequest; + int32_t msgqRetVal; + + INFO_PRINT( + "[Link local task] NetApp Request Received - AppId = %d, Type = %d," + "Handle = %d\n\r", + pNetAppRequest->AppId, pNetAppRequest->Type, pNetAppRequest->Handle); + + if((pNetAppRequest->Type == SL_NETAPP_REQUEST_HTTP_GET) || + (pNetAppRequest->Type == SL_NETAPP_REQUEST_HTTP_DELETE) || + (pNetAppRequest->Type == SL_NETAPP_REQUEST_HTTP_POST) || + (pNetAppRequest->Type == SL_NETAPP_REQUEST_HTTP_PUT)) + { + /* Prepare pending response */ + pNetAppResponse->Status = SL_NETAPP_RESPONSE_PENDING; + pNetAppResponse->ResponseData.pMetadata = NULL; + pNetAppResponse->ResponseData.MetadataLen = 0; + pNetAppResponse->ResponseData.pPayload = NULL; + pNetAppResponse->ResponseData.PayloadLen = 0; + pNetAppResponse->ResponseData.Flags = 0; + } + else + { + NetAppRequestErrorResponse(pNetAppResponse); + + return; + } + + netAppRequest = (SlNetAppRequest_t *) malloc (sizeof(SlNetAppRequest_t)); + if(NULL == netAppRequest) + { + NetAppRequestErrorResponse(pNetAppResponse); + + return; + } + + memset(netAppRequest,0,sizeof(SlNetAppRequest_t)); + netAppRequest->AppId = pNetAppRequest->AppId; + netAppRequest->Type = pNetAppRequest->Type; + netAppRequest->Handle = pNetAppRequest->Handle; + netAppRequest->requestData.Flags = pNetAppRequest->requestData.Flags; + + /* Copy Metadata */ + if(pNetAppRequest->requestData.MetadataLen > 0) + { + netAppRequest->requestData.pMetadata = (uint8_t *) malloc ( + pNetAppRequest->requestData.MetadataLen); + if(NULL == netAppRequest->requestData.pMetadata) + { + NetAppRequestErrorResponse(pNetAppResponse); + free(netAppRequest); + return; + } + sl_Memcpy(netAppRequest->requestData.pMetadata, + pNetAppRequest->requestData.pMetadata, + pNetAppRequest->requestData.MetadataLen); + netAppRequest->requestData.MetadataLen = + pNetAppRequest->requestData.MetadataLen; + } + else + { + netAppRequest->requestData.MetadataLen = 0; + } + + /* Copy the payload */ + if(pNetAppRequest->requestData.PayloadLen > 0) + { + netAppRequest->requestData.pPayload = (uint8_t *) malloc ( + pNetAppRequest->requestData.PayloadLen); + if(NULL == netAppRequest->requestData.pPayload) + { + NetAppRequestErrorResponse(pNetAppResponse); + + if(netAppRequest->requestData.pMetadata != NULL) + { + free(netAppRequest->requestData.pMetadata); + } + free(netAppRequest); + return; + } + sl_Memcpy (netAppRequest->requestData.pPayload, + pNetAppRequest->requestData.pPayload, + pNetAppRequest->requestData.PayloadLen); + netAppRequest->requestData.PayloadLen = + pNetAppRequest->requestData.PayloadLen; + } + else + { + netAppRequest->requestData.PayloadLen = 0; + } + + msgqRetVal = mq_send(linkLocalMQueue, (char *)&netAppRequest, 1, 0); + if(msgqRetVal < 0) + { + UART_PRINT("[Link local task] could not send element to msg queue\n\r"); + while(1) + { + ; + } + } +} + +//***************************************************************************** +// +//! \brief This is a filesystem service callback function for HTTP PUT +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the +//! service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t otaPutCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest) +{ + uint8_t *argvArray; + uint16_t metadataLen; + uint8_t *filename; + int32_t Status; + uint32_t flags; + uint32_t fileLen = 0; + uint16_t elementType; + int16_t otaState, processedBytes, unprocessedBytes, chunkLen, otaChunkLen; + int32_t accumulatedLen; + uint8_t otaProgressBar; + uint32_t deviceType; + struct timespec ts; + + StartLedEvtTimer(LED_TOGGLE_OTA_PROCESS_TIMEOUT); + + Status = 0; + accumulatedLen = 0; + deviceType = getDeviceType(); + argvArray = *argvCallback; + + /* get the filename */ + filename = argvArray + 2 * ARGV_VALUE_OFFSET + 1; + + elementType = setElementType(1, requestIdx, CONTENT_LEN_TYPE); + + /* search for the file length */ + while((*argcCallback > 0) && (*((uint16_t *)argvArray) != elementType)) + { + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + + (*argcCallback)--; + } + + if(*((uint16_t *)argvArray) == elementType) + { + sl_Memcpy ((uint8_t*)&fileLen, (argvArray + ARGV_VALUE_OFFSET), + *(argvArray + ARGV_LEN_OFFSET)); + } + + UART_PRINT("[Link local task] Received OTA filename %s, len = %lu \n\r", + filename, + fileLen); + + /* Init the Tar parser module */ + //OtaArchive_Init(&gOtaArcive); + + otaProgressBar = 0; + + /* at this point start the report server in the background */ + /* signal to ota task */ + sem_post(&LinkLocal_ControlBlock.otaReportServerStartSignal); + + /* set the flags to check for more data */ + flags = netAppRequest->requestData.Flags; + + /* must be archive file name */ + if(strstr((const char *)filename, ".tar") == NULL) + { + UART_PRINT( + "[Link local task] OTA filename should be in *.tar format\n\r"); + Status = -1; + goto exit_ota_put; + } + + /* updating versions */ + // OtaArchive_CheckVersion(&gOtaArcive, filename); + + sl_Memcpy(gPayloadBuffer, netAppRequest->requestData.pPayload, + netAppRequest->requestData.PayloadLen); + // Status = + // (int32_t)OtaArchive_Process(&gOtaArcive, gPayloadBuffer, + // netAppRequest->requestData.PayloadLen, + // &processedBytes); + INFO_PRINT("[Link local task] Received OTA payload %d. Processed %d \n\r", + netAppRequest->requestData.PayloadLen, + processedBytes); + + // if(Status < 0) + // { + // goto exit_ota_put; + // } + // else if(Status == ARCHIVE_STATUS_DOWNLOAD_DONE) + // { + // otaProgressBar = 100; + // mq_send(LinkLocal_ControlBlock.reportServerMQueue, + // (char *)&otaProgressBar, 1, + // 0); + + // /* Tar file parsing completed */ + // //UART_PRINT( + // // "[Link local task] sl_extLib_OtaRun: ---- " + // // "Download file completed %s\r\n", + // // filename); + + // Status = 0; + + // goto exit_ota_put; + // } + unprocessedBytes = netAppRequest->requestData.PayloadLen - processedBytes; + accumulatedLen += processedBytes; + otaProgressBar = (accumulatedLen * 100) / fileLen; + mq_send(LinkLocal_ControlBlock.reportServerMQueue, (char *)&otaProgressBar, + 1, + 0); + + while(OOB_IS_NETAPP_MORE_DATA(flags) || + ((unprocessedBytes > 0) && + ((fileLen - accumulatedLen) < NETAPP_MAX_RX_FRAGMENT_LEN))) + { + /* copy the unprocessed part to the start of the buffer */ + if(unprocessedBytes > 0) + { + sl_Memcpy(&gPayloadBuffer[0], &gPayloadBuffer[processedBytes], + unprocessedBytes); + } + + if(OOB_IS_NETAPP_MORE_DATA(flags)) + { + chunkLen = NETAPP_MAX_RX_FRAGMENT_LEN - unprocessedBytes; + Status = + sl_NetAppRecv(netAppRequest->Handle, (uint16_t *)&chunkLen, + &gPayloadBuffer[unprocessedBytes], + (unsigned long *)&flags); + INFO_PRINT( + "[Link local task] sl_NetAppRecv payload=%d, flags=%d \n\r", + chunkLen, flags); + if(Status < 0) + { + UART_PRINT( + "[Link local task] sl_NetAppRecv error=%d, flags=%d \n\r", + Status, flags); + /* Stop the parsing of the archive file */ + // OtaArchive_Abort(&gOtaArcive); + + goto exit_ota_put; + } + } + else + { + /* cover cases where netapp has no more data and + download is close to 100%. + Archive module needs more processing time to complete */ + INFO_PRINT( + "[Link local task] No more data in NetApp but archive module " + "still has processing to do \n\r"); + Status = 0; + chunkLen = 0; + } + + //otaState = OtaArchive_GetSktatus(&gOtaArcive); + //INFO_PRINT("[Link local task] OTA state is %d \n\r", otaState); + // if(otaState == OtaArchiveState_OpenFile) + // { + // //INFO_PRINT("[Link local task] File size is %d \n\r", + // // gOtaArcive.CurrTarObj.FileSize); + // } + + // if(otaState == OtaArchiveState_OpenFile) + // { + // if(strstr((const char *)gOtaArcive.CurrTarObj.pFileName, + // "mcuimg.bin") != NULL) + // { + // if((deviceType == DEV_TYPE_CC3220FS) || + // (deviceType == DEV_TYPE_CC323XFS)) + // { + // //UART_PRINT( + // // "[Link local task] mcu image of CC32xxR or CC32xxRS " + // // "cannot be programmed onto CC32xxSF\n\r"); + + // /* Stop the parsing of the archive file */ + // OtaArchive_Abort(&gOtaArcive); + + // goto exit_ota_put; + // } + // } + + // if(strstr((const char *)gOtaArcive.CurrTarObj.pFileName, + // "mcuflashimg.bin") != NULL) + // { + // if((deviceType == DEV_TYPE_CC3220R) || + // (deviceType == DEV_TYPE_CC3220RS) || + // (deviceType == DEV_TYPE_CC323XR) || + // (deviceType == DEV_TYPE_CC323XRS)) + // { + // //UART_PRINT( + // // "[Link local task] mcu image of CC32xxSF cannot be " + // // "programmed onto CC32xxR or CC32xxRS\n\r"); + + // /* Stop the parsing of the archive file */ + // OtaArchive_Abort(&gOtaArcive); + + // goto exit_ota_put; + // } + // } + // } + + otaChunkLen = chunkLen + unprocessedBytes; + // Status = + // (int32_t)OtaArchive_Process(&gOtaArcive, gPayloadBuffer, + // otaChunkLen, + // &processedBytes); + + INFO_PRINT( + "[Link local task] Received OTA payload=%d. Processed=%d \n\r", + otaChunkLen, processedBytes); + if(Status < 0) + { + UART_PRINT("[Link local task] OtaArchive error %d \n\r", Status); + goto exit_ota_put; + } + // else if(Status == ARCHIVE_STATUS_DOWNLOAD_DONE) + // { + // clock_gettime(CLOCK_REALTIME, &ts); + // ts.tv_nsec += 1000000; + // if(ts.tv_nsec > 1000000000) + // { + // ts.tv_nsec -= 1000000000; + // ts.tv_sec++; + // } + + // otaProgressBar = 100; + // mq_timedsend(LinkLocal_ControlBlock.reportServerMQueue, + // (char *)&otaProgressBar, 1, 0, + // &ts); + // /* Tar file parsing completed */ + // //UART_PRINT( + // // "[Link local task] sl_extLib_OtaRun: ---- Download " + // // "file completed %s\r\n", + // // filename); + + // Status = 0; + + // goto exit_ota_put; + // } + unprocessedBytes = otaChunkLen - processedBytes; + accumulatedLen += processedBytes; + otaProgressBar = (accumulatedLen * 100) / fileLen; + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_nsec += 1000000; + if(ts.tv_nsec > 1000000000) + { + ts.tv_nsec -= 1000000000; + ts.tv_sec++; + } + + mq_timedsend(LinkLocal_ControlBlock.reportServerMQueue, + (char *)&otaProgressBar, 1, 0, + &ts); + } + +exit_ota_put: + + + + /* several use cases can occur at this point + + + ▼use case▼| good | bad | no rx bufer | internal error | + --------------------------------------------------------------- + Status | 0 | <0 | 0 | 0 | + --------------------------------------------------------------- + progress bar| 100 | <100 | <100 | <100 | + --------------------------------------------------------------- + flags | 0 | N/A | 0 | 80000000 | + --------------------------------------------------------------- + send metada?| yes | yes | yes | no | + --------------------------------------------------------------- + notes | | | bad case | bad case | + --------------------------------------------------------------- + + + */ + + /* progress bar is not yet 100% - bad case*/ + if(otaProgressBar != 100) + { + Status = -1; + } + UART_PRINT("[Link local task] ota put done. Status=%d \r\n", Status); + if(Status == 0) + { + /* flush the netapp data from client */ + otaFlushNetappReq(netAppRequest, &flags); + } + + /* sending metadata is not allowed in case of internal error */ + if(OOB_IS_NETAPP_ERROR(flags)) + { + UART_PRINT("[Link local task] sl_NetAppRecv error, flags=%d \n\r", + flags); + } + else + { + metadataLen = preparePostMetadata(Status); + + INFO_PRINT("[Link local task] ota put, sending metadata \r\n"); + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA); + } + + if(Status != 0) + { + /* mark progress bar to 0xFF so ota task + would get restarted to reopen socket */ + otaProgressBar = 0xFF; + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_nsec += 1000000; + if(ts.tv_nsec > 1000000000) + { + ts.tv_nsec -= 1000000000; + ts.tv_sec++; + } + + mq_timedsend(LinkLocal_ControlBlock.reportServerMQueue, + (char *)&otaProgressBar, 1, 0, + &ts); + } + + UART_PRINT("[Link local task] waiting for signal from report server\r\n"); + + /* waits for ota response server to + finish sending report messages to client */ + sem_wait(&LinkLocal_ControlBlock.otaReportServerStopSignal); + + StopLedEvtTimer(); + if(Status == 0) + { + //GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); + } + else + { + //GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); + } + + if(Status == 0) + { + /* it means Tar file is downloaded and parsed correctly. + Need to reset the MCU */ + mcuReboot(); + } + + return(Status); +} + +//***************************************************************************** +// +//! \brief This is the ota service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t otaGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest) +{ + uint8_t *argvArray, *pPayload; + uint16_t metadataLen, elementType; + int32_t Status = 0; + + argvArray = *argvCallback; + pPayload = gPayloadBuffer; + + while(*argcCallback > 0) + { + elementType = setElementType(1, requestIdx, CONTENT_LEN_TYPE); + /* content length is irrelevant for GET */ + if(*((uint16_t *)argvArray) != elementType) + { + switch(*(argvArray + ARGV_VALUE_OFFSET)) + { + case OtaIdx_Version: + + // Status = OtaArchive_GetCurrentVersion(gOtaVersion); + // if(Status < 0) + // { + // //UART_PRINT( + // // "[Link local task] ota bundle version file does " + // // "not exist\r\n"); + // strcpy((char *)gMetadataBuffer, "no version file exists"); + // Status = 0; + // } + // else + // { + // //sl_Memcpy(gMetadataBuffer, gOtaVersion, VERSION_STR_SIZE); + // gMetadataBuffer[VERSION_STR_SIZE] = '\0'; + // } + + break; + } + + sl_Memcpy ( + pPayload, + httpRequest[requestIdx].charValues[*(argvArray + + ARGV_VALUE_OFFSET)]. + characteristic, + strlen((const char *)httpRequest[requestIdx]. + charValues[*(argvArray+ARGV_VALUE_OFFSET)] + .characteristic)); + pPayload += strlen( + (const char *)httpRequest[requestIdx]. + charValues[*(argvArray +ARGV_VALUE_OFFSET)]. + characteristic); + *pPayload++ = '='; + sl_Memcpy (pPayload, gMetadataBuffer, + strlen((const char *)gMetadataBuffer)); + pPayload += strlen((const char *)gMetadataBuffer); + *pPayload++ = '&'; + } + + (*argcCallback)--; + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + } + + /* NULL terminate the payload */ + *(pPayload - 1) = '\0'; + + metadataLen = + prepareGetMetadata(Status, strlen( + (const char *)gPayloadBuffer), + HttpContentTypeList_UrlEncoded); + + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + (SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION | + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA)); + INFO_PRINT("[Link local task] Metadata Sent, len = %d \n\r", metadataLen); + /* mark as last segment */ + sl_NetAppSend(netAppRequest->Handle, + strlen ((const char *)gPayloadBuffer), + gPayloadBuffer, + 0); + INFO_PRINT("[Link local task] Data Sent, len = %d\n\r", + strlen ((const char *)gPayloadBuffer)); + + return(Status); +} + +//***************************************************************************** +// +//! \brief This is a light service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t lightGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest) +{ + uint8_t *argvArray, *pPayload; + //uint8_t ledIdx = Board_GPIO_LED0; + uint16_t ledState, metadataLen, elementType; + + argvArray = *argvCallback; + pPayload = gPayloadBuffer; + + while(*argcCallback > 0) + { + elementType = setElementType(1, requestIdx, CONTENT_LEN_TYPE); + // /* content length is irrelevant for GET */ + // if(*((uint16_t *)argvArray) != elementType) + // { + // switch(*(argvArray + ARGV_VALUE_OFFSET)) + // { + // case LedIdx_RedLed: + // ledIdx = Board_GPIO_LED0; + // break; + // case LedIdx_OrangeLed: + // ledIdx = Board_GPIO_LED0; + // break; + // case LedIdx_GreenLed: + // ledIdx = Board_GPIO_LED0; + // break; + // } + + // ledState = GPIO_read(ledIdx); + // sl_Memcpy ( + // pPayload, + // httpRequest[requestIdx].charValues[*(argvArray + + // ARGV_VALUE_OFFSET)]. + // characteristic, + // strlen((const char *)httpRequest[requestIdx]. + // charValues[*(argvArray+ARGV_VALUE_OFFSET)] + // .characteristic)); + // pPayload += strlen( + // (const char *)httpRequest[requestIdx]. + // charValues[*(argvArray + ARGV_VALUE_OFFSET)] + // .characteristic); + // *pPayload++ = '='; + // sl_Memcpy ( + // pPayload, + // httpRequest[requestIdx]. + // charValues[*(argvArray +ARGV_VALUE_OFFSET)]. + // value[ledState],strlen((const char *)httpRequest[requestIdx]. + // charValues[*(argvArray + + // ARGV_VALUE_OFFSET)]. + // value[ledState])); + + // pPayload += strlen( + // (const char *)httpRequest[requestIdx]. + // charValues[*(argvArray +ARGV_VALUE_OFFSET)]. + // value[ledState]); + // *pPayload++ = '&'; + // } + + (*argcCallback)--; + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + } + + /* NULL terminate the payload */ + *(pPayload - 1) = '\0'; + + metadataLen = prepareGetMetadata(0, + strlen((const char *)gPayloadBuffer), + HttpContentTypeList_UrlEncoded); + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + (SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION | + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA)); + INFO_PRINT("[Link local task] Metadata Sent, len = %d \n\r", metadataLen); + /* mark as last segment */ + sl_NetAppSend ( netAppRequest->Handle, + strlen ((const char *)gPayloadBuffer), + gPayloadBuffer, 0); + INFO_PRINT("[Link local task] Data Sent, len = %d\n\r", + strlen ((const char *)gPayloadBuffer)); + + return(0); +} + +//***************************************************************************** +// +//! \brief This is a light service callback function for HTTP POST +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t lightPostCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest) +{ + uint8_t *argvArray; + uint16_t metadataLen, elementType; + uint16_t ledState = 0xFF; + //uint16_t ledIdx = Board_GPIO_LED0; + argvArray = *argvCallback; + + while(*argcCallback > 0) + { + elementType = setElementType(1, requestIdx, CONTENT_LEN_TYPE); + // /* content length is irrelevant for POST */ + // if(*((uint16_t *)argvArray) != elementType) + // { + // /* means it is the value, not the parameter */ + // if(*(argvArray + 1) & 0x80) + // { + // /* get the light operation */ + // switch(*(argvArray + ARGV_VALUE_OFFSET)) + // { + // case LedValues_Off: + // ledState = Board_GPIO_LED_OFF; + // break; + // case LedValues_On: + // ledState = Board_GPIO_LED_ON; + // break; + // case LedValues_Toggle: + // ledState = 0xFF; + // break; + // } + + // if(ledState == 0xFF) + // { + // GPIO_toggle(ledIdx); + // } + // else + // { + // GPIO_write(ledIdx, ledState); + // } + // } + // else /* means it is the parameter, not the value */ + // { + // /* apply to the right light */ + // switch(*(argvArray + ARGV_VALUE_OFFSET)) + // { + // case LedIdx_RedLed: + // ledIdx = Board_GPIO_LED0; + // break; + // } + // } + // } + + (*argcCallback)--; + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + } + + metadataLen = preparePostMetadata(0); + + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA); + + return(0); +} + +//***************************************************************************** +// +//! \brief This is a sensors service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t sensorGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest) +{ + uint8_t *argvArray, *pPayload; + uint16_t metadataLen, elementType; + int16_t value = 0; + int32_t Status; + + argvArray = *argvCallback; + pPayload = gPayloadBuffer; + + /* Read accelerometer axis values */ + Status = accelarometerReading(); + if(Status != 0) + { + UART_PRINT( + "[Link local task] Failed to read data from accelerometer\n\r"); + } + + /* Read temperature sensor values */ + Status = temperatureReading(); + if(Status != 0) + { + UART_PRINT( + "[Link local task] Failed to" + " read data from temperature sensor\n\r"); + } + + while(*argcCallback > 0) + { + elementType = setElementType(1, requestIdx, CONTENT_LEN_TYPE); + /* content length is irrelevant for GET */ + if(*((uint16_t *)argvArray) != elementType) + { + switch(*(argvArray + ARGV_VALUE_OFFSET)) + { + case SensorIdx_XAxis: + value = xVal; + break; + case SensorIdx_YAxis: + value = yVal; + break; + case SensorIdx_ZAxis: + value = zVal; + break; + case SensorIdx_FarnTemp: + value = (int16_t)temperatureVal; + break; + } + + sl_Memcpy ( + pPayload, + httpRequest[requestIdx].charValues[*(argvArray + + ARGV_VALUE_OFFSET)]. + characteristic, + strlen((const char *)httpRequest[requestIdx]. + charValues[*(argvArray+ARGV_VALUE_OFFSET)]. + characteristic)); + pPayload += strlen( + (const char *)httpRequest[requestIdx]. + charValues[*(argvArray +ARGV_VALUE_OFFSET)]. + characteristic); + *pPayload++ = '='; + + snprintf((char *)pPayload, SENSOR_VALUE_STR_LEN, "%d", value); + /* add the value length */ + pPayload += strlen((const char *)pPayload); + *pPayload++ = '&'; + } + + (*argcCallback)--; + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + } + + /* NULL terminate the payload */ + *(pPayload - 1) = '\0'; + + metadataLen = prepareGetMetadata(0, + strlen((const char *)gPayloadBuffer), + HttpContentTypeList_UrlEncoded); + + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + (SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION | + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA)); + INFO_PRINT("[Link local task] Metadata Sent, len = %d \n\r", metadataLen); + /* mark as last segment */ + sl_NetAppSend (netAppRequest->Handle, strlen ( + (const char *)gPayloadBuffer), gPayloadBuffer, 0); + INFO_PRINT("[Link local task] Data Sent, len = %d\n\r", + strlen ((const char *)gPayloadBuffer)); + + return(0); +} + +//***************************************************************************** +// +//! \brief This is a generic device service callback function for HTTP GET +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] argcCallback count of input params to the service callback +//! +//! \param[in] argvCallback set of input params to the service callback +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t deviceGetCallback(uint8_t requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback, + SlNetAppRequest_t *netAppRequest) +{ + uint8_t *argvArray, *pPayload; + uint16_t metadataLen, elementType; + int32_t Status; + uint32_t deviceType; + + argvArray = *argvCallback; + pPayload = gPayloadBuffer; + deviceType = getDeviceType(); + + while(*argcCallback > 0) + { + elementType = setElementType(1, requestIdx, CONTENT_LEN_TYPE); + /* content length is irrelevant for GET */ + if(*((uint16_t *)argvArray) != elementType) + { + switch(*(argvArray + ARGV_VALUE_OFFSET)) + { + case DeviceIdx_Ssid: + Status = getDeviceSSID(); + if(Status != 0) + { + // UART_PRINT( + // "[Link local task] failed to get SSID. IP_ACQ=%d, " + // "IP_LEASED=%d\n\r", + // GET_STATUS_BIT(OutOfBox_ControlBlock.Status, + // AppStatusBits_IpAcquired), + // GET_STATUS_BIT(OutOfBox_ControlBlock.Status, + // AppStatusBits_IpLeased)); + goto exit_device_get; + } + break; + case DeviceIdx_IpAddress: + Status = getDeviceIpAddress(); + if(Status != 0) + { + goto exit_device_get; + } + break; + case DeviceIdx_MacAddress: + Status = getDeviceMacAddress(gMetadataBuffer); + if(Status != 0) + { + goto exit_device_get; + } + break; + case DeviceIdx_AppID: + /* 3235 applies for both CC3230 and CC3235 */ + if(deviceType == DEV_TYPE_CC323XFS) + { + strcpy((char *)gMetadataBuffer, "out_of_box_3235_fs"); + } + else if(deviceType == DEV_TYPE_CC323XRS) + { + strcpy((char *)gMetadataBuffer, "out_of_box_3235_rs"); + } + else if(deviceType == DEV_TYPE_CC323XR) + { + strcpy((char *)gMetadataBuffer, "out_of_box_3235_r"); + } + else if(deviceType == DEV_TYPE_CC3220FS) + { + strcpy((char *)gMetadataBuffer, "out_of_box_fs"); + } + else if(deviceType == DEV_TYPE_CC3220RS) + { + strcpy((char *)gMetadataBuffer, "out_of_box_rs"); + } + else if(deviceType == DEV_TYPE_CC3220R) + { + strcpy((char *)gMetadataBuffer, "out_of_box_r"); + } + else + { + UART_PRINT( + "[Link local task] device type %d is not supported\n\r", + deviceType); + Status = -1; + + goto exit_device_get; + } + + Status = 0; + + break; + } + + sl_Memcpy ( + pPayload, + httpRequest[requestIdx].charValues[*(argvArray + + ARGV_VALUE_OFFSET)]. + characteristic, + strlen((const char *)httpRequest[requestIdx]. + charValues[*(argvArray+ARGV_VALUE_OFFSET)]. + characteristic)); + pPayload += strlen( + (const char *)httpRequest[requestIdx]. + charValues[*(argvArray +ARGV_VALUE_OFFSET)]. + characteristic); + *pPayload++ = '='; + sl_Memcpy (pPayload, gMetadataBuffer, + strlen((const char *)gMetadataBuffer)); + pPayload += strlen((const char *)gMetadataBuffer); + *pPayload++ = '&'; + } + + (*argcCallback)--; + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + } + + /* NULL terminate the payload */ + *(pPayload - 1) = '\0'; + + Status = 0; + +exit_device_get: + if(Status != 0) + { + strcpy((char *)gPayloadBuffer, (const char *)pageNotFound); + } + + metadataLen = + prepareGetMetadata(Status, + strlen((const char *)gPayloadBuffer), + HttpContentTypeList_UrlEncoded); + + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + (SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION | + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA)); + INFO_PRINT("[Link local task] Metadata Sent, len = %d \n\r", metadataLen); + /* mark as last segment */ + sl_NetAppSend (netAppRequest->Handle, strlen ( + (const char *)gPayloadBuffer), gPayloadBuffer, 0); + INFO_PRINT("[Link local task] Data Sent, len = %d\n\r", + strlen ((const char *)gPayloadBuffer)); + + return(Status); +} + +//***************************************************************************** +// Local Functions +//***************************************************************************** + +//***************************************************************************** +// +//! \brief This function prepare error netapp response in case memory could +//! not be allocated +//! +//! \param[in] pNetAppResponse netapp response structure +//! +//! \return none +//! +//**************************************************************************** +void NetAppRequestErrorResponse(SlNetAppResponse_t *pNetAppResponse) +{ + UART_PRINT( + "[Link local task] could not allocate memory for netapp request\n\r"); + + /* Prepare error response */ + pNetAppResponse->Status = SL_NETAPP_RESPONSE_NONE; + pNetAppResponse->ResponseData.pMetadata = NULL; + pNetAppResponse->ResponseData.MetadataLen = 0; + pNetAppResponse->ResponseData.pPayload = NULL; + pNetAppResponse->ResponseData.PayloadLen = 0; + pNetAppResponse->ResponseData.Flags = 0; +} + +//***************************************************************************** +// +//! \brief This function fetches the device MAC address +//! +//! \param[out] buffer to occupy the MAC address in string format +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t getDeviceMacAddress(uint8_t *macAddress) +{ + uint8_t macAddressVal[6]; + uint16_t macAddressLen; + int32_t Status; + + macAddress[0] = '\0'; + + /* Get the device's MAC address */ + macAddressLen = 6; + Status = + sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET,NULL,&macAddressLen, + (uint8_t *)macAddressVal); + if(Status < 0) + { + return(Status); + } + + snprintf((char *)macAddress, MAC_ADDR_STR_LEN, + "%02x:%02x:%02x:%02x:%02x:%02x", + macAddressVal[0], + macAddressVal[1], + macAddressVal[2], + macAddressVal[3], + macAddressVal[4], + macAddressVal[5]); + + return(0); +} + +//***************************************************************************** +// +//! Function to read accelarometer +//! +//! \param none +//! +//! \return SUCCESS or FAILURE +//! +//***************************************************************************** +uint8_t accelarometerReading(void) +{ + int8_t xValRead, yValRead, zValRead; + int32_t Status; + + if(sensorLockObj != NULL) + { + pthread_mutex_lock(sensorLockObj); + } + + /* Read accelarometer axis values */ + Status = BMA2xxReadNew(i2cHandle, &xValRead, &yValRead, &zValRead); + if(Status != 0) + { + /* try to read again */ + Status = BMA2xxReadNew(i2cHandle, &xValRead, &yValRead, &zValRead); + if(Status != 0) /* leave previous values */ + { + UART_PRINT( + "[Link local task] Failed to read data from accelarometer\n\r"); + } + } + + if(Status == 0) + { + xVal = xValRead; + yVal = yValRead; + zVal = zValRead; + } + + if(sensorLockObj != NULL) + { + pthread_mutex_unlock(sensorLockObj); + } + + return(Status); +} + +//***************************************************************************** +// +//! Function to read temperature +//! +//! \param none +//! +//! \return SUCCESS or FAILURE +//! +//***************************************************************************** +uint8_t temperatureReading(void) +{ + int32_t Status; + float fTempRead; + + /* Read temperature axis values */ + Status = TMP006DrvGetTemp(i2cHandle, &fTempRead); + if(Status != 0) + { + /* try to read again */ + Status = TMP006DrvGetTemp(i2cHandle, &fTempRead); + if(Status != 0) /* leave previous values */ + { + UART_PRINT( + "[Link local task] Failed to read data from" + " temperature sensor\n\r"); + } + } + + if(Status == 0) + { + fTempRead = (fTempRead > 100) ? 100 : fTempRead; + temperatureVal = fTempRead; + } + + return(Status); +} + +//***************************************************************************** +// +//! \brief this function composes an element type from metadata/payload +//! (TLV structure) +//! +//! \param[in] isAnswer states whether this is a value or a parameter +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] elementVal value of element +//! +//! \return element type +//! +//**************************************************************************** +uint16_t setElementType(uint8_t isValue, + uint8_t requestIdx, + uint8_t elementVal) +{ + uint16_t elementType; + + elementType = elementVal; + elementType |= (((isValue << 7) | (requestIdx & 0x7F)) << 8); + + return(elementType); +} + +//***************************************************************************** +// +//! \brief This function prepares metadata for HTTP GET requests +//! +//! \param[in] parsingStatus validity of HTTP GET request +//! +//! \param[in] contentLen content length in respond to +//! HTTP GET request +//! +//! \return metadataLen +//! +//**************************************************************************** +uint16_t prepareGetMetadata(int32_t parsingStatus, + uint32_t contentLen, + HttpContentTypeList contentTypeId) +{ + char *contentType; + uint8_t *pMetadata; + uint16_t metadataLen; + + contentType = g_ContentTypes[contentTypeId].contentTypeText; + + pMetadata = gMetadataBuffer; + + /* http Status */ + *pMetadata = (uint8_t) SL_NETAPP_REQUEST_METADATA_TYPE_STATUS; + pMetadata++; + *(uint16_t *)pMetadata = (uint16_t) 2; + pMetadata += 2; + + if(parsingStatus < 0) + { + *(uint16_t *)pMetadata = + (uint16_t) SL_NETAPP_HTTP_RESPONSE_404_NOT_FOUND; + } + else + { + *(uint16_t *)pMetadata = (uint16_t) SL_NETAPP_HTTP_RESPONSE_200_OK; + } + + pMetadata += 2; + + /* Content type */ + *pMetadata = (uint8_t) SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_TYPE; + pMetadata++; + (*(uint16_t *)pMetadata) = (uint16_t) strlen ((const char *)contentType); + pMetadata += 2; + sl_Memcpy (pMetadata, contentType, strlen((const char *)contentType)); + pMetadata += strlen((const char *)contentType); + + /* Content len */ + *pMetadata = SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_LEN; + pMetadata++; + *(uint16_t *)pMetadata = (uint16_t) 4; + pMetadata += 2; + *(uint32_t *)pMetadata = (uint32_t) contentLen; + + metadataLen = 5 + 7 + strlen ((const char *)contentType) + 3; + + return(metadataLen); +} + +//***************************************************************************** +// +//! \brief This function prepares metadata for HTTP POST/PUT requests +//! +//! \param[in] parsingStatus validity of HTTP POST/PUT request +//! +//! \return metadataLen +//! +//**************************************************************************** +uint16_t preparePostMetadata(int32_t parsingStatus) +{ + uint8_t *pMetadata; + uint16_t metadataLen; + + pMetadata = gMetadataBuffer; + + /* http Status */ + *pMetadata = (uint8_t) SL_NETAPP_REQUEST_METADATA_TYPE_STATUS; + pMetadata++; + *(uint16_t *)pMetadata = (uint16_t) 2; + pMetadata += 2; + + if(parsingStatus < 0) + { + *(uint16_t *)pMetadata = + (uint16_t) SL_NETAPP_HTTP_RESPONSE_404_NOT_FOUND; + } + else + {/* no need for content so browser stays on the same page */ + *(uint16_t *)pMetadata = + (uint16_t) SL_NETAPP_HTTP_RESPONSE_204_OK_NO_CONTENT; + } + + pMetadata += 2; + + metadataLen = 5; + + return(metadataLen); +} + +//***************************************************************************** +// +//! \brief This function fetches the device IP address +//! +//! \param[in] none +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t getDeviceIpAddress(void) +{ + uint16_t ConfigOpt; + uint16_t ipLen; + SlNetCfgIpV4Args_t ipV4 = {0}; + int32_t Status; + + gMetadataBuffer[0] = '\0'; + + /* Get the device's IP address */ + ipLen = sizeof(SlNetCfgIpV4Args_t); + ConfigOpt = 0; + Status = + sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE,&ConfigOpt,&ipLen, + (uint8_t *)&ipV4); + if(Status < 0) + { + return(Status); + } + + snprintf((char *)gMetadataBuffer, IP_ADDR_STR_LEN, "%d.%d.%d.%d", + (int)SL_IPV4_BYTE(ipV4.Ip,3), + (int)SL_IPV4_BYTE(ipV4.Ip,2), + (int)SL_IPV4_BYTE(ipV4.Ip,1), + (int)SL_IPV4_BYTE(ipV4.Ip,0)); + + return(0); +} + +//***************************************************************************** +// +//! \brief This function fetches the SSID the device is connected to +//! +//! \param[in] none +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t getDeviceSSID(void) +{ + uint16_t len = 32; + uint16_t config_opt = SL_WLAN_AP_OPT_SSID; + /* simplelink as station connected to AP */ + if(GET_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_IpAcquired) && + GET_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_Connection)) + { + // sl_Memcpy ((uint8_t *)gMetadataBuffer, + // (const uint8_t *)nF_ControlBlock.connectionSSID, + // nF_ControlBlock.ssidLen); + // gMetadataBuffer[nF_ControlBlock.ssidLen] = '\0'; + } + /* simplelink as AP with connected client */ + else if(GET_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_IpAcquired) && + GET_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_IpLeased)) + { + // sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, + // (uint8_t *)nF_ControlBlock.connectionSSID); + // nF_ControlBlock.ssidLen = len - 1; + // sl_Memcpy ((uint8_t *)gMetadataBuffer, + // (const uint8_t *)nF_ControlBlock.connectionSSID, + // nF_ControlBlock.ssidLen); + // gMetadataBuffer[nF_ControlBlock.ssidLen] = '\0'; + } + else + { + return(-1); + } + + return(0); +} + +//***************************************************************************** +// +//! \brief This function flushes the netapp data from the client +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \param[in] flags netapp flags for more data +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t otaFlushNetappReq(SlNetAppRequest_t *netAppRequest, + uint32_t *flags) +{ + int32_t Status; + int32_t chunkLen; + + Status = 0; + + while((*flags & SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION) == + SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION) + { + chunkLen = NETAPP_MAX_RX_FRAGMENT_LEN; + Status = + sl_NetAppRecv(netAppRequest->Handle, (uint16_t *)&chunkLen, + gPayloadBuffer, + (_u32 *)flags); + INFO_PRINT("[Link local task] flushing NetApp packet, len=%d \n\r", + chunkLen); + if(Status < 0) + { + return(Status); + } + + if(*flags == 0) + { + break; + } + } + + return(Status); +} + +//***************************************************************************** +// +//! \brief This function create mailbox message queue between linkLocal task +//! and driver task +//! +//! \param[in] None +//! +//! \return 0 on success or -ve on error +//! +//**************************************************************************** +void initLinkLocalDB(void) +{ + httpRequest[0].charValues[0].characteristic = "version"; + httpRequest[0].serviceCallback = otaGetCallback; + + httpRequest[1].charValues[0].characteristic = "filename"; + httpRequest[1].serviceCallback = otaPutCallback; + + httpRequest[2].charValues[0].characteristic = "redled"; + httpRequest[2].charValues[0].value[0] = "off"; + httpRequest[2].charValues[0].value[1] = "on"; + httpRequest[2].charValues[0].value[2] = "toggle"; + httpRequest[2].charValues[1].characteristic = "orangeled"; + httpRequest[2].charValues[1].value[0] = "off"; + httpRequest[2].charValues[1].value[1] = "on"; + httpRequest[2].charValues[1].value[2] = "toggle"; + httpRequest[2].charValues[2].characteristic = "greenled"; + httpRequest[2].charValues[2].value[0] = "off"; + httpRequest[2].charValues[2].value[1] = "on"; + httpRequest[2].charValues[2].value[2] = "toggle"; + httpRequest[2].serviceCallback = lightGetCallback; + + httpRequest[3].charValues[0].characteristic = "redled"; + httpRequest[3].charValues[0].value[0] = "off"; + httpRequest[3].charValues[0].value[1] = "on"; + httpRequest[3].charValues[0].value[2] = "toggle"; + httpRequest[3].serviceCallback = lightPostCallback; + + httpRequest[4].charValues[0].characteristic = "axisx"; + httpRequest[4].charValues[1].characteristic = "axisy"; + httpRequest[4].charValues[2].characteristic = "axisz"; + httpRequest[4].charValues[3].characteristic = "temp"; + httpRequest[4].serviceCallback = sensorGetCallback; + + httpRequest[5].charValues[0].characteristic = "ssid"; + httpRequest[5].charValues[1].characteristic = "ipaddress"; + httpRequest[5].charValues[2].characteristic = "macaddress"; + httpRequest[5].charValues[3].characteristic = "appname"; + httpRequest[5].serviceCallback = deviceGetCallback; +} + +//***************************************************************************** +// +//! \brief This function scan netapp request and parse the payload +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] pPhrase pointer to HTTP metadata payload +//! +//! \param[in] payloadLen HTTP metadata or payload length +//! +//! \param[out] argcCallback count of input params to the service callback +//! +//! \param[out] argvCallback set of input params to the service callback +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t parseUrlEncoded(uint8_t requestIdx, + uint8_t * pPhrase, + uint16_t phraseLen, + uint8_t *argcCallback, + uint8_t **argvCallback) +{ + uint8_t *token; + uint8_t characteristic, value, isValueExpected, loopIdx; + int32_t Status = -1; + uint8_t *argvArray; + uint8_t remainingLen, actualLen; + uint16_t elementType; + + argvArray = *argvCallback; + /* it means parameters already exist - fast forward to the end of argv */ + if(*argcCallback > 0) + { + loopIdx = *argcCallback; + while(loopIdx > 0) + { + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + + loopIdx--; + } + } + + /* check if values are expected per characteristic */ + /* it is a 2 steps procedure: */ + /* 1) check that '=' sign exists */ + /* 2) check that the value is not NULL */ + /* if not, return */ + isValueExpected = 0; + token = (uint8_t *)strchr((char *)pPhrase, '='); + if(token != NULL) + { /* it means no value supplied */ + if((*(token + 1) == '&') || (*(token + 1) == '\0')) + { + return(-1); + } + else + { + isValueExpected = 1; + } + } + + /* Parse payload list */ + token = (uint8_t *)strtok((char *)pPhrase, "=&"); + + if(NULL == token) /* it means there is no url encoded data */ + { + return(0); + } + + while(token && ((pPhrase + phraseLen) > token)) + { + Status = -1; + characteristic = 0; + + /* run over all possible characteristics, if exist */ + while(httpRequest[requestIdx].charValues[characteristic].characteristic + != NULL) + { + if(!strncmp((const char *)token, + (const char *)httpRequest[requestIdx].charValues[ + characteristic]. + characteristic, + strlen((const char *)httpRequest[requestIdx].charValues + [ + characteristic].characteristic))) + { + Status = 0; + + /* found a characteristic. save its index number */ + (*argcCallback)++; + elementType = setElementType(0, requestIdx, characteristic); + sl_Memcpy ((uint8_t*)argvArray, (uint8_t*)&elementType, + ARGV_LEN_OFFSET); + argvArray += ARGV_LEN_OFFSET; + *argvArray++ = 1; /* length field */ + *argvArray++ = characteristic; + /* remaining length is for cases where the last value is of + string type */ + remainingLen =(uint8_t) + (phraseLen -(uint8_t)(token -pPhrase) - + strlen((const char *)token) - 1); + + UART_PRINT ( + "[Link local task] characteristic is: %s\n\r", + (int8_t *)httpRequest[requestIdx]. + charValues[characteristic]. + characteristic); + break; + } + else + { + characteristic++; + } + } + /* it means the characteristics is not valid/known */ + if(-1 == Status) + { + return(Status); + } + + token = (uint8_t *)strtok(NULL, "=&"); + + if(isValueExpected) + { + Status = -1; + value = 0; + + if(token != NULL) + { + /* it means any value is OK */ + if(NULL == + httpRequest[requestIdx]. + charValues[characteristic].value[value]) + { + Status = 0; + + /* found a string value. copy its content */ + (*argcCallback)++; + elementType = setElementType(1, requestIdx, value); + sl_Memcpy ((uint8_t*)argvArray, (uint8_t*)&elementType, + ARGV_LEN_OFFSET); + argvArray += ARGV_LEN_OFFSET; + if(strlen((const char *)token) > remainingLen) + { + actualLen = remainingLen; + } + else + { + actualLen = strlen((const char *)token); + } + + *argvArray++ = (actualLen + 1); + sl_Memcpy(argvArray, token, actualLen); + argvArray += actualLen; + *argvArray++ = '\0'; + + UART_PRINT ("[Link local task] value is: %s\n\r", + (int8_t *)(argvArray - actualLen - 1)); + } + else + { + /* run over all possible values, if exist */ + while(httpRequest[requestIdx].charValues[characteristic]. + value[value] != NULL) + { + if(!strncmp((const char *)token, + (const char *)httpRequest[requestIdx]. + charValues[ + characteristic].value[value], + strlen((const char *)httpRequest[requestIdx + ].charValues[ + characteristic].value[value]))) + { + Status = 0; + + /* found a value. save its index number */ + (*argcCallback)++; + elementType = setElementType(1, requestIdx, value); + sl_Memcpy ((uint8_t*)argvArray, + (uint8_t*)&elementType, + ARGV_LEN_OFFSET); + argvArray += ARGV_LEN_OFFSET; + *argvArray++ = 1; /* length field */ + *argvArray++ = value; + + UART_PRINT ( + "[Link local task] value is: %s\n\r", + (int8_t *)httpRequest[requestIdx]. + charValues[ + characteristic].value[value]); + + break; + } + else + { + value++; + } + } + /* it means the value is not valid/known */ + if(-1 == Status) + { + return(Status); + } + } + } + token = (uint8_t *)strtok(NULL, (const char *)"=&"); + } + } + + return(Status); +} + +//***************************************************************************** +// +//! \brief This function maps header type to its string value +//! +//! \param[in] httpHeaderType http header type +//! +//! \param[out] httpHeaderText http header text +//! +//! \return none +//! +//**************************************************************************** +void convertHeaderType2Text(uint8_t httpHeaderType, + uint8_t **httpHeaderText) +{ + int i; + *httpHeaderText = NULL; + + for(i = 0; i < sizeof (g_HeaderFields) / sizeof(http_headerFieldType_t); + i++) + { + if(g_HeaderFields[i].headerType == httpHeaderType) + { + *httpHeaderText = (uint8_t *)(g_HeaderFields[i].headerText); + break; + } + } +} + +//***************************************************************************** +// +//! \brief This function scan netapp request and parse the metadata +//! +//! \param[in] requestType HTTP method (GET, POST, PUT or DEL) +//! +//! \param[in] pMetadata pointer to HTTP metadata +//! +//! \param[in] metadataLen HTTP metadata length +//! +//! \param[out] requestIdx request index to indicate the message +//! +//! \param[out] argcCallback count of input params to +//! the service callback +//! +//! \param[out] argvCallback set of input params to the service callback +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t parseHttpRequestMetadata(uint8_t requestType, + uint8_t * pMetadata, + uint16_t metadataLen, + uint8_t *requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback) +{ + uint8_t *pTlv; + uint8_t *pEnd; + + int32_t Status = -1; + uint8_t loopIdx; + uint8_t type; + uint16_t len; + uint32_t value; + uint8_t *typeText; + uint8_t nullTerminator; + uint8_t *argvArray; + uint16_t elementType; + + argvArray = *argvCallback; + + *requestIdx = 0xFF; + pTlv = pMetadata; + pEnd = pMetadata + metadataLen; + + if(metadataLen < 3) + { + UART_PRINT("[Link local task] Metadata parsing error\n\r"); + + return(-1); + } + + INFO_PRINT ("[Link local task] Metadata:\n\r"); + + while(pTlv < pEnd) + { + type = *pTlv; + pTlv++; + len = *(uint16_t *)pTlv; + pTlv += 2; + + convertHeaderType2Text(type, &typeText); + + if(typeText != NULL) + { + INFO_PRINT ("[Link local task] %s ", typeText); + } + + switch(type) + { + case SL_NETAPP_REQUEST_METADATA_TYPE_STATUS: + /* there are browsers that seem to send many 0 type for no reason */ + /* in this case, do not print anything */ + break; + + case SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_LEN: + /* it means there is a content length and URI is OK. Add it to the argv */ + if(0 == Status) + { + /* it means parameters already exist from query type */ + if(*argcCallback > 0) + { + loopIdx = *argcCallback; + while(loopIdx > 0) + { + argvArray += ARGV_LEN_OFFSET; /* skip the type */ + argvArray += *argvArray; /* add the length */ + argvArray++; /* skip the length */ + + loopIdx--; + } + } + + (*argcCallback)++; + /* add content type */ + elementType = setElementType(1, *requestIdx, CONTENT_LEN_TYPE); + sl_Memcpy ((uint8_t*)argvArray, (uint8_t*)&elementType, + ARGV_LEN_OFFSET); + argvArray += ARGV_LEN_OFFSET; + *argvArray++ = len; /* add content length */ + sl_Memcpy ((uint8_t*)argvArray, pTlv, len); + sl_Memcpy ((uint8_t*)&value, pTlv, len); + + INFO_PRINT ("%d\n\r", (uint32_t)value); + } + + break; + + case SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_REQUEST_URI: + /* this is the 1st stop in every http method. + zero out the character counter argument */ + *argcCallback = 0; + + for(loopIdx = 0; loopIdx < NUMBER_OF_URI_SERVICES; loopIdx++) + { + if((strncmp((const char *)pTlv, + (const char *)httpRequest[loopIdx].service, + strlen((const char *)httpRequest[loopIdx].service))) + == 0) + { + if(requestType == httpRequest[loopIdx].httpMethod) + { + Status = 0; + *requestIdx = httpRequest[loopIdx].requestIdx; + INFO_PRINT ("%s\n\r", httpRequest[loopIdx].service); + + break; + } + } + } + + if(Status != 0) + { + INFO_PRINT ("unknown service\n\r"); + } + + break; + + case SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_QUERY_STRING: + if(0 == Status) + { + Status = parseUrlEncoded(*requestIdx, pTlv, len, argcCallback, + argvCallback); + + if(Status != 0) + { + INFO_PRINT ( + "query string in metadata section is not" + " valid/known\n\r"); + } + } + + break; + + default: + nullTerminator = *(pTlv + len); + *(pTlv + len) = '\0'; + INFO_PRINT("%s\n\r", pTlv); + *(pTlv + len) = nullTerminator; + + break; + } + pTlv += len; + } + + return(Status); +} + +//***************************************************************************** +// +//! \brief This function scan netapp request and parse the payload +//! +//! \param[in] requestIdx request index to indicate the message +//! +//! \param[in] pPayload pointer to HTTP payload +//! +//! \param[in] payloadLen HTTP payload length +//! +//! \param[out] argcCallback count of input params to the +//! service callback +//! +//! \param[out] argvCallback set of input params to the service callback +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t parseHttpRequestPayload(uint8_t requestIdx, + uint8_t * pPayload, + uint16_t payloadLen, + uint8_t *argcCallback, + uint8_t **argvCallback) +{ + int32_t Status = -1; + + Status = parseUrlEncoded(requestIdx, pPayload, payloadLen, argcCallback, + argvCallback); + + if(Status != 0) + { + UART_PRINT ( + "[Link local task] query string in payload section is " + "not valid/known\n\r"); + } + + return(Status); +} + +//***************************************************************************** +// +//! \brief This function checks that the content requested via HTTP +//! message exists +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \param[out] requestIdx request index to indicate the message +//! +//! \param[out] argcCallback count of input params to the service +//! callback +//! +//! \param[out] argvCallback set of input params to the service +//! callback +//! +//! +//! \return 0 on success else negative +//! +//**************************************************************************** +int32_t httpCheckContentInDB(SlNetAppRequest_t *netAppRequest, + uint8_t *requestIdx, + uint8_t *argcCallback, + uint8_t **argvCallback) +{ + int32_t Status = -1; + + if(netAppRequest->AppId != SL_NETAPP_HTTP_SERVER_ID) + { + return(Status); + } + + Status = + parseHttpRequestMetadata(netAppRequest->Type, + netAppRequest->requestData.pMetadata, + netAppRequest->requestData.MetadataLen, + requestIdx, argcCallback, + argvCallback); + + /* PUT does not contain parseable data - only POST does */ + if((0 == Status) && (netAppRequest->requestData.PayloadLen != 0) && + (netAppRequest->Type != SL_NETAPP_REQUEST_HTTP_PUT)) + { + Status = + parseHttpRequestPayload(*requestIdx, + netAppRequest->requestData.pPayload, + netAppRequest->requestData.PayloadLen, + argcCallback, + argvCallback); + } + + return(Status); +} + +//***************************************************************************** +// +//! \brief This function parse and execute HTTP GET requests +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return None +//! +//**************************************************************************** +void httpGetHandler(SlNetAppRequest_t *netAppRequest) +{ + uint16_t metadataLen; + int32_t Status; + uint8_t requestIdx; + + uint8_t argcCallback; + uint8_t *argvArray; + uint8_t **argvCallback = &argvArray; + + argvArray = gHttpGetBuffer; + + Status = httpCheckContentInDB(netAppRequest, &requestIdx, &argcCallback, + argvCallback); + + if(Status < 0) + { + metadataLen = + prepareGetMetadata(Status, strlen ( + (const char *)pageNotFound), + HttpContentTypeList_TextHtml); + + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + (SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION | + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA)); + INFO_PRINT("[Link local task] Metadata Sent, len = %d \n\r", + metadataLen); +/* mark as last segment */ + sl_NetAppSend (netAppRequest->Handle, + strlen ((const char *)pageNotFound), + (uint8_t *)pageNotFound,0); + + INFO_PRINT("[Link local task] Data Sent, len = %d\n\r", + strlen ((const char *)pageNotFound)); + } + else + { + httpRequest[requestIdx].serviceCallback(requestIdx, &argcCallback, + argvCallback, + netAppRequest); + } +} + +//***************************************************************************** +// +//! \brief This function parse and execute HTTP POST/PUT requests +//! +//! \param[in] netAppRequest netapp request structure +//! +//! \return None +//! +//**************************************************************************** +void httpPostHandler(SlNetAppRequest_t *netAppRequest) +{ + uint16_t metadataLen; + int32_t Status; + uint8_t requestIdx; + + uint8_t argcCallback; + uint8_t *argvArray; + uint8_t **argvCallback = &argvArray; + + argvArray = gHttpPostBuffer; + + Status = httpCheckContentInDB(netAppRequest,&requestIdx,&argcCallback, + argvCallback); + + if(Status < 0) + { + metadataLen = preparePostMetadata(Status); + + sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, + SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA); + } + else + { + httpRequest[requestIdx].serviceCallback(requestIdx, &argcCallback, + argvCallback, + netAppRequest); + } +} + +//**************************************************************************** +// MAIN FUNCTION +//**************************************************************************** + +//***************************************************************************** +// +//! \brief This function fetches the device type and prints it +//! +//! \param[in] None +//! +//! \return device type +//! +//**************************************************************************** +uint32_t getDeviceType(void) +{ + uint32_t deviceType; + uint16_t configSize = 0; + uint8_t configOpt = SL_DEVICE_GENERAL_VERSION; + SlDeviceVersion_t ver = {0}; + configSize = sizeof(SlDeviceVersion_t); + + /* Print device version info. */ + sl_DeviceGet(SL_DEVICE_GENERAL, &configOpt, &configSize, (uint8_t*)(&ver)); + + deviceType = ver.ChipId & 0xFF; + /* Update deviceType to 323XX or 3220X */ + if((HWREG(GPRCM_BASE + GPRCM_O_GPRCM_DIEID_READ_REG4) >> 24) & 0x02) + { + deviceType |= (0x01 << 8); + } + + switch(deviceType) + { + case DEV_TYPE_CC323XR: // 323xR + UART_PRINT("[Provisioning task] detected device is CC323xR\n\r"); + break; + case DEV_TYPE_CC323XRS: // 323xRS + UART_PRINT("[Provisioning task] detected device is CC323xRS\n\r"); + break; + case DEV_TYPE_CC323XFS: // 323xFS + UART_PRINT("[Provisioning task] detected device is CC323xSF\n\r"); + break; + case DEV_TYPE_CC3220R: // 3220R + UART_PRINT("[Provisioning task] detected device is CC3220R\n\r"); + break; + case DEV_TYPE_CC3220RS: // 3220RS + UART_PRINT("[Provisioning task] detected device is CC3220RS\n\r"); + break; + case DEV_TYPE_CC3220FS: // 3220FS + UART_PRINT("[Provisioning task] detected device is CC3220SF\n\r"); + break; + default: + break; + } + + return(deviceType); +} + +//***************************************************************************** +// +//! \brief This task handles LinkLocal transactions with the client +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void * linkLocalTask(void *pvParameters) +{ + mq_attr attr; + int32_t msgqRetVal; + I2C_Params i2cParams; + + /* initializes I2C */ + I2C_Params_init(&i2cParams); + i2cParams.bitRate = I2C_400kHz; + // i2cHandle = I2C_open(Board_I2C0, &i2cParams); + // if(i2cHandle == NULL) + // { + // //UART_PRINT("[Link local task] Error Initializing I2C\n\r"); + // } + + /* Setup mutex operations for sensors reading */ + sensorLockObj = malloc(sizeof(pthread_mutex_t)); + pthread_mutex_init(sensorLockObj, (pthread_mutexattr_t*)NULL); + + /* initializes mailbox for http messages */ + attr.mq_maxmsg = 10; /* queue size */ + attr.mq_msgsize = sizeof(SlNetAppRequest_t*); /* Size of message */ + linkLocalMQueue = mq_open("linklocal msg q", O_CREAT, 0, &attr); + if(linkLocalMQueue == NULL) + { + UART_PRINT("[Link local task] could not create msg queue\n\r"); + while(1) + { + ; + } + } + + initLinkLocalDB(); + + /* waits for valid local connection - via provisioning task */ + sem_wait(&Provisioning_ControlBlock.provisioningDoneSignal); + + while(1) + { + SlNetAppRequest_t *netAppRequest; + + msgqRetVal = + mq_receive(linkLocalMQueue, (char *)&netAppRequest, + sizeof(SlNetAppRequest_t*), NULL); + if(msgqRetVal < 0) + { + UART_PRINT( + "[Link local task] could not receive element from msg \ + queue\n\r"); + while(1) + { + ; + } + } + + INFO_PRINT( + "[Link local task] NetApp Request Received - handle from main " + "context AppId = %d, Type = %d, Handle = %d\n\r", + netAppRequest->AppId, netAppRequest->Type, netAppRequest->Handle); + + INFO_PRINT("[Link local task] Metadata len = %d\n\r", + netAppRequest->requestData.MetadataLen); + + if((netAppRequest->Type == SL_NETAPP_REQUEST_HTTP_GET) || + (netAppRequest->Type == SL_NETAPP_REQUEST_HTTP_DELETE)) + { + if(netAppRequest->Type == SL_NETAPP_REQUEST_HTTP_GET) + { + UART_PRINT("[Link local task] HTTP GET Request\n\r"); + } + else + { + UART_PRINT("[Link local task] HTTP DELETE Request\n\r"); + } + + httpGetHandler(netAppRequest); + } + else if((netAppRequest->Type == SL_NETAPP_REQUEST_HTTP_POST) || + (netAppRequest->Type == SL_NETAPP_REQUEST_HTTP_PUT)) + { + if(netAppRequest->Type == SL_NETAPP_REQUEST_HTTP_POST) + { + UART_PRINT("[Link local task] HTTP POST Request\n\r"); + } + else + { + UART_PRINT("[Link local task] HTTP PUT Request\n\r"); + } + + INFO_PRINT( + "[Link local task] Data received, len = %d, flags= %x\n\r", + netAppRequest->requestData.PayloadLen, + netAppRequest->requestData.Flags); + + httpPostHandler(netAppRequest); + } + + if(netAppRequest->requestData.MetadataLen > 0) + { + free (netAppRequest->requestData.pMetadata); + } + if(netAppRequest->requestData.PayloadLen > 0) + { + free (netAppRequest->requestData.pPayload); + } + + free (netAppRequest); + } +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_ProvisioningTask.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_ProvisioningTask.c new file mode 100644 index 00000000..53422724 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_ProvisioningTask.c @@ -0,0 +1,1547 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +/* standard includes */ +#include +#include + +/* driverlib Header files */ +#include +#include +#include + +/* TI-DRIVERS Header files */ +#include +#include +#include +#include +#include + +/* Example/Board Header files */ +#include +#include +#include +// #include "platform.h" +// #include "ota_archive.h" + +/* POSIX Header files */ +#include +#include + +/* In msecs. Used to detect good/bad sl_start() */ +#define ASYNC_EVT_TIMEOUT (5000) +/*In sec. Used for connecting to stored profile */ +#define PROFILE_ASYNC_EVT_TIMEOUT (5) +#define LED_TOGGLE_CONFIGURATION_TIMEOUT (1000) /* In msecs */ +#define LED_TOGGLE_CONFIRMATION_TIMEOUT (500) /* In msecs */ +#define LED_TOGGLE_CONNECTION_TIMEOUT (250) /* In msecs */ +/* Provisioning inactivity timeout in seconds */ +#define PROVISIONING_INACTIVITY_TIMEOUT (600) + +#define ROLE_SELECTION_BY_SL (0xFF) + +/* OCP register used to store device role when coming out of hibernate */ +#define OCP_REGISTER_INDEX (0) +/* if ocpRegOffset is set -> AP role, otherwise -> STATION role */ +#define OCP_REGISTER_OFFSET (10) + +/*! + * \brief Provisioning modes + */ +typedef enum +{ + PrvsnMode_AP, /* AP provisioning (AP role) */ + PrvsnMode_SC, /* Smart Config provisioning (STA role) */ + PrvsnMode_APSC /* AP + Smart Config provisioning (AP role) */ +}PrvsnMode; + +/** By default, setting the provisioning mode to AP + Smart Config. + * Other values could be PrvsnMode_SC or PrvsnMode_AP + */ +#define PROVISIONING_MODE PrvsnMode_APSC + +/*! + * \brief Provisioning status + */ +typedef enum +{ + PrvsnStatus_Stopped, + PrvsnStatus_InProgress +}PrvsnStatus; + +/* + * \brief Application state's context + */ +typedef struct _Provisioning_AppContext_t_ +{ + PrvnState currentState; /* Current state of provisioning */ + uint32_t pendingEvents; /* Events pending to be processed */ +/* SimpleLink's role - STATION/AP/P2P */ + uint8_t role; +/* SimpleLink's default role, try not to change this */ + uint8_t defaultRole; + PrvsnMode provisioningMode; /* Provisioning Mode */ + PrvsnStatus provisioningStatus; /* */ + + uint32_t asyncEvtTimeout; /* Timeout value*/ + + uint32_t ledToggleTimeout; /* Timeout value */ +}Provisioning_AppContext; + +/*! + * \brief Function pointer to the event handler + */ +typedef int32_t (*fptr_EventHandler)(void); + +/*! + * \brief Entry in the lookup table + */ +typedef struct +{ + fptr_EventHandler p_evtHndl; /* Pointer to the event handler */ + PrvnState nextState; /* Next state of provisioning */ +}s_TblEntry; + + + +/**************************************************************************** + LOCAL FUNCTION PROTOTYPES +****************************************************************************/ + +//***************************************************************************** +// +//! \brief This function initializes provisioning process +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void provisioningInit(void); + +//***************************************************************************** +// +//! \brief This function starts provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +int32_t provisioningStart(void); + +//***************************************************************************** +// +//! \brief main provisioning loop +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t provisioningAppTask(void); + +//***************************************************************************** +//! \brief This function puts the device in its default state. It: +//! - Set the mode to AP +//! - Configures connection policy to Auto +//! - Deletes all the stored profiles +//! - Enables DHCP +//! - Disable IPV6 +//! - Disables Scan policy +//! - Sets Tx power to maximum +//! - Sets power policy to normal +//! - Unregister mDNS services +//! - Remove all filters +//! +//! IMPORTANT NOTE - This is an example reset function, user must +//! update this function to match the application settings. +//! +//! \param none +//! \return On success, zero is returned. On error, negative is returned +//***************************************************************************** +static int32_t ConfigureSimpleLinkToDefaultState(void); + +//***************************************************************************** +// +//! \brief This function starts the SimpleLink in the configured role. +//! The device notifies the host asynchronously +//! when the initialization is +//! completed +//! +//! \param[in] role Device shall be configured in this role +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t InitSimplelink(uint8_t const role); + +//***************************************************************************** +// +//! \brief This function handles 'APP_EVENT_STARTED' event +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t HandleStrtdEvt(void); + +//***************************************************************************** +// +//! \brief This function starts the async-event timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t StartAsyncEvtTimer(uint32_t timeout); + +//***************************************************************************** +// +//! \brief This function stops the async-event timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t StopAsyncEvtTimer(void); + +//***************************************************************************** +// +//! \brief internal error detection during provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t ReportError(void); + +//***************************************************************************** +// +//! \brief internal report current state during provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t ReportSM(void); + +//***************************************************************************** +// +//! \brief steps following a successful provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t ReportSuccess(void); + +//***************************************************************************** +// +//! \brief wait for connection following a successful provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t WaitForConn(void); + +//***************************************************************************** +// +//! \brief checks for local link connecion to peer device +//! when set as Station, checks for AP connection +//! when set as Access Point, no check is required +//! +//! \param[out] deviceRole role of the device +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t validateLocalLinkConnection(SlWlanMode_e *deviceRole); + +//***************************************************************************** +// +//! Notify if device return to factory image +//! +//! \param None +//! +//! \return None +// +//***************************************************************************** +static void NotifyReturnToFactoryImage(void); + +/**************************************************************************** + GLOBAL VARIABLES +****************************************************************************/ +/*! + * \brief Application state's context + */ +Provisioning_AppContext gAppCtx; + +timer_t gAsyncEventTimer; +timer_t gLedTimer; +/*! + * \brief Application lookup/transition table + */ +const s_TblEntry gProvisioningTransitionTable[PrvnState_Max][PrvnEvent_Max] = +{ + /* PrvnState_Init */ + { + /* Event: PrvnEvent_Triggered */ + {provisioningStart, PrvnState_Idle }, + /* Event: PrvnEvent_Started */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_StartFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_ConfirmationSuccess */ + /* special case where confirmation is received after application is + restarted and NWP is still in provisioning */ + {ReportSM, PrvnState_Completed }, + /* in this case, need to move to COMPLETED state */ + /* Event: PrvnEvent_ConfirmationFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Stopped */ + /* in case of auto provisioning */ + {ReportSM, PrvnState_Init }, + /* Event: PrvnEvent_WaitForConn */ + {ReportSM, PrvnState_Error }, + /* Event: PrvnEvent_Timeout */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Error */ + {ReportError, PrvnState_Error }, + }, + /* PrvnState_Idle */ + { + /* Event: PrvnEvent_Triggered */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Started */ + {HandleStrtdEvt, PrvnState_WaitForConfirmation }, + /* Event: PrvnEvent_StartFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_ConfirmationSuccess */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_ConfirmationFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Stopped */ + {ReportSM, PrvnState_Init }, + /* Event: PrvnEvent_WaitForConn */ + {ReportSM, PrvnState_Error }, + /* Event: PrvnEvent_Timeout */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Error */ + {ReportError, PrvnState_Error }, + }, + /* PrvnState_WaitForConfirmation */ + { + /* Event: PrvnEvent_Triggered */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Started */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_StartFailed */ + {ReportSM, PrvnState_Idle }, + /* Event: PrvnEvent_ConfirmationSuccess */ + {ReportSM, PrvnState_Completed }, + /* Event: PrvnEvent_ConfirmationFailed */ + {ReportSM, PrvnState_WaitForConfirmation }, + /* Event: PrvnEvent_Stopped */ + {ReportSM, PrvnState_Init }, + /* Event: PrvnEvent_WaitForConn */ + {ReportSM, PrvnState_Error }, + /* Event: PrvnEvent_Timeout */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Error */ + {ReportError, PrvnState_Error }, + }, + /* PrvnState_Completed */ + { + /* Event: PrvnEvent_Triggered */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Started */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_StartFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_ConfirmationSuccess */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_ConfirmationFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Stopped */ + {ReportSuccess, PrvnState_Init }, + /* Event: PrvnEvent_WaitForConn */ + /* this state should cover cases where + feedback failed but profile exists */ + {WaitForConn, PrvnState_Init }, + /* Event: PrvnEvent_Timeout */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Error */ + {ReportError, PrvnState_Error }, + }, + /* PrvnState_Error */ + { + /* Event: PrvnEvent_Triggered */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Started */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_StartFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_ConfirmationSuccess */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_ConfirmationFailed */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Stopped */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_WaitForConn */ + {ReportSM, PrvnState_Error }, + /* Event: PrvnEvent_Timeout */ + {ReportError, PrvnState_Error }, + /* Event: PrvnEvent_Error */ + {ReportError, PrvnState_Error }, + } +}; + +Provisioning_CB Provisioning_ControlBlock; + +/***************************************************************************** + Callback Functions +*****************************************************************************/ + +//***************************************************************************** +// +//! \brief The device init callback +//! +//! \param[in] status Mode the device is configured in +//! +//! \return None +//! +//**************************************************************************** +void SimpleLinkInitCallback(uint32_t status, + SlDeviceInitInfo_t *DeviceInitInfo) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + + // UART_PRINT("[Provisioning task] Device started in %s role\n\r", + // (0 == status) ? "Station" : \ + // ((2 == status) ? "AP" : "P2P")); + + /** While provisioning is ongoing, the appropriate role is choosen by the + * device itself, and host can remain agnostic to these details + */ + if(pCtx->role == ROLE_SELECTION_BY_SL) + { + SignalProvisioningEvent(PrvnEvent_Started); + } + else + { + /* Either trigger an error/started event here */ + if(pCtx->role == status) + { + SignalProvisioningEvent(PrvnEvent_Started); + } + else + { + // UART_PRINT("[Provisioning task] But the intended role is %s \n\r", \ + // (0 == pCtx->role) ? "Station" : \ + // ((2 == pCtx->role) ? "AP" : "P2P")); + SignalProvisioningEvent(PrvnEvent_Error); + } + } +} + +//***************************************************************************** +// +//! \brief The interrupt handler for the async-evt timer +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void AsyncEvtTimerIntHandler(sigval val) +{ + /* Clear the timer interrupt. */ + Platform_TimerInterruptClear(); + + /* One Shot */ + /* TBD - Check role for One-shot/periodic */ + StopAsyncEvtTimer(); + SignalProvisioningEvent(PrvnEvent_Timeout); +} + +//***************************************************************************** +// +//! \brief The interrupt handler for the LED timer +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void LedTimerIntHandler(sigval val) +{ + /* Clear the timer interrupt. */ + Platform_TimerInterruptClear(); + + GPIO_toggle(Board_GPIO_LED0); +} + +//***************************************************************************** +// Local Functions +//***************************************************************************** + +//***************************************************************************** +// +//! \brief This function initializes provisioning process +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void provisioningInit(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + + Platform_TimerInit(AsyncEvtTimerIntHandler, &gAsyncEventTimer); + + /** By default, setting the provisioning mode to AP + Smart Config. + * Other values could be PrvsnMode_SC or PrvsnMode_AP + */ + pCtx->provisioningMode = PROVISIONING_MODE; + switch(pCtx->provisioningMode) + { + case PrvsnMode_APSC: pCtx->defaultRole = ROLE_AP; + break; + + case PrvsnMode_AP: pCtx->defaultRole = ROLE_AP; + break; + + case PrvsnMode_SC: pCtx->defaultRole = ROLE_STA; + break; + } + + /* Provisioning has not started yet */ + pCtx->provisioningStatus = PrvsnStatus_Stopped; + pCtx->currentState = PrvnState_Init; +} + +//***************************************************************************** +// +//! \brief This function starts provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +int32_t provisioningStart(void) +{ + int32_t retVal = 0; + Provisioning_AppContext *const pCtx = &gAppCtx; + SlDeviceVersion_t ver = {0}; + uint8_t configOpt = 0; + uint16_t configLen = 0; + + /* check if provisioning is running */ + /* if auto provisioning - the command stops it automatically */ + /* in case host triggered provisioning - need to stop it explicitly */ + configOpt = SL_DEVICE_GENERAL_VERSION; + configLen = sizeof(ver); + retVal = + sl_DeviceGet(SL_DEVICE_GENERAL, &configOpt, &configLen, + (uint8_t *)(&ver)); + if(SL_RET_CODE_PROVISIONING_IN_PROGRESS == retVal) + { + // UART_PRINT( + // "[Provisioning task] Provisioning is already running," + // " stopping it...\r\n"); + retVal = + sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP,ROLE_STA,0,NULL, + 0); + + /* return SL_RET_CODE_PROVISIONING_IN_PROGRESS to indicate the SM + to stay in the same state*/ + return(SL_RET_CODE_PROVISIONING_IN_PROGRESS); + } + + /* + IMPORTANT NOTE - This is an example reset function, user must update + this function to match the application settings. + */ + retVal = ConfigureSimpleLinkToDefaultState(); + + if(retVal < 0) + { + // UART_PRINT( + // "[Provisioning task] Failed to configure the device in its default " + // "state \n\r"); + return(retVal); + } + + // UART_PRINT( + // "[Provisioning task] Device is configured \ + // in default state \n\r" ); + + /* Provisioning has not started yet */ + pCtx->provisioningStatus = PrvsnStatus_Stopped; + + /* Set the LED toggling timeout before starting the timer */ + pCtx->ledToggleTimeout = LED_TOGGLE_CONFIGURATION_TIMEOUT; + StartLedEvtTimer(pCtx->ledToggleTimeout); + + retVal = InitSimplelink(pCtx->defaultRole); + if(retVal < 0) + { + // UART_PRINT("[Provisioning task] Failed to initialize the device\n\r"); + return(retVal); + } + + return(retVal); +} + +//***************************************************************************** +// +//! \brief main provisioning loop +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t provisioningAppTask(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + s_TblEntry *pEntry = NULL; + uint16_t eventIdx = 0; + int32_t retVal = 0; + + for(eventIdx = 0; eventIdx < PrvnEvent_Max; eventIdx++) + { + if(0 != (pCtx->pendingEvents & (1 << eventIdx))) + { + if(eventIdx != PrvnEvent_Triggered) + { + /** Events received - Stop the respective timer if its still + * running + */ + StopAsyncEvtTimer(); + } + + pEntry = + (s_TblEntry *)&gProvisioningTransitionTable[pCtx->currentState] + [ + eventIdx]; + if(NULL != pEntry->p_evtHndl) + { + /* no state transition is required */ + retVal = pEntry->p_evtHndl(); + if(retVal == SL_RET_CODE_PROVISIONING_IN_PROGRESS) + { + pCtx->pendingEvents &= ~(1 << eventIdx); + continue; + } + else if(retVal < 0) + { + // UART_PRINT( + // "[Provisioning task]" + // " Event handler failed, error=%d\n\r", + // retVal); + while(1) /*this is to let other tasks recover by + mcu reset, e.g. in case of switching + to AP mode */ + { + usleep(1000); + } + } + } + + if(pEntry->nextState != pCtx->currentState) + { + pCtx->currentState = pEntry->nextState; + } + + pCtx->pendingEvents &= ~(1 << eventIdx); + } + + /* No more events to handle. Break.! */ + if(0 == pCtx->pendingEvents) + { + break; + } + } + + usleep(1000); + + return(0); +} + +//***************************************************************************** +//! \brief This function puts the device in its default state. It: +//! - Set the mode to AP +//! - Configures connection policy to Auto +//! - Deletes all the stored profiles +//! - Enables DHCP +//! - Disable IPV6 +//! - Disables Scan policy +//! - Sets Tx power to maximum +//! - Sets power policy to normal +//! - Unregister mDNS services +//! - Remove all filters +//! +//! IMPORTANT NOTE - This is an example reset function, user must +//! update this function to match the application settings. +//! +//! \param none +//! \return On success, zero is returned. On error, negative is returned +//***************************************************************************** +static int32_t ConfigureSimpleLinkToDefaultState(void) +{ + SlWlanRxFilterOperationCommandBuff_t RxFilterIdMask; + + uint8_t ucConfigOpt = 0; + uint16_t ifBitmap = 0; + uint8_t ucPower = 0; + + int32_t ret = -1; + int32_t mode = -1; + + memset(&RxFilterIdMask,0,sizeof(SlWlanRxFilterOperationCommandBuff_t)); + + /* Start Simplelink - Blocking mode */ + mode = sl_Start(0, 0, 0); + if(SL_RET_CODE_DEV_ALREADY_STARTED != mode) + { + ASSERT_ON_ERROR(mode); + } + + /* If the device is not in AP mode, try configuring it in AP mode + in case device is already started + (got SL_RET_CODE_DEV_ALREADY_STARTED error code), then mode would remain + -1 and in this case we do not know the role. Move to AP role anyway */ + if(ROLE_AP != mode) + { + /* Switch to AP role and restart */ + ret = sl_WlanSetMode(ROLE_AP); + ASSERT_ON_ERROR(ret); + + ret = sl_Stop(SL_STOP_TIMEOUT); + ASSERT_ON_ERROR(ret); + + ret = sl_Start(0, 0, 0); + ASSERT_ON_ERROR(ret); + + /* Check if the device is in AP again */ + if(ROLE_AP != ret) + { + return(ret); + } + } + + /* Set connection policy to Auto (no AutoProvisioning) */ + ret = sl_WlanPolicySet(SL_WLAN_POLICY_CONNECTION, + SL_WLAN_CONNECTION_POLICY(1, 0, 0, 0), NULL, 0); + ASSERT_ON_ERROR(ret); + + /* Remove all profiles */ + ret = sl_WlanProfileDel(0xFF); + ASSERT_ON_ERROR(ret); + + /* Enable DHCP client */ + ret = sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE,SL_NETCFG_ADDR_DHCP,0,0); + ASSERT_ON_ERROR(ret); + + /* Disable IPV6 */ + ifBitmap = 0; + ret = + sl_NetCfgSet(SL_NETCFG_IF, SL_NETCFG_IF_STATE, sizeof(ifBitmap), + (uint8_t *)&ifBitmap); + ASSERT_ON_ERROR(ret); + + /* Disable scan */ + ucConfigOpt = SL_WLAN_SCAN_POLICY(0, 0); + ret = sl_WlanPolicySet(SL_WLAN_POLICY_SCAN, ucConfigOpt, NULL, 0); + ASSERT_ON_ERROR(ret); + + /* Set Tx power level for station mode + Number between 0-15, as dB offset from max power - 0 will + set max power */ + ucPower = 0; + ret = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, + SL_WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1, + (uint8_t *)&ucPower); + ASSERT_ON_ERROR(ret); + + /* Set PM policy to normal */ + ret = sl_WlanPolicySet(SL_WLAN_POLICY_PM, SL_WLAN_NORMAL_POLICY, NULL, 0); + ASSERT_ON_ERROR(ret); + + /* Unregister mDNS services */ + ret = sl_NetAppMDNSUnRegisterService(0, 0, 0); + ASSERT_ON_ERROR(ret); + + /* Remove all 64 filters (8*8) */ + memset(RxFilterIdMask.FilterBitmap, 0xFF, 8); + ret = sl_WlanSet(SL_WLAN_RX_FILTERS_ID, + SL_WLAN_RX_FILTER_REMOVE, + sizeof(SlWlanRxFilterOperationCommandBuff_t), + (uint8_t *)&RxFilterIdMask); + ASSERT_ON_ERROR(ret); + + ret = sl_Stop(SL_STOP_TIMEOUT); + ASSERT_ON_ERROR(ret); + + return(ret); +} + +//***************************************************************************** +// +//! \brief This function starts the SimpleLink in the configured role. +//! The device notifies the host asynchronously +//! when the initialization is +//! completed +//! +//! \param[in] role Device shall be configured in this role +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t InitSimplelink(uint8_t const role) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + int32_t retVal = -1; + + pCtx->role = role; + pCtx->pendingEvents = 0; + + retVal = sl_Start(0, 0, (P_INIT_CALLBACK)SimpleLinkInitCallback); + ASSERT_ON_ERROR(retVal); + + /* Start timer */ + pCtx->asyncEvtTimeout = ASYNC_EVT_TIMEOUT; + retVal = StartAsyncEvtTimer(pCtx->asyncEvtTimeout); + ASSERT_ON_ERROR(retVal); + + return(retVal); +} + +//***************************************************************************** +// +//! \brief This function handles 'APP_EVENT_STARTED' event +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** + +static int32_t HandleStrtdEvt(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + int32_t retVal = 0; + + /** If provisioning has already started, don't do anything here + * The state-machine shall keep waiting for the provisioning status + */ + if(PrvsnStatus_Stopped == pCtx->provisioningStatus) + { + SlDeviceVersion_t firmwareVersion = {0}; + + uint8_t ucConfigOpt = 0; + uint16_t ucConfigLen = 0; + + /* Get the device's version-information */ + ucConfigOpt = SL_DEVICE_GENERAL_VERSION; + ucConfigLen = sizeof(firmwareVersion); + retVal = sl_DeviceGet(SL_DEVICE_GENERAL, &ucConfigOpt, \ + &ucConfigLen, + (unsigned char *)(&firmwareVersion)); + ASSERT_ON_ERROR(retVal); + + // UART_PRINT("[Provisioning task] Host Driver Version: %s\n\r", + // SL_DRIVER_VERSION); + // UART_PRINT( + // "[Provisioning task] Build Version " + // "%d.%d.%d.%d.31.%d.%d.%d.%d.%d.%d.%d.%d\n\r", \ + // firmwareVersion.NwpVersion[0], \ + // firmwareVersion.NwpVersion[1], \ + // firmwareVersion.NwpVersion[2], \ + // firmwareVersion.NwpVersion[3], \ + // firmwareVersion.FwVersion[0], \ + // firmwareVersion.FwVersion[1], \ + // firmwareVersion.FwVersion[2], \ + // firmwareVersion.FwVersion[3], \ + // firmwareVersion.PhyVersion[0], \ + // firmwareVersion.PhyVersion[1], \ + // firmwareVersion.PhyVersion[2], \ + // firmwareVersion.PhyVersion[3]); + + /* Start provisioning process */ + // UART_PRINT("[Provisioning task] Starting Provisioning - "); + // UART_PRINT( + // "[Provisioning task] in mode %d (0 = AP, 1 = SC, 2 = AP+SC)\r\n", + // pCtx->provisioningMode); + + retVal = sl_WlanProvisioning(pCtx->provisioningMode, ROLE_STA, + PROVISIONING_INACTIVITY_TIMEOUT, NULL,0); + ASSERT_ON_ERROR(retVal); + + pCtx->provisioningStatus = PrvsnStatus_InProgress; + // UART_PRINT( + // "[Provisioning task] Provisioning Started. Waiting to " + // "be provisioned..!! \r\n"); + } + + return(retVal); +} + +//***************************************************************************** +// +//! \brief This function starts the async-event timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t StartAsyncEvtTimer(uint32_t timeout) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + + pCtx->asyncEvtTimeout = timeout; + Platform_TimerStart(pCtx->asyncEvtTimeout, gAsyncEventTimer, 0); + return(0); +} + +//***************************************************************************** +// +//! \brief This function stops the async-event timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t StopAsyncEvtTimer(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + + if(0 != pCtx->asyncEvtTimeout) + { + Platform_TimerStop(gAsyncEventTimer); + pCtx->asyncEvtTimeout = 0; + } + + return(0); +} + +//***************************************************************************** +// +//! \brief internal error detection during provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t ReportError(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + uint16_t eventIdx = 0; + + for(eventIdx = 0; eventIdx < PrvnEvent_Max; eventIdx++) + { + if(0 != (pCtx->pendingEvents & (1 << eventIdx))) + { + break; + } + } + + // UART_PRINT("[Provisioning task]" + // " Unexpected SM: State = %d, Event = %d\n\r",\ + // pCtx->currentState, eventIdx); + return(-1); +} + +//***************************************************************************** +// +//! \brief internal report current state during provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t ReportSM(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + uint16_t eventIdx = 0; + + for(eventIdx = 0; eventIdx < PrvnEvent_Max; eventIdx++) + { + if(0 != (pCtx->pendingEvents & (1 << eventIdx))) + { + break; + } + } + + if(PrvnEvent_Stopped == eventIdx) + { + StopLedEvtTimer(); + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); + } + + return(0); +} + +//***************************************************************************** +// +//! \brief steps following a successful provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t ReportSuccess(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + uint16_t ConfigOpt; + uint16_t ipLen; + SlNetCfgIpV4Args_t ipV4 = {0}; + int32_t retVal; + + // UART_PRINT("[Provisioning task] " + // "Provisioning completed successfully..!\n\r"); + pCtx->provisioningStatus = PrvsnStatus_Stopped; + StopLedEvtTimer(); + + /* Get the device's IP address */ + ipLen = sizeof(SlNetCfgIpV4Args_t); + ConfigOpt = 0; + retVal = + sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE,&ConfigOpt,&ipLen, + (uint8_t *)&ipV4); + if(retVal == 0) + { + // UART_PRINT("[Provisioning task] IP address is %d.%d.%d.%d\n\r", \ + // SL_IPV4_BYTE(ipV4.Ip,3), \ + // SL_IPV4_BYTE(ipV4.Ip,2), \ + // SL_IPV4_BYTE(ipV4.Ip,1), \ + // SL_IPV4_BYTE(ipV4.Ip,0)); + } + + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); + + /* signal to linklocal task */ + sem_post(&Provisioning_ControlBlock.provisioningDoneSignal); + + /* signal to report server task */ + sem_post(&Provisioning_ControlBlock.provisioningConnDoneToOtaServerSignal); + + return(0); +} + +//***************************************************************************** +// +//! \brief wait for connection following a successful provisioning process +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t WaitForConn(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + struct timespec ts; + int32_t retVal; + + // while(((!IS_IPV6L_ACQUIRED(OutOfBox_ControlBlock.status) || + // !IS_IPV6G_ACQUIRED(OutOfBox_ControlBlock.status)) && + // !IS_IP_ACQUIRED(OutOfBox_ControlBlock.status)) || + // !IS_CONNECTED(OutOfBox_ControlBlock.status)) + // { + // clock_gettime(CLOCK_REALTIME, &ts); + // ts.tv_sec += PROFILE_ASYNC_EVT_TIMEOUT; + + // retVal = sem_timedwait(&Provisioning_ControlBlock.connectionAsyncEvent, + // &ts); + // /* freertos return -1 in case of timeout */ + // if((retVal == 116) || (retVal == -1)) + // { + // UART_PRINT( + // "[Provisioning task] Cannot connect to AP or profile does" + // " not exist\n\r"); + // GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); + // /* this state is set so that PrvnEvent_Triggered + // would invoke provisioning again */ + // pCtx->currentState = PrvnState_Init; + // SignalProvisioningEvent(PrvnEvent_Triggered); + + // return(0); + // } + // } + + // UART_PRINT("[Provisioning task] Connection to AP succeeded\n\r"); + + return(ReportSuccess()); +} + +//***************************************************************************** +// +//! \brief checks for local link connecion to peer device +//! when set as Station, checks for AP connection +//! when set as Access Point, no check is required +//! +//! \param[out] deviceRole role of the device +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +static int32_t validateLocalLinkConnection(SlWlanMode_e *deviceRole) +{ + uint16_t ConfigOpt; + uint16_t ipLen; + SlNetCfgIpV4Args_t ipV4 = {0}; + int32_t retVal; + uint32_t ocpRegVal; + + struct timespec ts; + + retVal = sl_Start(0, 0, 0); + /* when calibration fails, reboot is required */ + if(SL_ERROR_CALIB_FAIL == retVal) + { + mcuReboot(); + } + else + { + ASSERT_ON_ERROR(retVal); + } + + /* if in AP role + * 1) check OCP register value + * 2) if set, it means user set AP mode via switch. + * check for IP_ACQUIRED to indicate NWP is running + * 4) if not set, procede with STATION role + */ + if(retVal == ROLE_AP) + { + *deviceRole = ROLE_AP; + ocpRegVal = MAP_PRCMOCRRegisterRead(OCP_REGISTER_INDEX); + ocpRegVal &= (1 << OCP_REGISTER_OFFSET); + if(ocpRegVal) + { + if(IS_IP_ACQUIRED(nF_ControlBlock.Status)) + { + return(0); + } + else + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += PROFILE_ASYNC_EVT_TIMEOUT; + + retVal = sem_timedwait( + &Provisioning_ControlBlock.connectionAsyncEvent, &ts); + /* freertos return -1 in case of timeout */ + if((retVal == 116) || (retVal == -1)) + { + // UART_PRINT("[Provisioning task] AP role failed to initialize\n\r"); + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); + retVal = -1; + } + return(retVal); + } + } + } + + if(retVal != ROLE_STA) + { + retVal = sl_WlanSetMode(ROLE_STA); + ASSERT_ON_ERROR(retVal); + + retVal = sl_Stop(SL_STOP_TIMEOUT); + ASSERT_ON_ERROR(retVal); + + retVal = sl_Start(0, 0, 0); + if(retVal < 0 || (retVal != ROLE_STA)) + { + ASSERT_ON_ERROR(retVal); + } + // UART_PRINT("[Provisioning task] Device started as STATION \n\r"); + } + + *deviceRole = ROLE_STA; + + while(((!IS_IPV6L_ACQUIRED(nF_ControlBlock.Status) || + !IS_IPV6G_ACQUIRED(nF_ControlBlock.Status)) && + !IS_IP_ACQUIRED(nF_ControlBlock.Status)) || + !IS_CONNECTED(nF_ControlBlock.Status)) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += PROFILE_ASYNC_EVT_TIMEOUT; + + retVal = sem_timedwait(&Provisioning_ControlBlock.connectionAsyncEvent, &ts); + // freertos return -1 in case of timeout + if((retVal == 116) || (retVal == -1)) + { + // UART_PRINT( + // "[Provisioning task] Cannot connect to AP or" + // " profile does not exist\n\r"); + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); + retVal = -1; + + return(retVal); + } + } + + // UART_PRINT("[Provisioning task] Connection to AP succeeded\n\r"); + + // Get the device's IP address + ipLen = sizeof(SlNetCfgIpV4Args_t); + ConfigOpt = 0; + sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE, &ConfigOpt, &ipLen, (uint8_t *)&ipV4); + if(retVal < 0) + { + return(retVal); + } + + // UART_PRINT("[Provisioning task] IP address is %d.%d.%d.%d\n\r", \ + // SL_IPV4_BYTE(ipV4.Ip,3), \ + // SL_IPV4_BYTE(ipV4.Ip,2), \ + // SL_IPV4_BYTE(ipV4.Ip,1), \ + // SL_IPV4_BYTE(ipV4.Ip,0)); + + return(0); +} + +//***************************************************************************** +// +//! Notify if device return to factory image +//! +//! \param None +//! +//! \return None +// +//***************************************************************************** +static void NotifyReturnToFactoryImage(void) +{ + if(((HWREG(HIB3P3_BASE + 0x00000418) & (1 << 7)) != 0) && + ((HWREG(0x4402F0C8) & 0x01) != 0)) + { + // UART_PRINT("Return To Factory Image successful, Do a power cycle(POR)" + // " of the device using switch SW1-Reset\n\r"); + while(1) + { + ; + } + } +} + +//**************************************************************************** +// MAIN FUNCTION +//**************************************************************************** + +//***************************************************************************** +// +//! \brief This function signals the application events +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +int16_t SignalProvisioningEvent(PrvnEvent event) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + pCtx->pendingEvents |= (1 << event); + + return(0); +} + +//***************************************************************************** +// +//! \brief This function gets the current provisioning state +//! +//! \param[in] None +//! +//! \return provisioning state +//! +//**************************************************************************** +PrvnState GetProvisioningState() +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + + return(pCtx->currentState); +} + +//***************************************************************************** +// +//! \brief This function starts the led toggling timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +int32_t StartLedEvtTimer(uint32_t timeout) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + + pCtx->ledToggleTimeout = timeout; + Platform_TimerStart(pCtx->ledToggleTimeout, gLedTimer, 1); + + return(0); +} + +//***************************************************************************** +// +//! \brief This function stops the led toggling timer +//! +//! \param[in] None +//! +//! \return 0 on success, negative value otherwise +//! +//**************************************************************************** +int32_t StopLedEvtTimer(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + + if(0 != pCtx->ledToggleTimeout) + { + Platform_TimerStop(gLedTimer); + pCtx->ledToggleTimeout = 0; + } + + return(0); +} + +//***************************************************************************** +// +//! \brief This function stops provisioning process +//! +//! \param[in] None +//! +//! \return SL_RET_CODE_PROVISIONING_IN_PROGRESS if provisioning was running, +//! otherwise 0 +//! +//**************************************************************************** +int32_t provisioningStop(void) +{ + Provisioning_AppContext *const pCtx = &gAppCtx; + int32_t retVal; + PrvnState provisioningState; + SlDeviceVersion_t ver = {0}; + uint8_t configOpt = 0; + uint16_t configLen = 0; + + /* check if provisioning is running */ + configOpt = SL_DEVICE_GENERAL_VERSION; + configLen = sizeof(ver); + retVal = + sl_DeviceGet(SL_DEVICE_GENERAL, &configOpt, &configLen, + (uint8_t *)(&ver)); + if(SL_RET_CODE_PROVISIONING_IN_PROGRESS == retVal) + { + // UART_PRINT( + // "[Provisioning task] Provisioning is already running, " + // "stopping it...\r\n"); + retVal = + sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP,ROLE_STA,0,NULL, + 0); + + /* wait for the stopped event to arrive - wait for PrvnState_Init */ + do + { + provisioningState = GetProvisioningState(); + usleep(1000); + } + while(provisioningState != PrvnState_Init); + + pCtx->provisioningStatus = PrvsnStatus_Stopped; + + retVal = SL_RET_CODE_PROVISIONING_IN_PROGRESS; + } + else if(retVal < 0) + { + return(retVal); + } + else + { + retVal = 0; + } + + return(retVal); +} + +//***************************************************************************** +// +//! \brief This is the main provisioning task +//! +//! \param[in] None +//! +//! \return None +//! +//**************************************************************************** +void * provisioningTask(void *pvParameters) +{ + int32_t retVal = -1; + Provisioning_AppContext *const pCtx = &gAppCtx; + SlWlanMode_e deviceRole; + SlFsControl_t FsControl; + int32_t status; + + /* Check the wakeup source. If first time entry or wakeup from HIB */ + if(MAP_PRCMSysResetCauseGet() == 0) + { + //UART_PRINT("[Provisioning task] Wake up on Power ON\n\r"); + } + else if(MAP_PRCMSysResetCauseGet() == PRCM_HIB_EXIT) + { + //UART_PRINT("[Provisioning task] Woken up from Hibernate\n\r"); + } + + /* + Following function first try to connect to a stored profile. + If fails, it first configure the device to default state by cleaning + the persistent settings stored in NVMEM (viz. connection profiles & + policies, power policy etc) + + Applications may choose to skip this step if the developer is sure + that the device is in its desired state at start of applicaton + + Note that all profiles and persistent settings that were done on the + device will be lost */ + + /* initialize one-time parameters for provisioning */ + provisioningInit(); + + /* Configure Provisioning Toggle LED */ + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); + + Platform_TimerInit(LedTimerIntHandler, &gLedTimer); + + /* Set the LED toggling timeout before starting the timer */ + pCtx->ledToggleTimeout = LED_TOGGLE_CONFIRMATION_TIMEOUT; + + StartLedEvtTimer(pCtx->ledToggleTimeout); + + /* check whether return-to-default occured */ + NotifyReturnToFactoryImage(); + + /* 1) try to connect to a stored profile if in STATION mode + * 2) if successful, procede and validate ota bundle and then try to connect + to cloud + * 3) if unsuccessful when in STATION mode, procede to provisioning + * 4) if in AP mode, procede and validate ota bundle + */ + retVal = validateLocalLinkConnection(&deviceRole); + getDeviceType(); + /* at this point, provisioning has not started yet, unless auto provisioning + is running */ + /* in this case, if provisioning from mobile app is running, it would not be + possible to send most of the commands to the device */ + /* need to stop provisioning */ + provisioningStop(); + + StopLedEvtTimer(); + + /* 1) in case coming from ota procedure, a profile should reside on serial + flash and connect immediately + * 2) check if pending commit and set commit the bundle + * 3) On failure, reset the MCU to rollback */ + /* it means OtaArchive is in + SL_FS_BUNDLE_STATE_PENDING_COMMIT */ + // if(OtaArchive_GetPendingCommit()) + // {/* validation of new ota bundle failed, + // reverting to previous bundle */ + // if(retVal != 0) + // { + // /* rollback is not required for production devices + // - but it is not harmfull */ + // FsControl.IncludeFilters = 0; + // status = + // sl_FsCtl(SL_FS_CTL_BUNDLE_ROLLBACK, 0, NULL, + // (uint8_t *)&FsControl, + // sizeof(SlFsControl_t), NULL, 0, + // NULL); + // if(status < 0) + // { + // //UART_PRINT( + // // "[Provisioning task] Rollback error sl_FsCtl, status=%d\n\r", + // // status); + // } + + // mcuReboot(); + // } + // /* validation of new ota bundle succeeded, + // commit the new ota bundle */ + // else + // { + // //UART_PRINT( + // // "[Provisioning task] committing new ota download... \n\r"); + // if(OtaArchive_Commit() < 0) + // { + // //UART_PRINT( + // // "[Provisioning task] failed to commit new download, " + // // "reverting to previous copy by reseting the device \n\r"); + // mcuReboot(); + // } + // //UART_PRINT("[Provisioning task] commit succeeded \n\r"); + + // /* need to stop the WDT so MCU is not reset */ + // PowerCC32XX_reset(PowerCC32XX_PERIPH_WDT); + // } + // } + + if(deviceRole == ROLE_STA) + { + /* it means a connection to AP has been established, + no need to trigger provisioning */ + if(retVal == 0) + { + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); + + /* signal to linklocal task */ + sem_post(&Provisioning_ControlBlock.provisioningDoneSignal); + + /* signal to report server task */ + sem_post( + &Provisioning_ControlBlock. + provisioningConnDoneToOtaServerSignal); + } + /* it means a connection to AP failed, trigger provisioning */ + else if(retVal < 0) + { + SignalProvisioningEvent(PrvnEvent_Triggered); + } + } + /* it means device is initialized as AP, no need to trigger provisioning */ + if((retVal == 0) && (deviceRole == ROLE_AP)) + { + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); + + /* signal to linklocal task */ + sem_post(&Provisioning_ControlBlock.provisioningDoneSignal); + + /* signal to report server task */ + sem_post( + &Provisioning_ControlBlock.provisioningConnDoneToOtaServerSignal); + } + + do + { + retVal = provisioningAppTask(); + } + while(!retVal); /* Exit on failure */ + + return(0); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Sntp.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Sntp.c new file mode 100644 index 00000000..81fccbc3 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Sntp.c @@ -0,0 +1,407 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +// POSIX Header files +#include +#include +#include + +// RTOS header files +#include "FreeRTOS.h" +#include "task.h" + +#include +#include + +// nanoFramework header files +#include + +static struct sntp_server SNTP_ServersList[NTP_SERVERS]; + +pthread_t sntpWorkingThread = (pthread_t)NULL; +void * SntpWorkingThread(void *arg0); + +void sntp_init(void) +{ + struct sched_param priorityParams; + pthread_attr_t threadAttributes; + int retc; + + if(sntpWorkingThread == NULL) + { + pthread_attr_init(&threadAttributes); + priorityParams.sched_priority = NF_TASK_PRIORITY; + retc = pthread_attr_setschedparam(&threadAttributes, &priorityParams); + retc |= pthread_attr_setstacksize(&threadAttributes, 1024); + if (retc != 0) + { + // failed to set attributes + while (1) {} + } + + retc = pthread_create(&sntpWorkingThread, &threadAttributes, SntpWorkingThread, NULL); + if(retc != 0) + { + // pthread_create() failed + HAL_AssertEx(); + UART_PRINT("Unable to create SNTP thread \n"); + + while(1) + { + ; + } + } + } +} + +void sntp_stop(void) +{ + pthread_cancel(sntpWorkingThread); + sntpWorkingThread = NULL; +} + +bool sntp_enabled(void) +{ + return (sntpWorkingThread != NULL)? true : false; +} + +char* sntp_getservername(int index) +{ + if(index < NTP_SERVERS) + { + return SNTP_ServersList[index].name; + } + + return NULL; +} + +void sntp_setservername(int index, char* server) +{ + if(index < NTP_SERVERS) + { + SNTP_ServersList[index].name = server; + } +} + +static int32_t getAddrByName(const char *name, uint32_t *addr, uint16_t *family) +{ + int32_t ifID; + uint16_t addrLen = 1; + + /* Query DNS for IPv4 address. */ + ifID = SlNetUtil_getHostByName(0, (char *)name, strlen(name), addr, &addrLen, SLNETSOCK_AF_INET); + + if(ifID < 0) + { + /* If call fails, try again for IPv6. */ + ifID = SlNetUtil_getHostByName(0, (char *)name, strlen(name), addr, &addrLen, SLNETSOCK_AF_INET6); + if(ifID < 0) + { + /* return an error */ + return -1; + } + else + { + *family = SLNETSOCK_AF_INET6; + } + } + else + { + *family = SLNETSOCK_AF_INET; + } + + /* Return the interface ID */ + return (ifID); +} + +static int32_t hasKissCode(char *str) +{ + if (strncmp((char *)SNTP_KOD_RATE_STR, str, SNTP_KOD_ERROR_CODE_SIZE) == 0) + { + return (SNTP_KOD_RATE_CODE); + } + else if (strncmp((char *)SNTP_KOD_DENY_STR, str, SNTP_KOD_ERROR_CODE_SIZE) == 0) + { + return (SNTP_KOD_DENY_CODE); + } + else if (strncmp((char *)SNTP_KOD_RSTR_STR, str, SNTP_KOD_ERROR_CODE_SIZE) == 0) + { + return (SNTP_KOD_RSTR_CODE); + } + else + { + return (0); + } +} + +static int32_t getTime(SlNetSock_Addr_t *server, uint16_t ifID, + SlNetSock_Timeval_t *timeout, uint64_t *ntpTimeStamp) +{ + SNTP_Header_t sntpPkt; + int32_t ret = 0; + int16_t sd = -1; + SlNetSocklen_t saLen; + uint32_t integrityCheck; + struct timespec tspec; + + if (server->sa_family == SLNETSOCK_AF_INET) + { + saLen = sizeof(SlNetSock_AddrIn_t); + } + else if (server->sa_family == SLNETSOCK_AF_INET6) + { + saLen = sizeof(SlNetSock_AddrIn6_t); + } + else + { + return (SNTP_EINVALIDFAMILY); + } + + /* Create a UDP socket to communicate with NTP server */ + sd = SlNetSock_create(server->sa_family, SLNETSOCK_SOCK_DGRAM, SLNETSOCK_PROTO_UDP, ifID, 0); + if (sd < 0) + { + return (SNTP_ESOCKCREATEFAIL); + } + + ret = SlNetSock_connect(sd, server, saLen); + if (ret < 0) + { + SlNetSock_close(sd); + return (SNTP_ECONNECTFAIL); + } + + if (timeout != NULL) + { + /* Set the timeout for the server response to the user's value */ + ret = SlNetSock_setOpt(sd, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_RCV_TIMEO, timeout, sizeof(SlNetSock_Timeval_t)); + if (ret < 0) + { + SlNetSock_close(sd); + return (SNTP_ESOCKOPTFAIL); + } + } + + /* Initialize the SNTP packet, setting version and mode = client */ + memset(&sntpPkt, 0, sizeof(SNTP_Header_t)); + sntpPkt.flags = SNTP_VERSION << 3; + sntpPkt.flags |= SNTP_MODE_CLIENT; + + /* Set packet's transmit time as integrity check value */ + clock_gettime(CLOCK_REALTIME, &tspec); + integrityCheck = tspec.tv_sec; + sntpPkt.transmitTS[0] = integrityCheck; + + /* Send out our SNTP request to the current server */ + ret = SlNetSock_send(sd, (void *)&sntpPkt, sizeof(SNTP_Header_t), 0); + if (ret < 0) + { + SlNetSock_close(sd); + return (SNTP_ESENDFAIL); + } + + memset(&sntpPkt, 0, sizeof(SNTP_Header_t)); + + /* Retrieve the NTP packet from the socket and update our time. */ + ret = SlNetSock_recv(sd, &sntpPkt, sizeof(SNTP_Header_t), 0); + if ((ret < 0) || (ret != sizeof(SNTP_Header_t)) || (sntpPkt.originateTS[0] != integrityCheck)) + { + SlNetSock_close(sd); + return (SNTP_ERECVFAIL); + } + + /* Check for errors in server response */ + if (sntpPkt.stratum == 0) + { + /* Per RFC5905, we MUST handle Kiss O' Death packet */ + if ((sntpPkt.flags >> 6) == SNTP_NOSYNC) + { + /* KOD recv'd. Inspect kiss code & handle accordingly */ + ret = hasKissCode((char *)&sntpPkt.referenceID); + + if (ret == SNTP_KOD_RATE_CODE) + { + SlNetSock_close(sd); + return (SNTP_ERATEBACKOFF); + } + /* Check for fatal kiss codes */ + else if ((ret == SNTP_KOD_DENY_CODE) || (ret == SNTP_KOD_RSTR_CODE)) + { + SlNetSock_close(sd); + return (SNTP_EFATALNORETRY); + } + /* Per RFC5905, other kiss codes are ignored */ + } + else + { + /* + * A server response with stratum == 0, with no kiss + * code, is a fatal error. Mark server as invalid + */ + SlNetSock_close(sd); + return (SNTP_EINVALIDRESP); + } + } + + /* return the time in seconds */ + sntpPkt.transmitTS[0] = SlNetUtil_ntohl(sntpPkt.transmitTS[0]); + sntpPkt.transmitTS[1] = SlNetUtil_ntohl(sntpPkt.transmitTS[1]); + + *ntpTimeStamp = ((uint64_t)sntpPkt.transmitTS[0] << 32) | sntpPkt.transmitTS[1]; + + SlNetSock_close(sd); + return (0); +} + +int32_t SNTP_getTime(SlNetSock_Timeval_t *timeout, uint64_t *ntpTimeStamp) +{ + int32_t ret = 0; + int32_t ifID; + SlNetSock_AddrIn_t sa4; + SlNetSock_AddrIn6_t sa6; + SlNetSock_Addr_t *sa; + uint32_t addr[4]; + uint16_t family; + uint32_t i; + size_t count = NTP_SERVERS; + + for (i = 0; i < count; i++) + { + memset(&addr, 0, sizeof(addr)); + ifID = getAddrByName(SNTP_ServersList[i].name, addr, &family); + if(ifID >= 0) + { + if (family == SLNETSOCK_AF_INET) + { + sa4.sin_family = SLNETSOCK_AF_INET; + sa4.sin_port = SlNetUtil_htons(NTP_SERVER_PORT); + sa4.sin_addr.s_addr = SlNetUtil_htonl(addr[0]); + sa = (SlNetSock_Addr_t *)&sa4; + } + else + { + sa6.sin6_family = SLNETSOCK_AF_INET6; + sa6.sin6_port = SlNetUtil_htons(NTP_SERVER_PORT); + sa6.sin6_addr._S6_un._S6_u32[0] = SlNetUtil_htonl(addr[0]); + sa6.sin6_addr._S6_un._S6_u32[1] = SlNetUtil_htonl(addr[1]); + sa6.sin6_addr._S6_un._S6_u32[2] = SlNetUtil_htonl(addr[2]); + sa6.sin6_addr._S6_un._S6_u32[3] = SlNetUtil_htonl(addr[3]); + sa = (SlNetSock_Addr_t *)&sa6; + } + } + else + { + ret = SNTP_EGETHOSTBYNAMEFAIL; + continue; + } + + ret = getTime(sa, ifID, timeout, ntpTimeStamp); + if (ret == 0) + { + break; + } + } + + return (ret); +} + +//////////////////////////////////////////////////////////////////////////////// +// SNTP working thread +//////////////////////////////////////////////////////////////////////////////// +void* SntpWorkingThread(void* argument) +{ + (void)argument; + + uint64_t ntpTimeStamp; + uint32_t currentTime; + int32_t retval; + time_t ts; + SlNetSock_Timeval_t timeval; + struct timespec tspec; + + // Set timeout value for NTP server reply + timeval.tv_sec = NTP_REPLY_WAIT_TIME; + timeval.tv_usec = 0; + + UART_PRINT("[SNTP task] started\n\r"); + + // delay 1st request, if configured + if(SNTP_STARTUP_DELAY > 0) + { + UART_PRINT("[SNTP task] start delay: %d\n\r", SNTP_STARTUP_DELAY); + + ClockP_sleep(SNTP_STARTUP_DELAY); + } + + while(1) + { + // need to be connected and have an IP + if(!IS_IP_ACQUIRED(nF_ControlBlock.Status)) + { + UART_PRINT("[SNTP task] not connected. Retrying in %d seconds.\n\r", SNTP_RETRY_TIMEOUT); + + clock_gettime(CLOCK_REALTIME, &tspec); + tspec.tv_sec += SNTP_RETRY_TIMEOUT; + + // wait for connection event with retry timeout + // don't bother checking if it exited on timeout or event + // because the loop is restarted and the check for connection & address is performed + sem_timedwait(&Provisioning_ControlBlock.connectionAsyncEvent, &tspec); + + // retrying: start over + continue; + } + + UART_PRINT("[SNTP task] getting time...\n\r"); + + // Get the time use the SNTP_ServersList + retval = SNTP_getTime(&timeval, &ntpTimeStamp); + + if (retval != 0) + { + UART_PRINT("[SNTP task] failed to get time. Error: %d\n\r", retval); + + clock_gettime(CLOCK_REALTIME, &tspec); + tspec.tv_sec += SNTP_RETRY_TIMEOUT; + + // wait for connection event with retry timeout + // don't bother checking if it exited on timeout or event + // because the loop is restarted and the check for connection & address is performed + sem_timedwait(&Provisioning_ControlBlock.connectionAsyncEvent, &tspec); + + // retrying: start over + continue; + } + + currentTime = ntpTimeStamp >> 32; + currentTime = TIME_NTP_TO_LOCAL(currentTime); + + tspec.tv_nsec = 0; + tspec.tv_sec = currentTime; + + UART_PRINT("[SNTP task] updated time: %d\n\r", currentTime); + + if (clock_settime(CLOCK_REALTIME, &tspec) != 0) + { + // failed to set current time + // don't do anything, just wait for the next attempt + } + + // wait for connection event with retry timeout + // don't bother checking if it exited on timeout or event + // because the loop is restarted and the check for connection & address is performed + clock_gettime(CLOCK_REALTIME, &tspec); + tspec.tv_sec += SNTP_UPDATE_DELAY; + + sem_timedwait(&Provisioning_ControlBlock.connectionAsyncEvent, &tspec); + } + + pthread_exit(0); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Threads.c b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Threads.c new file mode 100644 index 00000000..c6cab4e5 --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/targetSimpleLinkCC32xx_Threads.c @@ -0,0 +1,1062 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Portions Copyright (c) Texas Instruments Incorporated. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// POSIX Header files +#include +#include +#include + +// RTOS header files +#include "FreeRTOS.h" +#include "task.h" + +// TI-RTOS Header files +#include +#include +#include + +#include + +// Board Header files +#include "Board.h" + +#include +#include +#include +#include +#include +#include + +// externals from Simple Link sockets +extern void Status_callback(); +extern void Link_callback(bool linkUp); + +extern void * CLRStartupThread(void *arg0); +extern void * ReceiverThread(void *arg0); +extern void sntp_init(void); + +// other externals +extern void ConfigUART(); + +////////////////////////////// +#define SL_STOP_TIMEOUT (200) + +#define SPAWN_TASK_PRIORITY (9) +#define TASK_STACK_SIZE (2048) + +#define SLNET_IF_WIFI_PRIO (5) + +////////////////////////////// + +// Stack size in bytes +#define THREADSTACKSIZE 4096 + +pthread_t provisioningThread = (pthread_t)NULL; +pthread_t slThread = (pthread_t)NULL; +pthread_t receiverThread = (pthread_t)NULL; +pthread_t nanoCLRThread = (pthread_t)NULL; + +nanoFramework_CB nF_ControlBlock; + +/***************************************************************************** + Callback Functions +*****************************************************************************/ + +//***************************************************************************** +// +//! The Function Handles WLAN Events +//! +//! \param[in] pWlanEvent - Pointer to WLAN Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) +{ + switch(pWlanEvent->Id) + { + case SL_WLAN_EVENT_CONNECT: + { + SET_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_Connection); + CLR_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_IpAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6lAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6gAcquired); + + // Information about the connected AP (like name, MAC etc) will be + // available in 'slWlanConnectAsyncResponse_t'-Applications + // can use it if required: + + // slWlanConnectAsyncResponse_t *pEventData = NULL; + // pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected; + + // Copy new connection SSID and BSSID to global parameters + // memcpy(nF_ControlBlock.connectionSSID, + // pWlanEvent->Data.Connect.SsidName, + // pWlanEvent->Data.Connect.SsidLen); + + // nF_ControlBlock.ssidLen = pWlanEvent->Data.Connect.SsidLen; + + // memcpy(nF_ControlBlock.connectionBSSID, + // pWlanEvent->Data.Connect.Bssid, + // SL_WLAN_BSSID_LENGTH); + + UART_PRINT( + "[WLAN EVENT] STA Connected to the AP: %s ," + "BSSID: %x:%x:%x:%x:%x:%x\n\r", + pWlanEvent->Data.Connect.SsidName, + pWlanEvent->Data.Connect.Bssid[0], + pWlanEvent->Data.Connect.Bssid[1], + pWlanEvent->Data.Connect.Bssid[2], + pWlanEvent->Data.Connect.Bssid[3], + pWlanEvent->Data.Connect.Bssid[4], + pWlanEvent->Data.Connect.Bssid[5]); + + sem_post(&Provisioning_ControlBlock.connectionAsyncEvent); + + Link_callback(true); + } + break; + + case SL_WLAN_EVENT_DISCONNECT: + { + SlWlanEventDisconnect_t* pEventData = NULL; + + CLR_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_Connection); + CLR_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_IpAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6lAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6gAcquired); + + pEventData = &pWlanEvent->Data.Disconnect; + + // If the user has initiated 'Disconnect' request, + // 'reason_code' is SL_WLAN_DISCONNECT_USER_INITIATED. + + if(SL_WLAN_DISCONNECT_USER_INITIATED == pEventData->ReasonCode) + { + UART_PRINT("[WLAN EVENT]Device disconnected from the AP"); + } + else + { + UART_PRINT("[WLAN ERROR]Device disconnected from the AP"); + } + // memset(nF_ControlBlock.connectionSSID, 0, + // sizeof(nF_ControlBlock.connectionSSID)); + // memset(nF_ControlBlock.connectionBSSID, 0, + // sizeof(nF_ControlBlock.connectionBSSID)); + + Link_callback(false); + } + break; + + case SL_WLAN_EVENT_STA_ADDED: + { + UART_PRINT( + "[WLAN EVENT] External Station connected to SimpleLink AP\r\n"); + + UART_PRINT("[WLAN EVENT] STA BSSID: %02x:%02x:%02x:%02x:%02x:%02x\r\n", + pWlanEvent->Data.STAAdded.Mac[0], + pWlanEvent->Data.STAAdded.Mac[1], + pWlanEvent->Data.STAAdded.Mac[2], + pWlanEvent->Data.STAAdded.Mac[3], + pWlanEvent->Data.STAAdded.Mac[4], + pWlanEvent->Data.STAAdded.Mac[5]); + } + break; + + case SL_WLAN_EVENT_STA_REMOVED: + { + UART_PRINT( + "[WLAN EVENT] External Station disconnected from SimpleLink AP\r\n"); + } + break; + + case SL_WLAN_EVENT_PROVISIONING_PROFILE_ADDED: + { + UART_PRINT("[WLAN EVENT] Profile Added\r\n"); + } + break; + + case SL_WLAN_EVENT_PROVISIONING_STATUS: + { + uint16_t status = + pWlanEvent->Data.ProvisioningStatus.ProvisioningStatus; + switch(status) + { + case SL_WLAN_PROVISIONING_GENERAL_ERROR: + case SL_WLAN_PROVISIONING_ERROR_ABORT: + { + // SignalProvisioningEvent(PrvnEvent_Error); + } + break; + + case SL_WLAN_PROVISIONING_ERROR_ABORT_INVALID_PARAM: + case SL_WLAN_PROVISIONING_ERROR_ABORT_HTTP_SERVER_DISABLED: + case SL_WLAN_PROVISIONING_ERROR_ABORT_PROFILE_LIST_FULL: + { + UART_PRINT("[WLAN EVENT] Provisioning Error status=%d\r\n", status); + // SignalProvisioningEvent(PrvnEvent_StartFailed); + } + break; + + case SL_WLAN_PROVISIONING_ERROR_ABORT_PROVISIONING_ALREADY_STARTED: + { + UART_PRINT("[WLAN EVENT] Provisioning already started"); + } + break; + + case SL_WLAN_PROVISIONING_CONFIRMATION_STATUS_FAIL_NETWORK_NOT_FOUND: + { + UART_PRINT("[WLAN EVENT] Confirmation fail: network not found\r\n"); + // SignalProvisioningEvent(PrvnEvent_ConfirmationFailed); + } + break; + + case SL_WLAN_PROVISIONING_CONFIRMATION_STATUS_FAIL_CONNECTION_FAILED: + { + UART_PRINT("[WLAN EVENT] Confirmation fail: Connection failed\r\n"); + // SignalProvisioningEvent(PrvnEvent_ConfirmationFailed); + } + break; + + case + SL_WLAN_PROVISIONING_CONFIRMATION_STATUS_CONNECTION_SUCCESS_IP_NOT_ACQUIRED + : + { + UART_PRINT( + "[WLAN EVENT] Confirmation fail: IP address not acquired\r\n"); + // SignalProvisioningEvent(PrvnEvent_ConfirmationFailed); + } + break; + + case SL_WLAN_PROVISIONING_CONFIRMATION_STATUS_SUCCESS_FEEDBACK_FAILED: + { + UART_PRINT( + "[WLAN EVENT] Connection Success " + "(feedback to Smartphone app failed)\r\n"); + // SignalProvisioningEvent(PrvnEvent_ConfirmationFailed); + } + break; + + case SL_WLAN_PROVISIONING_CONFIRMATION_STATUS_SUCCESS: + { + UART_PRINT("[WLAN EVENT] Confirmation Success!\r\n"); + // SignalProvisioningEvent(PrvnEvent_ConfirmationSuccess); + } + break; + + case SL_WLAN_PROVISIONING_AUTO_STARTED: + { + UART_PRINT("[WLAN EVENT] Auto-Provisioning Started\r\n"); + + // stop auto provisioning - + // may trigger in case of returning to default + // SignalProvisioningEvent(PrvnEvent_Stopped); + } + break; + + case SL_WLAN_PROVISIONING_STOPPED: + { + if(ROLE_STA == pWlanEvent->Data.ProvisioningStatus.Role) + { + UART_PRINT(" [WLAN EVENT] - WLAN Connection Status:%d\r\n", + pWlanEvent->Data.ProvisioningStatus.WlanStatus); + + if(SL_WLAN_STATUS_CONNECTED == + pWlanEvent->Data.ProvisioningStatus.WlanStatus) + { + UART_PRINT(" [WLAN EVENT] - Connected to SSID:%s\r\n", + pWlanEvent->Data.ProvisioningStatus.Ssid); + // memcpy (nF_ControlBlock.connectionSSID, + // pWlanEvent->Data.ProvisioningStatus.Ssid, + // pWlanEvent->Data.ProvisioningStatus.Ssidlen); + // nF_ControlBlock.ssidLen = + // pWlanEvent->Data.ProvisioningStatus.Ssidlen; + + // Provisioning is stopped by the device and + // provisioning is done successfully + // SignalProvisioningEvent(PrvnEvent_Stopped); + + break; + } + else + { + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Connection); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_IpAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6lAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6gAcquired); + + // Provisioning is stopped by the device and provisioning + // is not done yet, still need to connect to AP + // SignalProvisioningEvent(PrvnEvent_WaitForConn); + + break; + } + } + } + // SignalProvisioningEvent(PrvnEvent_Stopped); + break; + + case SL_WLAN_PROVISIONING_SMART_CONFIG_SYNCED: + { + UART_PRINT("[WLAN EVENT] Smart Config Synced!\r\n"); + } + break; + + case SL_WLAN_PROVISIONING_CONFIRMATION_WLAN_CONNECT: + { + SET_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Connection); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_IpAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6lAcquired); + CLR_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6gAcquired); + + UART_PRINT("[WLAN EVENT] Connection to AP succeeded\r\n"); + } + break; + + case SL_WLAN_PROVISIONING_CONFIRMATION_IP_ACQUIRED: + { + SET_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_IpAcquired); + + UART_PRINT("[WLAN EVENT] IP address acquired\r\n"); + } + break; + + case SL_WLAN_PROVISIONING_SMART_CONFIG_SYNC_TIMEOUT: + { + UART_PRINT("[WLAN EVENT] Smart Config Sync timeout\r\n"); + } + break; + + default: + { + UART_PRINT("[WLAN EVENT] Unknown Provisioning Status: %d\r\n", + pWlanEvent->Data.ProvisioningStatus.ProvisioningStatus); + } + break; + } + } + break; + + default: + { + UART_PRINT("[WLAN EVENT] Unexpected event [0x%x]\n\r", + pWlanEvent->Id); + + // SignalProvisioningEvent(PrvnEvent_Error); + } + break; + } +} + +//***************************************************************************** +// +//! The Function Handles the Fatal errors +//! +//! \param[in] slFatalErrorEvent - Pointer to Fatal Error Event info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t *slFatalErrorEvent) +{ + uint8_t msg = 4; + int32_t msgqRetVal; + + switch(slFatalErrorEvent->Id) + { + case SL_DEVICE_EVENT_FATAL_DEVICE_ABORT: + { + } + break; + + case SL_DEVICE_EVENT_FATAL_DRIVER_ABORT: + { + } + break; + + case SL_DEVICE_EVENT_FATAL_NO_CMD_ACK: + { + } + break; + + case SL_DEVICE_EVENT_FATAL_SYNC_LOSS: + { + } + break; + + case SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT: + { + } + break; + + default: + break; + } + + // msgqRetVal = mq_send(controlMQueue, (char *)&msg, 1, 0); + // if(msgqRetVal < 0) + // { + // //UART_PRINT("[Control task] could not send element to msg queue\n\r"); + // while(1) + // { + // ; + // } + // } +} + +//***************************************************************************** +// +//! This function handles network events such as IP acquisition, IP +//! leased, IP released etc. +//! +//! \param[in] pNetAppEvent - Pointer to NetApp Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent) +{ + SlNetAppEventData_u *pNetAppEventData = NULL; + + if(NULL == pNetAppEvent) + { + return; + } + + pNetAppEventData = &pNetAppEvent->Data; + + switch(pNetAppEvent->Id) + { + case SL_NETAPP_EVENT_IPV4_ACQUIRED: + { + SlIpV4AcquiredAsync_t *pEventData = NULL; + + SET_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_IpAcquired); + + // Ip Acquired Event Data + pEventData = &pNetAppEvent->Data.IpAcquiredV4; + + // Gateway IP address + // nF_ControlBlock.gatewayIP = pEventData->Gateway; + + sem_post(&Provisioning_ControlBlock.connectionAsyncEvent); + + Status_callback(); + } + break; + + case SL_NETAPP_EVENT_IPV6_ACQUIRED: + { + if(!GET_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6lAcquired)) + { + SET_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6lAcquired); + } + else + { + SET_STATUS_BIT(nF_ControlBlock.Status, + AppStatusBits_Ipv6gAcquired); + } + + sem_post(&Provisioning_ControlBlock.connectionAsyncEvent); + + Status_callback(); + } + break; + + case SL_NETAPP_EVENT_DHCPV4_LEASED: + { + SET_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_IpLeased); + } + break; + + case SL_NETAPP_EVENT_DHCPV4_RELEASED: + { + CLR_STATUS_BIT(nF_ControlBlock.Status, AppStatusBits_IpLeased); + + switch(pNetAppEventData->IpReleased.Reason) + { + case SL_IP_LEASE_PEER_RELEASE: + break; + + case SL_IP_LEASE_PEER_DECLINE: + break; + + case SL_IP_LEASE_EXPIRED: + break; + } + } + break; + + case SL_NETAPP_EVENT_DHCP_IPV4_ACQUIRE_TIMEOUT: + { + } + break; + + default: + { + } + break; + } +} + +//***************************************************************************** +// +//! This function handles HTTP server events +//! +//! \param[in] pServerEvent - Contains the relevant event information +//! \param[in] pServerResponse - Should be filled by the user with the +//! relevant response information +//! +//! \return None +//! +//**************************************************************************** +void SimpleLinkHttpServerEventHandler(SlNetAppHttpServerEvent_t *pHttpEvent, + SlNetAppHttpServerResponse_t * + pHttpResponse) +{ + // Unused in this application +} + +//***************************************************************************** +// +//! This function handles General Events +//! +//! \param[in] pDevEvent - Pointer to General Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent) +{ + uint8_t msg = 4; + int32_t msgqRetVal; + + // Most of the general errors are not FATAL are are to be handled + // appropriately by the application. + + if(NULL == pDevEvent) + { + return; + } + switch(pDevEvent->Id) + { + case SL_DEVICE_EVENT_RESET_REQUEST: + { + } + break; + + default: + { + // msgqRetVal = mq_send(controlMQueue, (char *)&msg, 1, 0); + // if(msgqRetVal < 0) + // { + // //UART_PRINT("[Control task] could not send element to msg queue\n\r"); + // while(1) + // { + // ; + // } + // } + } + break; + } +} + +//***************************************************************************** +// +//! This function handles socket events indication +//! +//! \param[in] pSock - Pointer to Socket Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) +{ + if(SL_SOCKET_ASYNC_EVENT == pSock->Event) + { + nFSlSocketAsyncEvent_t event; + event.Sd = pSock->SocketAsyncEvent.SockAsyncData.Sd; + event.Type = pSock->SocketAsyncEvent.SockAsyncData.Type; + + mq_send(nF_ControlBlock.socketAsyncEvent, + (char *)&event, sizeof(nFSlSocketAsyncEvent_t), 0); + + switch(pSock->SocketAsyncEvent.SockAsyncData.Type) + { + case SL_SSL_NOTIFICATION_CONNECTED_SECURED: + break; + case SL_SSL_NOTIFICATION_HANDSHAKE_FAILED: + break; + case SL_SSL_ACCEPT: + break; + case SL_OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED: + break; + case SL_SSL_NOTIFICATION_WRONG_ROOT_CA: + break; + default: + break; + } + } + + // This application doesn't work w/ socket - Events are not expected + switch(pSock->Event) + { + case SL_SOCKET_TX_FAILED_EVENT: + switch(pSock->SocketAsyncEvent.SockTxFailData.Status) + { + case SL_ERROR_BSD_ECLOSE: + break; + default: + break; + } + break; + + default: + break; + } +} + +void SimpleLinkNetAppRequestMemFreeEventHandler(uint8_t *buffer) +{ + // Unused in this application +} + + +//////////// these are coming from link task, they probably don't belong here + +void SimpleLinkSocketTriggerEventHandler(SlSockTriggerEvent_t *pSlTriggerEvent) +{ + // Unused in this application + (void)pSlTriggerEvent; +} + +void * mainThread(void *arg) +{ + struct sched_param priorityParams; + + pthread_attr_t threadAttributes; + + int retc; + struct timespec ts = {0}; + + // peripherals initialization + // make this dependent on having the corresponding NF FEATURE enabled + GPIO_init(); + UART_init(); + SPI_init(); + I2C_init(); + ADC_init(); + PWM_init(); + + // initialize UART (need UART to be functional ASAP in order to output to terminal, if required) + ConfigUART(); + + // Initialize SlNetSock layer + SlNetIf_init(0); + SlNetIf_add(SLNETIF_ID_1, "nF", + (const SlNetIf_Config_t *)&SlNetIfConfigWifi, + SLNET_IF_WIFI_PRIO); + + SlNetSock_init(0); + SlNetUtil_init(0); + + // initialize the realtime clock + clock_settime(CLOCK_REALTIME, &ts); + + // Switch off all LEDs on boards + GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF); + + // clear SimpleLink Status + nF_ControlBlock.Status = 0; + + // reset control block vars + nF_ControlBlock.configurationDone = 0; + + // Create sockets Async event queue + mq_attr attr; + attr.mq_maxmsg = SLNETSOCK_MAX_CONCURRENT_SOCKETS; + attr.mq_msgsize = sizeof(nFSlSocketAsyncEvent_t); + nF_ControlBlock.socketAsyncEvent = mq_open("", O_CREAT, 0, &attr); + + // initializes signals for all tasks + sem_init(&Provisioning_ControlBlock.connectionAsyncEvent, 0, 0); + sem_init(&Provisioning_ControlBlock.provisioningDoneSignal, 0, 0); + sem_init(&Provisioning_ControlBlock.provisioningConnDoneToOtaServerSignal, + 0, + 0); + sem_init(&LinkLocal_ControlBlock.otaReportServerStartSignal, 0, 0); + sem_init(&LinkLocal_ControlBlock.otaReportServerStopSignal, 0, 0); + + // Create the sl_Task internal spawn thread + pthread_attr_init(&threadAttributes); + priorityParams.sched_priority = SPAWN_TASK_PRIORITY; + retc = pthread_attr_setschedparam(&threadAttributes, &priorityParams); + retc |= pthread_attr_setstacksize(&threadAttributes, 2 * TASK_STACK_SIZE); + + // The SimpleLink host driver architecture mandate spawn + // thread to be created prior to calling Sl_start (turning the NWP on). + // The purpose of this thread is to handle + // asynchronous events sent from the NWP. + // Every event is classified and later handled + // by the Host driver event handlers. + retc = pthread_create(&slThread, &threadAttributes, sl_Task, NULL); + if(retc) + { + // Handle Error + UART_PRINT("Unable to create sl_Task thread \n"); + HAL_AssertEx(); + while(1) + { + ; + } + } + + // Before turning on the NWP on, reset any previously configured parameters + // TODO: check if we should have a better reset implementation instead of using the standard one + retc = sl_WifiConfig(); + if(retc < 0) + { + // Handle Error + UART_PRINT("Network Terminal - Couldn't configure Network Processor - %d\n", retc); + HAL_AssertEx(); + return(NULL); + } + + // need to setup the network interface to enable IPv6 otherwise there are errors in socket + // when IPv6 addresses are brought in (for example on a response to a DNS query) + // this can probably go away when support for IPv6 is official + uint32_t ifBitmap = 0; + ifBitmap = SL_NETCFG_IF_IPV6_LOCAL_STATEFUL | SL_NETCFG_IF_IPV6_GLOBAL_STATEFUL; + sl_NetCfgSet(SL_NETCFG_IF, SL_NETCFG_IF_STATE, sizeof(ifBitmap), &ifBitmap); + + // start network processor + retc = sl_Start(NULL, NULL, NULL); + if(retc >= 0) + { + // we are good! + // sl_Start returns on success the role that device started on + nF_ControlBlock.Role = retc; + ////////////////////////////////////// **** uncomment this if using provisioning + // retc = sl_Stop(SL_STOP_TIMEOUT); + // if(retc < 0) + // { + // /* Handle Error */ + // // UART_PRINT("\n sl_Stop failed\n"); + // while(1) + // { + // ; + // } + // } + ////////////////////////////////////// **** + } + else if((retc < 0) && (retc != SL_ERROR_RESTORE_IMAGE_COMPLETE)) + { + // Handle Error + HAL_AssertEx(); + while(1) + { + ; + } + } + + // // provisioning task + // pthread_attr_init(&threadAttributes); + // priorityParams.sched_priority = NF_TASK_PRIORITY; + // retc = pthread_attr_setschedparam(&threadAttributes, &priorityParams); + // retc |= pthread_attr_setstacksize(&threadAttributes, TASK_STACK_SIZE); + // if(retc) + // { + // // Handle Error + // // UART_PRINT("Unable to configure provisioningTask thread parameters \n"); + // while(1) + // { + // ; + // } + // } + // retc = pthread_create(&provisioningThread, &threadAttributes, provisioningTask, NULL); + // if (retc != 0) { + // // Unable to create provisioningTask thread + // while (1) {} + // } + + // retc |= pthread_attr_setstacksize(&threadAttributes, 2048); + // if(retc) + // { + // // Handle Error + // // UART_PRINT("Unable to create provisioningTask thread \n"); + // while(1) + // { + // ; + // } + // } + + // receiver thread + pthread_attr_init(&threadAttributes); + priorityParams.sched_priority = NF_TASK_PRIORITY + 1; + retc = pthread_attr_setschedparam(&threadAttributes, &priorityParams); + retc |= pthread_attr_setstacksize(&threadAttributes, 2048); + if (retc != 0) + { + // failed to set attributes + while (1) {} + } + + retc = pthread_create(&receiverThread, &threadAttributes, ReceiverThread, NULL); + if(retc != 0) + { + // pthread_create() failed + UART_PRINT("Unable to create receiver thread \n"); + HAL_AssertEx(); + while(1) + { + ; + } + } + + // CLR thread + pthread_attr_init(&threadAttributes); + priorityParams.sched_priority = NF_TASK_PRIORITY; + retc = pthread_attr_setschedparam(&threadAttributes, &priorityParams); + retc |= pthread_attr_setstacksize(&threadAttributes, 5116); + if (retc != 0) + { + // failed to set attributes + while (1) {} + } + + // forward CLR_SETTINGS to CLR startup thread + retc = pthread_create(&nanoCLRThread, &threadAttributes, CLRStartupThread, arg); + if(retc != 0) + { + // pthread_create() failed + UART_PRINT("Unable to create CLR thread \n"); + HAL_AssertEx(); + while(1) + { + ; + } + } + + #ifdef SL_APP_SNTP + sntp_setservername(0, SNTP_SERVER_DEFAULT_ADDRESS); + sntp_init(); + #endif + + return (0); +} + +//***************************************************************************** +// +//! \brief Application defined malloc failed hook +//! +//! \param none +//! +//! \return none +//! +//***************************************************************************** +void vApplicationMallocFailedHook() +{ + // Handle Memory Allocation Errors + while(1) + { + } +} + +//***************************************************************************** +// +//! \brief Application defined stack overflow hook +//! +//! \param none +//! +//! \return none +//! +//***************************************************************************** +void vApplicationStackOverflowHook(TaskHandle_t pxTask, + char *pcTaskName) +{ + //Handle FreeRTOS Stack Overflow + while(1) + { + } +} + +void vApplicationTickHook(void) +{ + // This function will be called by each tick interrupt if + // configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be + // added here, but the tick hook is called from an interrupt context, so + // code must not attempt to block, and only the interrupt safe FreeRTOS API + // functions can be used (those that end in FromISR()). + +} + +void vPreSleepProcessing(uint32_t ulExpectedIdleTime) +{ +} + +//***************************************************************************** +// +//! \brief Application defined idle task hook +//! +//! \param none +//! +//! \return none +//! +//***************************************************************************** +void +vApplicationIdleHook(void) +{ + // Handle Idle Hook for Profiling, Power Management etc +} + +//***************************************************************************** +// +//! \brief Overwrite the GCC _sbrk function which check the heap limit related +//! to the stack pointer. +//! In case of freertos this checking will fail. +//! \param none +//! +//! \return none +//! +//***************************************************************************** +void * _sbrk(uint32_t delta) +{ + extern char _end; // Defined by the linker + extern char __HeapLimit; + static char *heap_end; + static char *heap_limit; + char *prev_heap_end; + + if(heap_end == 0) + { + heap_end = &_end; + heap_limit = &__HeapLimit; + } + + prev_heap_end = heap_end; + if(prev_heap_end + delta > heap_limit) + { + return((void *) -1L); + } + heap_end += delta; + return((void *) prev_heap_end); +} + + +// /***************************************************************************** +// Local Functions +// *****************************************************************************/ + +//***************************************************************************** +// +//! This function clears and enables a GPIO pin interrupt flag +//! +//! \param index - GPIO index +//! +//! \return None +//! +//***************************************************************************** +static void GPIO_clearAndEnable(uint8_t index) +{ + GPIO_clearInt(index); + GPIO_enableInt(index); +} + +void Platform_TimerInit(void (*timerIntHandler)(sigval val), + timer_t *timerId) +{ + sigevent sev; + + // Create Timer + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_notify_function = timerIntHandler; + timer_create(CLOCK_MONOTONIC, &sev, timerId); +} + +void Platform_TimerStart(uint32_t asyncEvtTimeoutMsec, + timer_t timerId, + uint8_t periodic) +{ + struct itimerspec value; + + // set the timeout + value.it_value.tv_sec = (asyncEvtTimeoutMsec / 1000); + value.it_value.tv_nsec = (asyncEvtTimeoutMsec % 1000) * 1000000; + + value.it_value.tv_sec += (value.it_value.tv_nsec / 1000000000); + value.it_value.tv_nsec = value.it_value.tv_nsec % 1000000000; + + if(periodic) + { + // set as periodic timer + value.it_interval.tv_sec = value.it_value.tv_sec; + value.it_interval.tv_nsec = value.it_value.tv_nsec; + } + else + { + // set as one shot timer + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 0; + } + + // kick the timer + timer_settime(timerId, 0, &value, NULL); +} + +void Platform_TimerStop(timer_t timerId) +{ + struct itimerspec value; + + // stop timer + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 0; + value.it_value.tv_sec = 0; + value.it_value.tv_nsec = 0; + timer_settime(timerId, 0, &value, NULL); +} + +void Platform_TimerInterruptClear(void) +{ + // Do nothing... +} + +//***************************************************************************** +// +//! \brief This function reboot the M4 host processor +//! +//! \param[in] none +//! +//! \return none +//! +//**************************************************************************** +void mcuReboot(void) +{ + // stop network processor activities before reseting the MCU + sl_Stop(SL_STOP_TIMEOUT); + + // UART_PRINT("[Common] CC32xx MCU reset request\r\n"); + + // Reset the MCU in order to test the bundle + PRCMHibernateCycleTrigger(); +} diff --git a/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/target_platform.h.in b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/target_platform.h.in new file mode 100644 index 00000000..bfb0d3eb --- /dev/null +++ b/source/native/nf-interpreter/targets/TI-SimpleLink/nanoCLR/target_platform.h.in @@ -0,0 +1,17 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_TI_SIMPLELINK_NANOCLR_H_ +#define _TARGET_TI_SIMPLELINK_NANOCLR_H_ + +// enable SNTP app +#define SL_APP_SNTP @NF_NETWORKING_SNTP@ + +#endif /* _TARGET_TI_SIMPLELINK_NANOCLR_H_ */ diff --git a/source/native/nf-interpreter/targets/os/win32/Include/TargetPAL_BlockStorage.h b/source/native/nf-interpreter/targets/os/win32/Include/TargetPAL_BlockStorage.h new file mode 100644 index 00000000..c18cb808 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/Include/TargetPAL_BlockStorage.h @@ -0,0 +1,767 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TARGET_PAL_BLOCKSTORAGE_H_ +#define _TARGET_PAL_BLOCKSTORAGE_H_ 1 + +//--// + +#include +#include + +#if defined(__GNUC__) +#define HAL_Time_Sleep_MicroSeconds_BS(x) HAL_Time_Sleep_MicroSeconds_InRam(x) + +#else +#define HAL_Time_Sleep_MicroSeconds_BS(x) HAL_Time_Sleep_MicroSeconds(x) + +#endif + + + + +// for convert byte size to storage sector size +#define CONVERTBYTETOSECTORSIZE(x,y) ( (size_t)x + (size_t)y-1)/(size_t)y + +#define CONVERTBYTETOSECTORSIZE_2(x,y,z) ( (size_t)x + (size_t)y-1)/(size_t)z + +///////////////////////////////////////////////////////// +// Description: +// Definitions for the Block Storage device interface +// for the .NET Micro Framework +// +// Remarks: +// The general design of the API is strongly influenced +// by the Windows Embedded CE Flash Media Driver (FMD) +// API. However, It is not intended to be a direct port +// of the FMD architecture to the .NET MF. This design +// overcomes some of the limitations of the CE design +// and includes functionalty an support that is specific +// to the .NET MF. +// +// In particular this design adds the following: +// * Generalized block storage rather than assuming +// a Resident Flash Array (RFA) +// * Support for multiple instances of block storage +// devices instead of only one +// * Support for legacy CLR Block usage information to +// Identify for the system where various types of +// information reside in the storage device. +// * Support for direct use of NOR flash without forcing +// additional layering for metadata if an FS is not +// needed or desired on the NOR flash. +// * Support for XIP storage media like NOR and ROM. +// * Use of an interface (as a structure of function +// pointers) to allow layering and standardized support +// for various common functionality. (e.g. treating +// NOR flash with varying sized sectors and no metadata +// as if it was NAND with fixed sized sectors including +// metadata. Thus this kind functionality need only be +// implemented once) +// +// Terminology: +// Block Storage Device - device that stores data addressable +// as a chunk as opposed to byte or unsigned short level +// +// Sector - smallest unit of storage for a Block device. Data is +// read or written as a complete sector(unless the device +// supports XIP which allows byte addresssing and reading +// directly from the processor memory bus) +// +// Block - smallest eraseable unit of the storage device. A block +// contains one or more sectors that are erased as a whole. +// All sectors within a block are always the same size. +// +// Region - Group of adjacent blocks that all contain sectors of the +// same size. +// +// Execute-In-Place (XIP) - Attribute of some storage types, NOR, ROM, +// RAM, that allows direct execution of code from the device. +// XIP capable devices are at least read-only and byte addresable +// on the CPU memory bus. +// + + +// struct BlockRange +// { + + +// public: + +// static bool IsBlocknanoBooterAgnostic( uint32_t BlockType ) +// { +// // The only blocks that should be distinguished by nanoBooter are CONFIG, +// // Bootstrap and reserved blocks (DirtyBit is another version of CONFIG). +// if( BlockType == BlockRange_BLOCKTYPE_BOOTSTRAP || +// BlockType == BlockRange_BLOCKTYPE_CONFIG || +// BlockType == BlockRange_BLOCKTYPE_RESERVED || +// BlockType == BlockRange_BLOCKTYPE_DIRTYBIT) +// { +// return FALSE; +// } + +// return TRUE; +// } + +// bool IsReserved() const { return ((RangeType & BlockRange_RESERVED) == BlockRange_RESERVED); } +// bool IsReadOnly() const { return ((RangeType & BlockRange_READONLY) == BlockRange_READONLY); } + +// bool IsReservedData() const { return ((RangeType & (BlockRange_RESERVED | BlockRange_DATATYPE_RAW )) == (BlockRange_RESERVED | BlockRange_DATATYPE_RAW )); } +// bool HasManagedCode() const { return ((RangeType & (BlockRange_DATATYPE_MANAGEDCODE )) == (BlockRange_DATATYPE_MANAGEDCODE )); } + +// bool IsCode() const { return ((RangeType & BlockRange_USAGE_MASK) == BlockUsage_CODE); } +// bool IsBootstrap() const { return ((RangeType & BlockRange_USAGE_MASK) == BlockUsage_BOOTSTRAP);} +// bool IsDirtyBit() const { return ((RangeType & BlockRange_BLOCKTYPE_CONFIG) == BlockRange_BLOCKTYPE_DIRTYBIT);} +// bool IsConfig() const { return ((RangeType & BlockRange_BLOCKTYPE_CONFIG) == BlockRange_BLOCKTYPE_CONFIG); } +// bool IsDeployment() const { return ((RangeType & BlockRange_USAGE_MASK) == BlockUsage_DEPLOYMENT);} +// bool IsFileSystem() const { return ((RangeType & BlockRange_USAGE_MASK) == BlockUsage_FILESYSTEM); } +// uint32_t GetBlockCount() const { return (EndBlock - StartBlock + 1); } + +// // NOTE: This is the application native code only (not including the managed DAT section) +// // and thus is different from the old MEMORY_USAGE_CODE which contained both +// // the Native code application and the DAT section. Obviously these inlines can be +// // altered or added upon to test for any combination of the flags as desired but seperating +// // the DAT region out on it's own allows for locating ANY managed code sections of storage +// bool IsLegacyCode() const { return (IsCode()); } +// uint32_t GetBlockUsage() const { return (RangeType & BlockRange_USAGE_MASK); } + + +// /* +// Due to the lack of a defined bit ordering for bit fields in the C/C++ +// languages a bit field structure isn't actually used but this should +// help clarify the layout and intent of the constant declarations below. + +// //MSB +// unsigned EXECUTABLE:1; +// unsigned RESERVED:1; +// unsigned READONLY:1; +// unsigned UNUSEDBITS:13; + +// // The lower 16 bits are used to define the specific +// // usage for blocks when the RESERVED bit set +// unsigned BlockType:4 +// unsigned Usage:12; +// //LSB +// */ +// uint32_t RangeType; +// uint32_t StartBlock; +// uint32_t EndBlock; +// }; + +// ///////////////////////////////////////////////////////// +// // Description: +// // This structure defines characteristics of a particular +// // region of a block device. +// // +// // Remarks: +// // There is often more than one instance of this structure for each +// // block device. +// // +// // The BytesPerBlock value is an optimization to prevent the need +// // to routinely caclulate it from SectorsPerBlock * DataBytesPerSector +// // +// struct BlockRegionInfo +// { +// uint32_t Size() const { return (NumBlocks * BytesPerBlock); } +// ByteAddress BlockAddress(uint32_t blockIndex) const { return (Start + (blockIndex * BytesPerBlock)); } +// uint32_t OffsetFromBlock(uint32_t Address) const { return ((Address - Start) % BytesPerBlock); } +// uint32_t BlockIndexFromAddress(uint32_t Address) const { return ((Address - Start) / BytesPerBlock); } + +// ByteAddress Start; // Starting Sector address +// uint32_t NumBlocks; // total number of blocks in this region +// uint32_t BytesPerBlock; // Total number of bytes per block + +// uint32_t NumBlockRanges; +// const BlockRange *BlockRanges; +// }; + +// ///////////////////////////////////////////////////////// +// // Description: +// // This structure defines characteristics of a particular +// // block device. +// // +// // Remarks: +// // THere is only one instance of this structure for each +// // block device. +// // + +// struct MediaAttribute +// { +// bool Removable :1; +// bool SupportsXIP:1; +// bool WriteProtected:1; +// bool SupportsCopyBack:1; +// bool ErasedBitsAreZero:1; +// }; + +// /////////////////////////////////////////////////////////// + +// struct DeviceBlockInfo +// { +// // indicates if the storage media is removeable + +// MediaAttribute Attribute; + +// // Maximum Sector Write Time. +// uint32_t MaxSectorWrite_uSec; + +// // Maximum erase time for the a block +// uint32_t MaxBlockErase_uSec; + +// // Bytes Per Sector +// uint32_t BytesPerSector; + +// // Total Size +// ByteAddress Size; + +// // count of regions in the flash. +// uint32_t NumRegions; + +// // pointer to an array (NumRegions long) of region information +// const BlockRegionInfo *Regions; + +// __nfweak SectorAddress PhysicalToSectorAddress( const BlockRegionInfo* pRegion, ByteAddress phyAddress ) const; + +// __nfweak bool FindRegionFromAddress(ByteAddress Address, uint32_t &BlockRegionIndex, uint32_t &BlockRangeIndex ) const; + +// __nfweak bool FindForBlockUsage(uint32_t BlockUsage, ByteAddress &Address, uint32_t &BlockRegionIndex, uint32_t &BlockRangeIndex ) const; + +// __nfweak bool FindNextUsageBlock(uint32_t BlockUsage, ByteAddress &Address, uint32_t &BlockRegionIndex, uint32_t &BlockRangeIndex ) const; +// }; + +// /////////////////////////////////////////////////////////////// +// // Description: +// // This structure describes the sector Metadata used for wear +// // leveling. +// // +// // Remarks: +// // This structure emulates the typical physical layout of the +// // extra area of flash. The wear leveling layer for NAND and +// // NOR flash supplied by Microsoft for Windows CE makes use +// // of 8 bytes of the Sector Extra Info area. +// // +// // This information is designed to match that used in +// // Windows Embedded CE systems so that the FAL algorithms from +// // CE can be more easily ported to the .NET MF. +// // +// // The following is a typical representation of how the extra area +// // is utilized: +// //- - - - - - - - - - - - - - - - +// //|R|R|R|R|O|V|R|R|E|E|E|E|E|E|E|E| +// //- - - - - - - - - - - - - - - - +// // +// //The following table describes each element. +// // +// //Element Description +// // R Reserved bytes used by the FAL +// // O Byte for use by the OEM +// // V Byte indicating if the block is valid (a.k.a. bad) +// // E Bytes typically used for by a NAND driver for ECC +// // +// struct GNU_PACKED SectorMetadata +// { +// unsigned long dwReserved1; // Used by the FAL to hold the logical to physical sector mapping information. +// unsigned char bOEMReserved; // For use by OEM. See OEMReservedBits for more information. +// unsigned char bBadBlock; // Indicates if a block is bad. +// unsigned short wReserved2; // Used by the FAL to maintain state information about the sector. + +// // TODO: Check ECC algorithm implementations on CE to see what data type works most conveniently for this +// uint32_t ECC[2]; // Error Correction Code [Should be all 0xFF if not used] + +// // Remarks: +// // Any sectors that the OEM does not want the wear leveling +// // code to touch should have both of these bits set. This +// // includes the sectors that include the boot loader and any +// // other flash data that exists at fixed locations. +// // +// // Note: +// // Because only full blocks can be erased, all sectors within +// // a block should have the same values for these flags. +// // +// static const unsigned char OEM_BLOCK_RESERVED = 0x01; +// static const unsigned char OEM_BLOCK_READONLY = 0x02; +// }; + +//--// + +// struct BLOCK_CONFIG +// { +// GPIO_FLAG WriteProtectionPin; +// const DeviceBlockInfo* BlockDeviceInformation; +// }; + +// UNDONE: FIXME: struct MEMORY_MAPPED_NOR_BLOCK_CONFIG +//{ +// BLOCK_CONFIG BlockConfig; +// CPU_MEMORY_CONFIG Memory; +// uint32_t ChipProtection; +// uint32_t ManufacturerCode; +// uint32_t DeviceCode; +//}; + +// ///////////////////////////////////////////////////////// +// // Description: +// // This structure defines an interface for block devices +// // +// // Remarks: +// // It is possible a given system might have more than one +// // storage device type. This interface abstracts the +// // hardware sepcifics from the rest of the system. +// // +// // All of the functions take at least one void* parameter +// // that normally points to a driver specific data structure +// // containing hardware specific settings to use. This +// // allows a single driver to support multiple instances of +// // the same type of storage device in the system. +// // +// // The sector read and write functions provide a parameter +// // for Sector Metadata. The metadata is used for flash arrays +// // without special controllers to manage wear leveling etc... +// // (mostly for directly attached NOR and NAND). The metadata +// // is used by upper layers for wear leveling to ensure that +// // data is moved around on the flash when writing to prevent +// // failure of the device from too many erase cycles on a sector. +// // +// // TODO: +// // Define standard method of notification that media is +// // removed for all removeable media. This will likely +// // be a continuation so that the FS Manager can mount +// // an FS and then notify the managed app of the new FS. +// // +// struct IBlockStorageDevice +// { +// ///////////////////////////////////////////////////////// +// // Description: +// // Initializes a given block device for use +// // +// // Input: +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // No other functions in this interface may be called +// // until after Init returns. +// // +// bool (*InitializeDevice)(void*); + +// ///////////////////////////////////////////////////////// +// // Description: +// // Initializes a given block device for use +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // De initializes the device when no longer needed +// // +// bool (*UninitializeDevice)(void*); + +// ///////////////////////////////////////////////////////// +// // Description: +// // Gets the information describing the device +// // +// const DeviceBlockInfo* (*GetDeviceInfo)(void*); + +// ///////////////////////////////////////////////////////// +// // Description: +// // Reads data from a set of sectors +// // +// // Input: +// // StartSector - Starting Sector for the read +// // NumSectors - Number of sectors to read +// // pSectorBuff - pointer to buffer to read the data into. +// // Must be large enough to hold all of the data +// // being read. +// // +// // pSectorMetadata - pointer to an array of structured (one for each sector) +// // for the extra sector information. +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // This function reads the number of sectors specified from the device. +// // +// // pSectorBuff may be NULL. This is to allow for reading just the metadata. +// // +// // pSectorMetadata can be set to NULL if the caller does not need the extra +// // data. +// // +// // If the device does not support sector Metadata it should fail if the +// // pSectorMetadata parameter is not NULL. +// // +// bool (*Read)(void*, ByteAddress StartSector, uint32_t NumBytes, unsigned char* pSectorBuff); + +// ///////////////////////////////////////////////////////// +// // Description: +// // Writes data to a set of sectors +// // +// // Input: +// // StartSector - Starting Sector for the write +// // NumSectors - Number of sectors to write +// // pSectorBuff - pointer to data to write. +// // Must be large enough to hold complete sectors +// // for the number of sectors being written. +// // +// // pSectorMetadata - pointer to an array of structures (one for each sector) +// // for the extra sector information. +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // This function reads the number of sectors specified from the device. +// // The SectorMetadata is used for flash arrays without special controllers +// // to manage wear leveling etc... (mostly for NOR and NAND). The metadata +// // is used by upper layers to ensure that data is moved around on the flash +// // when writing to prevent failure of the device from too many erase cycles +// // on a sector. +// // +// // If the device does not support sector Metadata it should fail if the +// // pSectorMetadata parameter is not NULL. +// // +// // pSectorMetadata can be set to NULL if the caller does not need the extra +// // data. Implementations must not attempt to write data through a NULL pointer! +// // +// bool (*Write)(void*, ByteAddress Address, uint32_t NumBytes, unsigned char* pSectorBuf, bool ReadModifyWrite); + +// bool (*Memset)(void*, ByteAddress Address, unsigned char Data, uint32_t NumBytes); + +// bool (*GetSectorMetadata)(void*, ByteAddress SectorStart, SectorMetadata* pSectorMetadata); + +// bool (*SetSectorMetadata)(void*, ByteAddress SectorStart, SectorMetadata* pSectorMetadata); + +// ///////////////////////////////////////////////////////// +// // Description: +// // Check a block is erased or not. +// // +// // Input: +// // BlockStartAddress - Logical Sector Address +// // +// // Returns: +// // true if it is erassed, otherwise false +// // +// // Remarks: +// // Check the block containing the sector address specified. +// // +// bool (*IsBlockErased)(void*, ByteAddress BlockStartAddress, uint32_t BlockLength); + +// ///////////////////////////////////////////////////////// +// // Description: +// // Erases a block +// // +// // Input: +// // Address - Logical Sector Address +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // Erases the block containing the sector address specified. +// // +// bool (*EraseBlock)(void*, ByteAddress Address); + +// ///////////////////////////////////////////////////////// +// // Description: +// // Changes the power state of the device +// // +// // Input: +// // State - true= power on; false = power off +// // +// // Remarks: +// // This function allows systems to conserve power by +// // shutting down the hardware when the system is +// // going into low power states. +// // +// void (*SetPowerState)(void*, uint32_t State); + +// uint32_t (*MaxSectorWrite_uSec)(void*); + +// uint32_t (*MaxBlockErase_uSec)(void*); +// }; + + +// //////////////////////////////////////////////// +// // Description: +// // Binding context for a driver and the physical device +// // +// // Remarks: +// // The design pattern here effectively mimics a C++ class +// // with virtuals. The reason virtuals are not used is that +// // the .NET MF supports a wide variety of compiler/Linker +// // tool chains and some of them bring in a large Run-time +// // library footprint when Certain C++ language features are +// // used. Since a major goal of the .NET MF is to reduce +// // code footprint we avoid anything that brings in additional +// // library code. +// // + +// struct BlockStorageDevice : public HAL_DblLinkedNode +// { + +// public: + +// ///////////////////////////////////////////////////////// +// // Description: +// // Initializes a given block device for use +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // No other functions in this interface may be called +// // until after Init returns. +// // +// bool InitializeDevice() { return this->m_BSD->InitializeDevice( this->m_context ); } + +// ///////////////////////////////////////////////////////// +// // Description: +// // Initializes a given block device for use +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // De initializes the device when no longer needed +// // +// bool UninitializeDevice() { return this->m_BSD->UninitializeDevice( this->m_context ); } + +// ///////////////////////////////////////////////////////// +// // Description: +// // Gets the information describing the device +// // +// const DeviceBlockInfo* GetDeviceInfo() { return this->m_BSD->GetDeviceInfo( this->m_context ); } + +// ///////////////////////////////////////////////////////// +// // Description: +// // Reads data from a set of sectors +// // +// // Input: +// // StartSector - Starting Sector for the read +// // NumSectors - Number of sectors to read +// // pSectorBuff - pointer to buffer to read the data into. +// // Must be large enough to hold all of the data +// // being read. +// // +// // pSectorMetadata - pointer to an array of structured (one for each sector) +// // for the extra sector information. +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // This function reads the number of sectors specified from the device. +// // +// // pSectorBuff may be NULL. This is to allow for reading just the metadata. +// // +// // pSectorMetadata can be set to NULL if the caller does not need the extra +// // data. +// // +// // If the device does not support sector Metadata it should fail if the +// // pSectorMetadata parameter is not NULL. +// // +// bool Read(ByteAddress Address, uint32_t NumBytes, unsigned char* pSectorBuff) +// { +// return this->m_BSD->Read(this->m_context, Address, NumBytes, pSectorBuff); +// } + +// ///////////////////////////////////////////////////////// +// // Description: +// // Writes data to a set of sectors +// // +// // Input: +// // StartSector - Starting Sector for the write +// // NumSectors - Number of sectors to write +// // pSectorBuff - pointer to data to write. +// // Must be large enough to hold complete sectors +// // for the number of sectors being written. +// // +// // pSectorMetadata - pointer to an array of structures (one for each sector) +// // for the extra sector information. +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // This function reads the number of sectors specified from the device. +// // The SectorMetadata is used for flash arrays without special controllers +// // to manage wear leveling etc... (mostly for NOR and NAND). The metadata +// // is used by upper layers to ensure that data is moved around on the flash +// // when writing to prevent failure of the device from too many erase cycles +// // on a sector. +// // +// // If the device does not support sector Metadata it should fail if the +// // pSectorMetadata parameter is not NULL. +// // +// // pSectorMetadata can be set to NULL if the caller does not need the extra +// // data. Implementations must not attempt to write data through a NULL pointer! +// // +// bool Write(ByteAddress Address, uint32_t NumBytes, unsigned char* pSectorBuf, bool ReadModifyWrite) +// { +// return this->m_BSD->Write(this->m_context, Address, NumBytes, pSectorBuf, ReadModifyWrite); +// } + +// bool Memset(ByteAddress Address, unsigned char Data, uint32_t NumBytes) +// { +// return this->m_BSD->Memset(this->m_context, Address, Data, NumBytes); +// } + +// bool GetSectorMetadata(ByteAddress SectorStart, SectorMetadata* pSectorMetadata) +// { +// return this->m_BSD->GetSectorMetadata(this->m_context, SectorStart, pSectorMetadata); +// } + +// bool SetSectorMetadata(ByteAddress SectorStart, SectorMetadata* pSectorMetadata) +// { +// return this->m_BSD->SetSectorMetadata(this->m_context, SectorStart, pSectorMetadata); +// } + +// ///////////////////////////////////////////////////////// +// // Description: +// // Check a block is erased or not +// // +// // Input: +// // Address - Logical Sector Address +// // +// // Returns: +// // true it is erased; false if not +// // +// // Remarks: +// // check the block containing the sector address specified. +// // +// bool IsBlockErased(ByteAddress BlockStartAddress, uint32_t BlockLength) { return this->m_BSD->IsBlockErased(this->m_context, BlockStartAddress, BlockLength); } + + +// ///////////////////////////////////////////////////////// +// // Description: +// // Erases a block +// // +// // Input: +// // Address - Logical Sector Address +// // +// // Returns: +// // true if succesful; false if not +// // +// // Remarks: +// // Erases the block containing the sector address specified. +// // +// bool EraseBlock(ByteAddress Address) const { return this->m_BSD->EraseBlock(this->m_context, Address); } + + +// ///////////////////////////////////////////////////////// +// // Description: +// // Changes the power state of the device +// // +// // Input: +// // State - true= power on; false = power off +// // +// // Remarks: +// // This function allows systems to conserve power by +// // shutting down the hardware when the system is +// // going into low power states. +// // +// void SetPowerState( uint32_t State ) { this->m_BSD->SetPowerState(this->m_context, State); } + +// bool FindRegionFromAddress(ByteAddress Address, uint32_t &BlockRegionIndex, uint32_t &BlockRangeIndex ) +// { +// const DeviceBlockInfo* pDevInfo = GetDeviceInfo(); + +// return pDevInfo->FindRegionFromAddress( Address, BlockRegionIndex, BlockRangeIndex ); +// } + +// bool FindForBlockUsage(uint32_t blockUsage, ByteAddress &Address, uint32_t &BlockRegionIndex, uint32_t &BlockRangeIndex ) +// { +// const DeviceBlockInfo* pDevInfo = GetDeviceInfo(); + +// return pDevInfo->FindForBlockUsage( blockUsage, Address, BlockRegionIndex, BlockRangeIndex ); +// } + +// bool FindNextUsageBlock(uint32_t blockUsage, ByteAddress &Address, uint32_t &BlockRegionIndex, uint32_t &BlockRangeIndex ) +// { +// const DeviceBlockInfo* pDevInfo = GetDeviceInfo(); + +// return pDevInfo->FindNextUsageBlock( blockUsage, Address, BlockRegionIndex, BlockRangeIndex ); +// } + + +// uint32_t MaxSectorWrite_uSec() +// { +// return this->m_BSD->MaxSectorWrite_uSec(this->m_context); +// } + +// uint32_t MaxBlockErase_uSec() +// { +// return this->m_BSD->MaxBlockErase_uSec(this->m_context); +// } + +// IBlockStorageDevice* m_BSD; // Vtable for this device +// void* m_context; // configuration for this instance of this driver + +// }; + +// -- global List + +// struct BlockStorageList +// { +// // initailize the storage +// __nfweak static void Initialize(); + +// // walk through list of devices and calls Init() function +// __nfweak static bool InitializeDevices(); + +// // walk through list of devices and calls UnInit() function +// __nfweak static bool UnInitializeDevices(); + +// // add pBSD to the list +// // If Init=true, the Init() will be called. +// __nfweak static bool AddDevice( BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, bool Init); + +// // remove pBSD from the list +// // Uninit = true, UnInit() will be called. +// __nfweak static bool RemoveDevice( BlockStorageDevice* pBSD, bool UnInit); + +// // Find the right Device with the corresponding phyiscal address. +// // +// __nfweak static bool FindDeviceForPhysicalAddress( BlockStorageDevice** pBSD, uint32_t PhysicalAddress, ByteAddress &BlockAddress); + +// __nfweak static BlockStorageDevice* GetFirstDevice(); + +// __nfweak static BlockStorageDevice* GetNextDevice( BlockStorageDevice& device ); + +// // returns number of devices has been declared in the system +// __nfweak static uint32_t GetNumDevices(); + +// // pointer to the BlockStorageDevice which is the primary device with CONFIG block +// static BlockStorageDevice* s_primaryDevice; + +// private: +// // global pointer of all the storage devices +// static HAL_DblLinkedList s_deviceList; + +// static bool s_Initialized; +// }; + +//////////////////////////////////////////////////////////////////////////////// + +// functions to included all the devices to be added in the system +void BlockStorage_AddDevices(); + +/////////////////////////////////////////////////////////////////////////////// + +#define FLASH_PROTECTION_KEY 0x1055AADD + + + +#define FLASH_BEGIN_PROGRAMMING_FAST() { GLOBAL_LOCK(FlashIrq) +#define FLASH_BEGIN_PROGRAMMING(x) { uint32_t FlashOperationStatus = Flash_StartOperation( x ) +#define FLASH_END_PROGRAMMING(banner,address) Flash_EndOperation( FlashOperationStatus ); } +#define FLASH_END_PROGRAMMING_FAST(banner,address) } + + +//--// + +#endif // _TARGET_PAL_BLOCKSTORAGE_H_ + diff --git a/source/native/nf-interpreter/targets/os/win32/Include/Target_Windows_Storage.h b/source/native/nf-interpreter/targets/os/win32/Include/Target_Windows_Storage.h new file mode 100644 index 00000000..888c34fe --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/Include/Target_Windows_Storage.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_WINDOWS_STORAGE_H_ +#define _TARGET_WINDOWS_STORAGE_H_ 1 + +#endif //_TARGET_WINDOWS_STORAGE_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/Include/targetHAL.h b/source/native/nf-interpreter/targets/os/win32/Include/targetHAL.h new file mode 100644 index 00000000..287b1d37 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/Include/targetHAL.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_HAL_H_ +#define _TARGET_HAL_H_ + +// #include + +#if defined(_WIN32) +#define NANOCLR_STOP() ::DebugBreak() +#pragma warning( error : 4706 ) // error C4706: assignment within conditional expression +#endif + +#if !defined(BUILD_RTM) + +inline void __cdecl HARD_Breakpoint() +{ + if(::IsDebuggerPresent()) + { + ::DebugBreak(); + } +} + +#define HARD_BREAKPOINT() HARD_Breakpoint() + +inline bool Target_ConfigUpdateRequiresErase() +{ + return true; +} + +// #if defined(_DEBUG) +// #define DEBUG_HARD_BREAKPOINT() HARD_Breakpoint() +// #else +// #define DEBUG_HARD_BREAKPOINT() +// #endif + +// #else + +// #define HARD_BREAKPOINT() +// #define DEBUG_HARD_BREAKPOINT() + +#endif // !defined(BUILD_RTM) + + +inline bool Target_HasNanoBooter() { return false; }; + +inline uint32_t GetPlatformCapabilities() +{ + return 0; +}; + +inline uint32_t GetTargetCapabilities() +{ + return 0; +}; + +#endif //_TARGET_HAL_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Power.h b/source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Power.h new file mode 100644 index 00000000..30060ef3 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Power.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TARGET_HAL_POWER_H_ +#define _TARGET_HAL_POWER_H_ 1 + +inline void CPU_Reset(){ ::ExitProcess( 0 ); }; +inline bool CPU_IsSoftRebootSupported() { return true; }; + +#endif //_TARGET_HAL_POWER_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Time.h b/source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Time.h new file mode 100644 index 00000000..0c580877 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/Include/targetHAL_Time.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TARGET_HAL_TIME_H_ +#define _TARGET_HAL_TIME_H_ 1 + + +#define HAL_Time_CurrentSysTicks HAL_Time_CurrentSysTicks +unsigned int HAL_Time_CurrentSysTicks(); + + + + + + +///// +///// Converts 64bit time value to SystemTime structure. 64bit time is assumed as an offset from 1/1/1601:00:00:00.000 in 100ns. +///// +///// True if conversion is successful. +//bool Time_ToSystemTime(TIME time, SYSTEMTIME* systemTime); +// +///// +///// Converts SystemTime structure to 64bit time, which is assumed as an offset from 1/1/1601:00:00:00.000 in 100ns. +///// +///// Time value. +//TIME Time_FromSystemTime(const SYSTEMTIME* systemTime); +// +///// +///// Retrieves time since device was booted. +///// +///// Time in 100ns. +//signed __int64 HAL_Time_GetMachineTime(); +// +///// +///// Offset from GMT. +///// +///// In minutes, for example Pacific Time would be GMT-8 = -480. +//signed int Time_GetTimeZoneOffset(); +// +///// +///// UTC time according to this system. +///// +///// Returns current UTC time in 100ns elapsed since 1/1/1601:00:00:00.000 UTC. +//signed __int64 Time_GetUtcTime(); +// +///// +///// Local time according to the Time subsystem. +///// +///// Local time in 100ns elapsed since 1/1/1601:00:00:00.000 local time. +//signed __int64 Time_GetLocalTime(); +// +///// +///// Retrieves number of days since the beginning of the year given a month and a year. Calculates for leap years. +///// +///// S_OK if successful. +//HRESULT Time_AccDaysInMonth(signed int year, signed int month, signed int* days); +// +///// +///// Retrieves number of days given a month and a year. Calculates for leap years. +///// +///// S_OK if successful. +//HRESULT Time_DaysInMonth(signed int year, signed int month, signed int* days); +// +///// APIs to convert between types +//bool Time_TimeSpanToStringEx( const signed __int64& ticks, char*& buf, size_t& len ); +//const char* Time_TimeSpanToString( const signed __int64& ticks ); +//bool Time_DateTimeToStringEx( const signed __int64& time, char*& buf, size_t& len ); +//const char* Time_DateTimeToString( const signed __int64& time); +//const char* Time_CurrentDateTimeToString(); + + +#endif //_TARGET_HAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/Include/targetPAL_time.h b/source/native/nf-interpreter/targets/os/win32/Include/targetPAL_time.h new file mode 100644 index 00000000..5e999482 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/Include/targetPAL_time.h @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGET_PAL_TIME_H_ +#define _TARGET_PAL_TIME_H_ 1 + +#endif //_TARGET_PAL_TIME_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/Include/target_BlockStorage.h b/source/native/nf-interpreter/targets/os/win32/Include/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/Include/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR.sln b/source/native/nf-interpreter/targets/os/win32/nanoCLR.sln new file mode 100644 index 00000000..89b08188 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR.sln @@ -0,0 +1,319 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2027 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nanoCLR", "nanoCLR\nanoCLR.vcxproj", "{B5515C8A-B056-4320-8EA4-8CACE21A7D2E}" + ProjectSection(ProjectDependencies) = postProject + {247F9798-E240-4D5B-956D-35E5EAD21CE2} = {247F9798-E240-4D5B-956D-35E5EAD21CE2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\..\src\CLR\Core\Core.vcxproj", "{89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CorLib", "..\..\..\src\CLR\CorLib\CorLib.vcxproj", "{58E950CC-2FF6-423C-B006-A70A19272F20}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Diagnostics", "..\..\..\src\CLR\Diagnostics\Diagnostics.vcxproj", "{A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Startup", "..\..\..\src\CLR\Startup\StartUp.vcxproj", "{2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Messaging", "..\..\..\src\CLR\Messaging\Messaging.vcxproj", "{131001E3-0201-451F-A87B-951D1C5C3EEE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Debugger", "..\..\..\src\CLR\Debugger\Debugger.vcxproj", "{DD397EC4-844B-4B59-A67B-CAD6B46F1F00}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WireProtocol", "..\..\..\src\CLR\WireProtocol\WireProtocol.vcxproj", "{2337C4A4-3AB4-4014-9C29-9EBE32F4510E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hardware", "..\..\..\src\CLR\Core\Hardware\Hardware.vcxproj", "{5D50772E-DAC8-407D-972F-37DEB4450B72}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InterruptHandler", "..\..\..\src\CLR\Core\InterruptHandler\InterruptHandler.vcxproj", "{D32EE397-7E49-452D-AC95-AFCB3C962E3D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPC", "..\..\..\src\CLR\Core\RPC\RPC.vcxproj", "{ED4C887A-EC09-465B-B5D9-075450ADC52D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Serialization", "..\..\..\src\CLR\Core\Serialization\Serialization.vcxproj", "{16BF6131-A3B8-4B97-B867-E45669FB48BD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Features", "Features", "{76169580-0DE3-48D0-9545-8FC438C54094}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stubs", "Stubs", "{2662E293-2538-40C2-9472-D936B1220EC2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Debugger_stub", "..\..\..\src\CLR\Debugger\Debugger_stub.vcxproj", "{6DABCBF1-245A-4E76-BD36-8BC300C7DD82}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Diagnostics_stub", "..\..\..\src\CLR\Diagnostics\Diagnostics_stub.vcxproj", "{C97A9845-02DC-46E4-B219-BF5EA8FB28E3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InterruptHandler_stub", "..\..\..\src\CLR\Core\InterruptHandler\InterruptHandler_stub.vcxproj", "{5772D362-7277-49CF-9B49-42335A3154BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeEventDispatcher_stub", "..\..\..\src\CLR\Core\NativeEventDispatcher\NativeEventDispatcher_stub.vcxproj", "{5406EB0C-2243-47E1-9F21-F2D7CA277092}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Messaging_stub", "..\..\..\src\CLR\Messaging\Messaging_stub.vcxproj", "{8ACD05E8-42FB-4A49-9D8B-79239F0EED25}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPC_stub", "..\..\..\src\CLR\Core\RPC\RPC_stub.vcxproj", "{D0B2ADFE-3347-4D73-9364-9C36935D12F8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Serialization_stub", "..\..\..\src\CLR\Core\Serialization\Serialization_stub.vcxproj", "{C337041D-344D-49FE-AD99-B137E7FD0188}" +EndProject +Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "NF.TestApplication", "netnf\TestApplication\NF.TestApplication.nfproj", "{247F9798-E240-4D5B-956D-35E5EAD21CE2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A5089650-2C81-4C04-ABA9-AABCEBDA3AA4}" + ProjectSection(SolutionItems) = preProject + packages.config = packages.config + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hardware_stub", "..\..\..\src\CLR\Core\Hardware\Hardware_stub.vcxproj", "{31253D7F-147E-49A3-BC0D-E0ADE6CF040B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeEventDispatcher", "..\..\..\src\CLR\Core\NativeEventDispatcher\NativeEventDispatcher.vcxproj", "{6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x64.ActiveCfg = Debug|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x64.Build.0 = Debug|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x86.ActiveCfg = Debug|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x86.Build.0 = Debug|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|Any CPU.ActiveCfg = Release|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x64.ActiveCfg = Release|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x64.Build.0 = Release|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x86.ActiveCfg = Release|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x86.Build.0 = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.ActiveCfg = Debug|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.Build.0 = Debug|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.ActiveCfg = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.Build.0 = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|Any CPU.ActiveCfg = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.ActiveCfg = Release|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.Build.0 = Release|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.ActiveCfg = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.Build.0 = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.ActiveCfg = Debug|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.Build.0 = Debug|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.ActiveCfg = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.Build.0 = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|Any CPU.ActiveCfg = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.ActiveCfg = Release|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.Build.0 = Release|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.ActiveCfg = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.Build.0 = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.ActiveCfg = Debug|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.Build.0 = Debug|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.ActiveCfg = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.Build.0 = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|Any CPU.ActiveCfg = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.ActiveCfg = Release|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.Build.0 = Release|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.ActiveCfg = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.Build.0 = Release|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x64.ActiveCfg = Debug|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x64.Build.0 = Debug|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x86.ActiveCfg = Debug|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x86.Build.0 = Debug|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|Any CPU.ActiveCfg = Release|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x64.ActiveCfg = Release|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x64.Build.0 = Release|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x86.ActiveCfg = Release|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x86.Build.0 = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.ActiveCfg = Debug|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.Build.0 = Debug|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.ActiveCfg = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.Build.0 = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|Any CPU.ActiveCfg = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.ActiveCfg = Release|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.Build.0 = Release|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.ActiveCfg = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.Build.0 = Release|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x64.ActiveCfg = Debug|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x64.Build.0 = Debug|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x86.ActiveCfg = Debug|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x86.Build.0 = Debug|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|Any CPU.ActiveCfg = Release|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x64.ActiveCfg = Release|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x64.Build.0 = Release|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x86.ActiveCfg = Release|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x86.Build.0 = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.ActiveCfg = Debug|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.Build.0 = Debug|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.ActiveCfg = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.Build.0 = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|Any CPU.ActiveCfg = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.ActiveCfg = Release|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.Build.0 = Release|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.ActiveCfg = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.Build.0 = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.ActiveCfg = Debug|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.Build.0 = Debug|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.ActiveCfg = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.Build.0 = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|Any CPU.ActiveCfg = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.ActiveCfg = Release|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.Build.0 = Release|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.ActiveCfg = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.Build.0 = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.ActiveCfg = Debug|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.Build.0 = Debug|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.ActiveCfg = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.Build.0 = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|Any CPU.ActiveCfg = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.ActiveCfg = Release|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.Build.0 = Release|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.ActiveCfg = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.Build.0 = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.ActiveCfg = Debug|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.Build.0 = Debug|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.ActiveCfg = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.Build.0 = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|Any CPU.ActiveCfg = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.ActiveCfg = Release|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.Build.0 = Release|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.ActiveCfg = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.Build.0 = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.ActiveCfg = Debug|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.Build.0 = Debug|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.ActiveCfg = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.Build.0 = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|Any CPU.ActiveCfg = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.ActiveCfg = Release|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.Build.0 = Release|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.ActiveCfg = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.Build.0 = Release|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x64.ActiveCfg = Debug|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x64.Build.0 = Debug|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x86.ActiveCfg = Debug|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x86.Build.0 = Debug|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|Any CPU.ActiveCfg = Release|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x64.ActiveCfg = Release|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x64.Build.0 = Release|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x86.ActiveCfg = Release|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x86.Build.0 = Release|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x64.ActiveCfg = Debug|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x64.Build.0 = Debug|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x86.ActiveCfg = Debug|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x86.Build.0 = Debug|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|Any CPU.ActiveCfg = Release|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x64.ActiveCfg = Release|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x64.Build.0 = Release|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x86.ActiveCfg = Release|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x86.Build.0 = Release|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x64.ActiveCfg = Debug|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x64.Build.0 = Debug|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x86.ActiveCfg = Debug|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x86.Build.0 = Debug|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|Any CPU.ActiveCfg = Release|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x64.ActiveCfg = Release|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x64.Build.0 = Release|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x86.ActiveCfg = Release|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x86.Build.0 = Release|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x64.ActiveCfg = Debug|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x64.Build.0 = Debug|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x86.ActiveCfg = Debug|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x86.Build.0 = Debug|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|Any CPU.ActiveCfg = Release|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x64.ActiveCfg = Release|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x64.Build.0 = Release|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x86.ActiveCfg = Release|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x86.Build.0 = Release|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x64.ActiveCfg = Debug|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x64.Build.0 = Debug|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x86.ActiveCfg = Debug|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x86.Build.0 = Debug|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|Any CPU.ActiveCfg = Release|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x64.ActiveCfg = Release|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x64.Build.0 = Release|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x86.ActiveCfg = Release|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x86.Build.0 = Release|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x64.ActiveCfg = Debug|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x64.Build.0 = Debug|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x86.ActiveCfg = Debug|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x86.Build.0 = Debug|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|Any CPU.ActiveCfg = Release|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x64.ActiveCfg = Release|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x64.Build.0 = Release|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x86.ActiveCfg = Release|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x86.Build.0 = Release|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x64.ActiveCfg = Debug|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x64.Build.0 = Debug|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x86.ActiveCfg = Debug|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x86.Build.0 = Debug|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|Any CPU.ActiveCfg = Release|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x64.ActiveCfg = Release|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x64.Build.0 = Release|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x86.ActiveCfg = Release|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x86.Build.0 = Release|Win32 + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|x64.ActiveCfg = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|x64.Build.0 = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|x86.ActiveCfg = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|x86.Build.0 = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Release|Any CPU.Build.0 = Release|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Release|x64.ActiveCfg = Release|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Release|x64.Build.0 = Release|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Release|x86.ActiveCfg = Release|Any CPU + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x64.ActiveCfg = Debug|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x64.Build.0 = Debug|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x86.ActiveCfg = Debug|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x86.Build.0 = Debug|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|Any CPU.ActiveCfg = Release|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x64.ActiveCfg = Release|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x64.Build.0 = Release|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x86.ActiveCfg = Release|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x86.Build.0 = Release|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x64.ActiveCfg = Debug|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x64.Build.0 = Debug|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x86.ActiveCfg = Debug|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x86.Build.0 = Debug|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|Any CPU.ActiveCfg = Release|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x64.ActiveCfg = Release|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x64.Build.0 = Release|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x86.ActiveCfg = Release|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B} = {76169580-0DE3-48D0-9545-8FC438C54094} + {131001E3-0201-451F-A87B-951D1C5C3EEE} = {76169580-0DE3-48D0-9545-8FC438C54094} + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00} = {76169580-0DE3-48D0-9545-8FC438C54094} + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E} = {76169580-0DE3-48D0-9545-8FC438C54094} + {5D50772E-DAC8-407D-972F-37DEB4450B72} = {76169580-0DE3-48D0-9545-8FC438C54094} + {D32EE397-7E49-452D-AC95-AFCB3C962E3D} = {76169580-0DE3-48D0-9545-8FC438C54094} + {ED4C887A-EC09-465B-B5D9-075450ADC52D} = {76169580-0DE3-48D0-9545-8FC438C54094} + {16BF6131-A3B8-4B97-B867-E45669FB48BD} = {76169580-0DE3-48D0-9545-8FC438C54094} + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82} = {2662E293-2538-40C2-9472-D936B1220EC2} + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3} = {2662E293-2538-40C2-9472-D936B1220EC2} + {5772D362-7277-49CF-9B49-42335A3154BD} = {2662E293-2538-40C2-9472-D936B1220EC2} + {5406EB0C-2243-47E1-9F21-F2D7CA277092} = {2662E293-2538-40C2-9472-D936B1220EC2} + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25} = {2662E293-2538-40C2-9472-D936B1220EC2} + {D0B2ADFE-3347-4D73-9364-9C36935D12F8} = {2662E293-2538-40C2-9472-D936B1220EC2} + {C337041D-344D-49FE-AD99-B137E7FD0188} = {2662E293-2538-40C2-9472-D936B1220EC2} + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B} = {2662E293-2538-40C2-9472-D936B1220EC2} + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2} = {76169580-0DE3-48D0-9545-8FC438C54094} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {432A3A35-F7BC-47DA-B887-9F18A369A065} + EndGlobalSection +EndGlobal diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/CLRStartup.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/CLRStartup.cpp new file mode 100644 index 00000000..d4686e7e --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/CLRStartup.cpp @@ -0,0 +1,736 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +#if defined(_WIN32) + + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +struct Settings +#if defined(_WIN32) +: CLR_RT_ParseOptions +#endif +{ + CLR_SETTINGS m_clrOptions; +#if defined(_WIN32) + CLR_RT_ParseOptions::BufferMap m_assemblies; +#endif + bool m_fInitialized; + + //--// + + HRESULT Initialize(CLR_SETTINGS params) + { + NANOCLR_HEADER(); + + m_clrOptions = params; + +#if defined(PLATFORM_WINDOWS_EMULATOR) + g_CLR_RT_ExecutionEngine.m_fPerformGarbageCollection = params.PerformGarbageCollection; + g_CLR_RT_ExecutionEngine.m_fPerformHeapCompaction = params.PerformHeapCompaction; + + CLR_UINT32 clockFrequencyBaseline = 27000000; + CLR_UINT32 clockFrequency = CPU_SystemClock(); + double clockFrequencyRatio = 1; + + if(clockFrequency > 0) + { + clockFrequencyRatio = (double)clockFrequencyBaseline / (double)clockFrequency; + } + + g_HAL_Configuration_Windows.ProductType = HAL_Configuration_Windows::Product_Aux; + g_HAL_Configuration_Windows.SlowClockPerSecond = 32768; + g_HAL_Configuration_Windows.TicksPerMethodCall = (CLR_UINT64)(45.0*clockFrequencyRatio); + g_HAL_Configuration_Windows.TicksPerOpcode = (CLR_UINT64)( 5.0*clockFrequencyRatio); + g_HAL_Configuration_Windows.GraphHeapEnabled = false; +#endif + + NANOCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CreateInstance()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Created EE.\r\n" ); +#endif + +#if !defined(BUILD_RTM) + if(params.WaitForDebugger) + { +#if defined(_WIN32) + CLR_EE_DBG_SET( Enabled ); +#endif + CLR_EE_DBG_SET( Stopped ); + } +#endif + + NANOCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.StartHardware()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Started Hardware.\r\n" ); +#endif + + m_fInitialized = true; + + + NANOCLR_NOCLEANUP(); + } + + + HRESULT LoadAssembly( const CLR_RECORD_ASSEMBLY* header, CLR_RT_Assembly*& assm ) + { + NANOCLR_HEADER(); + + const CLR_RT_NativeAssemblyData *pNativeAssmData; + + NANOCLR_CHECK_HRESULT(CLR_RT_Assembly::CreateInstance( header, assm )); + + // Get handlers for native functions in assembly + pNativeAssmData = GetAssemblyNativeData( assm->m_szName ); + + // If pNativeAssmData not NULL- means this assembly has native calls and there is pointer to table with native calls. + if ( pNativeAssmData != NULL ) + { + // First verify that check sum in assembly object matches hardcoded check sum. + if ( assm->m_header->nativeMethodsChecksum != pNativeAssmData->m_checkSum ) + { + CLR_Debug::Printf("***********************************************************************\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* ERROR!!!! Firmware version does not match managed code version!!!! *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* Invalid native checksum: %s 0x%08X!=0x%08X *\r\n", + assm->m_szName, + assm->m_header->nativeMethodsChecksum, + pNativeAssmData->m_checkSum + ); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("***********************************************************************\r\n"); + + NANOCLR_SET_AND_LEAVE(CLR_E_ASSM_WRONG_CHECKSUM); + } + + // Assembly has valid pointer to table with native methods. Save it. + assm->m_nativeCode = (const CLR_RT_MethodHandler *)pNativeAssmData->m_pNativeMethods; + } + g_CLR_RT_TypeSystem.Link( assm ); + NANOCLR_NOCLEANUP(); + } + + + HRESULT Load() + { + NANOCLR_HEADER(); + + // clear flag (in case EE wasn't restarted) + CLR_EE_DBG_CLR(StateResolutionFailed); + +#if defined(_WIN32) + CLR_RT_StringVector vec; + + vec.push_back(L"-load"); +#if defined _DEBUG + vec.push_back(L"..\\netnf\\TestApplication\\bin\\Debug\\TestApplication.pe"); +#else + vec.push_back(L"..\\netnf\\TestApplication\\bin\\Release\\TestApplication.pe"); +#endif + + // grab mscorlib.pe from the packages folder (it has to be there because the NF.TestApplication has just build) + // ************************************************************************* // + // just need to update the path on the package folder as the version changes // + // ************************************************************************* // + vec.push_back(L"-load"); + vec.push_back(L"..\\packages\\nanoFramework.CoreLibrary.1.0.0-preview038\\lib\\mscorlib.pe"); + + // grab Windows.Devices.Gpio.pe from the packages folder (it has to be there because the NF.TestApplication has just build) + // ************************************************************************* // + // just need to update the path on the package folder as the version changes // + // ************************************************************************* // + vec.push_back(L"-load"); + vec.push_back(L"..\\packages\\nanoFramework.Windows.Devices.Gpio.1.0.0-preview164\\lib\\Windows.Devices.Gpio.pe"); + + // grab nanoFramework.Runtime.Events.pe from the packages folder (it has to be there because the NF.TestApplication has just build) + // ************************************************************************* // + // just need to update the path on the package folder as the version changes // + // ************************************************************************* // + vec.push_back(L"-load"); + vec.push_back(L"..\\packages\\nanoFramework.Runtime.Events.1.0.0-preview165\\lib\\nanoFramework.Runtime.Events.pe"); + + // grab Windows.Devices.Spi.pe from the packages folder (it has to be there because the NF.TestApplication has just build) + // ************************************************************************* // + // just need to update the path on the package folder as the version changes // + // ************************************************************************* // + vec.push_back(L"-load"); + vec.push_back(L"..\\packages\\nanoFramework.Windows.Devices.Spi.1.0.0-preview164\\lib\\Windows.Devices.Spi.pe"); + + + //vec.push_back(L"-load"); + //vec.push_back(L"C:\\Program Files (x86)\\Microsoft .NET Micro Framework\\v4.4\\Assemblies\\le\\Microsoft.SPOT.Native.pe"); + + //wchar_t* pContext = NULL; + //wchar_t* pch = wcstok_s(emulatorArgs, L" ", &pContext); // UNDONE: FIXME: wcstok_s(this->m_clrOptions.EmulatorArgs, L" ", &pContext); + + //while (pch != NULL) + //{ + // //printf ("%s\n",pch); + // vec.push_back(pch); + + // pch = wcstok_s(NULL, L" ", &pContext); + //} + + ProcessOptions(vec); + + for(CLR_RT_ParseOptions::BufferMapIter it = m_assemblies.begin(); it != m_assemblies.end(); it++) + { + CLR_RT_Assembly* assm; + const CLR_RT_Buffer* buffer = (const CLR_RT_Buffer*)it->second; + const CLR_RECORD_ASSEMBLY* header = (CLR_RECORD_ASSEMBLY*)&(*buffer)[0]; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + NANOCLR_CHECK_HRESULT( LoadAssembly( header, assm ) ); + } +#else + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Create TS.\r\n" ); +#endif + + NANOCLR_CHECK_HRESULT(LoadKnownAssemblies( nanoCLR_Dat_Start, nanoCLR_Dat_End )); + +#endif // defined(PLATFORM_WINDOWS_EMULATOR) + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Loading Deployment Assemblies.\r\n" ); +#endif + + LoadDeploymentAssemblies( BlockUsage_DEPLOYMENT ); + + //--// + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolving.\r\n" ); +#endif + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll()); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.PrepareForExecution()); + +#if defined(NANOCLR_PROFILE_HANDLER) + CLR_PROF_Handler::Calibrate(); +#endif + + NANOCLR_CLEANUP(); + +#if !defined(BUILD_RTM) + if(FAILED(hr)) + { + CLR_Debug::Printf( "Error: %08x\r\n", hr ); + + if(hr == CLR_E_TYPE_UNAVAILABLE) + { + // exception occurred during type resolution + CLR_EE_DBG_SET(StateResolutionFailed); + } + } +#endif + + NANOCLR_CLEANUP_END(); + } + + HRESULT CheckKnownAssembliesForNonXIP( char** start, char** end ) + { + //--// + NANOCLR_HEADER(); + + BlockStorageDevice *device; + ByteAddress datByteAddress; + unsigned int datSize = ROUNDTOMULTIPLE((unsigned int)(*end)- (unsigned int)(*start), CLR_UINT32); + + if (BlockStorageList_FindDeviceForPhysicalAddress( &device, (unsigned int)(*start), &datByteAddress ) && device != NULL) + { + const DeviceBlockInfo * deviceInfo= BlockStorageDevice_GetDeviceInfo(device); + + if (deviceInfo->Attribute & MediaAttribute_SupportsXIP) + { + unsigned char * datAssembliesBuffer = (unsigned char*)CLR_RT_Memory::Allocate_And_Erase( datSize, CLR_RT_HeapBlock ::HB_Unmovable ); CHECK_ALLOCATION(datAssembliesBuffer); + + if ( !BlockStorageDevice_Read(device, datByteAddress, datSize, datAssembliesBuffer )) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + *start = (char *)datAssembliesBuffer; + *end = (char *)((unsigned int) datAssembliesBuffer + (unsigned int)datSize); + + } + } + + // else data in RAM + NANOCLR_NOCLEANUP(); + } + + + HRESULT LoadKnownAssemblies( char* start, char* end ) + { + //--// + NANOCLR_HEADER(); + char *assStart = start; + char *assEnd = end; + const CLR_RECORD_ASSEMBLY* header; + + NANOCLR_CHECK_HRESULT(CheckKnownAssembliesForNonXIP( &assStart, &assEnd )); +#if !defined(BUILD_RTM) + CLR_Debug::Printf(" Loading start at %x, end %x\r\n", (unsigned int)assStart, (unsigned int)assEnd); +#endif + + g_buildCRC = SUPPORT_ComputeCRC( assStart, (unsigned int)assEnd -(unsigned int) assStart, 0 ); + + + header = (const CLR_RECORD_ASSEMBLY*)assStart; + + while((char*)header + sizeof(CLR_RECORD_ASSEMBLY) < assEnd && header->GoodAssembly()) + { + CLR_RT_Assembly* assm; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + NANOCLR_CHECK_HRESULT(LoadAssembly( header, assm )); + + header = (const CLR_RECORD_ASSEMBLY*)ROUNDTOMULTIPLE((size_t)header + header->TotalSize(), CLR_UINT32); + } + + NANOCLR_NOCLEANUP(); + } + + + HRESULT ContiguousBlockAssemblies( BlockStorageStream stream, bool isXIP ) + { + NANOCLR_HEADER(); + + const CLR_RECORD_ASSEMBLY* header; + unsigned char * assembliesBuffer ; + signed int headerInBytes = sizeof(CLR_RECORD_ASSEMBLY); + unsigned char * headerBuffer = NULL; + + if(!isXIP) + { + headerBuffer = (unsigned char*)CLR_RT_Memory::Allocate( headerInBytes, true ); CHECK_ALLOCATION(headerBuffer); + CLR_RT_Memory::ZeroFill( headerBuffer, headerInBytes ); + } + + while(TRUE) + { + if(!BlockStorageStream_Read(&stream, &headerBuffer, headerInBytes )) break; + + header = (const CLR_RECORD_ASSEMBLY*)headerBuffer; + + // check header first before read + if(!header->GoodHeader()) + { + break; + } + + unsigned int AssemblySizeInByte = ROUNDTOMULTIPLE(header->TotalSize(), CLR_UINT32); + + if(!isXIP) + { + // read the assemblies + assembliesBuffer = (unsigned char*)CLR_RT_Memory::Allocate_And_Erase( AssemblySizeInByte, CLR_RT_HeapBlock ::HB_Unmovable ); + + if (!assembliesBuffer) + { + // release the headerbuffer which has being used and leave + CLR_RT_Memory::Release( headerBuffer ); + + NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + } + + BlockStorageStream_Seek(&stream, -headerInBytes, BlockStorageStream_SeekCurrent); + + if(!BlockStorageStream_Read(&stream, &assembliesBuffer, AssemblySizeInByte )) break; + + header = (const CLR_RECORD_ASSEMBLY*)assembliesBuffer; + + if(!header->GoodAssembly()) + { + if(!isXIP) CLR_RT_Memory::Release( assembliesBuffer ); + break; + } + + // we have good Assembly + CLR_RT_Assembly* assm; + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Attaching deployed file.\r\n" ); +#endif + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + if (FAILED(LoadAssembly( header, assm ) )) + { + if(!isXIP) CLR_RT_Memory::Release( assembliesBuffer ); + break; + } + assm->m_flags |= CLR_RT_Assembly::Deployed; + } + if(!isXIP) CLR_RT_Memory::Release( headerBuffer ); + + NANOCLR_NOCLEANUP(); + } + + + HRESULT LoadDeploymentAssemblies( unsigned int memoryUsage ) + { + NANOCLR_HEADER(); + + BlockStorageStream stream; + const DeviceBlockInfo* deviceInfo; + + // find the block + if (!BlockStorageStream_Initialize(&stream, memoryUsage )) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "ERROR: Could not find device for DEPLOYMENT usage\r\n" ); +#endif + NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + do + { + deviceInfo = BlockStorageDevice_GetDeviceInfo(stream.Device); + + ContiguousBlockAssemblies( stream, (deviceInfo->Attribute & MediaAttribute_SupportsXIP)); + } + while(BlockStorageStream_NextStream(&stream)); + + NANOCLR_NOCLEANUP(); + } + + void Cleanup() + { + CLR_RT_ExecutionEngine::DeleteInstance(); + + memset( &g_CLR_RT_ExecutionEngine, 0, sizeof(g_CLR_RT_ExecutionEngine)); + memset( &g_CLR_RT_WellKnownTypes, 0, sizeof(g_CLR_RT_WellKnownTypes)); + memset( &g_CLR_RT_WellKnownMethods, 0, sizeof(g_CLR_RT_WellKnownMethods)); + memset( &g_CLR_RT_TypeSystem, 0, sizeof(g_CLR_RT_TypeSystem)); + memset( &g_CLR_RT_EventCache, 0, sizeof(g_CLR_RT_EventCache)); + memset( &g_CLR_RT_GarbageCollector, 0, sizeof(g_CLR_RT_GarbageCollector)); + memset( &g_CLR_HW_Hardware, 0, sizeof(g_CLR_HW_Hardware)); + + m_fInitialized = false; + } + + Settings() + { + m_fInitialized = false; +#if defined(_WIN32) + BuildOptions(); +#endif + } + +#if defined(_WIN32) + ~Settings() + { + for(CLR_RT_ParseOptions::BufferMapIter it = m_assemblies.begin(); it != m_assemblies.end(); it++) + { + delete it->second; + } + + m_assemblies.clear(); // CLR_RT_ParseOptions::BufferMap m_assemblies; + } + + struct Command_Call : CLR_RT_ParseOptions::Command + { + typedef HRESULT (Settings::*FPN)( CLR_RT_ParseOptions::ParameterList* params ); + + Settings& m_parent; + FPN m_call; + + Command_Call( Settings& parent, FPN call, const wchar_t* szName, const wchar_t* szDescription ) + : CLR_RT_ParseOptions::Command( szName, szDescription ), m_parent(parent), m_call(call) + { + } + + virtual HRESULT Execute() + { + return (m_parent.*m_call)( &m_params ); + } + }; + +#define PARAM_GENERIC(parm1Name,parm1Desc) param = new CLR_RT_ParseOptions::Parameter_Generic( parm1Name, parm1Desc ); cmd->m_params.push_back( param ) +#define OPTION_CALL(fpn,optName,optDesc) cmd = new Command_Call( *this, &Settings::fpn, optName, optDesc ); m_commands.push_back( cmd ) +#define PARAM_EXTRACT_STRING(lst,idx) ((CLR_RT_ParseOptions::Parameter_Generic*)(*lst)[idx])->m_data.c_str() + + void BuildOptions() + { + CLR_RT_ParseOptions::Command* cmd; + CLR_RT_ParseOptions::Parameter* param; + + OPTION_CALL( Cmd_Load, L"-load", L"Loads an assembly formatted for nanoCLR" ); + PARAM_GENERIC( L"", L"File to load" ); + + OPTION_CALL( Cmd_LoadDatabase, L"-loadDatabase", L"Loads a set of assemblies" ); + PARAM_GENERIC( L"", L"Image to load" ); + + OPTION_CALL( Cmd_Resolve, L"-resolve", L"Tries to resolve cross-assembly references" ); + } + + HRESULT CheckAssemblyFormat( CLR_RECORD_ASSEMBLY* header, const wchar_t* src ) + { + NANOCLR_HEADER(); + + if(header->GoodAssembly() == false) + { + wprintf( L"Invalid assembly format for '%s': ", src ); + for(int i=0; imarker); i++) + { + wprintf( L"%02x", header->marker[i] ); + } + wprintf( L"\n" ); + + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + NANOCLR_NOCLEANUP(); + } + + HRESULT Cmd_Load( CLR_RT_ParseOptions::ParameterList* params = NULL ) + { + NANOCLR_HEADER(); + + const wchar_t* szName = PARAM_EXTRACT_STRING( params, 0 ); + CLR_RT_Buffer* buffer = new CLR_RT_Buffer(); + CLR_RECORD_ASSEMBLY* header; + + NANOCLR_CHECK_HRESULT(CLR_RT_FileStore::LoadFile( szName, *buffer )); + + header = (CLR_RECORD_ASSEMBLY*)&(*buffer)[0]; NANOCLR_CHECK_HRESULT(CheckAssemblyFormat( header, szName )); + + m_assemblies[szName] = buffer; + + NANOCLR_CLEANUP(); + + if(FAILED(hr)) + { + delete buffer; + } + + NANOCLR_CLEANUP_END(); + } + + + HRESULT Cmd_LoadDatabase( CLR_RT_ParseOptions::ParameterList* params = NULL ) + { + NANOCLR_HEADER(); + + if(!m_fInitialized) + { + CLR_RT_ExecutionEngine::CreateInstance(); + } + + { + const wchar_t* szFile = PARAM_EXTRACT_STRING( params, 0 ); + CLR_RT_Buffer buffer; + CLR_RECORD_ASSEMBLY* header; + CLR_RECORD_ASSEMBLY* headerEnd; + std::wstring strName; + + NANOCLR_CHECK_HRESULT(CLR_RT_FileStore::LoadFile( szFile, buffer )); + + header = (CLR_RECORD_ASSEMBLY*)&buffer[0 ]; + headerEnd = (CLR_RECORD_ASSEMBLY*)&buffer[buffer.size()-1]; + + while(header + 1 <= headerEnd && header->GoodAssembly()) + { + CLR_RT_Buffer* bufferSub = new CLR_RT_Buffer(); + CLR_RECORD_ASSEMBLY* headerSub; + CLR_RT_Assembly* assm; + + bufferSub->resize( header->TotalSize() ); + + headerSub = (CLR_RECORD_ASSEMBLY*)&(*bufferSub)[0]; + + if((CLR_UINT8*)header + header->TotalSize() > (CLR_UINT8*)headerEnd) + { + //checksum passed, but not enough data in assembly + _ASSERTE(FALSE); + delete bufferSub; + break; + } + memcpy( headerSub, header, header->TotalSize() ); + + m_assemblies[strName] = bufferSub; + + if(FAILED(hr = CLR_RT_Assembly::CreateInstance( headerSub, assm ))) + { + delete bufferSub; + break; + } + + CLR_RT_UnicodeHelper::ConvertFromUTF8( assm->m_szName, strName ); m_assemblies[strName] = bufferSub; + + assm->DestroyInstance(); + + header = (CLR_RECORD_ASSEMBLY*)ROUNDTOMULTIPLE( (size_t)header + header->TotalSize(), CLR_UINT32 ); + } + } + + NANOCLR_CLEANUP(); + + if(!m_fInitialized) + { + CLR_RT_ExecutionEngine::DeleteInstance(); + } + + NANOCLR_CLEANUP_END(); + } + + HRESULT Cmd_Resolve( CLR_RT_ParseOptions::ParameterList* params = NULL ) + { + NANOCLR_HEADER(); + + bool fError = false; + + NANOCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + const CLR_RECORD_ASSEMBLYREF* src = (const CLR_RECORD_ASSEMBLYREF*)pASSM->GetTable( TBL_AssemblyRef ); + for(int i=0; im_pTablesSize[TBL_AssemblyRef]; i++, src++) + { + const char* szName = pASSM->GetString( src->name ); + + if(g_CLR_RT_TypeSystem.FindAssembly( szName, &src->version, true ) == NULL) + { + printf( "Missing assembly: %s (%d.%d.%d.%d)\n", szName, src->version.iMajorVersion, src->version.iMinorVersion, src->version.iBuildNumber, src->version.iRevisionNumber ); + + fError = true; + } + } + } + NANOCLR_FOREACH_ASSEMBLY_END(); + + if(fError) NANOCLR_SET_AND_LEAVE(CLR_E_ENTRY_NOT_FOUND); + + NANOCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll()); + + NANOCLR_NOCLEANUP(); + } +#endif //#if defined(_WIN32) + +}; + +static Settings s_ClrSettings; + +//--// + +#if defined(_WIN32) +HRESULT ClrLoadPE( const wchar_t* szPeFilePath ) +{ + CLR_RT_StringVector vec; + + vec.push_back(L"-load"); + + vec.push_back(szPeFilePath); + + return s_ClrSettings.ProcessOptions(vec); +} + +HRESULT ClrLoadDAT( const wchar_t* szDatFilePath ) +{ + CLR_RT_StringVector vec; + + vec.push_back(L"-loadDatabase"); + + vec.push_back(szDatFilePath); + + return s_ClrSettings.ProcessOptions(vec); +} +#endif + + +void ClrStartup( CLR_SETTINGS params ) +{ + NATIVE_PROFILE_CLR_STARTUP(); + //Settings settings; + ASSERT(sizeof(CLR_RT_HeapBlock_Raw) == sizeof(CLR_RT_HeapBlock)); + bool softReboot; + + do + { + softReboot = false; + + CLR_RT_Assembly::InitString(); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "\r\nnanoCLR (Build %d.%d.%d.%d)\r\n\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION ); +#endif + + CLR_RT_Memory::Reset (); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Starting...\r\n" ); +#endif + + HRESULT hr; + + if(SUCCEEDED(hr = s_ClrSettings.Initialize(params))) + { + if(SUCCEEDED(hr = s_ClrSettings.Load())) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Ready.\r\n" ); +#endif + +//#if defined(_WIN32) +// (void)g_CLR_RT_ExecutionEngine.Execute( params.EmulatorArgs, params.MaxContextSwitches ); +//#else + (void)g_CLR_RT_ExecutionEngine.Execute( NULL, params.MaxContextSwitches ); +//#endif + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Done.\r\n" ); +#endif + } + } + + // process setting of power mode, if reboot was requested along with a power mode "higher" then PowerLevel__Active + if(CLR_EE_REBOOT_IS( ClrOnly ) && g_CLR_HW_Hardware.m_powerLevel > PowerLevel__Active) + { + CPU_SetPowerMode(g_CLR_HW_Hardware.m_powerLevel); + } + + if( CLR_EE_DBG_IS_NOT( RebootPending )) + { +#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET_MASK(StateProgramExited, StateMask); + CLR_EE_DBG_EVENT_BROADCAST(CLR_DBG_Commands::c_Monitor_ProgramExit, 0, NULL,WP_Flags_c_NonCritical); +#endif //#if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(params.EnterDebuggerLoopAfterExit) + { + CLR_DBG_Debugger::Debugger_WaitForCommands(); + } + } + + // DO NOT USE 'ELSE IF' here because the state can change in Debugger_WaitForCommands() call + + if( CLR_EE_DBG_IS( RebootPending )) + { + if(CLR_EE_REBOOT_IS( ClrOnly )) + { + softReboot = true; + + params.WaitForDebugger = CLR_EE_REBOOT_IS(WaitForDebugger); + + s_ClrSettings.Cleanup(); + + //nanoHAL_Uninitialize(); + + //re-init the hal for the reboot (initially it is called in bootentry) + //nanoHAL_Initialize(); + } + else + { + CPU_Reset(); + } + } + } while( softReboot ); +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Events.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Events.cpp new file mode 100644 index 00000000..32da6a67 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Events.cpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//using namespace Microsoft::SPOT::Emulator; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//--// + +bool Events_Initialize() +{ + return TRUE; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Initialize(); +} + +bool Events_Uninitialize() +{ + return TRUE; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Uninitialize(); +} + +void Events_Set( uint32_t events ) +{ + // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Set( Events ); +} + +uint32_t Events_Get( uint32_t eventsOfInterest ) +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Get( EventsOfInterest ); +} + +void Events_Clear( uint32_t Events ) +{ + // UNDONE: FIXME: return EmulatorNative::GetIEventsDriver()->Clear( Events ); +} + +uint32_t Events_MaskedRead( uint32_t Events ) +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->MaskedRead( Events ); +} + +uint32_t Events_WaitForEvents( uint32_t powerLevel, uint32_t WakeupSystemEvents, uint32_t TimeoutMilliseconds ) +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->WaitForEvents( powerLevel, WakeupSystemEvents, TimeoutMilliseconds ); +} + +void Events_SetBoolTimer( bool* TimerCompleteFlag, uint32_t MillisecondsFromNow ) +{ + // UNDONE: FIXME: return EmulatorNative::GetIEventsDriver()->SetBoolTimer( (IntPtr)TimerCompleteFlag, MillisecondsFromNow ); +} + +void Events_SetCallback( set_Event_Callback pfn, void* arg ) +{ + _ASSERTE(FALSE); +} + +void FreeManagedEvent(UINT8 category, UINT8 subCategory, UINT16 data1, UINT32 data2) +{ + +} + + diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/FileStore_Win32.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/FileStore_Win32.cpp new file mode 100644 index 00000000..9dea424a --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/FileStore_Win32.cpp @@ -0,0 +1,237 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_FileStore::LoadFile( const wchar_t* szFile, CLR_RT_Buffer& vec ) +{ + NANOCLR_HEADER(); + + FILE* stream; + if(_wfopen_s(&stream, szFile, L"rb" ) != 0) + { + wprintf( L"Cannot open '%s'!\n", szFile ); + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + /*********/ fseek( stream, 0, SEEK_END ); + long size = ftell( stream ); + /*********/ fseek( stream, 0, SEEK_SET ); + + vec.resize( size ); + + if(vec.size() && fread( &vec[ 0 ], vec.size(), 1, stream ) != 1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + + NANOCLR_CLEANUP(); + + if(stream) + { + fclose( stream ); + } + + NANOCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_FileStore::SaveFile( const wchar_t* szFile, const CLR_RT_Buffer& vec ) +{ + NANOCLR_HEADER(); + + const CLR_UINT8* buf = NULL; + size_t size = vec.size(); + + if(size > 0) + { + buf = &vec[ 0 ]; + } + + NANOCLR_SET_AND_LEAVE(SaveFile( szFile, buf, size )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_FileStore::SaveFile( const wchar_t* szFile, const CLR_UINT8* buf, size_t size ) +{ + NANOCLR_HEADER(); + FILE* stream; + + if(_wfopen_s(&stream, szFile, L"wb" ) != 0) + { + wprintf( L"Cannot open '%s' for writing!\n", szFile ); + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + if(buf != NULL && size != 0) + { + if(fwrite( buf, size, 1, stream ) != 1) + { + NANOCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + NANOCLR_CLEANUP(); + + if(stream) + { + fclose( stream ); + } + + NANOCLR_CLEANUP_END(); +} + +//--// + +HRESULT CLR_RT_FileStore::ExtractTokensFromFile( const wchar_t* szFileName, std::vector< std::wstring >& vec, const wchar_t* separators, bool fNoComments ) +{ + NANOCLR_HEADER(); + + CLR_RT_Buffer buf; + + NANOCLR_CHECK_HRESULT(LoadFile( szFileName, buf )); + + ExtractTokens( buf, vec, separators, fNoComments ); + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_FileStore::ExtractTokens( const CLR_RT_Buffer& buf, CLR_RT_StringVector& vec, const wchar_t* separators, bool fNoComments ) +{ + std::wstring tmp; + char* szBufA = NULL; + wchar_t* szBufW = NULL; + const wchar_t* src; + size_t len; + + if (buf.size() == 0) { return; } + else if(buf.size() >= 2 && buf[ 0 ] == 0xFF && buf[ 1 ] == 0xFE) + { + len = (buf.size() - 2) / sizeof(wchar_t); + + src = (const wchar_t*)&buf[ 2 ]; + } + else + { + len = buf.size() / sizeof(char); + + szBufA = new char[ len+1 ]; memcpy( szBufA, &buf[ 0 ], len ); szBufA[ len ] = 0; + CLR_RT_UnicodeHelper::ConvertFromUTF8( szBufA, tmp ); + + src = tmp.c_str(); + len = tmp.size(); + } + + //--// + + szBufW = new wchar_t[ len+1 ]; memcpy( szBufW, src, len * sizeof(wchar_t) ); szBufW[ len ] = 0; + + vec.reserve( len / 60 ); + + ExtractTokensFromBuffer( szBufW, vec, separators, fNoComments ); + + //--// + + delete[] szBufW; + delete[] szBufA; +} + +void CLR_RT_FileStore::ExtractTokensFromBuffer( wchar_t* szLine, CLR_RT_StringVector& vec, const wchar_t* separators, bool fNoComments ) +{ + while(*szLine) + { + wchar_t* szNextLine = szLine; + + while(*szNextLine) + { + if(*szNextLine == '\r' || *szNextLine == '\n') + { + while(*szNextLine == '\r' || *szNextLine == '\n') + { + *szNextLine++ = 0; + } + + break; + } + + szNextLine++; + } + + if(fNoComments == false || szLine[ 0 ] != '#') + { + CLR_RT_FileStore::ExtractTokensFromString( szLine, vec, separators ); + } + + szLine = szNextLine; + } +} + +void CLR_RT_FileStore::ExtractTokensFromString( const wchar_t* szLine, CLR_RT_StringVector& vec, const wchar_t* separators ) +{ + if(separators) + { + while(szLine[ 0 ] && wcschr( separators, szLine[0] )) szLine++; + + while(szLine[ 0 ]) + { + wchar_t token [ 2048 ]; + wchar_t tokenExpanded[ 2048 ]; + bool fQuote = false; + size_t pos; + + for(pos=0; pos +#include +#include + +#define NATIVE_PROFILE_PAL_COM() + +////////////////////////////////////////////////////////////////////////////////// + +__nfweak bool DebuggerPort_Initialize( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool DebuggerPort_Uninitialize( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak int DebuggerPort_Write( COM_HANDLE ComPortNum, const char* Data, size_t size ) +{ + NATIVE_PROFILE_PAL_COM(); + return DebuggerPort_Write( ComPortNum, Data, size, COM_MAX_RETRIES ); +} + +__nfweak int DebuggerPort_Write( COM_HANDLE ComPortNum, const char* Data, size_t size, int maxRetries ) +{ + NATIVE_PROFILE_PAL_COM(); + return 0; +} + + +__nfweak int DebuggerPort_Read( COM_HANDLE ComPortNum, char* Data, size_t size ) +{ + NATIVE_PROFILE_PAL_COM(); + return 0; +} + +__nfweak bool DebuggerPort_Flush( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +__nfweak bool DebuggerPort_IsSslSupported( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +__nfweak bool DebuggerPort_UpgradeToSsl( COM_HANDLE ComPortNum, unsigned int flags ) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +__nfweak bool DebuggerPort_IsUsingSsl( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +////////////////////////////////////////////////////////////////////////////////// + +void CPU_InitializeCommunication() +{ + NATIVE_PROFILE_PAL_COM(); +} + +void CPU_UninitializeCommunication() +{ + NATIVE_PROFILE_PAL_COM(); +} + + +void CPU_ProtectCommunicationGPIOs( bool On ) +{ + NATIVE_PROFILE_PAL_COM(); +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp new file mode 100644 index 00000000..bf4258b0 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//--// + +//bool HAL_CONFIG_BLOCK::IsGoodBlock() const +//{ +// return TRUE; +//} +// +//bool HAL_CONFIG_BLOCK::IsGoodData() const +//{ +// return TRUE; +//} +// +//bool HAL_CONFIG_BLOCK::IsGood() const +//{ +// return TRUE; +//} +// +//const HAL_CONFIG_BLOCK* HAL_CONFIG_BLOCK::Next() const +//{ +// return NULL; +//} +// +//const void* HAL_CONFIG_BLOCK::Data() const +//{ +// return NULL; +//} +// +////--// +// +//bool HAL_CONFIG_BLOCK::Prepare( const char* Name, void* Data, unsigned int Size ) +//{ +// return TRUE; +//} +// +////--// +// +//const HAL_CONFIG_BLOCK* HAL_CONFIG_BLOCK::Find( const char* Name, bool fSkipCurrent, bool fAppend ) const +//{ +// return NULL; +//} +// +////--// +// +//bool HAL_CONFIG_BLOCK::GetConfigSectorAddress(HAL_CONFIG_BLOCK_STORAGE_DATA& blData) +//{ +// return FALSE; +//} +// +//bool HAL_CONFIG_BLOCK::CompactBlock(HAL_CONFIG_BLOCK_STORAGE_DATA& blData, const ConfigurationSector* cfgStatic, const HAL_CONFIG_BLOCK* cfgEnd) +//{ +// return FALSE; +//} +// +// +//bool HAL_CONFIG_BLOCK::UpdateBlock( const HAL_CONFIG_BLOCK_STORAGE_DATA &blData, const void* pAddress, const HAL_CONFIG_BLOCK *Header, void* Data, size_t Length, const void* LastConfigAddress, bool isChipRO ) +//{ +// return FALSE; +//} +// +//bool HAL_CONFIG_BLOCK::UpdateBlockWithName( const char* Name, void* Data, size_t Length, bool isChipRO ) +//{ +// return FALSE; +//} +// + +bool GetHalSystemInfo(HalSystemInfo& systemInfo) +{ + return FALSE; +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Target_BlockStorage.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Target_BlockStorage.cpp new file mode 100644 index 00000000..3d7d7349 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Target_BlockStorage.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +bool BlockStorageStream_Initialize(BlockStorageStream* stream, uint32_t blockUsage) +{ + return false; +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp new file mode 100644 index 00000000..3c5522ad --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//--// + +void Watchdog_Init(){} + +void Watchdog_Reset(){} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp new file mode 100644 index 00000000..d924b548 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp @@ -0,0 +1,151 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//--// + +//HAL_DblLinkedList BlockStorageList::s_deviceList; +//BlockStorageDevice* BlockStorageList::s_primaryDevice = NULL; +static BlockStorageDevice* s_primaryDevice = NULL; + +//--// + +//void BlockStorageList::Initialize() +//{ +//} +// +//bool BlockStorageList::InitializeDevices() +//{ +// return TRUE; +//} +// +//bool BlockStorageList::UnInitializeDevices() +//{ +// return TRUE; +//} +// +//bool BlockStorageList::AddDevice( BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, bool Init) +//{ +// return TRUE; +//} +bool BlockStorageList_AddDevice(BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, bool init) +{ + s_primaryDevice = pBSD; + + // TODO what to do with vtable and config?? + return true; +} +// +//bool BlockStorageList::RemoveDevice( BlockStorageDevice* pBSD, bool UnInit) +//{ +// return TRUE; +//} + +//BlockStorageDevice* BlockStorageList::GetFirstDevice() +//{ +// return NULL; +//} +BlockStorageDevice* BlockStorageList_GetFirstDevice() +{ + return s_primaryDevice; +} + +//BlockStorageDevice* BlockStorageList::GetNextDevice( BlockStorageDevice& device ) +//{ +// return NULL; +//} + +//unsigned int BlockStorageList::GetNumDevices() +//{ +// return 0; +//} + +//bool BlockStorageList::FindDeviceForPhysicalAddress( BlockStorageDevice** pBSD, unsigned int PhysicalAddress, ByteAddress &SectAddress) +//{ +// *pBSD = NULL; +// return FALSE; +//} +bool BlockStorageList_FindDeviceForPhysicalAddress(BlockStorageDevice** pBSD, unsigned int physicalAddress, ByteAddress* blockAddress) +{ + return false; +} + +//bool BlockStorageStream::Initialize(unsigned int blockUsage) +//{ +// return FALSE; +//} +// +//bool BlockStorageStream::Initialize(unsigned int usage, BlockStorageDevice* pDevice) +//{ +// return FALSE; +//} +// +// +//unsigned int BlockStorageStream::CurrentAddress() +//{ +// return 0xFFFFFFFF; +//} +// +//bool BlockStorageStream::PrevStream() +//{ +// return FALSE; +//} +// +//bool BlockStorageStream::NextStream() +//{ +// return FALSE; +//} +// +//bool BlockStorageStream::Seek( signed int offset, SeekOrigin origin ) +//{ +// return TRUE; +//} +// +//bool BlockStorageStream::Erase( unsigned int length ) +//{ +// return TRUE; +//} +// +//bool BlockStorageStream::Write( unsigned char* data , unsigned int length ) +//{ +// return TRUE; +//} +// +//bool BlockStorageStream::ReadIntoBuffer( unsigned char* pBuffer, unsigned int length ) +//{ +// return TRUE; +//} +// +//bool BlockStorageStream::Read( unsigned char** ppBuffer, unsigned int length ) +//{ +// return TRUE; +//} +// + +//--// + +//SectorAddress DeviceBlockInfo::PhysicalToSectorAddress( const BlockRegionInfo* pRegion, ByteAddress phyAddress ) const +//{ +// return phyAddress; +//} +// +//bool DeviceBlockInfo::FindRegionFromAddress(ByteAddress Address, unsigned int &BlockRegionIndex, unsigned int &BlockRangeIndex ) const +//{ +// return FALSE; +//} +// +//bool DeviceBlockInfo::FindNextUsageBlock(unsigned int BlockUsage, ByteAddress &Address, unsigned int &BlockRegionIndex, unsigned int &BlockRangeIndex ) const +//{ +// return FALSE; +//} +// +//bool DeviceBlockInfo::FindForBlockUsage(unsigned int BlockUsage, ByteAddress &Address, unsigned int &BlockRegionIndex, unsigned int &BlockRangeIndex ) const +//{ +// return FALSE; +//} + + +//--// diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/time_stubs.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/time_stubs.cpp new file mode 100644 index 00000000..db709752 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/PAL/time_stubs.cpp @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +HRESULT Time_Initialize() +{ + return CLR_E_NOTIMPL; +} + +HRESULT Time_Uninitialize() +{ + return CLR_E_NOTIMPL; +} + +// signed __int64 Time_GetUtcTime() +// { +// return 0; +// } + +signed __int64 Time_SetUtcTime( signed __int64 UtcTime, bool calibrate ) +{ + return 0; +} + +signed __int64 Time_GetLocalTime() +{ + return 0; +} + +signed int Time_GetTimeZoneOffset() +{ + return 0; +} + +signed int Time_SetTimeZoneOffset(signed int offset) +{ + return 0; +} + +signed __int64 Time_GetTickCount() +{ + return 0; +} + +bool HAL_Time_ToSystemTime(unsigned long long time, SYSTEMTIME* systemTime) +{ + return FALSE; +} + +uint64_t HAL_Time_ConvertFromSystemTime(const SYSTEMTIME* systemTime) +{ + return 0; +} + +HRESULT HAL_Time_DaysInMonth(signed int year, signed int month, signed int* days) +{ + return CLR_E_NOTIMPL; +} + +HRESULT HAL_Time_AccDaysInMonth(signed int year, signed int month, signed int* days) +{ + return CLR_E_NOTIMPL; +} + +bool Utility_SafeSprintfV( char*& szBuffer, size_t& iBuffer, const char* format, va_list arg ) +{ + return FALSE; +} + +bool Utility_SafeSprintf( char*& szBuffer, size_t& iBuffer, const char* format, ... ) +{ + return FALSE; +} + +bool HAL_Time_TimeSpanToStringEx( const signed __int64& ticks, char*& buf, size_t& len ) +{ + return FALSE; +} + +const char* HAL_Time_TimeSpanToString( const signed __int64& ticks ) +{ + return NULL; +} + +bool Time_DateTimeToStringEx( const signed __int64& time, char*& buf, size_t& len ) +{ + return FALSE; +} + +const char* Time_DateTimeToString( const signed __int64& time) +{ + return NULL; +} + +const char* HAL_Time_CurrentDateTimeToString() +{ + return NULL; +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/ParseOptions_Win32.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/ParseOptions_Win32.cpp new file mode 100644 index 00000000..a4e31d4d --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/ParseOptions_Win32.cpp @@ -0,0 +1,317 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_ParseOptions::Parameter::Parameter( const wchar_t* szName, const wchar_t* szDescription ) +{ + m_szName = szName; + m_szDescription = szDescription; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Generic::Parameter_Generic( const wchar_t* szName, const wchar_t* szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ +} + +bool CLR_RT_ParseOptions::Parameter_Generic::Parse( const wchar_t* arg ) +{ + m_data = arg; + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_String::Parameter_String( std::wstring* data, const wchar_t* szName, const wchar_t* szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_String::Parse( const wchar_t* arg ) +{ + *m_dataPtr = arg; + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Boolean::Parameter_Boolean( bool* data, const wchar_t* szName, const wchar_t* szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Boolean::Parse( const wchar_t* arg ) +{ + int num; + + if(!_wcsicmp( arg, L"true" ) || + !_wcsicmp( arg, L"on" ) ) + { + *m_dataPtr = true; + return true; + } + + if(!_wcsicmp( arg, L"false" ) || + !_wcsicmp( arg, L"off" ) ) + { + *m_dataPtr = false; + return true; + } + + if(swscanf_s( arg, L"%d", &num ) == 0) + { + wprintf( L"Expecting a boolean for parameter '%s': %s\n\n", m_szName, arg ); + return false; + } + + *m_dataPtr = (num != 0); + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Integer::Parameter_Integer( int* data, const wchar_t* szName, const wchar_t* szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Integer::Parse( const wchar_t* arg ) +{ + if(swscanf_s( arg, L"%d", m_dataPtr ) == 0) + { + wprintf( L"Expecting a number for parameter '%s': %s\n\n", m_szName, arg ); + return false; + } + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Float::Parameter_Float( float* data, const wchar_t* szName, const wchar_t* szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Float::Parse( const wchar_t* arg ) +{ + if(swscanf_s( arg, L"%f", m_dataPtr ) == 0) + { + wprintf( L"Expecting a number for parameter '%s': %s\n\n", m_szName, arg ); + return false; + } + + return true; +} + +//--// + +CLR_RT_ParseOptions::Command::Command( const wchar_t* szName, const wchar_t* szDescription ) +{ + m_szName = szName; + m_szDescription = szDescription; +} + +bool CLR_RT_ParseOptions::Command::Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options ) +{ + size_t argc = argv.size(); + + for(ParameterListIter it = m_params.begin(); it != m_params.end(); it++) + { + Parameter* param = *it; + + if(pos >= argc) + { + if(options.m_commands.size() > 1) + { + wprintf( L"Missing parameter for option '%s': %s\n\n", m_szName, param->m_szName ); + } + else + { + wprintf( L"Missing parameter for option '%s'\n\n", param->m_szName ); + } + + return false; + } + else + { + if(param->Parse( argv[ pos++ ].c_str() ) == false) + { + return false; + } + } + } + + return true; +} + +HRESULT CLR_RT_ParseOptions::Command::Execute() +{ + NANOCLR_HEADER(); + + NANOCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +CLR_RT_ParseOptions::Command_SetFlag::Command_SetFlag( bool* data, const wchar_t* szName, const wchar_t* szDescription ) : CLR_RT_ParseOptions::Command( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Command_SetFlag::Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options) +{ + *m_dataPtr = true; + return true; +} + +//--// + +CLR_RT_ParseOptions::CLR_RT_ParseOptions() +{ + m_fVerbose = false; +} + +HRESULT CLR_RT_ParseOptions::ExtractOptionsFromFile( const wchar_t* szFileName ) +{ + NANOCLR_HEADER(); + + CLR_RT_StringVector vec; + + NANOCLR_CHECK_HRESULT(CLR_RT_FileStore::ExtractTokensFromFile( szFileName, vec )); + + NANOCLR_CHECK_HRESULT(ProcessOptions( vec )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ParseOptions::ReprocessOptions() +{ + NANOCLR_HEADER(); + + if(CommandLineArgs.size() == 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + } + + NANOCLR_SET_AND_LEAVE(ProcessOptions( CommandLineArgs )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ParseOptions::ProcessOptions( CLR_RT_StringVector& argv ) +{ + NANOCLR_HEADER(); + + if(CommandLineArgs.size() == 0) + { + CommandLineArgs = CLR_RT_StringVector(argv); + } + + size_t argc = argv.size(); + + for(size_t i=0; im_szName )) + { + if(m_fVerbose) + { + size_t len = cmd->m_params.size(); + size_t pos = i; + + wprintf( L"Processing" ); + + wprintf( L" %s", arg ); + while(len-- > 0 && pos < argc) wprintf( L" %s", argv[ ++pos ].c_str() ); + wprintf( L"\n" ); + } + + i++; + + if(cmd->Parse( argv, i, *this ) == false) + { + Usage(); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + + NANOCLR_CHECK_HRESULT(cmd->Execute()); + break; + } + } + + if(it == m_commands.end()) + { + wprintf( L"Unknown option '%s'\n\n", arg ); + + Usage(); + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + + NANOCLR_NOCLEANUP(); +} + +void CLR_RT_ParseOptions::Usage() +{ + CommandListIter it; + ParameterListIter it2; + size_t maxCmdLen = 0; + + for(it = m_commands.begin(); it != m_commands.end(); it++) + { + Command* cmd = *it; + std::wstring option = cmd->m_szName; + size_t cmdLen = wcslen( cmd->m_szName ); + size_t maxLen = 0; + + wprintf( L" %s\n", cmd->m_szDescription ); + for(it2 = cmd->m_params.begin(); it2 != cmd->m_params.end(); it2++) + { + Parameter* param = *it2; + size_t len = wcslen( param->m_szName ); + + option += L" "; + option += param->m_szName; + + if(maxLen < len) maxLen = len; + } + + if(m_commands.size() > 1) + { + wprintf( L" %s\n", option.c_str()); + } + + for(it2 = cmd->m_params.begin(); it2 != cmd->m_params.end(); it2++) + { + Parameter* param = *it2; + + wprintf( L" %-*s = %s\n", maxLen, param->m_szName, param->m_szDescription ); + } + wprintf( L"\n" ); + } +} + +void CLR_RT_ParseOptions::PushArguments( int argc, wchar_t* argv[], CLR_RT_StringVector& vec ) +{ + for(int i=0; iDevice == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) return false; + + const BlockRegionInfo* pRegion; + const DeviceBlockInfo* pDevInfo;// UNDONE: FIXME: = stream->Device->GetDeviceInfo(); + + BlockStorageStream orig; + + memcpy(&orig, stream, sizeof(orig)); + + do + { + bool fLastIndex = false; + + if (stream->RangeIndex == 0) + { + if (stream->RegionIndex == 0) + { + stream->Device = BlockStorageDevice_Prev(stream->Device); + + if (stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + { + memcpy(stream, &orig, sizeof(orig)); + return false; + } + + // UNDONE: FIXME: pDevInfo = stream->Device->GetDeviceInfo(); + + stream->RegionIndex = pDevInfo->NumRegions - 1; + } + else + { + stream->RegionIndex--; + } + + fLastIndex = true; + } + else + { + stream->RangeIndex--; + } + + pRegion = &pDevInfo->Regions[stream->RegionIndex]; + + if (fLastIndex) + { + stream->RangeIndex = pRegion->NumBlockRanges - 1; + } + + } while (BlockRange_GetBlockUsage(pRegion->BlockRanges[stream->RangeIndex]) != stream->Usage); + + // if( pDevInfo->Attribute.SupportsXIP ) Flags |= c_BlockStorageStream__XIP; + // else Flags &= ~c_BlockStorageStream__XIP; + + stream->BlockLength = pRegion->BytesPerBlock; + stream->BaseAddress = pRegion->Start + pRegion->BlockRanges[stream->RangeIndex].StartBlock * stream->BlockLength; + stream->Length = BlockRange_GetBlockCount(pRegion->BlockRanges[stream->RangeIndex]) * stream->BlockLength; + stream->CurrentIndex = 0; + + return true; +} + +bool BlockStorageStream_PrevStream(BlockStorageStream* stream) +{ + if (stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) return false; + + const BlockRegionInfo* pRegion; + const DeviceBlockInfo* pDevInfo;// UNDONE: FIXME: = this->Device->GetDeviceInfo(); + + BlockStorageStream orig; + + memcpy(&orig, stream, sizeof(orig)); + + do + { + bool fLastIndex = false; + + if (stream->RangeIndex == 0) + { + if (stream->RegionIndex == 0) + { + stream->Device = BlockStorageDevice_Prev(stream->Device); + + if (stream->Device == NULL || BlockStorageDevice_Prev(stream->Device) == NULL) + { + memcpy(stream, &orig, sizeof(orig)); + return false; + } + + // UNDONE: FIXME: pDevInfo = this->Device->GetDeviceInfo(); + + stream->RegionIndex = pDevInfo->NumRegions - 1; + } + else + { + stream->RegionIndex--; + } + + fLastIndex = true; + } + else + { + stream->RangeIndex--; + } + + pRegion = &pDevInfo->Regions[stream->RegionIndex]; + + if (fLastIndex) + { + stream->RangeIndex = pRegion->NumBlockRanges - 1; + } + + } while (BlockRange_GetBlockUsage(pRegion->BlockRanges[stream->RangeIndex]) != stream->Usage); + + // if( pDevInfo->Attribute.SupportsXIP ) Flags |= c_BlockStorageStream__XIP; + // else Flags &= ~c_BlockStorageStream__XIP; + + stream->BlockLength = pRegion->BytesPerBlock; + stream->BaseAddress = pRegion->Start + pRegion->BlockRanges[stream->RangeIndex].StartBlock * stream->BlockLength; + stream->Length = BlockRange_GetBlockCount(pRegion->BlockRanges[stream->RangeIndex]) * stream->BlockLength; + stream->CurrentIndex = 0; + + return true; +} + +bool BlockStorageStream_Seek(BlockStorageStream *stream, unsigned int offset, SeekOrigin origin) +{ + unsigned int seekIndex; + + switch (origin) + { + case BlockStorageStream_SeekBegin: + seekIndex = 0; + break; + + case BlockStorageStream_SeekCurrent: + seekIndex = stream->CurrentIndex; + break; + + case BlockStorageStream_SeekEnd: + seekIndex = stream->Length; + break; + + default: + + return false; + } + + seekIndex += offset; + + while (seekIndex >= (int32_t)stream->Length) + { + // out of region address space + return false; + } + + while (seekIndex < 0) + { + // out of region address space + return false; + } + + stream->CurrentIndex = seekIndex; + + return true; +} + +__nfweak bool BlockStorageStream_Write(BlockStorageStream *stream, unsigned char *data, unsigned int length) +{ + return false; +} + +__nfweak bool BlockStorageStream_Erase(BlockStorageStream *stream, unsigned int length) +{ + return false; +} + +__nfweak bool BlockStorageStream_ReadIntoBuffer(BlockStorageStream *stream, unsigned char *buffer, unsigned int length) +{ + return false; +} + +bool BlockStorageStream_Read(BlockStorageStream* stream, unsigned char** buffer, unsigned int length) +{ + if (stream == NULL || !buffer) return false; + + unsigned char* pBuffer = *buffer; + bool fXIPFound = false; + + while (length > 0) + { + int readLen = length; + + if ((stream->CurrentIndex + readLen) > stream->Length) + { + readLen = stream->Length - stream->CurrentIndex; + } + + if (!fXIPFound) + { + *buffer = (unsigned char*)(BlockStorageStream_CurrentAddress(stream)); + + fXIPFound = true; + } + + length -= readLen; + pBuffer += readLen; + stream->CurrentIndex += readLen; + } + + return true; +} + +unsigned int BlockStorageStream_CurrentAddress(BlockStorageStream *stream) +{ + return stream->BaseAddress + stream->CurrentIndex; +} + +__nfweak bool BlockStorageStream_IsErased(BlockStorageStream *stream, unsigned int length) +{ + return false; +} + +///////////////////////////////////////////////////// +// BlockStorageDevice stubs + + +__nfweak BlockStorageDevice* BlockStorageDevice_Next(BlockStorageDevice* device) +{ + return NULL; +} + +__nfweak BlockStorageDevice* BlockStorageDevice_Prev(BlockStorageDevice* device) +{ + return NULL; +} + +__nfweak bool BlockStorageDevice_InitializeDevice(BlockStorageDevice* device) +{ + return false; +} + +__nfweak bool BlockStorageDevice_UninitializeDevice(BlockStorageDevice* device) +{ + return false; +} + +__nfweak DeviceBlockInfo* BlockStorageDevice_GetDeviceInfo(BlockStorageDevice* device) +{ + return NULL; +} + +__nfweak bool BlockStorageDevice_Read(BlockStorageDevice* device, unsigned int address, unsigned int numBytes, unsigned char* pSectorBuff) +{ + return false; +} + +__nfweak bool BlockStorageDevice_Write(BlockStorageDevice* device, unsigned int address, unsigned int numBytes, unsigned char* pSectorBuf, bool readModifyWrite) +{ + return false; +} + +__nfweak bool BlockStorageDevice_Memset(BlockStorageDevice* device, unsigned int address, unsigned char data, unsigned int NumBytes) +{ + return false; +} + +//__nfweak bool BlockStorageDevice_GetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, SectorMetadata* pSectorMetadata); +//__nfweak bool BlockStorageDevice_SetSectorMetadata(BlockStorageDevice* device, unsigned int sectorStart, SectorMetadata* pSectorMetadata); + +__nfweak bool BlockStorageDevice_IsBlockErased(BlockStorageDevice* device, unsigned int blockStartAddress, unsigned int blockLength) +{ + return false; +} + +__nfweak bool BlockStorageDevice_EraseBlock(BlockStorageDevice* device, unsigned int address) +{ + return false; +} + +__nfweak void BlockStorageDevice_SetPowerState(BlockStorageDevice* device, unsigned int state) +{ + return; +} + +__nfweak bool BlockStorageDevice_FindRegionFromAddress(BlockStorageDevice* device, unsigned int address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + return false; +} + +__nfweak bool BlockStorageDevice_FindForBlockUsage(BlockStorageDevice* device, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + return false; +} + +__nfweak bool BlockStorageDevice_FindNextUsageBlock(BlockStorageDevice* device, unsigned int blockUsage, unsigned int* address, unsigned int* blockRegionIndex, unsigned int* blockRangeIndex) +{ + return false; +} + +///////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Various.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Various.cpp new file mode 100644 index 00000000..d0dca907 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Various.cpp @@ -0,0 +1,617 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +#include "platform_selector.h" +//--// + +//using namespace System; +//using namespace System::Diagnostics; +//using namespace Microsoft::SPOT::Emulator; + +bool HAL_Windows_IsShutdownPending() +{ + return false; //return EmulatorNative::GetEmulatorNative()->IsShuttingDown(); +} + +void HAL_Windows_AcquireGlobalLock() +{ + // UNDONE: FIXME: EmulatorNative::GetEmulatorNative()->DisableInterrupts(); +} + +void HAL_Windows_ReleaseGlobalLock() +{ + // UNDONE: FIXME: EmulatorNative::GetEmulatorNative()->EnableInterrupts(); +} + +bool HAL_Windows_HasGlobalLock() +{ + return false; // UNDONE: FIXME: !EmulatorNative::GetEmulatorNative()->AreInterruptsEnabled(); +} + +uint64_t HAL_Windows_GetPerformanceTicks() +{ + return 0; // UNDONE: FIXME: return EmulatorNative::GetEmulatorNative()->GetCurrentTicks(); +} + +void HAL_Windows_Debug_Print( char* szText ) +{ + // UNDONE: FIXME: System::Diagnostics::Debug::Print( gcnew System::String(szText) ); +} + + +//HAL_Configuration_Windows g_HAL_Configuration_Windows; + +//unsigned int LOAD_IMAGE_CalcCRC; + +//OEM_MODEL_SKU OEM_Model_SKU = { 1, 2, 3 }; + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + //--// + + // unsigned int DebuggerPorts[MAX_DEBUGGERS]; + DEBUGGER_PORT, + + DEBUG_TEXT_PORT, + 921600, + 0, // STDIO = COM2 or COM1 + + { 0, 0 }, // { SRAM1_MEMORY_Base, SRAM1_MEMORY_Size }, + { 0, 0 }, // { FLASH_MEMORY_Base, FLASH_MEMORY_Size }, +}; + +bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex) +{ + return true; +} + +bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize) +{ + return true; +} + +int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen) +{ + return 0; +} + +int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen) +{ + return 0; +} + +//const ConfigurationSector g_ConfigurationSector = +//{ +// // ConfigurationLength +// offsetof(ConfigurationSector, FirstConfigBlock), +// +// //CONFIG_SECTOR_VERSION +// { +// ConfigurationSector::c_CurrentVersionMajor, +// ConfigurationSector::c_CurrentVersionMinor, +// ConfigurationSector::c_CurrentVersionBooter, +// 0, // extra +// }, +// +// // backwards compatibility buffer (88 bytes to put booterflagarray at offset 96) +// { +// 0x0, +// }, +// +// // BooterFlagArray - determines if we enter the bootloader or not +// { +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// }, +// +// // unsigned int SectorSignatureCheck[9*8]; // 287 sectors max * 8 changes before erase +// { +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// }, +// +// //NANOBOOTER_KEY_CONFIG DeploymentKey = +// { +// {// ODM key configuration for programming firmware (non deployment sectors) +// { // ODM public key for firware sectors +// // exponent length +// 0xFF,0xFF,0xFF, 0xFF, +// +// // module +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// +// // exponent +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// } +// }, +// {// OEM key configuration for programming Deployment sector +// { // OEM public key for Deployment sector +// // exponent length +// 0xFF,0xFF,0xFF, 0xFF, +// +// // module +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// +// // exponent +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// } +// } +// }, +// +// //--//--//--// +// +// // OEM_MODEL_SKU OEM_Model_SKU; +// { +// 1, // unsigned char OEM; +// 2, // unsigned char Model; +// 3, // unsigned short int SKU; +// }, +// +// //--//--//--// +// +// // OEM_SERIAL_NUMBERS OemSerialNumbers +// { +// { 0, }, +// { 0, } // unsigned char system_serial_number[16]; +// }, +// +// // CLR Config Data +// { +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// }, +// +// //--//--//--// +// +// // HAL_CONFIG_BLOCK FirstConfigBlock; +// { +// HAL_CONFIG_BLOCK::c_Version_V2, // unsigned int Signature; +// 0x8833794c, // unsigned int HeaderCRC; +// 0x00000000, // unsigned int DataCRC; +// 0x00000000, // unsigned int Size; +// // char DriverName[64]; +// }, +//}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static ON_SOFT_REBOOT_HANDLER s_rebootHandlers[5] = {NULL, NULL, NULL, NULL, NULL}; + +void __cdecl HAL_AddSoftRebootHandler(ON_SOFT_REBOOT_HANDLER handler) +{ + for(int i=0; i 0) + { + ::QueryPerformanceFrequency( &frequency ); + + ::QueryPerformanceCounter ( &countStart ); + + double ratio = (double)TIME_CONVERSION__TO_SECONDS / (double)frequency.QuadPart; + + countEnd.QuadPart = (signed __int64)(((countStart.QuadPart * ratio) + ticks) / ratio); + + while(countStart.QuadPart < countEnd.QuadPart) + { + ::QueryPerformanceCounter( &countStart ); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma managed(push, off) + + +int hal_printf( const char* format, ... ) +{ + va_list arg_ptr; + + va_start(arg_ptr, format); + + int chars = hal_vprintf( format, arg_ptr ); + + va_end( arg_ptr ); + + return chars; +} + +int hal_vprintf( const char* format, va_list arg ) +{ + return vprintf( format, arg ); +} + + +int hal_fprintf( COM_HANDLE stream, const char* format, ... ) +{ + va_list arg_ptr; + int chars; + + va_start( arg_ptr, format ); + + chars = hal_vfprintf( stream, format, arg_ptr ); + + va_end( arg_ptr ); + + return chars; +} + +int hal_vfprintf( COM_HANDLE stream, const char* format, va_list arg ) +{ + char buffer[512]; + int chars = 0; + + chars = hal_vsnprintf( buffer, sizeof(buffer), format, arg ); + + //switch(ExtractTransport(stream)) + //{ + //default: + DebuggerPort_Write( stream, buffer, chars); // skip null terminator + // break; + + //case FLASH_WRITE_TRANSPORT: + // _ASSERTE(FALSE); + //} + + return chars; +} + +int hal_snprintf( char* buffer, size_t len, const char* format, ... ) +{ + va_list arg_ptr; + int chars; + + va_start( arg_ptr, format ); + + chars = hal_vsnprintf( buffer, len, format, arg_ptr ); + + va_end( arg_ptr ); + + return chars; +} + +int hal_vsnprintf( char* buffer, size_t len, const char* format, va_list arg ) +{ + return _vsnprintf_s( buffer, len, len-1/* force space for trailing zero*/, format, arg ); +} + + +// Compares 2 ASCII strings case insensitive. Does not take locale into account. +int hal_stricmp(const char * dst, const char * src) +{ + int f = 0, l = 0; + + do + { + if (((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z')) + { + f -= 'A' - 'a'; + } + if (((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z')) + { + l -= 'A' - 'a'; + } + } while (f && (f == l)); + + return(f - l); +} + +#pragma managed(pop) + +///////////////////////////////////////////////////////////////////////////// +// +// CRC 32 table for use under ZModem protocol, IEEE 802 +// G(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 +// +static const unsigned int c_CRCTable[256] = +{ + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, + 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, + 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, + 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, + 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, + 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, + 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, + 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, + 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, + 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, + 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, + 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, + 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, + 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, + 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, + 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, + 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, + 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, + 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, + 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, + 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 +}; + +unsigned int SUPPORT_ComputeCRC(const void* rgBlock, int nLength, unsigned int crc) +{ + const unsigned char* ptr = (const unsigned char*)rgBlock; + + while (nLength-- > 0) + { + crc = c_CRCTable[((crc >> 24) ^ (*ptr++)) & 0xFF] ^ (crc << 8); + } + + return crc; +}; + +/////////////////////////////////////////////////////////////// + +size_t CPU_GetCachableAddress( size_t address ) +{ + return address; +} + +//--// + +size_t CPU_GetUncachableAddress( size_t address ) +{ + return address; +} + +/////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/WatchDog.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/WatchDog.cpp new file mode 100644 index 00000000..9303b20e --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/WatchDog.cpp @@ -0,0 +1,9 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" +//--// + +// EMPTY ON PURPOSE diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.cpp new file mode 100644 index 00000000..72405284 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "win_dev_gpio_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController::get_PinCount___I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Read___WindowsDevicesGpioGpioPinValue, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Toggle___VOID, + NULL, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::DisposeNative___VOID, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeInit___BOOLEAN__I4, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDebounceTimeout___VOID, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::WriteNative___VOID__WindowsDevicesGpioGpioPinValue, + Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetAlternateFunction___VOID__I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Gpio = +{ + "Windows.Devices.Gpio", + 0xB1F30A6A, + method_lookup, + { 1, 1, 0, 0 } +}; diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.h b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.h new file mode 100644 index 00000000..5b795fbb --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native.h @@ -0,0 +1,81 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_GPIO_NATIVE_H_ +#define _WIN_DEV_GPIO_NATIVE_H_ + +#include "stdafx.h" + + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController +{ + static const int FIELD_STATIC__s_instance = 0; + + NANOCLR_NATIVE_DECLARE(get_PinCount___I4); + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin +{ + static const int FIELD_STATIC__s_eventListener = 1; + + static const int FIELD___syncLock = 1; + static const int FIELD___pinNumber = 2; + static const int FIELD___driveMode = 3; + static const int FIELD___debounceTimeout = 4; + static const int FIELD___callbacks = 5; + static const int FIELD___lastOutputValue = 6; + static const int FIELD___lastInputValue = 7; + static const int FIELD___disposedValue = 8; + + NANOCLR_NATIVE_DECLARE(Read___WindowsDevicesGpioGpioPinValue); + NANOCLR_NATIVE_DECLARE(Toggle___VOID); + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + NANOCLR_NATIVE_DECLARE(NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode); + NANOCLR_NATIVE_DECLARE(NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode); + NANOCLR_NATIVE_DECLARE(NativeInit___BOOLEAN__I4); + NANOCLR_NATIVE_DECLARE(NativeSetDebounceTimeout___VOID); + NANOCLR_NATIVE_DECLARE(WriteNative___VOID__WindowsDevicesGpioGpioPinValue); + NANOCLR_NATIVE_DECLARE(NativeSetAlternateFunction___VOID__I4); + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPinEvent +{ + static const int FIELD__PinNumber = 3; + static const int FIELD__Edge = 4; + + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPinEventListener +{ + static const int FIELD___pinMap = 1; + + + //--// + +}; + +struct Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPinValueChangedEventArgs +{ + static const int FIELD___edge = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Gpio; + +#endif //_WIN_DEV_GPIO_NATIVE_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp new file mode 100644 index 00000000..d97752d4 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioController.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "win_dev_gpio_native.h" + + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioController::get_PinCount___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Return value to the managed application + stack.SetResult_I4( 144 ); // Fixme: temporary arbitrary value + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp new file mode 100644 index 00000000..bb88eeb3 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Gpio/win_dev_gpio_native_Windows_Devices_Gpio_GpioPin.cpp @@ -0,0 +1,197 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "stdafx.h" +#include "win_dev_gpio_native.h" + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Gpio.GpioPinDriveMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// + +enum GpioPinDriveMode +{ + GpioPinDriveMode_Input = 0, + GpioPinDriveMode_InputPullDown, + GpioPinDriveMode_InputPullUp, + GpioPinDriveMode_Output, + GpioPinDriveMode_OutputOpenDrain, + GpioPinDriveMode_OutputOpenDrainPullUp, + GpioPinDriveMode_OutputOpenSource, + GpioPinDriveMode_OutputOpenSourcePullDown, +}; + +/////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Gpio.GpioPinValue (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////// + +enum GpioPinValue +{ + GpioPinValue_Low = 0, + GpioPinValue_High, +}; + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Read___WindowsDevicesGpioGpioPinValue( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + signed int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + + //stack.SetResult_I4(palReadPad(GPIO_PORT(pinNumber), pinNumber % 16)); + stack.SetResult_I4(1); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::Toggle___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeIsDriveModeSupported___BOOLEAN__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + signed int driveMode = stack.Arg1().NumericByRef().s4; + + // Return value to the managed application + stack.SetResult_Boolean( driveMode < 5 ) ; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDriveMode___VOID__WindowsDevicesGpioGpioPinDriveMode( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue ].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + signed int pinNumber = pThis[ FIELD___pinNumber ].NumericByRefConst().s4; + signed int driveMode = stack.Arg1().NumericByRef().s4; + + // switch (driveMode) + // { + // case 0 : palSetPadMode(GPIO_PORT(pinNumber), pinNumber % 16, PAL_MODE_INPUT); + // break; + // case 1 : palSetPadMode(GPIO_PORT(pinNumber), pinNumber % 16, PAL_MODE_INPUT_PULLDOWN); + // break; + // case 2 : palSetPadMode(GPIO_PORT(pinNumber), pinNumber % 16, PAL_MODE_INPUT_PULLUP); + // break; + // case 3 : palSetPadMode(GPIO_PORT(pinNumber), pinNumber % 16, PAL_MODE_OUTPUT_PUSHPULL); + // break; + // case 4 : palSetPadMode(GPIO_PORT(pinNumber), pinNumber % 16, PAL_MODE_OUTPUT_OPENDRAIN); + // break; + // default : palSetPadMode(GPIO_PORT(pinNumber), pinNumber % 16, PAL_MODE_INPUT_PULLDOWN); + // break; + // } + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeInit___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + signed int pinNumber = stack.Arg1().NumericByRef().s4; + + // TODO is probably a good idea keep track of the used pins, so we can check that here + // TODO is probably a good idea to check if this pin exists + + // TODO initialize the pin INT + + // Return value to the managed application + stack.SetResult_Boolean(true ); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetDebounceTimeout___VOID(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + // nothing to do here + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::WriteNative___VOID__WindowsDevicesGpioGpioPinValue(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if (pThis[Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::FIELD___disposedValue].NumericByRef().u1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + signed int pinNumber = pThis[FIELD___pinNumber].NumericByRefConst().s4; + GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[FIELD___driveMode].NumericByRefConst().s4; + + GpioPinValue state = (GpioPinValue)stack.Arg1().NumericByRef().s4; + + + // sanity check for drive mode set to output so we don't mess up writing to an input pin + if ((driveMode == GpioPinDriveMode_Output) || + (driveMode == GpioPinDriveMode_OutputOpenDrain) || + (driveMode == GpioPinDriveMode_OutputOpenDrainPullUp) || + (driveMode == GpioPinDriveMode_OutputOpenSource) || + (driveMode == GpioPinDriveMode_OutputOpenSourcePullDown)) + { + if (state == GpioPinValue_Low) + { + //palClearPad(GPIO_PORT(pinNumber), pinNumber % 16); + } + else + { + //palSetPad(GPIO_PORT(pinNumber), pinNumber % 16); + } + } + else + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_gpio_native_Windows_Devices_Gpio_GpioPin::NativeSetAlternateFunction___VOID__I4(CLR_RT_StackFrame& stack) +{ + NANOCLR_HEADER(); + + NANOCLR_NOCLEANUP(); +} \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.cpp new file mode 100644 index 00000000..120dedcb --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "stdafx.h" +#include "win_dev_spi_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MaxClockFrequency___I4, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MinClockFrequency___I4, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeInit___VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::DisposeNative___VOID, + NULL, + NULL, + Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::GetDeviceSelector___STATIC__STRING, + NULL, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Spi = +{ + "Windows.Devices.Spi", + 0x083DBB79, + method_lookup, + { 1, 1, 3, 0 } +}; diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.h b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.h new file mode 100644 index 00000000..e86272f6 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native.h @@ -0,0 +1,70 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#ifndef _WIN_DEV_SPI_NATIVE_H_ +#define _WIN_DEV_SPI_NATIVE_H_ + + +#include "stdafx.h" + + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo +{ + static const int FIELD___ChipSelectLineCount = 1; + + NANOCLR_NATIVE_DECLARE(get_MaxClockFrequency___I4); + NANOCLR_NATIVE_DECLARE(get_MinClockFrequency___I4); + + //--// + +}; + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiConnectionSettings +{ + static const int FIELD___csLine = 1; + static const int FIELD___clockFrequency = 2; + static const int FIELD___databitLength = 3; + static const int FIELD___spiMode = 4; + static const int FIELD___spiSharingMode = 5; + static const int FIELD___bitOrder = 6; + + + //--// + +}; + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiController +{ + static const int FIELD_STATIC__DeviceCollection = 0; + + + //--// + +}; + +struct Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice +{ + static const int FIELD___syncLock = 1; + static const int FIELD___spiBus = 2; + static const int FIELD___deviceId = 3; + static const int FIELD___connectionSettings = 4; + static const int FIELD___disposedValue = 5; + + NANOCLR_NATIVE_DECLARE(NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN); + NANOCLR_NATIVE_DECLARE(NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN); + NANOCLR_NATIVE_DECLARE(NativeInit___VOID); + NANOCLR_NATIVE_DECLARE(DisposeNative___VOID); + NANOCLR_NATIVE_DECLARE(GetDeviceSelector___STATIC__STRING); + + //--// + + //static uint16_t ComputePrescaler (uint8_t bus, int32_t requestedFrequency); + //static nfSPIConfig GetConfig(int bus, CLR_RT_HeapBlock* config); +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_Windows_Devices_Spi; + +#endif //_WIN_DEV_SPI_NATIVE_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp new file mode 100644 index 00000000..2df23f29 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo.cpp @@ -0,0 +1,43 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "win_dev_spi_native.h" + + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MaxClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pArg = &(stack.Arg1()); + + // spiBus is an ASCII string with the bus name in format 'SPIn' + // need to grab 'n' from the string and convert to the integer value from the ASCII code + uint8_t bus = (uint8_t)pArg[0].RecoverString()[3] - 48; + + // According to STM : "At a minimum, the clock frequency should be twice the required communication frequency." + // So maximum useable frequency is CoreClock / 2. + // SPI2 or SPI3 are on APB1, so divide max frequency by four. + stack.SetResult_I4 (987654321); + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiBusInfo::get_MinClockFrequency___I4( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_HeapBlock* pArg = &(stack.Arg1()); + + // spiBus is an ASCII string with the bus name in format 'SPIn' + // need to grab 'n' from the string and convert to the integer value from the ASCII code + uint8_t bus = (uint8_t)pArg[0].RecoverString()[3] - 48; + + // Max prescaler value = 256 + // SPI2 or SPI3 are on APB1, so divide max frequency by four. + stack.SetResult_I4 (123456789); + } + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp new file mode 100644 index 00000000..ed5f1205 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/Windows.Devices.Spi/win_dev_spi_native_Windows_Devices_Spi_SpiDevice.cpp @@ -0,0 +1,380 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +#include "stdafx.h" +#include "win_dev_spi_native.h" + +//SPIConfig spi_cfg; + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Spi.SpiMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// + +enum DataBitOrder +{ + DataBitOrder_MSB = 0, + DataBitOrder_LSB +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// !!! KEEP IN SYNC WITH Windows.Devices.Spi.SpiMode (in managed code) !!! // +/////////////////////////////////////////////////////////////////////////////////////// + +enum SpiModes +{ + SpiModes_Mode0 = 0, + SpiModes_Mode1, + SpiModes_Mode2, + SpiModes_Mode3 +}; + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// + +// define this type here to make it shorter and improve code readability +typedef Library_win_dev_spi_native_Windows_Devices_Spi_SpiConnectionSettings SpiConnectionSettings; + +// Computes the prescaler registers given a frequency +// uint16_t Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::ComputePrescaler (uint8_t bus, int32_t requestedFrequency) +// { +// uint16_t pre = 0; +// int32_t clock = STM32_SPII2S_MAX >> 1; // SP1, SPI4, SPI5 and SPI6 on APB2 +// if (bus == 2 || bus == 3) clock >>= 1; // SPI2 and SPI3 on APB1 + +// if (clock > requestedFrequency << 3) +// { +// clock >>= 4; +// pre |= SPI_CR1_BR_2; +// } +// if (clock > requestedFrequency << 1) +// { +// clock >>= 2; +// pre |= SPI_CR1_BR_1; +// } +// if (clock > requestedFrequency) pre |= SPI_CR1_BR_0; + +// return pre; +// } + +// Give a complete low-level SPI configuration from user's managed connectionSettings +// nfSPIConfig Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::GetConfig(int bus, CLR_RT_HeapBlock* config) +// { +// SPIDriver * _drv; + +// int csPin = config[ SpiConnectionSettings::FIELD___csLine ].NumericByRef().s4; +// uint16_t CR1 = SPI_CR1_SSI | SPI_CR1_MSTR | SPI_CR1_SPE; + +// switch (config[ SpiConnectionSettings::FIELD___spiMode ].NumericByRef().s4) +// { +// case SpiModes_Mode1 : +// CR1 |= SPI_CR1_CPHA; +// break; +// case SpiModes_Mode2 : +// CR1 |= SPI_CR1_CPOL; +// break; +// case SpiModes_Mode3 : +// CR1 |= SPI_CR1_CPHA | SPI_CR1_CPOL; +// break; +// default : // Default to Mode0 if invalid mode specified +// break; +// } + +// if (config[ SpiConnectionSettings::FIELD___databitLength ].NumericByRef().s4 == 16) +// { +// // data length is 16 bits +// CR1 |= SPI_CR1_DFF; + +// // Sets the order of bytes transmission : MSB first or LSB first +// int bitOrder = config[ SpiConnectionSettings::FIELD___bitOrder ].NumericByRef().s4; +// if (bitOrder == DataBitOrder_LSB) CR1 |= SPI_CR1_LSBFIRST; +// } + +// // SPI on STM32 needs a prescaler value to set the frequency used +// CR1 |= ComputePrescaler(bus, config[ SpiConnectionSettings::FIELD___clockFrequency ].NumericByRef().s4); + +// // Choose the driver that is mapped to the chosen bus +// switch (bus) +// { +// #if STM32_SPI_USE_SPI1 +// case 1 : _drv = &SPID1; +// break; +// #endif +// #if STM32_SPI_USE_SPI2 +// case 2 : _drv = &SPID2; +// break; +// #endif +// #if STM32_SPI_USE_SPI3 +// case 3 : _drv = &SPID3; +// break; +// #endif +// #if STM32_SPI_USE_SPI4 +// case 4 : _drv = &SPID4; +// break; +// #endif +// #if STM32_SPI_USE_SPI5 +// case 5 : _drv = &SPID5; +// break; +// #endif +// #if STM32_SPI_USE_SPI6 +// case 6 : _drv = &SPID6; +// break; +// #endif +// } + +// // Create the final configuration +// nfSPIConfig cfg = +// { +// { +// NULL, +// GPIO_PORT(csPin), +// csPin % 16, +// CR1, +// 0 +// }, +// _drv +// }; + +// return cfg; +// } + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U1__SZARRAY_U1__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + unsigned char * writeData = NULL; + unsigned char * readData = NULL; + int writeSize = 0; + int readSize = 0; + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details + uint8_t bus = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // // Get a complete low-level SPI configuration, depending on user's managed parameters + // nfSPIConfig cfg = GetConfig(bus, pThis[ FIELD___connectionSettings ].Dereference()); + + // If databitLength is set to 16 bit, then temporarily set it to 8 bit + int databitLength = pConfig[ SpiConnectionSettings::FIELD___databitLength ].NumericByRef().s4; + //if (databitLength == 16) cfg.Configuration.cr1 &= ~SPI_CR1_DFF; + + // dereference the write and read buffers from the arguments + CLR_RT_HeapBlock_Array* writeBuffer = stack.Arg1().DereferenceArray(); + if (writeBuffer != NULL) + { + // grab the pointer to the array by getting the first element of the array + writeData = writeBuffer->GetFirstElement(); + + // get the size of the buffer by reading the number of elements in the HeapBlock array + writeSize = writeBuffer->m_numOfElements; + } + + CLR_RT_HeapBlock_Array* readBuffer = stack.Arg2().DereferenceArray(); + if (readBuffer != NULL) + { + // grab the pointer to the array by getting the first element of the array + readData = readBuffer->GetFirstElement(); + + // get the size of the buffer by reading the number of elements in the HeapBlock array + readSize = readBuffer->m_numOfElements; + } + + // // because the bus access is shared, acquire and select the appropriate bus + // spiStart(cfg.Driver, &cfg.Configuration); + // spiAcquireBus(cfg.Driver); + // spiSelect(cfg.Driver); + + // // Are we using SPI full-duplex for transfer ? + // bool fullDuplex = (bool)stack.Arg3().NumericByRef().u1; + + // if (writeSize != 0 && readSize != 0) + // { + // // Transmit+Receive + // if (fullDuplex) + // { + // // Full duplex + // spiExchange(cfg.Driver, writeSize, &writeData[0], &readData[0]); + // } + // else + // { + // spiSend(cfg.Driver, writeSize, &writeData[0]); + // spiReceive(cfg.Driver, readSize, &readData[0]); + // } + // } + // else + // { + // // Transmit only or Receive only + // if (readSize != 0) + // { + // spiReceive(cfg.Driver, readSize, &readData[0]); + // } + // else + // { + // spiSend(cfg.Driver, writeSize, &writeData[0]); + // } + // } + + // // Release the bus + // spiUnselect(cfg.Driver); + // spiReleaseBus(cfg.Driver); + // spiStop(cfg.Driver); + + // // If databitLength was set to 16 bit above, then set it back to 16 bit + // if (databitLength == 16) cfg.Configuration.cr1 |= SPI_CR1_DFF; + + // null pointers and vars + writeData = NULL; + readData = NULL; + writeBuffer = NULL; + readBuffer = NULL; + pThis = NULL; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeTransfer___VOID__SZARRAY_U2__SZARRAY_U2__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + CLR_RT_TypedArray writeData; + CLR_RT_TypedArray readData; + + // marshal the write and read buffers + Interop_Marshal_UINT16_ARRAY(stack, 1, writeData); + Interop_Marshal_UINT16_ARRAY(stack, 2, readData); + int writeSize = writeData.GetSize(); + int readSize = readData.GetSize(); + + // get a pointer to the managed object instance and check that it's not NULL + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // get a pointer to the managed spi connectionSettings object instance + CLR_RT_HeapBlock* pConfig = pThis[ FIELD___connectionSettings ].Dereference(); + + // get bus index + // this is coded with a multiplication, need to perform and int division to get the number + // see the comments in the SpiDevice() constructor in managed code for details + uint8_t bus = (uint8_t)(pThis[ FIELD___deviceId ].NumericByRef().s4 / 1000); + + // // Gets a complete low-level SPI configuration, depending on user's managed parameters + // nfSPIConfig cfg = GetConfig(bus, pConfig); + + // If current config databitLength is 8bit, then set it temporarily to 16bit + int databitLength = pConfig[ SpiConnectionSettings::FIELD___databitLength ].NumericByRef().s4; + //if (databitLength == 8) cfg.Configuration.cr1 |= SPI_CR1_DFF; + + // // because the bus access is shared, acquire and select the appropriate bus + // spiStart(cfg.Driver, &cfg.Configuration); + // spiAcquireBus(cfg.Driver); + // spiSelect(cfg.Driver); + + // // Are we using SPI full-duplex for transfer ? + // bool fullDuplex = (bool)stack.Arg3().NumericByRef().u1; + + // if (writeSize != 0 && readSize != 0) + // { + // // Transmit+Receive + // if (fullDuplex) + // { + // // Full duplex + // spiExchange(cfg.Driver, writeSize, &writeData[0], &readData[0]); + // } + // else + // { + // spiSend(cfg.Driver, writeSize, &writeData[0]); + // spiReceive(cfg.Driver, readSize, &readData[0]); + // } + // } + // else + // { + // // Transmit only or Receive only + // if (readSize != 0) + // { + // spiReceive(cfg.Driver, readSize, &readData[0]); + // } + // else + // { + // spiSend(cfg.Driver, writeSize, (const void*)&buffer[0]); + // } + // } + + // // Release the bus + // spiUnselect(cfg.Driver); + // spiReleaseBus(cfg.Driver); + // spiStop(cfg.Driver); + + // // If current config databitLength was 8bit, then set it back to 8bit + // if (databitLength == 8) cfg.Configuration.cr1 &= ~SPI_CR1_DFF; + + // null pointers and vars + pThis = NULL; + pConfig = NULL; + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::NativeInit___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + // nothing to do in the native init + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::DisposeNative___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // set pin to input to save power + // clear interrupts + // release the pin + } + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_win_dev_spi_native_Windows_Devices_Spi_SpiDevice::GetDeviceSelector___STATIC__STRING( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + { + // declare the device selector string whose max size is "SPI1,SPI2,SPI3,SPI4,SPI5,SPI6," + terminator and init with the terminator + char deviceSelectorString[ 30 + 1] = { 0 }; + + #if STM32_SPI_USE_SPI1 + strcat(deviceSelectorString, "SPI1,"); + #endif + #if STM32_SPI_USE_SPI2 + strcat(deviceSelectorString, "SPI2,"); + #endif + #if STM32_SPI_USE_SPI3 + strcat(deviceSelectorString, "SPI3,"); + #endif + #if STM32_SPI_USE_SPI4 + strcat(deviceSelectorString, "SPI4,"); + #endif + #if STM32_SPI_USE_SPI5 + strcat(deviceSelectorString, "SPI5,"); + #endif + #if STM32_SPI_USE_SPI6 + strcat(deviceSelectorString, "SPI6,"); + #endif + + // replace the last comma with a terminator + deviceSelectorString[hal_strlen_s(deviceSelectorString) - 1] = '\0'; + + // because the caller is expecting a result to be returned + // we need set a return result in the stack argument using the appropriate SetResult according to the variable type (a string here) + stack.SetResult_String(deviceSelectorString); + } + NANOCLR_NOCLEANUP(); +} + diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/main.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/main.cpp new file mode 100644 index 00000000..87cada1a --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/main.cpp @@ -0,0 +1,100 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +#include + + +// +// UNDONE: Feature configuration +// + +#define NF_CLR_FEATURE_ALL + +#if defined(NF_CLR_FEATURE_ALL) + +#pragma comment(lib, "WireProtocol.lib") + +#pragma comment(lib, "Debugger.lib") +#pragma comment(lib, "Diagnostics.lib") +#pragma comment(lib, "Hardware.lib") +#pragma comment(lib, "InterruptHandler.lib") +#pragma comment(lib, "Messaging.lib") +#pragma comment(lib, "RPC.lib") +#pragma comment(lib, "Serialization.lib") + +#else + +#pragma comment(lib, "WireProtocol.lib") // UNDONE: FIXME: SUPPORT_ComputeCRC required by TypeSystem.cpp, CLR_RT_HeapBlock + +#pragma comment(lib, "Debugger_stub.lib") +#pragma comment(lib, "Diagnostics_stub.lib") +#pragma comment(lib, "Hardware_stub.lib") +#pragma comment(lib, "InterruptHandler_stub.lib") +#pragma comment(lib, "IOPort_stub.lib") +#pragma comment(lib, "Messaging_stub.lib") +#pragma comment(lib, "RPC_stub.lib") +#pragma comment(lib, "Serialization_stub.lib") + + +#endif + + + + + + + +///////////////////////////////////////////////////////////////////////////// + + +// All solutions are expected to provide an implementation of this +bool Target_GetReleaseInfo(NFReleaseInfo& releaseInfo) +{ + NFReleaseInfo::Init( + releaseInfo, + VERSION_MAJOR, + VERSION_MINOR, + VERSION_BUILD, + VERSION_REVISION, + OEMSYSTEMINFOSTRING, + hal_strlen_s(OEMSYSTEMINFOSTRING), + TARGETNAMESTRING, + hal_strlen_s(TARGETNAMESTRING), + PLATFORMNAMESTRING, + hal_strlen_s(PLATFORMNAMESTRING) + ); + + return true; // alternatively, return false if you didn't initialize the releaseInfo structure. +} + +///////////////////////////////////////////////////////////////////////////// +// + +int main() +{ + //void ApplicationEntryPoint() + + // initialize nanoHAL + nanoHAL_Initialize(); + + CLR_SETTINGS clrSettings; + ZeroMemory(&clrSettings, sizeof(clrSettings)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + ClrStartup(clrSettings); + +//#if !defined(BUILD_RTM) +// debug_printf( "Exiting.\r\n" ); +//#else + //::CPU_Reset(); +//#endif + + return 0; +} + diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj new file mode 100644 index 00000000..033615f6 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj @@ -0,0 +1,280 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E} + Win32Proj + nanoCLR + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + true + $(BinDir) + $(IntDir) + + + true + $(BinDir) + $(IntDir) + + + false + $(BinDir) + $(IntDir) + + + false + $(BinDir) + $(IntDir) + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32 PLAYGROUND APP";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\..\src\CLR\Helpers\Base64;.;..\Include;..\..\..\..\src\CLR\Include;..\..\..\..\src\HAL\Include;..\..\..\..\src\PAL\Include;nanoFramework.Runtime.Events + + + Console + $(BinDir) + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + $(BinDir) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;VERSION_MAJOR=0;VERSION_MINOR=0;VERSION_BUILD=0;VERSION_REVISION=0;OEMSYSTEMINFOSTRING="WIN_32 PLAYGROUND APP";TARGETNAMESTRING="CLR_WIN32";PLATFORMNAMESTRING="WIN32";%(PreprocessorDefinitions) + ..\..\..\..\src\CLR\Helpers\Base64;.;..\Include;..\..\..\..\src\CLR\Include;..\..\..\..\src\HAL\Include;..\..\..\..\src\PAL\Include;nanoFramework.Runtime.Events + + + Console + true + true + $(BinDir) + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + $(BinDir) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + Use + + + + + + + + + + + + {89cf8bdb-9c8a-4d18-bc3e-4312c5bd34b1} + + + {5d50772e-dac8-407d-972f-37deb4450b72} + + + {d32ee397-7e49-452d-ac95-afcb3c962e3d} + + + {5772d362-7277-49cf-9b49-42335a3154bd} + false + false + false + + + {5406eb0c-2243-47e1-9f21-f2d7ca277092} + false + false + false + + + {ed4c887a-ec09-465b-b5d9-075450adc52d} + + + {d0b2adfe-3347-4d73-9364-9c36935d12f8} + false + false + false + + + {16bf6131-a3b8-4b97-b867-e45669fb48bd} + + + {c337041d-344d-49fe-ad99-b137e7fd0188} + false + false + false + + + {58e950cc-2ff6-423c-b006-a70a19272f20} + + + {dd397ec4-844b-4b59-a67b-cad6b46f1f00} + + + {6dabcbf1-245a-4e76-bd36-8bc300c7dd82} + false + false + false + + + {a5e9ae41-f4fa-40ce-ad82-a7861eba007b} + + + {c97a9845-02dc-46e4-b219-bf5ea8fb28e3} + false + false + false + + + {131001e3-0201-451f-a87b-951d1c5c3eee} + + + {8acd05e8-42fb-4a49-9d8b-79239f0eed25} + false + false + false + + + {2a840dc3-ffa8-4562-bd13-ab2b0ba02cb6} + + + {2337c4a4-3ab4-4014-9c29-9ebe32f4510e} + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters new file mode 100644 index 00000000..5e298b89 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters @@ -0,0 +1,141 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {4a8f1020-5d97-4a6f-b9c1-1460ae41f71b} + + + {917f0887-d239-439f-b246-e18c1f726304} + + + {7d83b23d-05f7-4660-9f84-a6fcdb0a0cf3} + + + {27c2cf5b-4789-40b1-b760-fc55c60546f0} + + + {a6b77d6f-6169-46dc-9bd2-dac8fdef5518} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Generated + + + Source Files + + + Source Files\PAL + + + Source Files\PAL + + + Source Files\PAL + + + Source Files\PAL + + + Source Files\PAL + + + Source Files\PAL + + + Source Files + + + Source Files\PAL + + + Source Files + + + Source Files\Windows.Devices.Gpio + + + Source Files\Windows.Devices.Gpio + + + Source Files\Windows.Devices.Gpio + + + Source Files\nanoFramework.Runtime.Events + + + Source Files\nanoFramework.Runtime.Events + + + Source Files\nanoFramework.Runtime.Events + + + Source Files\nanoFramework.Runtime.Events + + + Source Files\PAL + + + Source Files\Windows.Devices.Spi + + + Source Files\Windows.Devices.Spi + + + Source Files\Windows.Devices.Spi + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.cpp new file mode 100644 index 00000000..f43fd3ef --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.cpp @@ -0,0 +1,59 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "nf_rt_events_native.h" + + +static const CLR_RT_MethodHandler method_lookup[] = +{ + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::EnableInterrupt___VOID, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::DisableInterrupt___VOID, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::Dispose___VOID__BOOLEAN, + NULL, + NULL, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::_ctor___VOID__STRING__U8, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink::EventConfig___VOID, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Combine___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate, + Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Remove___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate, +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events = +{ + "nanoFramework.Runtime.Events", + 0xBFF88292, + method_lookup, + { 1, 0, 5, 0 } +}; diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.h b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.h new file mode 100644 index 00000000..17961374 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native.h @@ -0,0 +1,99 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#ifndef _NF_RT_EVENTS_NATIVE_H_ +#define _NF_RT_EVENTS_NATIVE_H_ + + +#include "stdafx.h" + + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher +{ + static const int FIELD__threadSpawn = 1; + static const int FIELD__callbacks = 2; + static const int FIELD__disposed = 3; + static const int FIELD___NativeEventDispatcher = 4; + + NANOCLR_NATIVE_DECLARE(EnableInterrupt___VOID); + NANOCLR_NATIVE_DECLARE(DisableInterrupt___VOID); + NANOCLR_NATIVE_DECLARE(Dispose___VOID__BOOLEAN); + NANOCLR_NATIVE_DECLARE(_ctor___VOID__STRING__U8); + + //--// + static CLR_RT_ObjectToEvent_Source* GetEventDispReference( CLR_RT_StackFrame& stack ); + static HRESULT GetEventDispatcher ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_NativeEventDispatcher*& event ); + static CLR_RT_HeapBlock_NativeEventDispatcher* GetEventDispatcher ( CLR_RT_StackFrame& stack ); +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink +{ + static const int FIELD_STATIC__s_eventSink = 0; + static const int FIELD_STATIC__s_eventInfoTable = 1; + + NANOCLR_NATIVE_DECLARE(EventConfig___VOID); + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink__EventInfo +{ + static const int FIELD__EventListener = 1; + static const int FIELD__EventFilter = 2; + static const int FIELD__EventProcessor = 3; + static const int FIELD__Category = 4; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_BaseEvent +{ + static const int FIELD__Source = 1; + static const int FIELD__Message = 2; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventArgs +{ + static const int FIELD_STATIC__Empty = 2; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_GenericEvent +{ + static const int FIELD__Category = 3; + static const int FIELD__Data = 4; + static const int FIELD__Time = 5; + + + //--// + +}; + +struct Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate +{ + NANOCLR_NATIVE_DECLARE(Combine___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate); + NANOCLR_NATIVE_DECLARE(Remove___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate); + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events; + +#endif //_NF_RT_EVENTS_NATIVE_H_ diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp new file mode 100644 index 00000000..f5e33661 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_EventSink.cpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "nf_rt_events_native.h" + +static CLR_RT_HeapBlock_NativeEventDispatcher *g_Context = NULL; + +void PostManagedEvent(uint8_t category, uint8_t subCategory, uint16_t data1, uint32_t data2) +{ + if(g_Context != NULL) + { + uint16_t d = ((uint16_t)data1 << 16) | (category << 8) | subCategory; + + SaveNativeEventToHALQueue( g_Context, d, data2 ); + } +} + +static HRESULT InitializeEventSink( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, uint64_t userData ) +{ + g_Context = pContext; + + return S_OK; +} + +static HRESULT EnableDisableEventSink( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, bool fEnable ) +{ + return S_OK; +} + +static HRESULT CleanupEventSink( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +{ + g_Context = NULL; + + CleanupNativeEventsFromHALQueue( pContext ); + + return S_OK; +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_EventSink::EventConfig___VOID( CLR_RT_StackFrame& stack ) +{ + return S_OK; +} + +static const CLR_RT_DriverInterruptMethods g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink = +{ + InitializeEventSink, + EnableDisableEventSink, + CleanupEventSink +}; + +const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink_DriverProcs = +{ + "EventSink", + DRIVER_INTERRUPT_METHODS_CHECKSUM, + &g_CLR_AssemblyNative_nanoFramework_Runtime_Events_EventSink, + { 1, 0, 0, 0 } +}; diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp new file mode 100644 index 00000000..2948ced2 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher.cpp @@ -0,0 +1,176 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "nf_rt_events_native.h" + + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::EnableInterrupt___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD__disposed ].NumericByRef().s1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Calls driver to enable interrupts. Consider that there could be no driver + // associated to this object so check that the driver methods are set + if(pNativeDisp->driverMethods == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + + NANOCLR_CHECK_HRESULT(pNativeDisp->driverMethods->enableProcessor( pNativeDisp, true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::DisableInterrupt___VOID( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + if(pThis[ FIELD__disposed ].NumericByRef().s1 != 0) + { + NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); + } + + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Calls driver to enable interrupts. Consider that there could be no driver + // associated to this object so check that the driver methods are set + // we will be tolerant in this case and not throw any exception + if(pNativeDisp->driverMethods != NULL) + { + NANOCLR_CHECK_HRESULT(pNativeDisp->driverMethods->enableProcessor( pNativeDisp, false )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::Dispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Cleanup the HAL queue from the instance of associated CLR_RT_HeapBlock_NativeEventDispatcher + pNativeDisp->RemoveFromHALQueue(); + + // Calls driver to enable interrupts. Consider that there could be no driver + // associated to this object so check that the driver methods are set + // we will be tolerant in this case and not throw any exception + if(pNativeDisp->driverMethods != NULL) + { + NANOCLR_CHECK_HRESULT(pNativeDisp->driverMethods->cleanupProcessor( pNativeDisp )); + } + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::_ctor___VOID__STRING__U8( CLR_RT_StackFrame& stack ) +{ + NANOCLR_HEADER(); + + CLR_RT_DriverInterruptMethods* pDriverMethods; + const CLR_RT_NativeAssemblyData* pNativeDriverData; + CLR_RT_HeapBlock_NativeEventDispatcher* pNativeDisp = NULL; + + const char * driverName; + uint64_t driverData; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Retrieve paramenters; + if (stack.Arg1().DataType() != DATATYPE_OBJECT) + { NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + driverName = stack.Arg1().RecoverString(); FAULT_ON_NULL(driverName); + + driverData = stack.Arg2().NumericByRef().u8; + + // Throw NULL exception if string is empty. + if(hal_strlen_s( driverName ) == 0) + { + NANOCLR_CHECK_HRESULT(CLR_E_ARGUMENT_NULL); + } + + // Retrives pointers to driver implemented functions. + pNativeDriverData = GetAssemblyNativeData( driverName ); + + // Validates check sum and presence of the structure. + if(pNativeDriverData == NULL || pNativeDriverData->m_checkSum != DRIVER_INTERRUPT_METHODS_CHECKSUM) + { + NANOCLR_CHECK_HRESULT(CLR_E_DRIVER_NOT_REGISTERED); + } + + // Get pointer to CLR_RT_DriverInterruptMethods + pDriverMethods = (CLR_RT_DriverInterruptMethods *)pNativeDriverData->m_pNativeMethods; + + // Check that all methods are present: + if(pDriverMethods->initProcessor == NULL || pDriverMethods->enableProcessor == NULL || pDriverMethods->cleanupProcessor == NULL) + { + NANOCLR_CHECK_HRESULT(CLR_E_DRIVER_NOT_REGISTERED); + } + + // So we found driver by name and now we create instance of CLR_RT_HeapBlock_NativeEventDispatcher + NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_NativeEventDispatcher::CreateInstance( *pThis, pThis[ FIELD___NativeEventDispatcher ] )); + + // Initialize the driver with and provide the instance of CLR_RT_HeapBlock_NativeEventDispatcher + NANOCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); + + // Now call the driver. First save pointer to driver data. + pNativeDisp->driverMethods = pDriverMethods; + NANOCLR_CHECK_HRESULT(pDriverMethods->initProcessor( pNativeDisp, driverData )); + + NANOCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_ObjectToEvent_Source* Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::GetEventDispReference( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_HARDWARE(); + CLR_RT_HeapBlock* pThis = stack.This(); + + return CLR_RT_ObjectToEvent_Source::ExtractInstance( pThis[ FIELD___NativeEventDispatcher ] ); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::GetEventDispatcher( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_NativeEventDispatcher*& event ) +{ + NATIVE_PROFILE_CLR_HARDWARE(); + NANOCLR_HEADER(); + + event = GetEventDispatcher( stack ); + if(event == NULL) + { + NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + NANOCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock_NativeEventDispatcher* Library_nf_rt_events_native_nanoFramework_Runtime_Events_NativeEventDispatcher::GetEventDispatcher( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_HARDWARE(); + CLR_RT_ObjectToEvent_Source* src = GetEventDispReference( stack ); + + return (src == NULL) ? NULL : (CLR_RT_HeapBlock_NativeEventDispatcher*)src->m_eventPtr; +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp new file mode 100644 index 00000000..0ec99f71 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/nanoFramework.Runtime.Events/nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" +#include "nf_rt_events_native.h" + + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Combine___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Delegate_List::Combine( stack.PushValue(), stack.Arg0(), stack.Arg1(), true )); + + NANOCLR_NOCLEANUP(); +} + +HRESULT Library_nf_rt_events_native_nanoFramework_Runtime_Events_WeakDelegate::Remove___STATIC__mscorlibSystemDelegate__mscorlibSystemDelegate__mscorlibSystemDelegate( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + NANOCLR_HEADER(); + + NANOCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Delegate_List::Remove( stack.PushValue(), stack.Arg0(), stack.Arg1() )); + + NANOCLR_NOCLEANUP(); +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_heap.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_heap.cpp new file mode 100644 index 00000000..42706d94 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_heap.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "stdafx.h" + +void* platform_malloc(size_t size) { + return malloc(size); +} + +void platform_free(void* ptr) { + free(ptr); +} + +void* platform_realloc(void* ptr, size_t size) { + return ptr; +} diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_selector.h b/source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_selector.h new file mode 100644 index 00000000..97cfc5a2 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/platform_selector.h @@ -0,0 +1,68 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _PLATFORM_WINDOWS_SELECTOR_H_ +#define _PLATFORM_WINDOWS_SELECTOR_H_ 1 + +#define PLATFORM_WINDOWS_EMULATOR 1 + +///////////////////////////////////////////////////////// +// +// macros +// + +#define FAT_FS__VALIDATE_READONLY_CACHELINE 1 +//#define FAT_FS__DO_NOT_UPDATE_FILE_ACCESS_TIME 1 +#define FAT_FS__CACHE_FLUSH_TIMEOUT_USEC (5*1000*1000) + +// +// macros +// +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// +// constants +// +#define PRODUCT_WATCH 1 +#define PRODUCT_AUXDISPLAY 1 + +// Port definitions +#define TOTAL_USART_PORT 2 +#define COM1 ConvertCOM_ComHandle(0) +#define COM2 ConvertCOM_ComHandle(1) + +#define TOTAL_USB_CONTROLLER 1 +#define USB1 ConvertCOM_UsbHandle(0) + +#define TOTAL_DEBUG_PORT 1 +#define COM_DEBUG ConvertCOM_DebugHandle(0) + +#define TOTAL_MESSAGING_PORT 1 +#define COM_MESSAGING ConvertCOM_MessagingHandle(0) + +#define DEBUG_TEXT_PORT COM_DEBUG +#define DEBUGGER_PORT COM_DEBUG +#define MESSAGING_PORT COM_DEBUG + +#define PLATFORM_DEPENDENT_TX_USART_BUFFER_SIZE 512 // there is one TX for each usart port +#define PLATFORM_DEPENDENT_RX_USART_BUFFER_SIZE 512 // there is one RX for each usart port +#define PLATFORM_DEPENDENT_USB_QUEUE_PACKET_COUNT 2 // there is one queue for each pipe of each endpoint and the size of a single packet is sizeof(USB_PACKET64) == 68 bytes + + +// These are configuration for FATFS, uncomment if non-default values are needed +//#define PLATFORM_DEPENDENT_FATFS_SECTORCACHE_MAXSIZE 8 +//#define PLATFORM_DEPENDENT_FATFS_SECTORCACHE_LINESIZE 2048 +//#define PLATFORM_DEPENDENT_FATFS_MAX_OPEN_HANDLES 8 +#define PLATFORM_DEPENDENT_FATFS_MAX_VOLUMES 8 +// +// constants +// +///////////////////////////////////////////////////////// + +//#include + +#endif // _PLATFORM_WINDOWS_SELECTOR_H_ 1 + diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.cpp new file mode 100644 index 00000000..968af34d --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.cpp @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +// stdafx.cpp : source file that includes just the standard includes +// test.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file + diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.h b/source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.h new file mode 100644 index 00000000..9678d3eb --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/stdafx.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + +//#include + +// TODO: reference additional headers your program requires here + +#include +#include +#include +#include +#include + +#include "nanoCLR_ParseOptions.h" + diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/targetHAL_Time.cpp b/source/native/nf-interpreter/targets/os/win32/nanoCLR/targetHAL_Time.cpp new file mode 100644 index 00000000..8ca94f92 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/targetHAL_Time.cpp @@ -0,0 +1,155 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + + +//using namespace Microsoft::SPOT::Emulator; + +void HAL_Time_Sleep_MicroSeconds( unsigned int uSec ) +{ + // UNDONE: FIXME: return EmulatorNative::GetITimeDriver()->Sleep_MicroSeconds( uSec ); +} + +void HAL_Time_Sleep_MicroSeconds_InterruptEnabled( unsigned int uSec ) +{ + // UNDONE: FIXME: return EmulatorNative::GetITimeDriver()->Sleep_MicroSecondsInterruptsEnabled( uSec ); +} + +unsigned int HAL_Time_CurrentSysTicks() +{ + // TODO need to check if using the Win32 100ns ticks works + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->CurrentTicks(); +} + +uint64_t HAL_Time_SysTicksToTime( unsigned int sysTicks ) +{ + _ASSERTE(sysTicks <= 0x7FFFFFFF); + + //No need to go to managed code just to return Time. + + // TODO need to convert from whatever ticks are these to Win32 100ns ticks + return sysTicks; +} + +uint64_t HAL_Time_CurrentTime() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->CurrentTime(); +} + +uint64_t HAL_Time_CurrentDateTime(bool datePartOnly) +{ + if (datePartOnly) + { + SYSTEMTIME st; + HAL_Time_ToSystemTime(HAL_Time_CurrentTime(), &st); + + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + return HAL_Time_ConvertFromSystemTime(&st); + } + else + { + // on Windows we'll just return what is the current time from HAL + return HAL_Time_CurrentTime(); + } +} + +void HAL_Time_GetDriftParameters ( signed int* a, signed int* b, signed __int64* c ) +{ + *a = 1; + *b = 1; + *c = 0; +} + +unsigned int CPU_SystemClock() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->SystemClock; +} + +unsigned int CPU_TicksPerSecond() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->TicksPerSecond; +} + +//Completions + +void HAL_COMPLETION::InitializeList() +{ +} + +void HAL_COMPLETION::EnqueueDelta( unsigned int uSecFromNow ) +{ + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->EnqueueCompletion( (IntPtr)this, uSecFromNow ); +} + +void HAL_COMPLETION::EnqueueTicks( uint64_t EventTimeTicks ) +{ + _ASSERTE(FALSE); +} + +void HAL_COMPLETION::Abort() +{ + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->AbortCompletion( (IntPtr)this ); +} + +void HAL_COMPLETION::Execute() +{ + if(this->ExecuteInISR) + { + HAL_CONTINUATION* cont = this; + + cont->Execute(); + } + else + { + this->Enqueue(); + } +} + +//Continuations +void HAL_CONTINUATION::InitializeList() +{ +} + +bool HAL_CONTINUATION::IsLinked() +{ + return false; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->IsLinked( (IntPtr)this ); +} + +bool HAL_CONTINUATION::Dequeue_And_Execute() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->DequeueAndExecuteContinuation(); +} + +void HAL_CONTINUATION::InitializeCallback( HAL_CALLBACK_FPN EntryPoint, void* Argument ) +{ + Initialize(); + + Callback.Initialize( EntryPoint, Argument ); +} + +void HAL_CONTINUATION::Enqueue() +{ + _ASSERTE(this->GetEntryPoint() != NULL); + + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->EnqueueContinuation( (IntPtr) this ); +} + +void HAL_CONTINUATION::Abort() +{ + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->AbortContinuation( (IntPtr) this ); +} + +//various + +//void CLR_RT_EmulatorHooks::Notify_ExecutionStateChanged() +//{ +// // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->IsExecutionPaused = ClrIsDebuggerStopped(); +//} + diff --git a/source/native/nf-interpreter/targets/os/win32/nanoCLR/targetver.h b/source/native/nf-interpreter/targets/os/win32/nanoCLR/targetver.h new file mode 100644 index 00000000..357aac41 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/nanoCLR/targetver.h @@ -0,0 +1,13 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include + diff --git a/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/NF.TestApplication.nfproj b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/NF.TestApplication.nfproj new file mode 100644 index 00000000..766d6142 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/NF.TestApplication.nfproj @@ -0,0 +1,56 @@ + + + + $(MSBuildToolsPath)..\..\..\nanoFramework\v1.0\ + + + + Debug + AnyCPU + {11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 247f9798-e240-4d5b-956d-35e5ead21ce2 + Exe + Properties + 512 + TestApplication + TestApplication + v1.0 + TestApplication + + + + + + + + + ..\..\packages\nanoFramework.CoreLibrary.1.0.0-preview038\lib\mscorlib.dll + True + True + + + ..\..\packages\nanoFramework.Runtime.Events.1.0.0-preview165\lib\nanoFramework.Runtime.Events.dll + True + True + + + ..\..\packages\nanoFramework.Windows.Devices.Gpio.1.0.0-preview164\lib\Windows.Devices.Gpio.dll + True + True + + + ..\..\packages\nanoFramework.Windows.Devices.Spi.1.0.0-preview164\lib\Windows.Devices.Spi.dll + True + True + + + + + + + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Program.cs b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Program.cs new file mode 100644 index 00000000..f21a544c --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Program.cs @@ -0,0 +1,104 @@ +using System; +using System.Threading; +using Windows.Devices.Gpio; +using Windows.Devices.Spi; + +namespace NF.TestApplication_NEW +{ + public class Program + { + // For F4-Discovery -> Off board LED is on PB7 = 1 * 16 + 7 = 23 + // For F429I-Discovery -> Off board LED is on PG13 = 6 * 16 + 13 = 109 + // For F769I-DISCO -> LED2_GREEN is on PJ5 = 9 * 16 + 5 = 149 + // For F769I-DISCO -> LED2_RED is on PJ13 = 9 * 16 + 13 = 157 + // For F769I-DISCO -> USER_BUTTON is on PA0 = 0 * 16 + 0 = 0 + // For F746ZG-NUCLEO -> Off board LED is on PC10 = 2 * 16 + 10 = 42 + private const int LED_PIN = 149; + private const int LED_RED_PIN = 157; + private const int USER_BUTTON_PIN = 0; + + // Set up the LED + private static GpioPin LED; + private static GpioPin LED1; + private static GpioPin UserButton; + + private static SpiDevice MemsSensor; + + private static int dummyIntForTimer = 0; + private static int dummyIntForGpio = 0; + + public static void Main() + { + //////////////////////////////////////////////////////////////////////////////////// + // ToString() test + int thisIsAnInteger = 64; + var testString = thisIsAnInteger.ToString(); + + + //////////////////////////////////////////////////////////////////////////////////// + // timer test + Timer t = new Timer(TimerCb, null, 5000, 5000); + + + //////////////////////////////////////////////////////////////////////////////////// + // Gpio test + + var gpio = GpioController.GetDefault(); + + // red LED + LED1 = gpio.OpenPin(109); + LED1.SetDriveMode(GpioPinDriveMode.Output); + + // user button + UserButton = gpio.OpenPin(USER_BUTTON_PIN); + UserButton.SetDriveMode(GpioPinDriveMode.Input); + UserButton.ValueChanged += UserButton_ValueChanged; + + + //////////////////////////////////////////////////////////////////////////////////// + // Spi test + + var settings = new SpiConnectionSettings(3) // PA3:CS1 + { + Mode = SpiMode.Mode1, + ClockFrequency = 12 * 1000 * 1000, // 12Mhz + DataBitLength = 8 + }; + + MemsSensor = SpiDevice.FromId("SPI5", settings); + + //ushort[] redBuffer = new ushort[4]; + //MemsSensor.TransferFullDuplex(new ushort[] { 0x100, 0x200, 0x300, 0x400 }, redBuffer); + + MemsSensor.Write(new ushort[] { 0x100, 0x200, 0x300, 0x400 }); + + //////////////////////////////////////////////////////////////////////////////////// + while (true) + { + Thread.Sleep(1000); + } + } + + private static void TimerCb(object state) + { + // doing stuff + dummyIntForTimer++; + + Console.WriteLine(dummyIntForTimer.ToString()); + } + + static void UserButton_ValueChanged(object sender, GpioPinValueChangedEventArgs e) + { + dummyIntForGpio++; + + if (e.Edge == GpioPinEdge.RisingEdge) + { + LED1.Write(GpioPinValue.High); + } + else + { + LED1.Write(GpioPinValue.Low); + } + } + } +} diff --git a/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Properties/AssemblyInfo.cs b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..262254df --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CSharp.BlankApplication")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CSharp.BlankApplication")] +[assembly: AssemblyCopyright("Copyright © ")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/TestApplication.sln b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/TestApplication.sln new file mode 100644 index 00000000..7f7c627f --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/TestApplication.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2003 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "NF.TestApplication", "NF.TestApplication.nfproj", "{247F9798-E240-4D5B-956D-35E5EAD21CE2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {247F9798-E240-4D5B-956D-35E5EAD21CE2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {62117BDC-3FD8-42D4-9171-A4B4F12F46BB} + EndGlobalSection +EndGlobal diff --git a/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/packages.config b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/packages.config new file mode 100644 index 00000000..7a4b9592 --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/netnf/TestApplication/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/targets/os/win32/packages.config b/source/native/nf-interpreter/targets/os/win32/packages.config new file mode 100644 index 00000000..2bc6cdfa --- /dev/null +++ b/source/native/nf-interpreter/targets/os/win32/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/source/native/nf-interpreter/version.json b/source/native/nf-interpreter/version.json new file mode 100644 index 00000000..edb657ad --- /dev/null +++ b/source/native/nf-interpreter/version.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "1.4.0-preview.{height}", + "assemblyVersion": { + "precision": "revision" + }, + "publicReleaseRefSpec": [ + "^refs/heads/master$", + "^refs/heads/v\\d+(?:\\.\\d+)?$" + ], + "cloudBuild": { + "setAllVariables": true, + "buildNumber": { + "enabled": true, + "includeCommitId": { + "when": "always" + } + } + }, + "release": { + "branchName": "release-v{version}", + "firstUnstableTag": "preview" + } +} From 4bb66059d08b665f19724910da9bfdc7bb6107c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Wed, 4 Dec 2019 19:04:05 +0000 Subject: [PATCH 2/2] Add managed version of MDP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update nuspec. - Update Azure Pipelines yaml. - Bump version to 2.0. Signed-off-by: José Simões --- README.md | 3 + azure-pipelines.yml | 5 +- .../MetadataProcessor.Console/FodyWeavers.xml | 10 + .../MetadataProcessor.Console/FodyWeavers.xsd | 111 +++ .../MetadataProcessor.Console.csproj | 88 ++ source/MetadataProcessor.Console/Options.cs | 38 + source/MetadataProcessor.Console/Program.cs | 172 ++++ .../Properties/AssemblyInfo.cs | 12 + source/MetadataProcessor.Console/app.config | 3 + ...oFramework.Tools.MetaDataProcessor.targets | 10 + .../MetadataProcessor.Console/package.nuspec | 30 + .../MetadataProcessor.Console/packages.config | 8 + .../Endianness/nanoBinaryWriter.cs | 383 ++++++++ source/MetadataProcessor.Core/InanoTable.cs | 21 + .../MetadataProcessor.Core.csproj | 100 ++ .../Mono.Cecil/CodeWriter.cs | 518 ++++++++++ .../Properties/AssemblyInfo.cs | 11 + .../Tables/ICustomStringSorter.cs | 24 + .../Tables/nanoAssemblyReferenceTable.cs | 84 ++ .../Tables/nanoAttributesTable.cs | 96 ++ .../Tables/nanoByteCodeTable.cs | 161 ++++ .../Tables/nanoEmptyTable.cs | 36 + .../Tables/nanoFieldDefinitionTable.cs | 189 ++++ .../Tables/nanoFieldReferenceTable.cs | 81 ++ .../Tables/nanoMethodDefinitionTable.cs | 244 +++++ .../Tables/nanoMethodReferenceTable.cs | 81 ++ .../Tables/nanoReferenceTableBase.cs | 139 +++ .../Tables/nanoResourceDataTable.cs | 62 ++ .../Tables/nanoResourceFileTable.cs | 79 ++ .../Tables/nanoResourcesTable.cs | 208 ++++ .../Tables/nanoSignaturesTable.cs | 591 ++++++++++++ .../Tables/nanoStringTable.cs | 116 +++ .../Tables/nanoTablesContext.cs | 400 ++++++++ .../Tables/nanoTypeDefinitionTable.cs | 378 ++++++++ .../Tables/nanoTypeReferenceTable.cs | 110 +++ .../Tables/nanoTypeSpecificationsTable.cs | 113 +++ .../MetadataProcessor.Core/Utility/Crc32.cs | 66 ++ .../Utility/LoadHintsAssemblyResolver.cs | 75 ++ .../Utility/NativeMethodsCrc.cs | 100 ++ .../Utility/nanoBitmapProcessor.cs | 80 ++ .../Utility/nanoCLR_DataType.cs | 40 + .../Utility/nanoFontProcessor.cs | 130 +++ .../Utility/nanoPdbxFileWriter.cs | 143 +++ .../Utility/nanoSerializationType.cs | 33 + .../Utility/nanoStringsConstants.cs | 898 ++++++++++++++++++ .../nanoAssemblyBuilder.cs | 113 +++ .../nanoAssemblyDefinition.cs | 186 ++++ source/MetadataProcessor.Core/packages.config | 5 + .../nanoFramework.Tools.MetadataProcessor.sln | 203 +--- source/version.json | 2 +- 50 files changed, 6598 insertions(+), 191 deletions(-) create mode 100644 source/MetadataProcessor.Console/FodyWeavers.xml create mode 100644 source/MetadataProcessor.Console/FodyWeavers.xsd create mode 100644 source/MetadataProcessor.Console/MetadataProcessor.Console.csproj create mode 100644 source/MetadataProcessor.Console/Options.cs create mode 100644 source/MetadataProcessor.Console/Program.cs create mode 100644 source/MetadataProcessor.Console/Properties/AssemblyInfo.cs create mode 100644 source/MetadataProcessor.Console/app.config create mode 100644 source/MetadataProcessor.Console/nanoFramework.Tools.MetaDataProcessor.targets create mode 100644 source/MetadataProcessor.Console/package.nuspec create mode 100644 source/MetadataProcessor.Console/packages.config create mode 100644 source/MetadataProcessor.Core/Endianness/nanoBinaryWriter.cs create mode 100644 source/MetadataProcessor.Core/InanoTable.cs create mode 100644 source/MetadataProcessor.Core/MetadataProcessor.Core.csproj create mode 100644 source/MetadataProcessor.Core/Mono.Cecil/CodeWriter.cs create mode 100644 source/MetadataProcessor.Core/Properties/AssemblyInfo.cs create mode 100644 source/MetadataProcessor.Core/Tables/ICustomStringSorter.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoAssemblyReferenceTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoAttributesTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoEmptyTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoFieldDefinitionTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoFieldReferenceTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoMethodDefinitionTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoMethodReferenceTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoReferenceTableBase.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoResourceDataTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoResourceFileTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoResourcesTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoSignaturesTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoStringTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoTablesContext.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoTypeDefinitionTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoTypeReferenceTable.cs create mode 100644 source/MetadataProcessor.Core/Tables/nanoTypeSpecificationsTable.cs create mode 100644 source/MetadataProcessor.Core/Utility/Crc32.cs create mode 100644 source/MetadataProcessor.Core/Utility/LoadHintsAssemblyResolver.cs create mode 100644 source/MetadataProcessor.Core/Utility/NativeMethodsCrc.cs create mode 100644 source/MetadataProcessor.Core/Utility/nanoBitmapProcessor.cs create mode 100644 source/MetadataProcessor.Core/Utility/nanoCLR_DataType.cs create mode 100644 source/MetadataProcessor.Core/Utility/nanoFontProcessor.cs create mode 100644 source/MetadataProcessor.Core/Utility/nanoPdbxFileWriter.cs create mode 100644 source/MetadataProcessor.Core/Utility/nanoSerializationType.cs create mode 100644 source/MetadataProcessor.Core/Utility/nanoStringsConstants.cs create mode 100644 source/MetadataProcessor.Core/nanoAssemblyBuilder.cs create mode 100644 source/MetadataProcessor.Core/nanoAssemblyDefinition.cs create mode 100644 source/MetadataProcessor.Core/packages.config diff --git a/README.md b/README.md index 2ba6145b..66ff55f6 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ This repo contains **nanoFramework** metadata processor tool. It's a console app that performs various tasks when running a build of a C# project, like parsing the PE file generated by Roslyn, generating the PDBX files, generate the stubs for native code. Is part of **nanoFramework** toolbox, along with other various tools that are required in **nanoFramework** development, usage or repository management. +Version 2.0 is a C# application adapted from the original work of [Oleg Rakhmatulin](@OlegRa). +Version 1.0 was a Visual C++ application adapted from .NETMF toolbox. + ## Feedback and documentation To provide feedback, report issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home). diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 3605056a..8b6406b6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -115,9 +115,9 @@ jobs: - task: NuGetCommand@2 inputs: command: 'custom' - arguments: 'pack source\Tools.MetaDataProcessor\package.nuspec -Version $(NBGV_NuGetPackageVersion)' + arguments: 'pack source\MetadataProcessor.Console\package.nuspec -Version $(NBGV_NuGetPackageVersion)' condition: succeeded() - displayName: Pack NuGet with MDP tool + displayName: Pack NuGet for MDP tool - task: CopyFiles@1 inputs: @@ -145,6 +145,7 @@ jobs: nuGetFeedType: external packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg' publishFeedCredentials: 'AzureArtifacts' + continueOnError: true condition: succeeded() displayName: Push NuGet packages to Azure Artifacts diff --git a/source/MetadataProcessor.Console/FodyWeavers.xml b/source/MetadataProcessor.Console/FodyWeavers.xml new file mode 100644 index 00000000..0ed55b76 --- /dev/null +++ b/source/MetadataProcessor.Console/FodyWeavers.xml @@ -0,0 +1,10 @@ + + + + + CommandLine + nanoFramework.Tools.MetadataProcessor* + Mono.* + + + diff --git a/source/MetadataProcessor.Console/FodyWeavers.xsd b/source/MetadataProcessor.Console/FodyWeavers.xsd new file mode 100644 index 00000000..44a53744 --- /dev/null +++ b/source/MetadataProcessor.Console/FodyWeavers.xsd @@ -0,0 +1,111 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/source/MetadataProcessor.Console/MetadataProcessor.Console.csproj b/source/MetadataProcessor.Console/MetadataProcessor.Console.csproj new file mode 100644 index 00000000..c8333759 --- /dev/null +++ b/source/MetadataProcessor.Console/MetadataProcessor.Console.csproj @@ -0,0 +1,88 @@ + + + + + Debug + AnyCPU + {A9E02E14-7321-4B12-8AB5-9A0408ED8FD0} + Exe + nanoFramework.Tools.MetadataProcessor.Console + nanoFramework.Tools.MetadataProcessor + v4.6.1 + + + + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + full + true + bin\Release + prompt + 4 + true + + + + ..\packages\CommandLineParser.2.6.0\lib\net461\CommandLine.dll + + + ..\packages\Costura.Fody.3.3.3\lib\net40\Costura.dll + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.dll + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.Mdb.dll + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.Pdb.dll + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.Rocks.dll + + + + + + + + + + + + + + + + + Designer + + + + + {e32f7d15-2499-440c-8026-4d5ee1c5ec3a} + MetadataProcessor.Core + True + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/source/MetadataProcessor.Console/Options.cs b/source/MetadataProcessor.Console/Options.cs new file mode 100644 index 00000000..34d76397 --- /dev/null +++ b/source/MetadataProcessor.Console/Options.cs @@ -0,0 +1,38 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using CommandLine; +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor.Console +{ + public class Options + { + + [Option( + "parse", + Required = false, + Default = null, + HelpText = "Analyses .NET assembly.")] + public string Parse { get; set; } + + [Option( + "compile", + Required = false, + Default = null, + HelpText = "Compiles an assembly into nanoCLR format.")] + public string Compile { get; set; } + + [Option( + "loadhints", + Separator = ' ', + Required = false, + HelpText = "Loads one (or more) assembly file(s) as a dependency(ies).")] + public IEnumerable LoadHints { get; set; } + + + } +} diff --git a/source/MetadataProcessor.Console/Program.cs b/source/MetadataProcessor.Console/Program.cs new file mode 100644 index 00000000..2a100270 --- /dev/null +++ b/source/MetadataProcessor.Console/Program.cs @@ -0,0 +1,172 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using CommandLine; +using CommandLine.Text; +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Xml; + +namespace nanoFramework.Tools.MetadataProcessor.Console +{ + internal static class MainClass + { + private sealed class MetadataProcessor + { + private readonly IDictionary _loadHints = + new Dictionary(StringComparer.Ordinal); + + private AssemblyDefinition _assemblyDefinition; + + public void Parse(string fileName) + { + try + { + _assemblyDefinition = AssemblyDefinition.ReadAssembly(fileName, + new ReaderParameters { AssemblyResolver = new LoadHintsAssemblyResolver(_loadHints)}); + } + catch (Exception) + { + System.Console.Error.WriteLine( + "Unable to parse input assembly file '{0}' - check if path and file exists.", fileName); + Environment.Exit(1); + } + } + + public void Compile(string fileName) + { + try + { + var builder = new nanoAssemblyBuilder(_assemblyDefinition); + + using (var stream = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite)) + using (var writer = new BinaryWriter(stream)) + { + builder.Write(GetBinaryWriter(writer)); + } + + using (var writer = XmlWriter.Create(Path.ChangeExtension(fileName, "pdbx"))) + { + builder.Write(writer); + } + } + catch (Exception) + { + System.Console.Error.WriteLine( + "Unable to compile output assembly file '{0}' - check parse command results.", fileName); + throw; + } + } + + private nanoBinaryWriter GetBinaryWriter(BinaryWriter writer) + { + return nanoBinaryWriter.CreateLittleEndianBinaryWriter(writer); + } + + public void AddLoadHint( + string assemblyName, + string assemblyFileName) + { + _loadHints[assemblyName] = assemblyFileName; + } + } + + public static void Main(string[] args) + { + // grab the assembly version + var informationalVersionAttribute = Attribute.GetCustomAttribute( + Assembly.GetEntryAssembly(), + typeof(AssemblyInformationalVersionAttribute)) + as AssemblyInformationalVersionAttribute; + + // build header information + var headerInfo = $"nanoFramework MetadataProcessor Utility v{informationalVersionAttribute.InformationalVersion}"; + var copyrightInfo = new CopyrightInfo(true, $"nanoFramework project contributors", 2019); + + // output header to console + System.Console.WriteLine($"nanoFramework MetadataProcessor Utility v{informationalVersionAttribute.InformationalVersion}"); + System.Console.WriteLine("Copyright (c) 2019 nanoFramework project contributors"); + System.Console.WriteLine(); + System.Console.WriteLine("For documentation, report issues and support visit our GitHub repo: www.github.com\\nanoFramework"); + System.Console.WriteLine(); + System.Console.WriteLine(); + + // check for empty argument collection + if (!args.Any()) + { + // no argument provided, show help text and usage examples + + // because of short-comings in CommandLine parsing + // need to customize the output to provide a consistent output + var parser = new Parser(config => config.HelpWriter = null); + var result = parser.ParseArguments(new string[] { "", "" }); + + var helpText = new HelpText( + new HeadingInfo(headerInfo), + copyrightInfo) + .AddPreOptionsLine("No command was provided.") + .AddPreOptionsLine("") + .AddPreOptionsLine(HelpText.RenderUsageText(result)) + .AddPreOptionsLine("") + .AddOptions(result); + + System.Console.WriteLine(helpText.ToString()); + + return; + } + + var parsedArguments = Parser.Default.ParseArguments(args); + + parsedArguments + .WithParsed(opts => RunOptionsAndReturnExitCode(opts)) + .WithNotParsed(errors => HandleErrors(errors)); + } + + static void RunOptionsAndReturnExitCode(Options o) + { + var md = new MetadataProcessor(); + + // arguments have to be processed in this order, otherwise the parsing will fail + + // load hints + if (o.LoadHints.Any()) + { + // load hints should be provided in the format: AssemblyName FilePath + // like in --loadhints mscorlib e:\folder\where\the\assembly\is\mscorlib.dll + // the LoadHints argument already provides the assembly details separated + + int hintCount = 0; + + do + { + md.AddLoadHint(o.LoadHints.ElementAt(hintCount++), o.LoadHints.ElementAt(hintCount++)); + } + while (hintCount < o.LoadHints.Count()); + } + + // parse assembly + if (!string.IsNullOrEmpty(o.Parse)) + { + md.Parse(o.Parse); + } + + // compile PE + if (!string.IsNullOrEmpty(o.Compile)) + { + md.Compile(o.Compile); + } + } + + static void HandleErrors(IEnumerable errors) + { + // empty on purpose + } + } +} diff --git a/source/MetadataProcessor.Console/Properties/AssemblyInfo.cs b/source/MetadataProcessor.Console/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..bbae2c0a --- /dev/null +++ b/source/MetadataProcessor.Console/Properties/AssemblyInfo.cs @@ -0,0 +1,12 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("nanoFramework.MetadataProcessor.Console")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("nanoFramework project contributors")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Copyright (c) 2019 The nanoFramework project contributors")] diff --git a/source/MetadataProcessor.Console/app.config b/source/MetadataProcessor.Console/app.config new file mode 100644 index 00000000..3dbff35f --- /dev/null +++ b/source/MetadataProcessor.Console/app.config @@ -0,0 +1,3 @@ + + + diff --git a/source/MetadataProcessor.Console/nanoFramework.Tools.MetaDataProcessor.targets b/source/MetadataProcessor.Console/nanoFramework.Tools.MetaDataProcessor.targets new file mode 100644 index 00000000..ebda3f9c --- /dev/null +++ b/source/MetadataProcessor.Console/nanoFramework.Tools.MetaDataProcessor.targets @@ -0,0 +1,10 @@ + + + + MSBuild + nanoFramework\v1.0\ + Always + true + + + diff --git a/source/MetadataProcessor.Console/package.nuspec b/source/MetadataProcessor.Console/package.nuspec new file mode 100644 index 00000000..92ce174a --- /dev/null +++ b/source/MetadataProcessor.Console/package.nuspec @@ -0,0 +1,30 @@ + + + + nanoFramework.Tools.MetadataProcessor + nanoFramework.Tools.MetadataProcessor + $version$ + nanoFramework project contributors + nanoFramework project contributors + + Metadata Processor tool to be used internally by the VS nanoFramework extension. + + + + + Metadata Processor tool to be used internally by the VS nanoFramework extension. + + https://github.com/nanoframework/metadata-processor + https://secure.gravatar.com/avatar/97d0e092247f0716db6d4b47b7d1d1ad + false + https://github.com/nanoframework/metadata-processor/LICENSE + Copyright (c) 2019 The nanoFramework project contributors + + + nanoFramework, nano Framework, NETNF, NETMF, Micro Framework, .net + + + + + + diff --git a/source/MetadataProcessor.Console/packages.config b/source/MetadataProcessor.Console/packages.config new file mode 100644 index 00000000..6cd53721 --- /dev/null +++ b/source/MetadataProcessor.Console/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Endianness/nanoBinaryWriter.cs b/source/MetadataProcessor.Core/Endianness/nanoBinaryWriter.cs new file mode 100644 index 00000000..05d2ee10 --- /dev/null +++ b/source/MetadataProcessor.Core/Endianness/nanoBinaryWriter.cs @@ -0,0 +1,383 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Binary writer for .NET nanoFramework assemblies emitting. Supports different endianness. + /// + public abstract class nanoBinaryWriter + { + /// + /// Specialized big endian version of class. + /// + private sealed class BigEndianBinaryWriter : nanoBinaryWriter + { + /// + /// Emulates C++ union using explicit fields layout (with same zero offset) + /// + [StructLayout(LayoutKind.Explicit)] + private struct BytesMappingHelper + { + [FieldOffset(0)] + public ushort uint16Value; + + [FieldOffset(0)] + public uint uint32Value; + + [FieldOffset(0)] + public ulong uint64Value; + + [FieldOffset(0)] + public float singleValue; + + [FieldOffset(0)] + public double doubleValue; + + [FieldOffset(0)] + public unsafe fixed byte bytes[8]; + } + + private BytesMappingHelper _helper; + + /// + /// Creates new instance of object. + /// + /// Base binary writer for operating on stream. + public BigEndianBinaryWriter( + BinaryWriter baseWriter) + : base(baseWriter) + { + } + + /// + public override unsafe void WriteUInt16(ushort value) + { + _helper.uint16Value = value; + fixed (byte* pBytes = _helper.bytes) + { + _baseWriter.Write(pBytes[1]); + _baseWriter.Write(pBytes[0]); + } + } + + /// + public override unsafe void WriteUInt32(uint value) + { + _helper.uint32Value = value; + fixed (byte* pBytes = _helper.bytes) + { + _baseWriter.Write(pBytes[3]); + _baseWriter.Write(pBytes[2]); + _baseWriter.Write(pBytes[1]); + _baseWriter.Write(pBytes[0]); + } + } + + /// + public override unsafe void WriteUInt64(ulong value) + { + _helper.uint64Value = value; + fixed (byte* pBytes = _helper.bytes) + { + _baseWriter.Write(pBytes[7]); + _baseWriter.Write(pBytes[6]); + _baseWriter.Write(pBytes[5]); + _baseWriter.Write(pBytes[4]); + _baseWriter.Write(pBytes[3]); + _baseWriter.Write(pBytes[2]); + _baseWriter.Write(pBytes[1]); + _baseWriter.Write(pBytes[0]); + } + } + + /// + public override unsafe void WriteSingle(float value) + { + _helper.singleValue = value; + fixed (byte* pBytes = _helper.bytes) + { + _baseWriter.Write(pBytes[3]); + _baseWriter.Write(pBytes[2]); + _baseWriter.Write(pBytes[1]); + _baseWriter.Write(pBytes[0]); + } + } + + /// + public override unsafe void WriteDouble(double value) + { + _helper.doubleValue = value; + fixed (byte* pBytes = _helper.bytes) + { + _baseWriter.Write(pBytes[7]); + _baseWriter.Write(pBytes[6]); + _baseWriter.Write(pBytes[5]); + _baseWriter.Write(pBytes[4]); + _baseWriter.Write(pBytes[3]); + _baseWriter.Write(pBytes[2]); + _baseWriter.Write(pBytes[1]); + _baseWriter.Write(pBytes[0]); + } + } + + /// + public override nanoBinaryWriter GetMemoryBasedClone( + MemoryStream stream) + { + return new BigEndianBinaryWriter(new BinaryWriter(stream)); + } + } + + /// + /// Specialized little endian version of class. + /// + private sealed class LittleEndianBinaryWriter : nanoBinaryWriter + { + /// + /// Creates new instance of object. + /// + /// Base binary writer for operating on stream. + public LittleEndianBinaryWriter( + BinaryWriter baseWriter) + : base(baseWriter) + { + } + + /// + public override void WriteUInt16(ushort value) + { + _baseWriter.Write(value); + } + + /// + public override void WriteUInt32(uint value) + { + _baseWriter.Write(value); + } + + /// + public override void WriteUInt64(ulong value) + { + _baseWriter.Write(value); + } + + /// + public override void WriteSingle(float value) + { + _baseWriter.Write(value); + } + + /// + public override void WriteDouble(double value) + { + _baseWriter.Write(value); + } + + /// + public override nanoBinaryWriter GetMemoryBasedClone( + MemoryStream stream) + { + return new LittleEndianBinaryWriter(new BinaryWriter(stream)); + } + } + + /// + /// Base binary writer instance for performing basic operation on underlying byte stream. + /// By design is always little endian regardless of platform. + /// + private readonly BinaryWriter _baseWriter; + + /// + /// Creates new instance of object. + /// + /// Base binary writer for operating on stream. + protected nanoBinaryWriter( + BinaryWriter baseWriter) + { + _baseWriter = baseWriter; + } + + /// + /// Factory mathod for creating little endian version of class. + /// + /// Base binary writer for operating on stream. + /// + /// Instance of which writes bytes in little endian. + /// + public static nanoBinaryWriter CreateLittleEndianBinaryWriter( + BinaryWriter baseWriter) + { + return new LittleEndianBinaryWriter(baseWriter); + } + + /// + /// Factory mathod for creating big endian version of class. + /// + /// Base binary writer for operating on stream. + /// + /// Instance of which writes bytes in big endian. + /// + public static nanoBinaryWriter CreateBigEndianBinaryWriter( + BinaryWriter baseWriter) + { + return new BigEndianBinaryWriter(baseWriter); + } + + /// + /// Write single unsigned byte into underying stream. + /// + /// Unsigned byte value for writing. + public void WriteByte(byte value) + { + _baseWriter.Write(value); + } + + /// + /// Write single signed byte into underying stream. + /// + /// Signed byte value for writing. + public void WriteSByte(sbyte value) + { + _baseWriter.Write(value); + } + + /// + /// Write version information into underying stream. + /// + /// Version information value for writing. + public void WriteVersion(Version value) + { + WriteUInt16((ushort)value.Major); + WriteUInt16((ushort)value.Minor); + WriteUInt16((ushort)value.Build); + WriteUInt16((ushort)value.Revision); + } + + /// + /// Write raw string value (in UTF-8 encoding) into underying stream. + /// + /// String value for writing. + public void WriteString(string value) + { + _baseWriter.Write(Encoding.UTF8.GetBytes(value)); + WriteByte(0); + } + + /// + /// Write raw bytes array into underying stream. + /// + /// Raw bytes array for writing. + public void WriteBytes(byte[] value) + { + _baseWriter.Write(value); + } + + /// + /// Write single signed word into underying stream. + /// + /// Signed word value for writing. + public void WriteInt16(short value) + { + WriteUInt16((ushort)value); + } + + /// + /// Write single signed double word into underying stream. + /// + /// Signed double word value for writing. + public void WriteInt32(int value) + { + WriteUInt32((uint)value); + } + + /// + /// Write single signed quad word into underying stream. + /// + /// Signed quad word value for writing. + public void WriteInt64(long value) + { + WriteUInt64((ulong)value); + } + + /// + /// Write metadata token in packed format (variable length). + /// + /// Metadata tocken in .NET Mico Framework format. + public void WriteMetadataToken(uint value) + { + if (value <= 0x7F) + { + WriteByte((byte) value); + } + else if (value <= 0x3FFF) + { + WriteByte((byte)(value >> 8 | 0x80)); + WriteByte((byte)value); + } + else + { + WriteByte((byte)(value >> 24 | 0xC0)); + WriteByte((byte)(value >> 16)); + WriteByte((byte)(value >> 8)); + WriteByte((byte)value); + } + } + + /// + /// Write single unsigned word into underying stream. + /// + /// Unsigned word value for writing. + public abstract void WriteUInt16(ushort value); + + /// + /// Write single signed double word into underying stream. + /// + /// Unsigned double word value for writing. + public abstract void WriteUInt32(uint value); + + /// + /// Write single signed quad word into underying stream. + /// + /// Unsigned quad word value for writing. + public abstract void WriteUInt64(ulong value); + + /// + /// Write single floating point value (4 bytes) into underying stream. + /// + /// Floating point value for writing. + public abstract void WriteSingle(float value); + + /// + /// Write single floating point value (8 bytes) into underying stream. + /// + /// Floating point value for writing. + public abstract void WriteDouble(double value); + + /// + /// Creates new instance of object with same endiannes + /// as current instance but based on new base stream . + /// + /// Base binary writer for operating on stream for new writer. + /// New instance of object with same endiannes. + public abstract nanoBinaryWriter GetMemoryBasedClone(MemoryStream stream); + + /// + /// Gets base stream for this binary writer object (used for changing stream position). + /// + public Stream BaseStream { get { return _baseWriter.BaseStream; } } + + /// + /// Returns true in case of this binary writer is write data in big endian format. + /// + public bool IsBigEndian { get { return (this is BigEndianBinaryWriter); } } + } +} diff --git a/source/MetadataProcessor.Core/InanoTable.cs b/source/MetadataProcessor.Core/InanoTable.cs new file mode 100644 index 00000000..b4141367 --- /dev/null +++ b/source/MetadataProcessor.Core/InanoTable.cs @@ -0,0 +1,21 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Common interface for all metadata tables in .NET nanoFramework assembly. + /// + public interface InanoTable + { + /// + /// Writes metadata table from memory representation into output stream. + /// + /// Binary writer with correct endianness. + void Write( + nanoBinaryWriter writer); + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj new file mode 100644 index 00000000..0d6cd659 --- /dev/null +++ b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj @@ -0,0 +1,100 @@ + + + + Debug + AnyCPU + {E32F7D15-2499-440C-8026-4D5EE1C5EC3A} + Library + nanoFramework.Tools.MetadataProcessor.Core + nanoFramework.Tools.MetadataProcessor.Core + v4.6.1 + + + + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + true + + + full + true + bin\Release + prompt + 4 + false + true + + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.dll + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.Mdb.dll + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.Pdb.dll + + + ..\packages\Mono.Cecil.0.11.1\lib\net40\Mono.Cecil.Rocks.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Mono.Cecil/CodeWriter.cs b/source/MetadataProcessor.Core/Mono.Cecil/CodeWriter.cs new file mode 100644 index 00000000..cb63a734 --- /dev/null +++ b/source/MetadataProcessor.Core/Mono.Cecil/CodeWriter.cs @@ -0,0 +1,518 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using Mono.Cecil.Cil; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + + /// + /// Encapsulates logic related for writing correct byte code and calculating stack size. + /// + /// + /// This class initially copy-pasted from Mono.Cecil codebase but changed a lot. + /// + internal sealed class CodeWriter + { + /// + /// Original method body information in Mono.Cecil format. + /// + private readonly MethodBody _body; + + /// + /// Binary writer for writing byte code in correct endianess. + /// + private readonly nanoBinaryWriter _writer; + + /// + /// String literals table (used for obtaining string literal ID). + /// + private readonly nanoStringTable _stringTable; + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// Creates new instance of object. + /// + /// Original method body in Mono.Cecil format. + /// Binary writer for writing byte code in correct endianess. + /// String references table (for obtaining string ID). + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public CodeWriter( + MethodDefinition method, + nanoBinaryWriter writer, + nanoStringTable stringTable, + nanoTablesContext context) + { + _stringTable = stringTable; + + _body = method.Body; + _context = context; + _writer = writer; + } + + /// + /// Writes method body into binary writer originally passed into constructor. + /// + public void WriteMethodBody() + { + foreach (var instruction in _body.Instructions) + { + WriteOpCode(instruction.OpCode); + WriteOperand(instruction); + } + + WriteExceptionsTable(); + } + + /// + /// Fixes instructions offsets according .NET nanoFramework operands sizes. + /// + /// Target method for fixing offsets + /// String table for populating strings from method. + public static IEnumerable> PreProcessMethod( + MethodDefinition methodDefinition, + nanoStringTable stringTable) + { + if (!methodDefinition.HasBody) + { + yield break; + } + + var offset = 0; + var offsetChanged = true; + foreach (var instruction in methodDefinition.Body.Instructions) + { + if (offset != 0) + { + if (offsetChanged) + { + yield return new Tuple( + (uint)instruction.Offset, (uint)(instruction.Offset + offset)); + offsetChanged = false; + } + instruction.Offset += offset; + } + + switch (instruction.OpCode.OperandType) + { + case OperandType.InlineSwitch: + var targets = (Instruction[]) instruction.Operand; + offset -= 3; // One bye used instead of Int32 + offset -= 2 * targets.Length; // each target use Int16 instead of Int32 + offsetChanged = true; + break; + case OperandType.InlineString: + stringTable.GetOrCreateStringId((string) instruction.Operand, false); + offset -= 2; + offsetChanged = true; + break; + case OperandType.InlineMethod: + case OperandType.InlineField: + case OperandType.InlineType: + case OperandType.InlineBrTarget: + // In full .NET these instructions followed by double word operand + // but in .NET nanoFramework these instruction's operand are word + offset -= 2; + offsetChanged = true; + break; + } + } + } + + /// + /// Calculates method stack size for passed method. + /// + /// Method body in Mono.Cecil format. + /// Maximal evaluated stack size for passed method body. + public static byte CalculateStackSize( + MethodBody methodBody) + { + if (methodBody == null) + { + return 0; + } + + IDictionary offsets = new Dictionary(); + + var size = 0; + var maxSize = 0; + foreach (var instruction in methodBody.Instructions) + { + int correctedStackSize; + if (offsets.TryGetValue(instruction.Offset, out correctedStackSize)) + { + size = correctedStackSize; + } + + switch (instruction.OpCode.Code) + { + case Code.Throw: + case Code.Endfinally: + case Code.Endfilter: + case Code.Leave_S: + case Code.Br_S: + case Code.Leave: + size = 0; + continue; + + case Code.Newobj: + { + var method = (MethodReference)instruction.Operand; + size -= method.Parameters.Count; + } + break; + + case Code.Callvirt: + case Code.Call: + { + var method = (MethodReference)instruction.Operand; + if (method.HasThis) + { + --size; + } + size -= method.Parameters.Count; + if (method.ReturnType.FullName != "System.Void") + { + ++size; + } + } + break; + } + + size = CorrectStackDepthByPushes(instruction, size); + size = CorrectStackDepthByPops(instruction, size); + + if (instruction.OpCode.OperandType == OperandType.ShortInlineBrTarget || + instruction.OpCode.OperandType == OperandType.InlineBrTarget) + { + int stackSize; + var target = (Instruction)instruction.Operand; + offsets.TryGetValue(target.Offset, out stackSize); + offsets[target.Offset] = Math.Max(stackSize, size); + } + + maxSize = Math.Max(maxSize, size); + } + + return (byte)maxSize; + } + + private static int CorrectStackDepthByPushes( + Instruction instruction, + int size) + { + switch (instruction.OpCode.StackBehaviourPush) + { + case StackBehaviour.Push1: + case StackBehaviour.Pushi: + case StackBehaviour.Pushi8: + case StackBehaviour.Pushr4: + case StackBehaviour.Pushr8: + case StackBehaviour.Pushref: + ++size; + break; + case StackBehaviour.Push1_push1: + size += 2; + break; + } + return size; + } + + private static int CorrectStackDepthByPops( + Instruction instruction, + int size) + { + switch (instruction.OpCode.StackBehaviourPop) + { + case StackBehaviour.Pop1: + case StackBehaviour.Popi: + case StackBehaviour.Popref: + --size; + break; + case StackBehaviour.Pop1_pop1: + case StackBehaviour.Popi_pop1: + case StackBehaviour.Popi_popi: + case StackBehaviour.Popi_popi8: + case StackBehaviour.Popi_popr4: + case StackBehaviour.Popi_popr8: + case StackBehaviour.Popref_pop1: + case StackBehaviour.Popref_popi: + size -= 2; + break; + case StackBehaviour.Popi_popi_popi: + case StackBehaviour.Popref_popi_popi: + case StackBehaviour.Popref_popi_popi8: + case StackBehaviour.Popref_popi_popr4: + case StackBehaviour.Popref_popi_popr8: + case StackBehaviour.Popref_popi_popref: + size -= 3; + break; + } + return size; + } + + private void WriteExceptionsTable() + { + if (!_body.HasExceptionHandlers) + { + return; + } + + foreach (var handler in _body.ExceptionHandlers + .OrderBy(item => item.HandlerStart.Offset)) + { + switch (handler.HandlerType) + { + case ExceptionHandlerType.Catch: + _writer.WriteUInt16(0x0000); + _writer.WriteUInt16(GetTypeReferenceId(handler.CatchType, 0x8000)); + break; + case ExceptionHandlerType.Fault: + _writer.WriteUInt16(0x0001); + _writer.WriteUInt16(0x0000); + break; + case ExceptionHandlerType.Finally: + _writer.WriteUInt16(0x0002); + _writer.WriteUInt16(0x0000); + break; + case ExceptionHandlerType.Filter: + _writer.WriteUInt16(0x0003); + _writer.WriteUInt16((ushort)handler.FilterStart.Offset); + break; + } + + _writer.WriteUInt16((ushort)handler.TryStart.Offset); + _writer.WriteUInt16((ushort)handler.TryEnd.Offset); + _writer.WriteUInt16((ushort)handler.HandlerStart.Offset); + if (handler.HandlerEnd == null) + { + _writer.WriteUInt16((ushort)_body.Instructions.Last().Offset); + } + else + { + _writer.WriteUInt16((ushort)handler.HandlerEnd.Offset); + } + } + + _writer.WriteByte((byte)_body.ExceptionHandlers.Count); + } + + private void WriteOpCode ( + OpCode opcode) + { + if (opcode.Size == 1) + { + _writer.WriteByte(opcode.Op2); + } + else + { + _writer.WriteByte(opcode.Op1); + _writer.WriteByte(opcode.Op2); + } + } + + private void WriteOperand ( + Instruction instruction) + { + var opcode = instruction.OpCode; + var operandType = opcode.OperandType; + + if (operandType == OperandType.InlineNone) + { + return; + } + + var operand = instruction.Operand; + if (operand == null) + { + throw new ArgumentException(); + } + + switch (operandType) + { + case OperandType.InlineSwitch: + { + var targets = (Instruction[]) operand; + _writer.WriteByte((byte)targets.Length); + var diff = instruction.Offset + opcode.Size + 2 * targets.Length + 1; + foreach (var item in targets) + { + _writer.WriteInt16((short)(GetTargetOffset(item) - diff)); + } + break; + } + case OperandType.ShortInlineBrTarget: + { + var target = (Instruction) operand; + _writer.WriteSByte((sbyte) + (GetTargetOffset(target) - (instruction.Offset + opcode.Size + 1))); + break; + } + case OperandType.InlineBrTarget: + { + var target = (Instruction) operand; + _writer.WriteInt16((short) + (GetTargetOffset(target) - (instruction.Offset + opcode.Size + 2))); + break; + } + case OperandType.ShortInlineVar: + _writer.WriteByte((byte)GetVariableIndex((VariableDefinition)operand)); + break; + case OperandType.ShortInlineArg: + _writer.WriteByte((byte)GetParameterIndex((ParameterDefinition)operand)); + break; + case OperandType.InlineVar: + _writer.WriteInt16((short)GetVariableIndex((VariableDefinition)operand)); + break; + case OperandType.InlineArg: + _writer.WriteInt16((short)GetParameterIndex((ParameterDefinition)operand)); + break; + case OperandType.InlineSig: + // TODO: implement this properly after finding when such code is generated + //WriteMetadataToken (GetStandAloneSignature ((CallSite) operand)); + break; + case OperandType.ShortInlineI: + if (opcode == OpCodes.Ldc_I4_S) + { + _writer.WriteSByte((sbyte)operand); + } + else + { + _writer.WriteByte((byte)operand); + } + break; + case OperandType.InlineI: + _writer.WriteInt32((int)operand); + break; + case OperandType.InlineI8: + _writer.WriteInt64((long)operand); + break; + case OperandType.ShortInlineR: + _writer.WriteSingle((float)operand); + break; + case OperandType.InlineR: + _writer.WriteDouble((double)operand); + break; + case OperandType.InlineString: + var stringReferenceId = _stringTable.GetOrCreateStringId((string) operand, false); + _writer.WriteUInt16(stringReferenceId); + break; + case OperandType.InlineMethod: + _writer.WriteUInt16(_context.GetMethodReferenceId((MethodReference)operand)); + break; + case OperandType.InlineType: + _writer.WriteUInt16(GetTypeReferenceId((TypeReference)operand)); + break; + case OperandType.InlineField: + _writer.WriteUInt16(GetFieldReferenceId((FieldReference)operand)); + break; + case OperandType.InlineTok: + _writer.WriteUInt32(GetMetadataToken((IMetadataTokenProvider)operand)); + break; + default: + throw new ArgumentException(); + } + } + + private uint GetMetadataToken( + IMetadataTokenProvider token) + { + ushort referenceId; + switch (token.MetadataToken.TokenType) + { + case TokenType.TypeRef: + _context.TypeReferencesTable.TryGetTypeReferenceId((TypeReference)token, out referenceId); + return (uint)0x01000000 | referenceId; + case TokenType.TypeDef: + _context.TypeDefinitionTable.TryGetTypeReferenceId((TypeDefinition)token, out referenceId); + return (uint)0x04000000 | referenceId; + case TokenType.TypeSpec: + _context.TypeSpecificationsTable.TryGetTypeReferenceId((TypeReference) token, out referenceId); + return (uint)0x08000000 | referenceId; + case TokenType.Field: + _context.FieldsTable.TryGetFieldReferenceId((FieldDefinition) token, false, out referenceId); + return (uint)0x05000000 | referenceId; + } + return 0U; + } + + private ushort GetFieldReferenceId( + FieldReference fieldReference) + { + ushort referenceId; + if (_context.FieldReferencesTable.TryGetFieldReferenceId(fieldReference, out referenceId)) + { + referenceId |= 0x8000; // External field reference + } + else + { + _context.FieldsTable.TryGetFieldReferenceId(fieldReference.Resolve(), false, out referenceId); + } + return referenceId; + } + + private ushort GetTypeReferenceId( + TypeReference typeReference, + ushort typeReferenceMask = 0x4000) + { + ushort referenceId; + if (_context.TypeReferencesTable.TryGetTypeReferenceId(typeReference, out referenceId)) + { + referenceId |= typeReferenceMask; // External type reference + } + else + { + if (!_context.TypeDefinitionTable.TryGetTypeReferenceId(typeReference.Resolve(), out referenceId)) + { + return 0x8000; + } + + } + return referenceId; + } + + private int GetTargetOffset ( + Instruction instruction) + { + if (instruction == null) + { + var last = _body.Instructions[_body.Instructions.Count - 1]; + return last.Offset + last.GetSize (); + } + + return instruction.Offset; + } + + private static int GetVariableIndex ( + VariableDefinition variable) + { + return variable.Index; + } + + private int GetParameterIndex ( + ParameterDefinition parameter) + { + if (_body.Method.HasThis) { + if (parameter == _body.ThisParameter) + return 0; + + return parameter.Index + 1; + } + + return parameter.Index; + } + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Properties/AssemblyInfo.cs b/source/MetadataProcessor.Core/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..63eaadf5 --- /dev/null +++ b/source/MetadataProcessor.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. +[assembly: AssemblyTitle ("nanoFramework.MetadataProcessor.Core")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("nanoFramework project contributors")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("Copyright (c) 2019 The nanoFramework project contributors")] diff --git a/source/MetadataProcessor.Core/Tables/ICustomStringSorter.cs b/source/MetadataProcessor.Core/Tables/ICustomStringSorter.cs new file mode 100644 index 00000000..d2da7c92 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/ICustomStringSorter.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Helper class for sorting string literals before merging (solve strings order problem). + /// + public interface ICustomStringSorter + { + /// + /// Sorts input sequence according needed logic. + /// + /// Existing string listerals list. + /// Original string listerals list sorted according test pattern. + IEnumerable Sort( + ICollection strings); + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Tables/nanoAssemblyReferenceTable.cs b/source/MetadataProcessor.Core/Tables/nanoAssemblyReferenceTable.cs new file mode 100644 index 00000000..285231c4 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoAssemblyReferenceTable.cs @@ -0,0 +1,84 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing external assembly references list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoAssemblyReferenceTable : + nanoReferenceTableBase + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class AssemblyNameReferenceComparer : IEqualityComparer + { + /// + public bool Equals(AssemblyNameReference lhs, AssemblyNameReference rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(AssemblyNameReference item) + { + return item.FullName.GetHashCode(); + } + } + + /// + /// Creates new instance of object. + /// + /// List of assembly references in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoAssemblyReferenceTable( + IEnumerable items, + nanoTablesContext context) + : base(items, new AssemblyNameReferenceComparer(), context) + { + } + + /// + protected override void WriteSingleItem( + nanoBinaryWriter writer, + AssemblyNameReference item) + { + WriteStringReference(writer, item.Name); + writer.WriteUInt16(0); // padding + + writer.WriteVersion(item.Version); + } + + /// + protected override void AllocateSingleItemStrings( + AssemblyNameReference item) + { + GetOrCreateStringId(item.Name); + } + + /// + /// Gets assembly reference ID by assembly name reference in Mono.Cecil format. + /// + /// Assembly name reference in Mono.Cecil format. + /// Refernce ID for passed item. + public ushort GetReferenceId( + AssemblyNameReference assemblyNameReference) + { + ushort referenceId; + TryGetIdByValue(assemblyNameReference, out referenceId); + return referenceId; + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoAttributesTable.cs b/source/MetadataProcessor.Core/Tables/nanoAttributesTable.cs new file mode 100644 index 00000000..16353ee5 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoAttributesTable.cs @@ -0,0 +1,96 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing attributes for types/methods/fields list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoAttributesTable : InanoTable + { + /// + /// List of custom attributes in Mono.Cecil format for all internal types. + /// + private readonly IEnumerable> _typesAttributes; + + /// + /// List of custom attributes in Mono.Cecil format for all internal fields. + /// + /// + private readonly IEnumerable> _fieldsAttributes; + + /// + /// List of custom attributes in Mono.Cecil format for all internal methods. + /// + private readonly IEnumerable> _methodsAttributes; + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// Creates new instance of object. + /// + /// + /// List of custom attributes in Mono.Cecil format for all internal types. + /// + /// + /// List of custom attributes in Mono.Cecil format for all internal fields. + /// + /// + /// List of custom attributes in Mono.Cecil format for all internal methods. + /// + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoAttributesTable( + IEnumerable> typesAttributes, + IEnumerable> fieldsAttributes, + IEnumerable> methodsAttributes, + nanoTablesContext context) + { + _typesAttributes = typesAttributes.ToList(); + _fieldsAttributes = fieldsAttributes.ToList(); + _methodsAttributes = methodsAttributes.ToList(); + + _context = context; + } + + /// + public void Write( + nanoBinaryWriter writer) + { + WriteAttributes(writer, 0x0004, _typesAttributes); + WriteAttributes(writer, 0x0005, _fieldsAttributes); + WriteAttributes(writer, 0x0006, _methodsAttributes); + } + + private void WriteAttributes( + nanoBinaryWriter writer, + ushort tableNumber, + IEnumerable> attributes) + { + foreach (var item in attributes) + { + var attribute = item.Item1; + var targetIdentifier = item.Item2; + + writer.WriteUInt16(tableNumber); + writer.WriteUInt16(targetIdentifier); + + writer.WriteUInt16(_context.GetMethodReferenceId(attribute.Constructor)); + writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(attribute)); + } + } + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs b/source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs new file mode 100644 index 00000000..b659ff59 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs @@ -0,0 +1,161 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.IO; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing method bodies (byte code) list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoByteCodeTable : InanoTable + { + /// + /// Maps method bodies (in form of byte array) to method identifiers. + /// + private readonly IList _methods = new List(); + + /// + /// Maps method full names to method RVAs (offsets in resutling table). + /// + private readonly IDictionary _rvasByMethodNames = + new Dictionary(StringComparer.Ordinal); + + /// + /// Temprorary string table for code generators used duing initial load. + /// + private readonly nanoStringTable _fakeStringTable = new nanoStringTable(); + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// Last available method RVA. + /// + private ushort _lastAvailableRva; + + /// + /// Creates new instance of object. + /// + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoByteCodeTable( + nanoTablesContext context) + { + _context = context; + } + + /// + /// Next method identifier. Used for reproducing strange original MetadataProcessor behavior. + /// + public ushort NextMethodId { get { return (ushort)_methods.Count; } } + + /// + /// Temprorary string table for code generators used duing initial load. + /// + public nanoStringTable FakeStringTable { get { return _fakeStringTable; } } + + /// + /// Returns method reference ID (index in methods definitions table) for passed method definition. + /// + /// Method definition in Mono.Cecil format. + /// + /// New method reference ID (byte code also prepared for writing as part of process). + /// + public ushort GetMethodId( + MethodDefinition method) + { + var rva = method.HasBody ? _lastAvailableRva : (ushort)0xFFFF; + var id = (ushort)_methods.Count; + + _context.NativeMethodsCrc.UpdateCrc(method); + var byteCode = CreateByteCode(method); + + _methods.Add(method); + _lastAvailableRva += (ushort)byteCode.Length; + + _rvasByMethodNames.Add(method.FullName, rva); + return id; + } + + /// + /// Returns method RVA (offset in byte code table) for passed method reference. + /// + /// Method reference in Mono.Cecil format. + /// + /// Method RVA (method should be generated using before this call. + /// + public ushort GetMethodRva( + MethodReference method) + { + ushort rva; + return (_rvasByMethodNames.TryGetValue(method.FullName, out rva) ? rva : (ushort)0xFFFF); + } + + /// + public void Write( + nanoBinaryWriter writer) + { + foreach (var method in _methods) + { + writer.WriteBytes(CreateByteCode(method, writer)); + } + } + + /// + /// Updates main string table with strings stored in temp string table before code generation. + /// + internal void UpdateStringTable() + { + _context.StringTable.MergeValues(_fakeStringTable); + } + + private byte[] CreateByteCode( + MethodDefinition method) + { + if (!method.HasBody) + { + return new byte[0]; + } + + using (var stream = new MemoryStream()) + using (var writer = new BinaryWriter(stream)) + { + var codeWriter = new CodeWriter( + method, nanoBinaryWriter.CreateBigEndianBinaryWriter(writer), + _fakeStringTable, _context); + codeWriter.WriteMethodBody(); + return stream.ToArray(); + } + } + + private byte[] CreateByteCode( + MethodDefinition method, + nanoBinaryWriter writer) + { + if (!method.HasBody) + { + return new byte[0]; + } + + using(var stream = new MemoryStream()) + { + var codeWriter = new CodeWriter( + method, writer.GetMemoryBasedClone(stream), + _context.StringTable, _context); + codeWriter.WriteMethodBody(); + return stream.ToArray(); + } + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoEmptyTable.cs b/source/MetadataProcessor.Core/Tables/nanoEmptyTable.cs new file mode 100644 index 00000000..fb441522 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoEmptyTable.cs @@ -0,0 +1,36 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Default implementation of interface. Do nothing and + /// used for emulating temporary not supported metadata tables and for last fake table. + /// + public sealed class nanoEmptyTable : InanoTable + { + /// + /// Singleton pattern - single unique instance of object. + /// + private static readonly InanoTable _instance = new nanoEmptyTable(); + + /// + /// Singleton pattern - private constructor prevents direct instantiation. + /// + private nanoEmptyTable() { } + + /// + public void Write( + nanoBinaryWriter writer) + { + } + + /// + /// Singleton pattern - gets single unique instance of object. + /// + public static InanoTable Instance { get { return _instance; } } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoFieldDefinitionTable.cs b/source/MetadataProcessor.Core/Tables/nanoFieldDefinitionTable.cs new file mode 100644 index 00000000..3d6baea0 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoFieldDefinitionTable.cs @@ -0,0 +1,189 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing fields definitions list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoFieldDefinitionTable : + nanoReferenceTableBase + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class FieldDefinitionComparer : IEqualityComparer + { + /// + public bool Equals(FieldDefinition lhs, FieldDefinition rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(FieldDefinition that) + { + return that.FullName.GetHashCode(); + } + } + + /// + /// Maximal returned field reference id - used for emulating old MetadataProcessor behavior. + /// + private int _maxReferenceId; + + /// + /// Creates new instance of object. + /// + /// List of field definitions in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoFieldDefinitionTable( + IEnumerable items, + nanoTablesContext context) + : base(items, new FieldDefinitionComparer(), context) + { + } + + /// + /// Gets maximal returned field reference id - used for emulating old MetadataProcessor behavior. + /// + public ushort MaxFieldId { get { return (ushort)_maxReferenceId; } } + + /// + protected override void WriteSingleItem( + nanoBinaryWriter writer, + FieldDefinition item) + { + WriteStringReference(writer, item.Name); + writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(item)); + + writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(item.InitialValue)); + writer.WriteUInt16(GetFlags(item)); + } + + /// + /// Gets field reference identifier (if field is defined inside target assembly). + /// + /// Field definition in Mono.Cecil format. + /// If set to true we should track max ID value. + /// Field reference identifier for filling. + /// Returns true if item found, otherwise returns false. + public bool TryGetFieldReferenceId( + FieldDefinition field, + bool trackMaxReferenceId, + out ushort referenceId) + { + var found = TryGetIdByValue(field, out referenceId); + if (trackMaxReferenceId && found) + { + _maxReferenceId = Math.Max(_maxReferenceId, referenceId + 1); + } + return found; + } + + private ushort GetFlags( + FieldDefinition field) + { + const ushort FD_Scope_Private = 0x0001; // Accessible only by the parent type. + const ushort FD_Scope_FamANDAssem = 0x0002; // Accessible by sub-types only in this Assembly. + const ushort FD_Scope_Assembly = 0x0003; // Accessibly by anyone in the Assembly. + const ushort FD_Scope_Family = 0x0004; // Accessible only by type and sub-types. + const ushort FD_Scope_FamORAssem = 0x0005; // Accessibly by sub-types anywhere, plus anyone in assembly. + const ushort FD_Scope_Public = 0x0006; // Accessibly by anyone who has visibility to this scope. + + const ushort FD_NotSerialized = 0x0008; // Field does not have to be serialized when type is remoted. + + const ushort FD_Static = 0x0010; // Defined on type, else per instance. + const ushort FD_InitOnly = 0x0020; // Field may only be initialized, not written to after init. + const ushort FD_Literal = 0x0040; // Value is compile time constant. + + const ushort FD_SpecialName = 0x0100; // field is special. Name describes how. + const ushort FD_HasDefault = 0x0200; // Field has default. + const ushort FD_HasFieldRVA = 0x0400; // Field has RVA. + + const ushort FD_NoReflection = 0x0800; // field does not allow reflection + + const ushort FD_HasAttributes = 0x8000; + + ushort flag = 0; + + if (field.IsPrivate) + { + flag = FD_Scope_Private; + } + else if (field.IsFamilyAndAssembly) + { + flag = FD_Scope_FamANDAssem; + } + else if (field.IsFamilyOrAssembly) + { + flag = FD_Scope_FamORAssem; + } + else if (field.IsAssembly) + { + flag = FD_Scope_Assembly; + } + else if (field.IsFamily) + { + flag = FD_Scope_Family; + } + else if (field.IsPublic) + { + flag = FD_Scope_Public; + } + + if (field.IsNotSerialized) + { + flag |= FD_NotSerialized; + } + + if (field.IsStatic) + { + flag |= FD_Static; + } + + if (field.IsInitOnly) + { + flag |= FD_InitOnly; + } + + if (field.IsLiteral) + { + flag |= FD_Literal; + } + + if (field.IsSpecialName) + { + flag |= FD_SpecialName; + } + + if (field.HasDefault) + { + flag |= FD_HasDefault; + } + + if (field.HasCustomAttributes) + { + flag |= FD_HasAttributes; + } + + if (field.RVA != 0) + { + flag |= FD_HasFieldRVA; + } + + return flag; + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoFieldReferenceTable.cs b/source/MetadataProcessor.Core/Tables/nanoFieldReferenceTable.cs new file mode 100644 index 00000000..3be40f05 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoFieldReferenceTable.cs @@ -0,0 +1,81 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing member (methods or fields) references list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoFieldReferenceTable : + nanoReferenceTableBase + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class MemberReferenceComparer : IEqualityComparer + { + /// + public bool Equals(FieldReference lhs, FieldReference rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(FieldReference that) + { + return that.FullName.GetHashCode(); + } + } + + /// + /// Creates new instance of object. + /// + /// List of member references in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoFieldReferenceTable( + IEnumerable items, + nanoTablesContext context) + : base(items, new MemberReferenceComparer(), context) + { + } + + /// + /// Gets field reference ID if possible (if field is external and stored in this table). + /// + /// Field reference metadata in Mono.Cecil format. + /// Field reference ID in .NET nanoFramework format. + /// Returns true if reference found, otherwise returns false. + public bool TryGetFieldReferenceId( + FieldReference fieldReference, + out ushort referenceId) + { + return TryGetIdByValue(fieldReference, out referenceId); + } + + /// + protected override void WriteSingleItem( + nanoBinaryWriter writer, + FieldReference item) + { + ushort referenceId; + _context.TypeReferencesTable.TryGetTypeReferenceId(item.DeclaringType, out referenceId); + + WriteStringReference(writer, item.Name); + writer.WriteUInt16(referenceId); + + writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(item)); + writer.WriteUInt16(0); // padding + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoMethodDefinitionTable.cs b/source/MetadataProcessor.Core/Tables/nanoMethodDefinitionTable.cs new file mode 100644 index 00000000..0d4d1267 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoMethodDefinitionTable.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using Mono.Cecil; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing methods definitions list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoMethodDefinitionTable : + nanoReferenceTableBase + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class MethodDefinitionComparer : IEqualityComparer + { + /// + public bool Equals(MethodDefinition lhs, MethodDefinition rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(MethodDefinition that) + { + return that.FullName.GetHashCode(); + } + } + + /// + /// Creates new instance of object. + /// + /// List of methods definitions in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoMethodDefinitionTable( + IEnumerable items, + nanoTablesContext context) + :base(items, new MethodDefinitionComparer(), context) + { + } + + /// + /// Gets method reference identifier (if method is defined inside target assembly). + /// + /// Method definition in Mono.Cecil format. + /// Method definition reference identifier for filling. + /// Returns true if item found, otherwise returns false. + public bool TryGetMethodReferenceId( + MethodDefinition methodDefinition, + out ushort referenceId) + { + return TryGetIdByValue(methodDefinition, out referenceId); + } + + /// + protected override void WriteSingleItem( + nanoBinaryWriter writer, + MethodDefinition item) + { + WriteStringReference(writer, item.Name); + writer.WriteUInt16(_context.ByteCodeTable.GetMethodRva(item)); + + writer.WriteUInt32(GetFlags(item)); + + var parametersCount = (byte)item.Parameters.Count; + if (!item.IsStatic) + { + ++parametersCount; // add implicit 'this' pointer into non-static methods + } + + _context.SignaturesTable.WriteDataType(item.ReturnType, writer, false, false); + if (item.ReturnType is TypeSpecification) + { + _context.TypeSpecificationsTable + .GetOrCreateTypeSpecificationId(item.ReturnType); + } + + writer.WriteByte(parametersCount); + writer.WriteByte((byte)(item.HasBody ? item.Body.Variables.Count : 0)); + writer.WriteByte(CodeWriter.CalculateStackSize(item.Body)); + + var methodSignature = _context.SignaturesTable.GetOrCreateSignatureId(item); + writer.WriteUInt16(item.HasBody ? + _context.SignaturesTable.GetOrCreateSignatureId(item.Body.Variables) : + (item.IsAbstract || item.IsRuntime ? (ushort)0x0000 : (ushort)0xFFFF)); + writer.WriteUInt16(methodSignature); + } + + private uint GetFlags( + MethodDefinition method) + { + const uint MD_Scope_Private = 0x00000001; // Accessible only by the parent type. + const uint MD_Scope_FamANDAssem = 0x00000002; // Accessible by sub-types only in this Assembly. + const uint MD_Scope_Assem = 0x00000003; // Accessibly by anyone in the Assembly. + const uint MD_Scope_Family = 0x00000004; // Accessible only by type and sub-types. + const uint MD_Scope_FamORAssem = 0x00000005; // Accessibly by sub-types anywhere, plus anyone in assembly. + const uint MD_Scope_Public = 0x00000006; // Accessibly by anyone who has visibility to this scope. + + const uint MD_Static = 0x00000010; // Defined on type, else per instance. + const uint MD_Final = 0x00000020; // Method may not be overridden. + const uint MD_Virtual = 0x00000040; // Method virtual. + const uint MD_HideBySig = 0x00000080; // Method hides by name+sig, else just by name. + + const uint MD_ReuseSlot = 0x00000000; // The default. + const uint MD_NewSlot = 0x00000100; // Method always gets a new slot in the vtable. + const uint MD_Abstract = 0x00000200; // Method does not provide an implementation. + const uint MD_SpecialName = 0x00000400; // Method is special. Name describes how. + const uint MD_NativeProfiled = 0x00000800; + + const uint MD_Constructor = 0x00001000; + const uint MD_StaticConstructor = 0x00002000; + const uint MD_Finalizer = 0x00004000; + + const uint MD_DelegateConstructor = 0x00010000; + const uint MD_DelegateInvoke = 0x00020000; + const uint MD_DelegateBeginInvoke = 0x00040000; + const uint MD_DelegateEndInvoke = 0x00080000; + + const uint MD_Synchronized = 0x01000000; + const uint MD_GloballySynchronized = 0x02000000; + const uint MD_Patched = 0x04000000; + const uint MD_EntryPoint = 0x08000000; + const uint MD_RequireSecObject = 0x10000000; // Method calls another method containing security code. + const uint MD_HasSecurity = 0x20000000; // Method has security associate with it. + const uint MD_HasExceptionHandlers = 0x40000000; + const uint MD_HasAttributes = 0x80000000; + + uint flag = 0; + if (method.IsPrivate) + { + flag = MD_Scope_Private; + } + else if (method.IsFamilyAndAssembly) + { + flag = MD_Scope_FamANDAssem; + } + else if (method.IsFamilyOrAssembly) + { + flag = MD_Scope_FamORAssem; + } + else if (method.IsAssembly) + { + flag = MD_Scope_Assem; + } + else if (method.IsFamily) + { + flag = MD_Scope_Family; + } + else if (method.IsPublic) + { + flag = MD_Scope_Public; + } + + if (method.IsStatic) + { + flag |= MD_Static; + } + if (method.IsFinal) + { + flag |= MD_Final; + } + if (method.IsVirtual) + { + flag |= MD_Virtual; + } + if (method.IsHideBySig) + { + flag |= MD_HideBySig; + } + + if (method.IsReuseSlot) + { + flag |= MD_ReuseSlot; + } + if (method.IsNewSlot) + { + flag |= MD_NewSlot; + } + if (method.IsAbstract) + { + flag |= MD_Abstract; + } + if (method.IsSpecialName) + { + flag |= MD_SpecialName; + } + if (method.IsNative) + { + flag |= MD_NativeProfiled; // ??? + } + + if (method.IsConstructor) + { + flag |= (method.IsStatic ? MD_StaticConstructor : MD_Constructor); + } + + if (method.IsSynchronized) + { + flag |= MD_Synchronized; + } + if (method.HasCustomAttributes) + { + flag |= MD_HasAttributes; // ??? + } + + if (method == method.Module.EntryPoint) + { + flag |= MD_EntryPoint; + } + + if (method.HasBody && method.Body.HasExceptionHandlers) + { + flag |= MD_HasExceptionHandlers; + } + + var baseType = method.DeclaringType.BaseType; + if (baseType != null && baseType.FullName == "System.MulticastDelegate") + { + if (method.IsConstructor) + { + flag |= MD_DelegateConstructor; + } + else if (method.Name == "Invoke") + { + flag |= MD_DelegateInvoke; + } + else if (method.Name == "BeginInvoke") + { + flag |= MD_DelegateBeginInvoke; + } + else if (method.Name == "EndInvoke") + { + flag |= MD_DelegateEndInvoke; + } + } + return flag; + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoMethodReferenceTable.cs b/source/MetadataProcessor.Core/Tables/nanoMethodReferenceTable.cs new file mode 100644 index 00000000..324bdabe --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoMethodReferenceTable.cs @@ -0,0 +1,81 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing methods references list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoMethodReferenceTable : + nanoReferenceTableBase + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class MemberReferenceComparer : IEqualityComparer + { + /// + public bool Equals(MethodReference lhs, MethodReference rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(MethodReference that) + { + return that.FullName.GetHashCode(); + } + } + + /// + /// Creates new instance of object. + /// + /// List of member references in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoMethodReferenceTable( + IEnumerable items, + nanoTablesContext context) + : base(items, new MemberReferenceComparer(), context) + { + } + + /// + /// Gets method reference ID if possible (if method is external and stored in this table). + /// + /// Method reference metadata in Mono.Cecil format. + /// Method reference ID in .NET nanoFramework format. + /// Returns true if reference found, otherwise returns false. + public bool TryGetMethodReferenceId( + MethodReference methodReference, + out ushort referenceId) + { + return TryGetIdByValue(methodReference, out referenceId); + } + + /// + protected override void WriteSingleItem( + nanoBinaryWriter writer, + MethodReference item) + { + ushort referenceId; + _context.TypeReferencesTable.TryGetTypeReferenceId(item.DeclaringType, out referenceId); + + WriteStringReference(writer, item.Name); + writer.WriteUInt16(referenceId); + + writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(item)); + writer.WriteUInt16(0); // padding + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoReferenceTableBase.cs b/source/MetadataProcessor.Core/Tables/nanoReferenceTableBase.cs new file mode 100644 index 00000000..b61de963 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoReferenceTableBase.cs @@ -0,0 +1,139 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Base class for all metadata tables with lookup functionality. Stores items in Mono.Cecil + /// format in dictionary and allows to get item ID by item value (using custom comparer). + /// + /// Type of stored metadata item (in Mono.Cecil format). + public abstract class nanoReferenceTableBase : InanoTable + { + /// + /// Lookup table for finding item ID by item value. + /// + private readonly Dictionary _idsByItemsDictionary; + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + protected readonly nanoTablesContext _context; + + /// + /// Creates new instance of object. + /// + /// List of items for initial loading. + /// Custom comparer for items (type-specific). + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + protected nanoReferenceTableBase( + IEnumerable tinyTableItems, + IEqualityComparer comparer, + nanoTablesContext context) + { + _idsByItemsDictionary = tinyTableItems + .Select((reference, index) => new { reference, index }) + .ToDictionary(item => item.reference, item => (ushort)item.index, + comparer); + + _context = context; + } + + /// + public void Write( + nanoBinaryWriter writer) + { + foreach (var item in _idsByItemsDictionary + .OrderBy(item => item.Value) + .Select(item => item.Key)) + { + WriteSingleItem(writer, item); + } + } + + public void ForEachItems(Action action) + { + foreach (var item in _idsByItemsDictionary + .OrderBy(item => item.Value)) + { + action(item.Value, item.Key); + } + } + + /// + /// Helper method for allocating strings from table before table will be written. + /// + public void AllocateStrings() + { + foreach (var item in _idsByItemsDictionary + .OrderBy(item => item.Value) + .Select(item => item.Key)) + { + AllocateSingleItemStrings(item); + } + } + + /// + /// Writes string reference ID related to passed string value into output stream. + /// + /// Target binary writer for writing reference ID. + /// String value for obtaining reference and writing. + protected void WriteStringReference( + nanoBinaryWriter writer, + string value) + { + writer.WriteUInt16(GetOrCreateStringId(value)); + } + + /// + /// Gets existing or creates new string reference ID for provided string value. + /// + /// String value for lookup in string literals table. + /// String reference ID which can be used for filling metadata and byte code. + protected ushort GetOrCreateStringId( + string value) + { + return _context.StringTable.GetOrCreateStringId(value); + } + + /// + /// Helper method for lookup in internal dictionary. Wraps + /// method. + /// + /// Key value for lookup. + /// Item reference identifier. + /// Returns true if item found, otherwise returns false. + protected bool TryGetIdByValue( + T key, + out ushort id) + { + return _idsByItemsDictionary.TryGetValue(key, out id); + } + + /// + /// Provides concrete implementation for string allocation method in this table. + /// + /// Table item for allocating strings. + protected virtual void AllocateSingleItemStrings(T item) + { + } + + /// + /// Inherited class should provides concrete implementation for writing single table item here. + /// + /// Target binary writer for writing item data. + /// Single table item for writing into ouptut stream. + protected abstract void WriteSingleItem( + nanoBinaryWriter writer, + T item); + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoResourceDataTable.cs b/source/MetadataProcessor.Core/Tables/nanoResourceDataTable.cs new file mode 100644 index 00000000..fa131284 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoResourceDataTable.cs @@ -0,0 +1,62 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing concrete resource data items list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoResourceDataTable : InanoTable + { + /// + /// List of registered resouce data for writing into output stream "as is". + /// + private readonly IList _dataByteArrays = new List(); + + /// + /// Gets current offset in resrouces data table (total size of all data blocks). + /// + public int CurrentOffset { get; private set; } + + /// + /// Adds new chunk of binary data for resouces into list of resources. + /// + /// Resouce data in binary format. + public void AddResourceData( + byte[] resourceData) + { + _dataByteArrays.Add(resourceData); + CurrentOffset += resourceData.Length; + } + + /// + public void Write( + nanoBinaryWriter writer) + { + foreach (var item in _dataByteArrays) + { + writer.WriteBytes(item); + } + } + + /// + /// Aligns current data in table by word boundary and return size of alignment. + /// + /// Number of bytes added into bytes block for proper data alignment. + public int AlignToWord() + { + var padding = (4 - (CurrentOffset % 4)) % 4; + if (padding != 0) + { + AddResourceData(new byte[padding]); + } + return padding; + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoResourceFileTable.cs b/source/MetadataProcessor.Core/Tables/nanoResourceFileTable.cs new file mode 100644 index 00000000..01f77ab9 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoResourceFileTable.cs @@ -0,0 +1,79 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.IO; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing resource files definitions list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoResourceFileTable : InanoTable + { + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// List of resource fiels data for producing correct output records. + /// + private readonly IList> _resouces = new List>(); + + /// + /// Creates new instance of object. + /// + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoResourceFileTable( + nanoTablesContext context) + { + _context = context; + } + + /// + /// Adds infromation about embedded resource file in Mono.Cecil format into list. + /// + /// Embedded resouce file information in Mono.Cecil format. + /// Number of recource items in this resouce file. + public void AddResourceFile( + EmbeddedResource item, + uint count) + { + var correctFileName = Path.ChangeExtension(item.Name, ".tinyresources"); + var nameStringId = _context.StringTable.GetOrCreateStringId(correctFileName); + + _resouces.Add(new Tuple(nameStringId, count)); + } + + /// + public void Write( + nanoBinaryWriter writer) + { + var offset = 0U; + foreach (var item in _resouces) + { + writer.WriteUInt32(0x02); // Version + writer.WriteUInt32(0x04); // Size of header + writer.WriteUInt32(0x08); // Size of resouce header + + writer.WriteUInt32(item.Item2); + + writer.WriteUInt16(item.Item1); + writer.WriteUInt16(0x0); // paddding + + writer.WriteUInt32(offset); + offset += 8; // Size of resource table record + } + + } + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Tables/nanoResourcesTable.cs b/source/MetadataProcessor.Core/Tables/nanoResourcesTable.cs new file mode 100644 index 00000000..8b69e16f --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoResourcesTable.cs @@ -0,0 +1,208 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Resources; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing embedded resources list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoResourcesTable : InanoTable + { + private enum ResourceKind : byte + { + None = 0x00, + Bitmap = 0x01, + Font = 0x02, + String = 0x03, + Binary = 0x04 + } + + private const uint FONT_HEADER_MAGIC = 0xf995b0a8; + + /// + /// Original list of resouces in Mono.Cecil format. + /// + private readonly IEnumerable _resources; + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// Creates new instance of object. + /// + /// Original list of resouces in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoResourcesTable( + IEnumerable resources, + nanoTablesContext context) + { + _resources = resources.ToList(); + _context = context; + } + + /// + public void Write( + nanoBinaryWriter writer) + { + var orderedResources = new SortedDictionary>(); + foreach (var item in _resources.OfType()) + { + var count = 0U; + using (var reader = new ResourceReader(item.GetResourceStream())) + { + foreach (DictionaryEntry resource in reader) + { + string resourceType; + byte[] resourceData; + var resourceName = resource.Key.ToString(); + + reader.GetResourceData(resourceName, out resourceType, out resourceData); + + var kind = GetResourceKind(resourceType, resourceData); + + if (kind == ResourceKind.Bitmap) + { + using (var stream = new MemoryStream(resourceData.Length)) + { + var bitmapProcessor = new nanoBitmapProcessor((Bitmap)resource.Value); + bitmapProcessor.Process(writer.GetMemoryBasedClone(stream)); + resourceData = stream.ToArray(); + } + } + + orderedResources.Add(GenerateIdFromResourceName(resourceName), + new Tuple(kind, resourceData)); + + ++count; + } + } + + _context.ResourceFileTable.AddResourceFile(item, count); + } + + foreach (var item in orderedResources) + { + var kind = item.Value.Item1; + var bytes = item.Value.Item2; + + var padding = 0; + switch (kind) + { + case ResourceKind.String: + var stringLength = (int)bytes[0]; + if (stringLength < 0x7F) + { + bytes = bytes.Skip(1).Concat(Enumerable.Repeat((byte)0, 1)).ToArray(); + } + else + { + bytes = bytes.Skip(2).Concat(Enumerable.Repeat((byte)0, 1)).ToArray(); + } + break; + case ResourceKind.Bitmap: + padding = _context.ResourceDataTable.AlignToWord(); + break; + case ResourceKind.Binary: + bytes = bytes.Skip(4).ToArray(); + break; + case ResourceKind.Font: + padding = _context.ResourceDataTable.AlignToWord(); + bytes = bytes.Skip(32).ToArray(); // File size + resource header size + break; + } + + // Pre-process font data (swap endiannes if needed). + if (kind == ResourceKind.Font) + { + using (var stream = new MemoryStream(bytes.Length)) + { + var fontProcessor = new nanoFontProcessor(bytes); + fontProcessor.Process(writer.GetMemoryBasedClone(stream)); + bytes = stream.ToArray(); + } + } + + writer.WriteInt16(item.Key); + writer.WriteByte((byte)kind); + writer.WriteByte((byte)padding); + writer.WriteInt32(_context.ResourceDataTable.CurrentOffset); + + _context.ResourceDataTable.AddResourceData(bytes); + } + + if (orderedResources.Count != 0) + { + writer.WriteInt16(0x7FFF); + writer.WriteByte((byte)ResourceKind.None); + writer.WriteByte(0x00); + writer.WriteInt32(_context.ResourceDataTable.CurrentOffset); + } + } + + private static ResourceKind GetResourceKind( + string resourceType, + byte[] resourceData) + { + if (resourceType.EndsWith(".String")) + { + return ResourceKind.String; + } + + if (resourceType.StartsWith("System.Drawing.Bitmap")) + { + return ResourceKind.Bitmap; + } + + using(var stream = new MemoryStream(resourceData)) + using (var reader = new BinaryReader(stream)) + { + var size = reader.ReadUInt32(); + return (size > 4 && reader.ReadUInt32() == FONT_HEADER_MAGIC + ? ResourceKind.Font + : ResourceKind.Binary); + } + } + + private static short GenerateIdFromResourceName( + string value) + { + var hash1 = (5381 << 16) + 5381; + var hash2 = hash1; + + for (var i = 0; i < value.Length; ++i) + { + var c = value[i]; + if (i % 2 == 0) + { + hash1 = ((hash1 << 5) + hash1) ^ c; + } + else + { + hash2 = ((hash2 << 5) + hash2) ^ c; + } + } + + var hash = hash1 + (hash2 * 1566083941); + + return (short)((short)(hash >> 16) ^ (short)hash); + } + + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoSignaturesTable.cs b/source/MetadataProcessor.Core/Tables/nanoSignaturesTable.cs new file mode 100644 index 00000000..eced3911 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoSignaturesTable.cs @@ -0,0 +1,591 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing member (methods or fields) signatures list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoSignaturesTable : InanoTable + { + /// + /// Helper class for comparing two instances of objects + /// using full array content for comparison (length of arrays also should be equal). + /// + private sealed class ByteArrayComparer : IEqualityComparer + { + /// + public bool Equals(byte[] lhs, byte[] rhs) + { + return (lhs.Length == rhs.Length && lhs.SequenceEqual(rhs)); + } + + /// + public int GetHashCode(byte[] that) + { + return that.Aggregate(37, (hash, item) => item ^ hash); + } + } + + private static readonly IDictionary _primitiveTypes = + new Dictionary(StringComparer.Ordinal); + + static nanoSignaturesTable() + { + _primitiveTypes.Add(typeof(void).FullName, nanoCLR_DataType.DATATYPE_VOID); + + _primitiveTypes.Add(typeof(sbyte).FullName, nanoCLR_DataType.DATATYPE_I1); + _primitiveTypes.Add(typeof(short).FullName, nanoCLR_DataType.DATATYPE_I2); + _primitiveTypes.Add(typeof(int).FullName, nanoCLR_DataType.DATATYPE_I4); + _primitiveTypes.Add(typeof(long).FullName, nanoCLR_DataType.DATATYPE_I8); + + _primitiveTypes.Add(typeof(byte).FullName, nanoCLR_DataType.DATATYPE_U1); + _primitiveTypes.Add(typeof(ushort).FullName, nanoCLR_DataType.DATATYPE_U2); + _primitiveTypes.Add(typeof(uint).FullName, nanoCLR_DataType.DATATYPE_U4); + _primitiveTypes.Add(typeof(ulong).FullName, nanoCLR_DataType.DATATYPE_U8); + + _primitiveTypes.Add(typeof(float).FullName, nanoCLR_DataType.DATATYPE_R4); + _primitiveTypes.Add(typeof(double).FullName, nanoCLR_DataType.DATATYPE_R8); + + _primitiveTypes.Add(typeof(char).FullName, nanoCLR_DataType.DATATYPE_CHAR); + _primitiveTypes.Add(typeof(string).FullName, nanoCLR_DataType.DATATYPE_STRING); + _primitiveTypes.Add(typeof(bool).FullName, nanoCLR_DataType.DATATYPE_BOOLEAN); + + _primitiveTypes.Add(typeof(object).FullName, nanoCLR_DataType.DATATYPE_OBJECT); + _primitiveTypes.Add(typeof(IntPtr).FullName, nanoCLR_DataType.DATATYPE_I4); + _primitiveTypes.Add(typeof(UIntPtr).FullName, nanoCLR_DataType.DATATYPE_U4); + } + + /// + /// Stores list of unique signatures and corresspoinding identifiers. + /// + private readonly IDictionary _idsBySignatures = + new Dictionary(new ByteArrayComparer()); + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// Last available signature id (offset in resulting table). + /// + private ushort _lastAvailableId; + + /// + /// Creates new instance of object. + /// + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoSignaturesTable( + nanoTablesContext context) + { + _context = context; + } + + /// + /// Gets existing or creates new singature identifier for method definition. + /// + /// Method definition in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + MethodDefinition methodDefinition) + { + return GetOrCreateSignatureIdImpl(GetSignature(methodDefinition)); + } + + /// + /// Gets existing or creates new singature identifier for field definition. + /// + /// Field definition in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + FieldDefinition fieldDefinition) + { + return GetOrCreateSignatureIdImpl(GetSignature(fieldDefinition.FieldType, true)); + } + + /// + /// Gets existing or creates new singature identifier for field reference. + /// + /// Field reference in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + FieldReference fieldReference) + { + return GetOrCreateSignatureIdImpl(GetSignature(fieldReference)); + } + + /// + /// Gets existing or creates new singature identifier for member reference. + /// + /// Method reference in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + MethodReference methodReference) + { + return GetOrCreateSignatureIdImpl(GetSignature(methodReference)); + } + + /// + /// Gets existing or creates new singature identifier for list of local variables. + /// + /// List of variables information in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + Collection variables) + { + if (variables == null || variables.Count == 0) + { + return 0xFFFF; // No local variables + } + + return GetOrCreateSignatureIdImpl(GetSignature(variables)); + } + + /// + /// Gets existing or creates new singature identifier for list of class interfaces. + /// + /// List of interfaes information in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + Collection interfaces) + { + if (interfaces == null || interfaces.Count == 0) + { + return 0xFFFF; // No implemented interfaces + } + + return GetOrCreateSignatureIdImpl(GetSignature(interfaces)); + } + + /// + /// Gets existing or creates new field default value (just writes value as is with size). + /// + /// Default field value in binary format. + public ushort GetOrCreateSignatureId( + byte[] defaultValue) + { + if (defaultValue == null || defaultValue.Length == 0) + { + return 0xFFFF; // No default value + } + + return GetOrCreateSignatureIdImpl(GetSignature(defaultValue)); + } + + /// + /// Gets existing or creates new type reference signature (used for encoding type specification). + /// + /// Interface implementation in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + InterfaceImplementation interfaceImplementation) + { + return GetOrCreateSignatureIdImpl(GetSignature(interfaceImplementation, false)); + } + + /// + /// Gets existing or creates new type reference signature (used for encoding type specification). + /// + /// Type reference in Mono.Cecil format. + public ushort GetOrCreateSignatureId( + TypeReference typeReference) + { + return GetOrCreateSignatureIdImpl(GetSignature(typeReference, false)); + } + + /// + /// Gets existing or creates new custom attribute signature. + /// + /// Custom attribute in Mono.Cecil format. + public ushort GetOrCreateSignatureId(CustomAttribute customAttribute) + { + return GetOrCreateSignatureIdImpl(GetSignature(customAttribute)); + } + + /// + /// Writes data tzpe signature into ouput stream. + /// + /// Tzpe reference or definition in Mono.Cecil format. + /// Target binary writer for writing signature information. + /// If set to true also sub-type will be written. + /// If set to true expand enum with base type. + public void WriteDataType( + TypeReference typeDefinition, + nanoBinaryWriter writer, + bool alsoWriteSubType, + bool expandEnumType) + { + nanoCLR_DataType dataType; + if (_primitiveTypes.TryGetValue(typeDefinition.FullName, out dataType)) + { + writer.WriteByte((byte)dataType); + return; + } + + if (typeDefinition is TypeSpecification) + { + //Debug.Fail("Gotcha!"); + } + + if (typeDefinition.MetadataType == MetadataType.Class) + { + writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_CLASS); + if (alsoWriteSubType) + { + WriteSubTypeInfo(typeDefinition, writer); + } + return; + } + + if (typeDefinition.MetadataType == MetadataType.ValueType) + { + var resolvedType = typeDefinition.Resolve(); + if (resolvedType != null && resolvedType.IsEnum && expandEnumType) + { + var baseTypeValue = resolvedType.Fields.FirstOrDefault(item => item.IsSpecialName); + if (baseTypeValue != null) + { + WriteTypeInfo(baseTypeValue.FieldType, writer); + return; + } + } + + writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_VALUETYPE); + if (alsoWriteSubType) + { + WriteSubTypeInfo(typeDefinition, writer); + } + return; + } + + if (typeDefinition.IsArray) + { + writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_SZARRAY); + + if (alsoWriteSubType) + { + var array = (ArrayType)typeDefinition; + WriteDataType(array.ElementType, writer, true, expandEnumType); + } + return; + } + + writer.WriteByte(0x00); + } + + /// + public void Write( + nanoBinaryWriter writer) + { + foreach (var signature in _idsBySignatures + .OrderBy(item => item.Value) + .Select(item => item.Key)) + { + writer.WriteBytes(signature); + } + } + + private byte[] GetSignature( + FieldReference fieldReference) + { + using (var buffer = new MemoryStream()) + using (var writer = new BinaryWriter(buffer)) // Only Write(Byte) will be used + { + var binaryWriter = nanoBinaryWriter.CreateBigEndianBinaryWriter(writer); + + binaryWriter.WriteByte(0x06); // Field reference calling convention + WriteTypeInfo(fieldReference.FieldType, binaryWriter); + + return buffer.ToArray(); + } + } + + private byte[] GetSignature( + IMethodSignature methodReference) + { + using (var buffer = new MemoryStream()) + using (var writer = new BinaryWriter(buffer)) // Only Write(Byte) will be used + { + var binaryWriter = nanoBinaryWriter.CreateLittleEndianBinaryWriter(writer); + writer.Write((byte)(methodReference.HasThis ? 0x20 : 0x00)); + + writer.Write((byte)(methodReference.Parameters.Count)); + + WriteTypeInfo(methodReference.ReturnType, binaryWriter); + foreach (var parameter in methodReference.Parameters) + { + WriteTypeInfo(parameter.ParameterType, binaryWriter); + } + + return buffer.ToArray(); + } + } + + private byte[] GetSignature( + IEnumerable variables) + { + using (var buffer = new MemoryStream()) + using (var writer = new BinaryWriter(buffer)) // Only Write(Byte) will be used + { + var binaryWriter = nanoBinaryWriter.CreateBigEndianBinaryWriter(writer); + foreach (var variable in variables) + { + WriteTypeInfo(variable.VariableType, binaryWriter); + } + + return buffer.ToArray(); + } + } + + private byte[] GetSignature( + Collection interfaces) + { + using (var buffer = new MemoryStream()) + using (var writer = new BinaryWriter(buffer)) // Only Write(Byte) will be used + { + var binaryWriter = nanoBinaryWriter.CreateBigEndianBinaryWriter(writer); + + binaryWriter.WriteByte((byte)interfaces.Count); + foreach (var item in interfaces) + { + WriteSubTypeInfo(item.InterfaceType, binaryWriter); + } + + return buffer.ToArray(); + } + } + + private byte[] GetSignature( + TypeReference typeReference, + bool isFieldSignature) + { + using (var buffer = new MemoryStream()) + using (var writer = new BinaryWriter(buffer)) // Only Write(Byte) will be used + { + var binaryWriter = nanoBinaryWriter.CreateBigEndianBinaryWriter(writer); + + if (isFieldSignature) + { + writer.Write((byte)0x06); // Field signature prefix + } + WriteTypeInfo(typeReference, binaryWriter); + + return buffer.ToArray(); + } + } + + private byte[] GetSignature( + InterfaceImplementation typeReference, + bool isFieldSignature) + { + return GetSignature(typeReference.InterfaceType, isFieldSignature); + } + + private byte[] GetSignature( + byte[] defaultValue) + { + using (var buffer = new MemoryStream()) + using (var writer = new BinaryWriter(buffer)) + { + writer.Write((byte)defaultValue.Length); + writer.Write((byte)0x00); // TODO: investigate this temporary fix + writer.Write(defaultValue); + + return buffer.ToArray(); + } + } + + private byte[] GetSignature( + CustomAttribute customAttribute) + { + using (var buffer = new MemoryStream()) + using (var writer = new BinaryWriter(buffer)) + { + foreach (var argument in customAttribute.ConstructorArguments) + { + WriteAttributeArgumentValue(writer, argument); + } + + // TODO: use compressed format + writer.Write((ushort)(customAttribute.Properties.Count + customAttribute.Fields.Count)); + + foreach (var namedArgument in customAttribute.Fields.OrderBy(item => item.Name)) + { + writer.Write((byte)nanoSerializationType.SERIALIZATION_TYPE_FIELD); + writer.Write(_context.StringTable.GetOrCreateStringId(namedArgument.Name)); + WriteAttributeArgumentValue(writer, namedArgument.Argument); + } + + foreach (var namedArgument in customAttribute.Properties.OrderBy(item => item.Name)) + { + writer.Write((byte)nanoSerializationType.SERIALIZATION_TYPE_PROPERTY); + writer.Write(_context.StringTable.GetOrCreateStringId(namedArgument.Name)); + WriteAttributeArgumentValue(writer, namedArgument.Argument); + } + + return buffer.ToArray(); + } + } + + private void WriteAttributeArgumentValue( + BinaryWriter writer, + CustomAttributeArgument argument) + { + nanoCLR_DataType dataType; + if (_primitiveTypes.TryGetValue(argument.Type.FullName, out dataType)) + { + switch (dataType) + { + case nanoCLR_DataType.DATATYPE_BOOLEAN: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_BOOLEAN); + writer.Write((byte)((bool)argument.Value ? 1 : 0)); + break; + case nanoCLR_DataType.DATATYPE_I1: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_I1); + writer.Write((sbyte)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_U1: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_U1); + writer.Write((byte)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_I2: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_I2); + writer.Write((short)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_U2: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_U2); + writer.Write((ushort)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_I4: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_I4); + writer.Write((int)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_U4: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_U4); + writer.Write((uint)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_I8: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_I8); + writer.Write((long)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_U8: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_U8); + writer.Write((ulong)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_R4: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_R4); + writer.Write((float)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_R8: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_R8); + writer.Write((double)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_CHAR: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_CHAR); + writer.Write((char)argument.Value); + break; + case nanoCLR_DataType.DATATYPE_STRING: + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_STRING); + writer.Write(_context.StringTable.GetOrCreateStringId((string)argument.Value)); + break; + default: + Debug.Fail(dataType.ToString()); + break; + } + } + if (argument.Type.FullName == "System.Type") + { + writer.Write((byte)nanoSerializationType.ELEMENT_TYPE_STRING); + writer.Write(_context.StringTable.GetOrCreateStringId(((TypeReference)argument.Value).FullName)); + } + } + + private ushort GetOrCreateSignatureIdImpl( + byte[] signature) + { + ushort id; + if (_idsBySignatures.TryGetValue(signature, out id)) + { + return id; + } + + var fullSignatures = GetFullSignaturesArray(); + for (var i = 0; i < fullSignatures.Length - signature.Length; ++i) + { + if (signature.SequenceEqual(fullSignatures.Skip(i).Take(signature.Length))) + { + return (ushort)i; + } + } + + id = _lastAvailableId; + _idsBySignatures.Add(signature, id); + _lastAvailableId += (ushort)signature.Length; + + return id; + } + + private void WriteTypeInfo( + TypeReference typeReference, + nanoBinaryWriter writer) + { + if (typeReference.IsOptionalModifier) + { + writer.WriteByte(0); // OpTypeModifier ??? + } + + var byReference = typeReference as ByReferenceType; + if (byReference != null) + { + writer.WriteByte((byte)nanoCLR_DataType.DATATYPE_BYREF); + WriteDataType(byReference.ElementType, writer, true, false); + } + else + { + WriteDataType(typeReference, writer, true, false); + } + } + + private byte[] GetFullSignaturesArray() + { + return _idsBySignatures + .OrderBy(item => item.Value) + .Select(item => item.Key) + .Aggregate(new List(), + (current, item) => + { + current.AddRange(item); + return current; + }) + .ToArray(); + } + + private void WriteSubTypeInfo(TypeReference typeDefinition, nanoBinaryWriter writer) + { + ushort referenceId; + if (typeDefinition is TypeSpecification && + _context.TypeSpecificationsTable.TryGetTypeReferenceId(typeDefinition, out referenceId)) + { + writer.WriteMetadataToken(((uint)referenceId << 2) | 0x04); + } + else if (_context.TypeReferencesTable.TryGetTypeReferenceId(typeDefinition, out referenceId)) + { + writer.WriteMetadataToken(((uint)referenceId << 2) | 0x01); + } + else if (_context.TypeDefinitionTable.TryGetTypeReferenceId( + typeDefinition.Resolve(), out referenceId)) + { + writer.WriteMetadataToken((uint)referenceId << 2); + } + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoStringTable.cs b/source/MetadataProcessor.Core/Tables/nanoStringTable.cs new file mode 100644 index 00000000..118debc2 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoStringTable.cs @@ -0,0 +1,116 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing strings list and writing this + /// list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoStringTable : InanoTable + { + /// + /// Default implementation of interface. + /// Do nothing and just returns original sequence of string literals. + /// + private sealed class EmptyStringSorter : ICustomStringSorter + { + /// + public IEnumerable Sort( + ICollection strings) + { + return strings; + } + } + + /// + /// Maps for each unique string and related identifier (offset in strings table). + /// + private readonly Dictionary _idsByStrings = + new Dictionary(StringComparer.Ordinal); + + /// + /// Concrete implementation of string literals sorting algorithm (used by UTs). + /// + private readonly ICustomStringSorter _stringSorter; + + /// + /// Last available string identifier. + /// + private ushort _lastAvailableId; + + /// + /// Creates new instance of object. + /// + public nanoStringTable( + ICustomStringSorter stringSorter = null) + { + GetOrCreateStringId(string.Empty); // First item in string table always empty string + _stringSorter = stringSorter ?? new EmptyStringSorter(); + } + + /// + /// Gets existing or creates new string reference identifier related to passed string value. + /// + /// + /// Identifier is offset in strings table or just number from table of pre-defined constants. + /// + /// String value for obtaining identifier. + /// + /// If true hard-coded string constants table will be used (should be false + /// for byte code writer because onlyloader use this pre-defined string table optimization). + /// + /// Existing identifier if string already in table or new one. + public ushort GetOrCreateStringId( + string value, + bool useConstantsTable = true) + { + ushort id; + if (useConstantsTable && nanoStringsConstants.TryGetStringIndex(value, out id)) + { + return id; + } + if (!_idsByStrings.TryGetValue(value, out id)) + { + id = _lastAvailableId; + _idsByStrings.Add(value, id); + var length = Encoding.UTF8.GetBytes(value).Length + 1; + _lastAvailableId += (ushort)(length); + } + return id; + } + + /// + public void Write( + nanoBinaryWriter writer) + { + foreach (var item in _idsByStrings + .OrderBy(item => item.Value) + .Select(item => item.Key)) + { + writer.WriteString(item); + } + } + + /// + /// Adds all string constants from table into this one. + /// + /// Additional string table for merging with this one. + internal void MergeValues( + nanoStringTable fakeStringTable) + { + foreach (var item in _stringSorter.Sort(fakeStringTable._idsByStrings.Keys)) + { + GetOrCreateStringId(item, false); + } + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoTablesContext.cs b/source/MetadataProcessor.Core/Tables/nanoTablesContext.cs new file mode 100644 index 00000000..fc54915f --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoTablesContext.cs @@ -0,0 +1,400 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + public sealed class nanoTablesContext + { + private readonly HashSet _ignoringAttributes = + new HashSet(StringComparer.Ordinal) + { + // Assembly-level attributes + "System.Reflection.AssemblyCultureAttribute", + "System.Reflection.AssemblyVersionAttribute", + "System.Reflection.AssemblyFileVersionAttribute", + "System.Reflection.AssemblyTrademarkAttribute", + "System.Reflection.AssemblyTitleAttribute", + "System.Reflection.AssemblyProductAttribute", + "System.Reflection.AssemblyKeyNameAttribute", + "System.Reflection.AssemblyKeyFileAttribute", + "System.Reflection.AssemblyInformationalVersionAttribute", + "System.Reflection.AssemblyFlagsAttribute", + "System.Reflection.AssemblyDescriptionAttribute", + "System.Reflection.AssemblyDelaySignAttribute", + "System.Reflection.AssemblyDefaultAliasAttribute", + "System.Reflection.AssemblyCopyrightAttribute", + "System.Reflection.AssemblyConfigurationAttribute", + "System.Reflection.AssemblyCompanyAttribute", + "System.Runtime.InteropServices.ComVisibleAttribute", + "System.Runtime.InteropServices.GuidAttribute", + + // Compiler-specific attributes + "System.ParamArrayAttribute", + "System.SerializableAttribute", + "System.NonSerializedAttribute", + "System.Runtime.InteropServices.StructLayoutAttribute", + "System.Runtime.InteropServices.LayoutKind", + "System.Runtime.InteropServices.OutAttribute", + "System.Runtime.CompilerServices.ExtensionAttribute", + "System.Runtime.CompilerServices.MethodImplAttribute", + "System.Runtime.CompilerServices.InternalsVisibleToAttribute", + "System.Runtime.CompilerServices.IndexerNameAttribute", + "System.Runtime.CompilerServices.MethodImplOptions", + "System.Reflection.FieldNoReflectionAttribute", + "System.Reflection.DefaultMemberAttribute", + + // Debugger-specific attributes + "System.Diagnostics.DebuggableAttribute", + "System.Diagnostics.DebuggerNonUserCodeAttribute", + "System.Diagnostics.DebuggerStepThroughAttribute", + "System.Diagnostics.DebuggerDisplayAttribute", + "System.Diagnostics.DebuggerBrowsableAttribute", + "System.Diagnostics.DebuggerBrowsableState", + "System.Diagnostics.DebuggerHiddenAttribute", + + // Compile-time attributes + "System.AttributeUsageAttribute", + "System.CLSCompliantAttribute", + "System.FlagsAttribute", + "System.ObsoleteAttribute", + "System.Diagnostics.ConditionalAttribute", + + // Intellisense filtering attributes + "System.ComponentModel.EditorBrowsableAttribute", + + // Not supported attributes + "System.MTAThreadAttribute", + "System.STAThreadAttribute", + "System.Reflection.DefaultMemberAttribute", + }; + + public nanoTablesContext( + AssemblyDefinition assemblyDefinition, + List explicitTypesOrder, + ICustomStringSorter stringSorter, + bool applyAttributesCompression) + { + AssemblyDefinition = assemblyDefinition; + + foreach (var item in assemblyDefinition.CustomAttributes) + { + _ignoringAttributes.Add(item.AttributeType.FullName); + } + + NativeMethodsCrc = new NativeMethodsCrc(assemblyDefinition); + + var mainModule = AssemblyDefinition.MainModule; + + // External references + + AssemblyReferenceTable = new nanoAssemblyReferenceTable( + mainModule.AssemblyReferences, this); + + var typeReferences = mainModule.GetTypeReferences() + .Where(item => !IsAttribute(item)) + .ToList(); + TypeReferencesTable = new nanoTypeReferenceTable( + typeReferences, this); + + var typeReferencesNames = new HashSet( + typeReferences.Select(item => item.FullName), + StringComparer.Ordinal); + var memberReferences = mainModule.GetMemberReferences() + .Where(item => typeReferencesNames.Contains(item.DeclaringType.FullName)) + .ToList(); + FieldReferencesTable = new nanoFieldReferenceTable( + memberReferences.OfType(), this); + MethodReferencesTable = new nanoMethodReferenceTable( + memberReferences.OfType(), this); + + // Internal types definitions + + var types = GetOrderedTypes(mainModule, explicitTypesOrder); + + TypeDefinitionTable = new nanoTypeDefinitionTable(types, this); + + var fields = types + .SelectMany(item => GetOrderedFields(item.Fields.Where(field => !field.HasConstant))) + .ToList(); + FieldsTable = new nanoFieldDefinitionTable(fields, this); + + var methods = types.SelectMany(item => GetOrderedMethods(item.Methods)).ToList(); + + MethodDefinitionTable = new nanoMethodDefinitionTable(methods, this); + + AttributesTable = new nanoAttributesTable( + GetAttributes(types, applyAttributesCompression), + GetAttributes(fields, applyAttributesCompression), + GetAttributes(methods, applyAttributesCompression), + this); + + TypeSpecificationsTable = new nanoTypeSpecificationsTable(this); + + // Resources information + + ResourcesTable = new nanoResourcesTable( + mainModule.Resources, this); + ResourceDataTable = new nanoResourceDataTable(); + + // Strings and signatures + + SignaturesTable = new nanoSignaturesTable(this); + StringTable = new nanoStringTable(stringSorter); + + // Byte code table + ByteCodeTable = new nanoByteCodeTable(this); + + // Additional information + + ResourceFileTable = new nanoResourceFileTable(this); + + // Pre-allocate strings from some tables + AssemblyReferenceTable.AllocateStrings(); + TypeReferencesTable.AllocateStrings(); + foreach (var item in memberReferences) + { + StringTable.GetOrCreateStringId(item.Name); + + var fieldReference = item as FieldReference; + if (fieldReference != null) + { + SignaturesTable.GetOrCreateSignatureId(fieldReference); + } + + var methodReference = item as MethodReference; + if (methodReference != null) + { + SignaturesTable.GetOrCreateSignatureId(methodReference); + } + } + } + + /// + /// Gets method reference identifier (external or internal) encoded with appropriate prefix. + /// + /// Method reference in Mono.Cecil format. + /// Reference identifier for passed value. + public ushort GetMethodReferenceId( + MethodReference methodReference) + { + ushort referenceId; + if (MethodReferencesTable.TryGetMethodReferenceId(methodReference, out referenceId)) + { + referenceId |= 0x8000; // External method reference + } + else + { + MethodDefinitionTable.TryGetMethodReferenceId(methodReference.Resolve(), out referenceId); + } + return referenceId; + } + + public AssemblyDefinition AssemblyDefinition { get; private set; } + + public NativeMethodsCrc NativeMethodsCrc { get; private set; } + + public nanoAssemblyReferenceTable AssemblyReferenceTable { get; private set; } + + public nanoTypeReferenceTable TypeReferencesTable { get; private set; } + + public nanoFieldReferenceTable FieldReferencesTable { get; private set; } + + public nanoMethodReferenceTable MethodReferencesTable { get; private set; } + + public nanoFieldDefinitionTable FieldsTable { get; private set; } + + public nanoMethodDefinitionTable MethodDefinitionTable { get; private set; } + + public nanoTypeDefinitionTable TypeDefinitionTable { get; private set; } + + public nanoAttributesTable AttributesTable { get; private set; } + + public nanoTypeSpecificationsTable TypeSpecificationsTable { get; private set; } + + public nanoResourcesTable ResourcesTable { get; private set; } + + public nanoResourceDataTable ResourceDataTable { get; private set; } + + public nanoSignaturesTable SignaturesTable { get; private set; } + + public nanoStringTable StringTable { get; private set; } + + public nanoByteCodeTable ByteCodeTable { get; private set; } + + public nanoResourceFileTable ResourceFileTable { get; private set; } + + private IEnumerable> GetAttributes( + IEnumerable types, + bool applyAttributesCompression) + { + if (applyAttributesCompression) + { + return types.SelectMany( + (item, index) => item.CustomAttributes + .Where(attr => !IsAttribute(attr.AttributeType)) + .OrderByDescending(attr => attr.AttributeType.FullName) + .Select(attr => new Tuple(attr, (ushort)index))); + + } + return types.SelectMany( + (item, index) => item.CustomAttributes + .Where(attr => !IsAttribute(attr.AttributeType)) + .Select(attr => new Tuple(attr, (ushort)index))); + } + + private bool IsAttribute( + MemberReference typeReference) + { + return + _ignoringAttributes.Contains(typeReference.FullName) || + (typeReference.DeclaringType != null && + _ignoringAttributes.Contains(typeReference.DeclaringType.FullName)); + } + + private static List GetOrderedTypes( + ModuleDefinition mainModule, + List explicitTypesOrder) + { + var unorderedTypes = mainModule.GetTypes() + .Where(item => item.FullName != "") + .ToList(); + + if (explicitTypesOrder == null || explicitTypesOrder.Count == 0) + { + return SortTypesAccordingUsages( + unorderedTypes, mainModule.FileName); + } + + return explicitTypesOrder + .Join(unorderedTypes, outer => outer, inner => inner.FullName, (inner, outer) => outer) + .ToList(); + } + + private static List SortTypesAccordingUsages( + IEnumerable types, + string mainModuleName) + { + var processedTypes = new HashSet(StringComparer.Ordinal); + return SortTypesAccordingUsagesImpl( + types.OrderBy(item => item.FullName), + mainModuleName, processedTypes) + .ToList(); + } + + private static IEnumerable SortTypesAccordingUsagesImpl( + IEnumerable types, + string mainModuleName, + ISet processedTypes) + { + foreach (var type in types) + { + if (processedTypes.Contains(type.FullName)) + { + continue; + } + + if (type.DeclaringType != null) + { + foreach (var declaredIn in SortTypesAccordingUsagesImpl( + Enumerable.Repeat(type.DeclaringType, 1), mainModuleName, processedTypes)) + { + yield return declaredIn; + } + } + + foreach (var implement in SortTypesAccordingUsagesImpl( + type.Interfaces.Select(itf => itf.InterfaceType.Resolve()) + .Where(item => item.Module.FileName == mainModuleName), + mainModuleName, processedTypes)) + { + yield return implement; + } + + if (processedTypes.Add(type.FullName)) + { + var operands = type.Methods + .Where(item => item.HasBody) + .SelectMany(item => item.Body.Instructions) + .Select(item => item.Operand) + .OfType() + .ToList(); + + foreach (var fieldType in SortTypesAccordingUsagesImpl( + operands.SelectMany(GetTypesList) + .Where(item => item.Module.FileName == mainModuleName), + mainModuleName, processedTypes)) + { + yield return fieldType; + } + + yield return type; + } + } + } + + private static IEnumerable GetTypesList( + MethodReference methodReference) + { + var returnType = methodReference.ReturnType.Resolve(); + if (returnType != null && returnType.FullName != "System.Void") + { + yield return returnType; + } + foreach (var parameter in methodReference.Parameters) + { + var parameterType = parameter.ParameterType.Resolve(); + if (parameterType != null) + { + yield return parameterType; + } + } + } + + private static IEnumerable GetOrderedMethods( + IEnumerable methods) + { + var ordered = methods + .ToList(); + + foreach (var method in ordered.Where(item => item.IsVirtual)) + { + yield return method; + } + + foreach (var method in ordered.Where(item => !(item.IsVirtual || item.IsStatic))) + { + yield return method; + } + + foreach (var method in ordered.Where(item => item.IsStatic)) + { + yield return method; + } + } + + private static IEnumerable GetOrderedFields( + IEnumerable fields) + { + var ordered = fields + .ToList(); + + foreach (var method in ordered.Where(item => item.IsStatic)) + { + yield return method; + } + + foreach (var method in ordered.Where(item => !item.IsStatic)) + { + yield return method; + } + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoTypeDefinitionTable.cs b/source/MetadataProcessor.Core/Tables/nanoTypeDefinitionTable.cs new file mode 100644 index 00000000..4ab64a5a --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoTypeDefinitionTable.cs @@ -0,0 +1,378 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using Mono.Collections.Generic; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing type definitions (complete type metadata) list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoTypeDefinitionTable : + nanoReferenceTableBase + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class TypeDefinitionEqualityComparer : IEqualityComparer + { + /// + public bool Equals(TypeDefinition lhs, TypeDefinition rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(TypeDefinition item) + { + return item.FullName.GetHashCode(); + } + } + + private IDictionary>> _byteCodeOffsets = + new Dictionary>>(); + + /// + /// Creates new instance of object. + /// + /// List of types definitins in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoTypeDefinitionTable( + IEnumerable items, + nanoTablesContext context) + : base(items, new TypeDefinitionEqualityComparer(), context) + { + } + + /// + /// Gets type reference identifier (if type is provided and this type is defined in target assembly). + /// + /// + /// For null value passed in returns 0xFFFF value. + /// + /// Type definition in Mono.Cecil format. + /// Type reference identifier for filling. + /// Returns true if item found, otherwise returns false. + public bool TryGetTypeReferenceId( + TypeDefinition typeDefinition, + out ushort referenceId) + { + if (typeDefinition == null) // This case is possible for encoding 'nested inside' case + { + referenceId = 0xFFFF; + return true; + } + + return TryGetIdByValue(typeDefinition, out referenceId); + } + + public IEnumerable> GetByteCodeOffsets( + uint clrMethodToken) + { + return _byteCodeOffsets[clrMethodToken]; + } + + /// + protected override void WriteSingleItem( + nanoBinaryWriter writer, + TypeDefinition item) + { + _context.StringTable.GetOrCreateStringId(item.Namespace); + + WriteStringReference(writer, item.Name); + WriteStringReference(writer, item.Namespace); + + writer.WriteUInt16(GetTypeReferenceOrDefinitionId(item.BaseType)); + writer.WriteUInt16(GetTypeReferenceOrDefinitionId(item.DeclaringType)); + + var fieldsList = item.Fields + .Where(field => !field.HasConstant) + .OrderByDescending(field => field.IsStatic) + .ToList(); + foreach (var field in fieldsList) + { + _context.SignaturesTable.GetOrCreateSignatureId(field); + _context.SignaturesTable.GetOrCreateSignatureId(field.InitialValue); + } + + using (var stream = new MemoryStream(6)) + { + WriteClassFields(fieldsList, writer.GetMemoryBasedClone(stream)); + + if (item.DeclaringType == null) + { + foreach (var method in item.Methods) + { + var offsets = CodeWriter + .PreProcessMethod(method, _context.ByteCodeTable.FakeStringTable) + .ToList(); + _byteCodeOffsets.Add(method.MetadataToken.ToUInt32(), offsets); + } + } + foreach (var nestedType in item.NestedTypes) + { + foreach (var method in nestedType.Methods) + { + var offsets = CodeWriter + .PreProcessMethod(method, _context.ByteCodeTable.FakeStringTable) + .ToList(); + _byteCodeOffsets.Add(method.MetadataToken.ToUInt32(), offsets); + } + } + + WriteMethodBodies(item.Methods, item.Interfaces, writer); + + _context.SignaturesTable.WriteDataType(item, writer, false, true); + + writer.WriteBytes(stream.ToArray()); + } + + writer.WriteUInt16(GetFlags(item)); // flags + } + + private void WriteClassFields( + IList fieldsList, + nanoBinaryWriter writer) + { + var firstStaticFieldId = _context.FieldsTable.MaxFieldId; + var staticFieldsNumber = 0; + foreach (var field in fieldsList.Where(item => item.IsStatic)) + { + ushort fieldReferenceId; + _context.FieldsTable.TryGetFieldReferenceId(field, true, out fieldReferenceId); + firstStaticFieldId = Math.Min(firstStaticFieldId, fieldReferenceId); + + _context.SignaturesTable.GetOrCreateSignatureId(field); + _context.StringTable.GetOrCreateStringId(field.Name); + + ++staticFieldsNumber; + } + + var firstInstanseFieldId = _context.FieldsTable.MaxFieldId; + var instanceFieldsNumber = 0; + foreach (var field in fieldsList.Where(item => !item.IsStatic)) + { + ushort fieldReferenceId; + _context.FieldsTable.TryGetFieldReferenceId(field, true, out fieldReferenceId); + firstInstanseFieldId = Math.Min(firstInstanseFieldId, fieldReferenceId); + + _context.SignaturesTable.GetOrCreateSignatureId(field); + _context.StringTable.GetOrCreateStringId(field.Name); + + ++instanceFieldsNumber; + } + + if (firstStaticFieldId > firstInstanseFieldId) + { + firstStaticFieldId = firstInstanseFieldId; + } + + writer.WriteUInt16(firstStaticFieldId); + writer.WriteUInt16(firstInstanseFieldId); + + writer.WriteByte((byte) staticFieldsNumber); + writer.WriteByte((byte) instanceFieldsNumber); + } + + private void WriteMethodBodies( + Collection methods, + Collection iInterfaces, + nanoBinaryWriter writer) + { + ushort firstMethodId = 0xFFFF; + var virtualMethodsNumber = 0; + foreach (var method in methods.Where(item => item.IsVirtual)) + { + firstMethodId = Math.Min(firstMethodId, _context.ByteCodeTable.GetMethodId(method)); + CreateMethodSignatures(method); + ++virtualMethodsNumber; + } + + var instanceMethodsNumber = 0; + foreach (var method in methods.Where(item => !(item.IsVirtual || item.IsStatic))) + { + firstMethodId = Math.Min(firstMethodId, _context.ByteCodeTable.GetMethodId(method)); + CreateMethodSignatures(method); + ++instanceMethodsNumber; + } + + var staticMethodsNumber = 0; + foreach (var method in methods.Where(item => item.IsStatic)) + { + firstMethodId = Math.Min(firstMethodId, _context.ByteCodeTable.GetMethodId(method)); + CreateMethodSignatures(method); + ++staticMethodsNumber; + } + + if (virtualMethodsNumber + instanceMethodsNumber + staticMethodsNumber == 0) + { + firstMethodId = _context.ByteCodeTable.NextMethodId; + } + + writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(iInterfaces)); + + writer.WriteUInt16(firstMethodId); + + writer.WriteByte((byte)virtualMethodsNumber); + writer.WriteByte((byte)instanceMethodsNumber); + writer.WriteByte((byte)staticMethodsNumber); + } + + private void CreateMethodSignatures( + MethodDefinition method) + { + _context.SignaturesTable.GetOrCreateSignatureId(method); + if (method.HasBody) + { + _context.SignaturesTable.GetOrCreateSignatureId(method.Body.Variables); + } + _context.StringTable.GetOrCreateStringId(method.Name); + } + + private ushort GetTypeReferenceOrDefinitionId( + TypeReference typeReference) + { + ushort referenceId; + if (_context.TypeReferencesTable.TryGetTypeReferenceId(typeReference, out referenceId)) + { + return (ushort)(0x8000 | referenceId); + } + + ushort typeId; + if (TryGetTypeReferenceId(typeReference.Resolve(), out typeId)) + { + return typeId; + } + + return 0xFFFF; + } + + private ushort GetFlags( + TypeDefinition definition) + { + const ushort TD_Scope_Public = 0x0001; // Class is public scope. + const ushort TD_Scope_NestedPublic = 0x0002; // Class is nested with public visibility. + const ushort TD_Scope_NestedPrivate = 0x0003; // Class is nested with private visibility. + const ushort TD_Scope_NestedFamily = 0x0004; // Class is nested with family visibility. + const ushort TD_Scope_NestedAssembly = 0x0005; // Class is nested with assembly visibility. + const ushort TD_Scope_NestedFamANDAssem = 0x0006; // Class is nested with family and assembly visibility. + const ushort TD_Scope_NestedFamORAssem = 0x0007; // Class is nested with family or assembly visibility. + + const ushort TD_Serializable = 0x0008; + + const ushort TD_Semantics_ValueType = 0x0010; + const ushort TD_Semantics_Interface = 0x0020; + const ushort TD_Semantics_Enum = 0x0030; + + const ushort TD_Abstract = 0x0040; + const ushort TD_Sealed = 0x0080; + + const ushort TD_SpecialName = 0x0100; + const ushort TD_Delegate = 0x0200; + const ushort TD_MulticastDelegate = 0x0400; + const ushort TD_Patched = 0x0800; + + const ushort TD_BeforeFieldInit = 0x1000; + const ushort TD_HasSecurity = 0x2000; + const ushort TD_HasFinalizer = 0x4000; + const ushort TD_HasAttributes = 0x8000; + + var flags = 0x0000; + + if (definition.IsPublic) + { + flags = TD_Scope_Public; + } + else if (definition.IsNestedPublic) + { + flags = TD_Scope_NestedPublic; + } + else if (definition.IsNestedPrivate) + { + flags = TD_Scope_NestedPrivate; + } + else if (definition.IsNestedFamily) + { + flags = TD_Scope_NestedFamily; + } + else if (definition.IsNestedAssembly) + { + flags = TD_Scope_NestedAssembly; + } + else if (definition.IsNestedFamilyAndAssembly) + { + flags = TD_Scope_NestedFamANDAssem; + } + else if (definition.IsNestedFamilyOrAssembly) + { + flags = TD_Scope_NestedFamORAssem; + } + + if (definition.IsSerializable) + { + flags |= TD_Serializable; + } + + if (definition.IsEnum) + { + flags |= TD_Semantics_Enum; + flags |= TD_Serializable; + } + else if (definition.IsValueType) + { + flags |= TD_Semantics_ValueType; + } + else if (definition.IsInterface) + { + flags |= TD_Semantics_Interface; + } + + if (definition.IsAbstract) + { + flags |= TD_Abstract; + } + if (definition.IsSealed) + { + flags |= TD_Sealed; + } + + if (definition.IsSpecialName) + { + flags |= TD_SpecialName; + } + + if (definition.IsBeforeFieldInit) + { + flags |= TD_BeforeFieldInit; + } + if (definition.HasSecurity) + { + flags |= TD_HasSecurity; + } + if (definition.HasCustomAttributes) + { + flags |= TD_HasAttributes; + } + + var baseType = definition.BaseType; + if (baseType != null && baseType.FullName == "System.MulticastDelegate") + { + flags |= TD_MulticastDelegate; + } + + return (ushort)flags; + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoTypeReferenceTable.cs b/source/MetadataProcessor.Core/Tables/nanoTypeReferenceTable.cs new file mode 100644 index 00000000..ad5b8c38 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoTypeReferenceTable.cs @@ -0,0 +1,110 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing external type references list and writing + /// this collected list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoTypeReferenceTable : + nanoReferenceTableBase + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class TypeReferenceEqualityComparer : IEqualityComparer + { + /// + public bool Equals(TypeReference lhs, TypeReference rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(TypeReference item) + { + return item.FullName.GetHashCode(); + } + } + + /// + /// Creates new instance of object. + /// + /// Type references list in Mono.Cecil format. + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoTypeReferenceTable( + IEnumerable items, + nanoTablesContext context) + : base(items, new TypeReferenceEqualityComparer(), context) + { + } + + /// + /// Gets type reference identifier (if type is provided and this type is defined in target assembly). + /// + /// + /// For null value passed in returns 0xFFFF value. + /// + /// Type definition in Mono.Cecil format. + /// Type reference identifier for filling. + /// Returns true if item found, otherwise returns false. + public bool TryGetTypeReferenceId( + TypeReference typeReference, + out ushort referenceId) + { + if (typeReference == null) // This case is possible for encoding 'nested inside' case + { + referenceId = 0xFFFF; + return true; + } + + return TryGetIdByValue(typeReference, out referenceId); + } + + /// + protected override void WriteSingleItem( + nanoBinaryWriter writer, + TypeReference item) + { + WriteStringReference(writer, item.Name); + WriteStringReference(writer, item.Namespace); + + writer.WriteUInt16(GetScope(item)); // scope - TBL_AssemblyRef | TBL_TypeRef // 0x8000 + writer.WriteUInt16(0); // padding + } + + /// + protected override void AllocateSingleItemStrings( + TypeReference item) + { + GetOrCreateStringId(item.Namespace); + GetOrCreateStringId(item.Name); + } + + private ushort GetScope( + TypeReference typeReference) + { + if (typeReference.DeclaringType == null) + { + return _context.AssemblyReferenceTable.GetReferenceId(typeReference.Scope as AssemblyNameReference); + } + else + { + ushort referenceId; + _context.TypeReferencesTable.TryGetTypeReferenceId(typeReference.DeclaringType, out referenceId); + return (ushort)(0x8000 | referenceId); + } + } + } +} diff --git a/source/MetadataProcessor.Core/Tables/nanoTypeSpecificationsTable.cs b/source/MetadataProcessor.Core/Tables/nanoTypeSpecificationsTable.cs new file mode 100644 index 00000000..4afce906 --- /dev/null +++ b/source/MetadataProcessor.Core/Tables/nanoTypeSpecificationsTable.cs @@ -0,0 +1,113 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for storing type sprcifications list and writing this + /// list into target assembly in .NET nanoFramework format. + /// + public sealed class nanoTypeSpecificationsTable : InanoTable + { + /// + /// Helper class for comparing two instances of objects + /// using property as unique key for comparison. + /// + private sealed class TypeReferenceComparer : IEqualityComparer + { + /// + public bool Equals(TypeReference lhs, TypeReference rhs) + { + return string.Equals(lhs.FullName, rhs.FullName, StringComparison.Ordinal); + } + + /// + public int GetHashCode(TypeReference that) + { + return that.FullName.GetHashCode(); + } + } + + /// + /// Maps for each unique type specification and related identifier. + /// + private readonly IDictionary _idByTypeSpecifications = + new Dictionary(new TypeReferenceComparer()); + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// Last available type specifier identificator. + /// + private ushort _lastAvailableId; + + /// + /// Creates new instance of object. + /// + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoTypeSpecificationsTable( + nanoTablesContext context) + { + _context = context; + } + + /// + /// Gets existing or creates new type specification reference identifier. + /// + /// Type reference value for obtaining identifier. + /// Existing identifier if specification already in table or new one. + public ushort GetOrCreateTypeSpecificationId( + TypeReference typeReference) + { + ushort referenceId; + if (!_idByTypeSpecifications.TryGetValue(typeReference, out referenceId)) + { + _idByTypeSpecifications.Add(typeReference, _lastAvailableId); + + referenceId = _lastAvailableId; + ++_lastAvailableId; + } + + return referenceId; + } + + /// + /// Gets type specification identifier (if it already added into type specifications list). + /// + /// Type reference in Mono.Cecil format. + /// Type reference identifier for filling. + /// Returns true if item found, otherwise returns false. + public bool TryGetTypeReferenceId( + TypeReference typeReference, + out ushort referenceId) + { + return _idByTypeSpecifications.TryGetValue(typeReference, out referenceId); + } + + /// + public void Write( + nanoBinaryWriter writer) + { + foreach (var item in _idByTypeSpecifications + .OrderBy(item => item.Value) + .Select(item => item.Key)) + { + writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(item)); + writer.WriteUInt16(0x0000); // padding + } + } + } +} diff --git a/source/MetadataProcessor.Core/Utility/Crc32.cs b/source/MetadataProcessor.Core/Utility/Crc32.cs new file mode 100644 index 00000000..32ad2eff --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/Crc32.cs @@ -0,0 +1,66 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Helper class for calculating CRC32 value according IEEE 802 standard (ZModem protocol). + /// + internal static class Crc32 + { + // + // CRC 32 table for use under ZModem protocol, IEEE 802 + // G(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 + // + private static readonly uint[] _crcTable = + { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, + 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, + 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, + 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, + 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, + 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, + 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, + 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, + 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, + 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, + 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, + 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, + 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, + 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, + 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, + 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, + 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, + 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, + 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, + 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, + 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 + }; + + /// + /// Calculates CRC32 value for passsed byte array using + /// initial value of parameter as base for CRC calculation. + /// + public static uint Compute(byte[] buffer, uint crc = 0) + { + return buffer.Aggregate(crc, + (index, item) => _crcTable[((index >> 24) ^ item) & 0xFF] ^ (index << 8)); + } + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Utility/LoadHintsAssemblyResolver.cs b/source/MetadataProcessor.Core/Utility/LoadHintsAssemblyResolver.cs new file mode 100644 index 00000000..929412f3 --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/LoadHintsAssemblyResolver.cs @@ -0,0 +1,75 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Implements special external .NET nanoFramework assemblies resolution logic. + /// MetadataTransformer gets maps with pair assembly name and assebly path in command line, + /// if we unable to load assemlby using default resolver we will try to use this map. + /// + public sealed class LoadHintsAssemblyResolver : BaseAssemblyResolver + { + /// + /// List of 'load hints' - map between assembly name and assembly path. + /// + private readonly IDictionary _loadHints; + + /// + /// Creates new instance of object. + /// + /// Metadata transformer load hints. + public LoadHintsAssemblyResolver( + IDictionary loadHints) + { + _loadHints = loadHints; + } + + /// + public override AssemblyDefinition Resolve(AssemblyNameReference name) + { + try + { + return base.Resolve(name); + } + catch (Exception) + { + string assemblyFileName; + if (_loadHints.TryGetValue(name.Name, out assemblyFileName)) + { + return AssemblyDefinition.ReadAssembly(assemblyFileName); + } + + throw; + } + } + + + /// + public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) + { + try + { + return base.Resolve(name, parameters); + } + catch (Exception) + { + string assemblyFileName; + if (_loadHints.TryGetValue(new AssemblyName(name.FullName).Name, out assemblyFileName)) + { + return AssemblyDefinition.ReadAssembly(assemblyFileName); + } + + throw; + } + } + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Utility/NativeMethodsCrc.cs b/source/MetadataProcessor.Core/Utility/NativeMethodsCrc.cs new file mode 100644 index 00000000..5fa45c43 --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/NativeMethodsCrc.cs @@ -0,0 +1,100 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Helper class for calculating native methods CRC value. Really caclulates CRC32 value + /// for native method signatures (not methods itself) and signatures treated as string + /// values, formatted by weird rules incompartible with all rest codebase. + /// + public sealed class NativeMethodsCrc + { + private readonly HashSet _generatedNames = new HashSet(StringComparer.Ordinal); + + private readonly byte[] _null = Encoding.ASCII.GetBytes("NULL"); + + private readonly byte[] _name; + + public NativeMethodsCrc( + AssemblyDefinition assembly) + { + _name = Encoding.ASCII.GetBytes(assembly.Name.Name); + } + + public uint Current { get; private set; } + + public void UpdateCrc(MethodDefinition method) + { + var type = method.DeclaringType; + if ((type.IsClass || type.IsValueType) && + (method.RVA == 0xFFFFFFF && !method.IsAbstract)) + { + Current = Crc32.Compute(_name, Current); + Current = Crc32.Compute(Encoding.ASCII.GetBytes(GetClassName(type)), Current); + Current = Crc32.Compute(Encoding.ASCII.GetBytes(GetMethodName(method)), Current); + } + else + { + Current = Crc32.Compute(_null, Current); + } + } + + private string GetClassName( + TypeDefinition type) + { + return (type != null + ? string.Concat(GetClassName(type.DeclaringType), type.Namespace, type.Name) + .Replace(".", string.Empty) + : string.Empty); + } + + private string GetMethodName( + MethodDefinition method) + { + var name = string.Concat(method.Name, (method.IsStatic ? "___STATIC__" : "___"), + string.Join("__", GetAllParameters(method))); + + var originalName = name.Replace(".", string.Empty); + + var index = 1; + name = originalName; + while (_generatedNames.Add(name)) + { + name = string.Concat(originalName, index.ToString(CultureInfo.InvariantCulture)); + ++index; + } + + return name; + } + + private IEnumerable GetAllParameters( + MethodDefinition method) + { + yield return GetParameterType(method.ReturnType); + + if (method.HasParameters) + { + foreach (var item in method.Parameters) + { + yield return GetParameterType(item.ParameterType); + } + } + } + + private string GetParameterType( + TypeReference parameterType) + { + return parameterType.Name.ToUpper(); + } + } +} diff --git a/source/MetadataProcessor.Core/Utility/nanoBitmapProcessor.cs b/source/MetadataProcessor.Core/Utility/nanoBitmapProcessor.cs new file mode 100644 index 00000000..469309e9 --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/nanoBitmapProcessor.cs @@ -0,0 +1,80 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System.Drawing; +using System.Drawing.Imaging; + +namespace nanoFramework.Tools.MetadataProcessor +{ + internal sealed class nanoBitmapProcessor + { + private readonly Bitmap _bitmap; + + public nanoBitmapProcessor( + Bitmap bitmap) + { + _bitmap = bitmap; + } + + public void Process( + nanoBinaryWriter writer) + { + writer.WriteUInt32((uint)_bitmap.Width); + writer.WriteUInt32((uint)_bitmap.Height); + + writer.WriteUInt16(0x00); // flags + + var tinyImageFormat = GetTinytImageFormat(_bitmap.RawFormat); + + if (tinyImageFormat != 0) + { + writer.WriteByte(0x01); // bpp + writer.WriteByte(tinyImageFormat); + _bitmap.Save(writer.BaseStream, _bitmap.RawFormat); + } + else + { + writer.WriteByte(0x10); // bpp + writer.WriteByte(tinyImageFormat); + + var rect = new Rectangle(Point.Empty, _bitmap.Size); + using (var convertedBitmap = + _bitmap.Clone(new Rectangle(Point.Empty, _bitmap.Size), + PixelFormat.Format16bppRgb565)) + { + var bitmapData = convertedBitmap.LockBits( + rect, ImageLockMode.ReadOnly, convertedBitmap.PixelFormat); + + var buffer = new short[bitmapData.Stride * convertedBitmap.Height / sizeof(short)]; + System.Runtime.InteropServices.Marshal.Copy( + bitmapData.Scan0, buffer, 0, buffer.Length); + + convertedBitmap.UnlockBits(bitmapData); + foreach (var item in buffer) + { + writer.WriteInt16(item); + } + } + } + } + + private byte GetTinytImageFormat( + ImageFormat rawFormat) + { + if (rawFormat.Equals(ImageFormat.Gif)) + { + return 1; + } + + if (rawFormat.Equals(ImageFormat.Jpeg)) + { + return 2; + } + + return 0; + } + } +} \ No newline at end of file diff --git a/source/MetadataProcessor.Core/Utility/nanoCLR_DataType.cs b/source/MetadataProcessor.Core/Utility/nanoCLR_DataType.cs new file mode 100644 index 00000000..2b3436de --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/nanoCLR_DataType.cs @@ -0,0 +1,40 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Tools.MetadataProcessor +{ + internal enum nanoCLR_DataType : byte + { + // these where defined @ enum CLR_DataType + + DATATYPE_VOID, // 0 bytes + + DATATYPE_BOOLEAN, // 1 byte + DATATYPE_I1, // 1 byte + DATATYPE_U1, // 1 byte + + DATATYPE_CHAR, // 2 bytes + DATATYPE_I2, // 2 bytes + DATATYPE_U2, // 2 bytes + + DATATYPE_I4, // 4 bytes + DATATYPE_U4, // 4 bytes + DATATYPE_R4, // 4 bytes + + DATATYPE_I8, // 8 bytes + DATATYPE_U8, // 8 bytes + DATATYPE_R8, // 8 bytes + DATATYPE_DATETIME, // 8 bytes // Shortcut for System.DateTime + DATATYPE_TIMESPAN, // 8 bytes // Shortcut for System.TimeSpan + DATATYPE_STRING, + + DATATYPE_OBJECT, // Shortcut for System.Object + DATATYPE_CLASS, // CLASS + DATATYPE_VALUETYPE, // VALUETYPE + DATATYPE_SZARRAY, // Shortcut for single dimension zero lower bound array SZARRAY + DATATYPE_BYREF, // BYREF + } +} diff --git a/source/MetadataProcessor.Core/Utility/nanoFontProcessor.cs b/source/MetadataProcessor.Core/Utility/nanoFontProcessor.cs new file mode 100644 index 00000000..2d1b16b5 --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/nanoFontProcessor.cs @@ -0,0 +1,130 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System.IO; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for processing .tinyfont resource data and swap endianness if neede. + /// + internal sealed class nanoFontProcessor + { + /// + /// Indicates additional font information in container (anti-aliasing). + /// + private const ushort FLAG_FONT_EX = 0x0008; + + /// + /// Original binary data for processing. + /// + private readonly byte[] _fontResouce; + + /// + /// Creates new instance of object. + /// + /// Original font binary data for processing. + public nanoFontProcessor( + byte[] fontResouce) + { + _fontResouce = fontResouce; + } + + /// + /// Processes original data and writes processed data into output writer. + /// + /// Endianness-aware binary writer. + public void Process( + nanoBinaryWriter writer) + { + using (var stream = new MemoryStream(_fontResouce, false)) + using (var reader = new BinaryReader(stream)) + { + // CLR_GFX_FontDescription + + { + // CLR_GFX_FontMetrics + + writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontMetrics.m_height + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_offset + + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_ascent + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_descent + + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_internalLeading + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_externalLeading + + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_aveCharWidth + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_aveCharWidth + } + + var rangesCount = reader.ReadInt16(); + writer.WriteInt16(rangesCount); // CLR_GFX_FontDescription.m_ranges + var charactersCount = reader.ReadInt16(); + writer.WriteInt16(charactersCount); // CLR_GFX_FontDescription.m_characters + + var flags = reader.ReadInt16(); + writer.WriteInt16(flags); // CLR_GFX_FontDescription.m_flags + writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontDescription.m_pad + + // CLR_GFX_BitmapDescription + + var width = reader.ReadUInt32(); + writer.WriteUInt32(width); // CLR_GFX_BitmapDescription.m_width + var height = reader.ReadUInt32(); + writer.WriteUInt32(height); // CLR_GFX_BitmapDescription.m_height + + writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_BitmapDescription.m_flags + + var bitsPerPixel = reader.ReadByte(); + writer.WriteByte(bitsPerPixel); // CLR_GFX_BitmapDescription.m_bitsPerPixel + writer.WriteByte(reader.ReadByte()); // CLR_GFX_BitmapDescription.m_type + + for (var i = 0; i <= rangesCount; ++i) // Including sentinel range + { + // CLR_GFX_FontCharacterRange + + writer.WriteUInt32(reader.ReadUInt32()); // CLR_GFX_FontCharacterRange.m_indexOfFirstFontCharacter + + writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontCharacterRange.m_firstChar + writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontCharacterRange.m_lastChar + + writer.WriteUInt32(reader.ReadUInt32()); // CLR_GFX_FontCharacterRange.m_rangeOffset + } + + for (var i = 0; i <= charactersCount; ++i) // Including sentinel character + { + // CLR_GFX_FontCharacter + + writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontCharacter.m_offset + + writer.WriteByte(reader.ReadByte()); // CLR_GFX_FontCharacter.m_marginLeft + writer.WriteByte(reader.ReadByte()); // CLR_GFX_FontCharacter.m_marginRight + } + + if (bitsPerPixel == 0) + { + bitsPerPixel = 16; // Native value, rest calculations are same + } + var totalSizeInWords = ((width * bitsPerPixel + 31) / 32) * height; + for (var i = 0; i < totalSizeInWords; ++i) + { + writer.WriteUInt32(reader.ReadUInt32()); + } + + if ((flags & FLAG_FONT_EX) == FLAG_FONT_EX) + { + // TODO: implement it according original idea if needed + } + + while (stream.Position < stream.Length) + { + writer.WriteByte(reader.ReadByte()); + } + } + } + } +} diff --git a/source/MetadataProcessor.Core/Utility/nanoPdbxFileWriter.cs b/source/MetadataProcessor.Core/Utility/nanoPdbxFileWriter.cs new file mode 100644 index 00000000..03d0726c --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/nanoPdbxFileWriter.cs @@ -0,0 +1,143 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Xml; + +namespace nanoFramework.Tools.MetadataProcessor +{ + internal sealed class nanoPdbxFileWriter + { + private readonly nanoTablesContext _context; + + public nanoPdbxFileWriter( + nanoTablesContext context) + { + _context = context; + } + + public void Write( + XmlWriter writer) + { + writer.WriteStartElement("PdbxFile"); + writer.WriteStartElement("Assembly"); + + WriteTokensPair(writer, _context.AssemblyDefinition.MetadataToken.ToUInt32(), 0x00000000); + writer.WriteElementString("FileName", _context.AssemblyDefinition.MainModule.Name); + WriteVersionInfo(writer, _context.AssemblyDefinition.Name.Version); + + writer.WriteStartElement("Classes"); + _context.TypeDefinitionTable.ForEachItems((token, item) => WriteClassInfo(writer, token, item)); + + writer.WriteEndDocument(); + } + + private void WriteVersionInfo( + XmlWriter writer, + Version version) + { + writer.WriteStartElement("Version"); + + writer.WriteElementString("Major", version.Major.ToString("D", CultureInfo.InvariantCulture)); + writer.WriteElementString("Minor", version.Minor.ToString("D", CultureInfo.InvariantCulture)); + writer.WriteElementString("Build", version.Build.ToString("D", CultureInfo.InvariantCulture)); + writer.WriteElementString("Revision", version.Revision.ToString("D", CultureInfo.InvariantCulture)); + + writer.WriteEndElement(); + } + + private void WriteClassInfo( + XmlWriter writer, + uint tinyClrItemToken, + TypeDefinition item) + { + writer.WriteStartElement("Class"); + + WriteTokensPair(writer, item.MetadataToken.ToUInt32(), 0x04000000 | tinyClrItemToken); + + writer.WriteStartElement("Methods"); + foreach (var tuple in GetMethodsTokens(item.Methods)) + { + writer.WriteStartElement("Method"); + + WriteTokensPair(writer, tuple.Item1, tuple.Item2); + + if (!tuple.Item3.HasBody) + { + writer.WriteElementString("HasByteCode", "false"); + } + writer.WriteStartElement("ILMap"); + foreach (var offset in _context.TypeDefinitionTable.GetByteCodeOffsets(tuple.Item1)) + { + writer.WriteStartElement("IL"); + + writer.WriteElementString("CLR", "0x" + offset.Item1.ToString("X8", CultureInfo.InvariantCulture)); + writer.WriteElementString("TinyCLR", "0x" + offset.Item2.ToString("X8", CultureInfo.InvariantCulture)); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteStartElement("Fields"); + foreach (var pair in GetFieldsTokens(item.Fields)) + { + writer.WriteStartElement("Field"); + + WriteTokensPair(writer, pair.Item1, pair.Item2); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteEndElement(); + } + + private IEnumerable> GetMethodsTokens( + IEnumerable methods) + { + foreach (var method in methods) + { + ushort fieldToken; + _context.MethodDefinitionTable.TryGetMethodReferenceId(method, out fieldToken); + yield return new Tuple( + method.MetadataToken.ToUInt32(), 0x06000000 | (uint)fieldToken, method); + } + } + + private IEnumerable> GetFieldsTokens( + IEnumerable fields) + { + foreach (var field in fields.Where(item => !item.HasConstant)) + { + ushort fieldToken; + _context.FieldsTable.TryGetFieldReferenceId(field, false, out fieldToken); + yield return new Tuple( + field.MetadataToken.ToUInt32(), 0x05000000 | (uint)fieldToken); + } + } + + private void WriteTokensPair( + XmlWriter writer, + uint clrToken, + uint tinyClrToken) + { + writer.WriteStartElement("Token"); + + writer.WriteElementString("CLR", "0x" + clrToken.ToString("X8", CultureInfo.InvariantCulture)); + writer.WriteElementString("TinyCLR", "0x" + tinyClrToken.ToString("X8", CultureInfo.InvariantCulture)); + + writer.WriteEndElement(); + } + } +} diff --git a/source/MetadataProcessor.Core/Utility/nanoSerializationType.cs b/source/MetadataProcessor.Core/Utility/nanoSerializationType.cs new file mode 100644 index 00000000..3dd86289 --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/nanoSerializationType.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// This list contains type codes used for serializing attributes signatures + /// + internal enum nanoSerializationType : byte + { + // these where defined @ typedef enum CorElementType + + ELEMENT_TYPE_BOOLEAN = 0x2, + ELEMENT_TYPE_CHAR = 0x3, + ELEMENT_TYPE_I1 = 0x4, + ELEMENT_TYPE_U1 = 0x5, + ELEMENT_TYPE_I2 = 0x6, + ELEMENT_TYPE_U2 = 0x7, + ELEMENT_TYPE_I4 = 0x8, + ELEMENT_TYPE_U4 = 0x9, + ELEMENT_TYPE_I8 = 0xa, + ELEMENT_TYPE_U8 = 0xb, + ELEMENT_TYPE_R4 = 0xc, + ELEMENT_TYPE_R8 = 0xd, + ELEMENT_TYPE_STRING = 0xe, + + SERIALIZATION_TYPE_FIELD = 0x53, + SERIALIZATION_TYPE_PROPERTY = 0x54, + } +} diff --git a/source/MetadataProcessor.Core/Utility/nanoStringsConstants.cs b/source/MetadataProcessor.Core/Utility/nanoStringsConstants.cs new file mode 100644 index 00000000..eb03ed55 --- /dev/null +++ b/source/MetadataProcessor.Core/Utility/nanoStringsConstants.cs @@ -0,0 +1,898 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Helper class for storing list of 'predefined' string constants which encoded in + /// .NET nanoFramework assembly metadata using special notation (highest possible values). + /// + internal static class nanoStringsConstants + { + /// + /// Gets string reference identifier for passed string from constants table. + /// + /// String value for lookup. + /// String reference identifier. + /// Returns true if string found in constants table, false otherwise. + public static bool TryGetStringIndex( + string value, + out ushort index) + { + return _idsByStrings.TryGetValue(value, out index); + } + + private static readonly IDictionary _idsByStrings = new[] + { + /* 0000 */ ".cctor", + /* 0001 */ ".ctor", + /* 0002 */ "Abort", + /* 0003 */ "Abs", + /* 0004 */ "AccessedThroughPropertyAttribute", + /* 0005 */ "Acos", + /* 0006 */ "Add", + /* 0007 */ "AddDays", + /* 0008 */ "AddHours", + /* 0009 */ "AddMilliseconds", + /* 000A */ "AddMinutes", + /* 000B */ "AddSeconds", + /* 000C */ "AddTicks", + /* 000D */ "AnyPendingFinalizers", + /* 000E */ "AppDomain", + /* 000F */ "AppDomainUnloadedException", + /* 0010 */ "Append", + /* 0011 */ "AppendHelper", + /* 0012 */ "AppendLine", + /* 0013 */ "AppendTrailingZeros", + /* 0014 */ "ApplicationException", + /* 0015 */ "ArgumentException", + /* 0016 */ "ArgumentNullException", + /* 0017 */ "ArgumentOutOfRangeException", + /* 0018 */ "Arguments", + /* 0019 */ "Array", + /* 001A */ "ArrayList", + /* 001B */ "ArraySize", + /* 001C */ "Asin", + /* 001D */ "Assembly", + /* 001E */ "AssemblyInfo", + /* 001F */ "AssemblyMemoryInfo", + /* 0020 */ "AssemblyName", + /* 0021 */ "AssemblyNameFlags", + /* 0022 */ "AssemblyRef", + /* 0023 */ "AssemblyRefElements", + /* 0024 */ "Assert", + /* 0025 */ "AsyncCallback", + /* 0026 */ "Atan", + /* 0027 */ "Atan2", + /* 0028 */ "Attribute", + /* 0029 */ "Attributes", + /* 002A */ "AttributesElements", + /* 002B */ "AutoResetEvent", + /* 002C */ "Backlight", + /* 002D */ "BaseEvent", + /* 002E */ "BeginInvoke", + /* 002F */ "Bias", + /* 0030 */ "BinarySearch", + /* 0031 */ "Binder", + /* 0032 */ "BindingFlags", + /* 0033 */ "BitConverter", + /* 0034 */ "BitPacked", + /* 0035 */ "Boolean", + /* 0036 */ "Break", + /* 0037 */ "Byte", + /* 0038 */ "ByteCode", + /* 0039 */ "Ceiling", + /* 003A */ "Change", + /* 003B */ "Char", + /* 003C */ "Check", + /* 003D */ "Clear", + /* 003E */ "Clone", + /* 003F */ "Close", + /* 0040 */ "Combine", + /* 0041 */ "CombineArrays", + /* 0042 */ "Compare", + /* 0043 */ "CompareExchange", + /* 0044 */ "CompareTo", + /* 0045 */ "ComputeCRC", + /* 0046 */ "Concat", + /* 0047 */ "ConstraintException", + /* 0048 */ "ConstructorInfo", + /* 0049 */ "ContactHeight", + /* 004A */ "ContactWidth", + /* 004B */ "Contains", + /* 004C */ "Convert", + /* 004D */ "Copy", + /* 004E */ "CopyTo", + /* 004F */ "CopyToCollection", + /* 0050 */ "Cos", + /* 0051 */ "Cosh", + /* 0052 */ "CreateDomain", + /* 0053 */ "CreateInstance", + /* 0054 */ "CreateInstanceAndUnwrap", + /* 0055 */ "CultureInfo", + /* 0056 */ "CultureTypes", + /* 0057 */ "CurrentSystemTimeZone", + /* 0058 */ "DateTime", + /* 0059 */ "DateTimeFormat", + /* 005A */ "DateTimeFormatInfo", + /* 005B */ "DateTimeKind", + /* 005C */ "Day", + /* 005D */ "DayOfWeek", + /* 005E */ "DaylightBias", + /* 005F */ "DaylightDate", + /* 0060 */ "DaylightName", + /* 0061 */ "DaylightTime", + /* 0062 */ "DaysInMonth", + /* 0063 */ "Debug", + /* 0064 */ "DebuggableAttribute", + /* 0065 */ "Debugger", + /* 0066 */ "DebuggingModes", + /* 0067 */ "Decoder", + /* 0068 */ "Decrement", + /* 0069 */ "Delegate", + /* 006A */ "Dequeue", + /* 006B */ "Deserialize", + /* 006C */ "DictionaryEntry", + /* 006D */ "Dispose", + /* 006E */ "Double", + /* 006F */ "DoubleToInt64Bits", + /* 0070 */ "Duration", + /* 0071 */ "EditorBrowsableState", + /* 0072 */ "Empty", + /* 0073 */ "EnableGCMessages", + /* 0074 */ "Encoding", + /* 0075 */ "EndInvoke", + /* 0076 */ "EndPoint", + /* 0077 */ "Enqueue", + /* 0078 */ "EnsureCapacity", + /* 0079 */ "EnsureStringArrayResource", + /* 007A */ "EnsureStringResource", + /* 007B */ "Enter", + /* 007C */ "Entry", + /* 007D */ "EntryForKey", + /* 007E */ "Enum", + /* 007F */ "EnumeratorType", + /* 0080 */ "Equals", + /* 0081 */ "EventArgs", + /* 0082 */ "EventCategory", + /* 0083 */ "EventData", + /* 0084 */ "EventMessage", + /* 0085 */ "Exception", + /* 0086 */ "Exchange", + /* 0087 */ "ExecutionConstraint", + /* 0088 */ "Exit", + /* 0089 */ "Exp", + /* 008A */ "ExpandByABlock", + /* 008B */ "ExtendedTimer", + /* 008C */ "ExtendedWeakReference", + /* 008D */ "ExtensionAttribute", + /* 008E */ "ExtractRangeFromArray", + /* 008F */ "ExtractValueFromArray", + /* 0090 */ "FalseString", + /* 0091 */ "FieldDef", + /* 0092 */ "FieldDefElements", + /* 0093 */ "FieldInfo", + /* 0094 */ "FieldRef", + /* 0095 */ "FieldRefElements", + /* 0096 */ "Finalize", + /* 0097 */ "FindChunkForIndex", + /* 0098 */ "FindResource", + /* 0099 */ "Flags", + /* 009A */ "Floor", + /* 009B */ "Flush", + /* 009C */ "FlushAll", + /* 009D */ "Format", + /* 009E */ "FormatCustomized", + /* 009F */ "FormatDigits", + /* 00A0 */ "FormatNative", + /* 00A1 */ "FromBase64CharArray", + /* 00A2 */ "FromBase64String", + /* 00A3 */ "FromTicks", + /* 00A4 */ "GC", + /* 00A5 */ "GenericEvent", + /* 00A6 */ "Gesture", + /* 00A7 */ "GetAssemblies", + /* 00A8 */ "GetAssembly", + /* 00A9 */ "GetAssemblyFromHash", + /* 00AA */ "GetAssemblyHash", + /* 00AB */ "GetAssemblyInfo", + /* 00AC */ "GetAssemblyMemoryInfo", + /* 00AD */ "GetBase64EncodedLength", + /* 00AE */ "GetBytes", + /* 00AF */ "GetChars", + /* 00B0 */ "GetConstructor", + /* 00B1 */ "GetCultures", + /* 00B2 */ "GetDaylightChanges", + /* 00B3 */ "GetDecoder", + /* 00B4 */ "GetDelimitedStringResource", + /* 00B5 */ "GetDelimitedStringResources", + /* 00B6 */ "GetDomain", + /* 00B7 */ "GetDoubleNumber", + /* 00B8 */ "GetEffectiveDate", + /* 00B9 */ "GetElementType", + /* 00BA */ "GetEnumerator", + /* 00BB */ "GetExecutingAssembly", + /* 00BC */ "GetExpirationDate", + /* 00BD */ "GetField", + /* 00BE */ "GetFields", + /* 00BF */ "GetFormat", + /* 00C0 */ "GetHashCode", + /* 00C1 */ "GetInterfaces", + /* 00C2 */ "GetMachineTime", + /* 00C3 */ "GetManifestResourceNames", + /* 00C4 */ "GetMessage", + /* 00C5 */ "GetMethod", + /* 00C6 */ "GetMethods", + /* 00C7 */ "GetName", + /* 00C8 */ "GetObject", + /* 00C9 */ "GetObjectChunkFromId", + /* 00CA */ "GetObjectFromId", + /* 00CB */ "GetObjectInternal", + /* 00CC */ "GetObjectValue", + /* 00CD */ "GetParentCultureName", + /* 00CE */ "GetPosition", + /* 00CF */ "GetRawCertData", + /* 00D0 */ "GetRealFormat", + /* 00D1 */ "GetSatelliteAssembly", + /* 00D2 */ "GetString", + /* 00D3 */ "GetSystemVersion", + /* 00D4 */ "GetTimeZoneOffset", + /* 00D5 */ "GetType", + /* 00D6 */ "GetTypeFromHandle", + /* 00D7 */ "GetTypeFromHash", + /* 00D8 */ "GetTypeHash", + /* 00D9 */ "GetTypeInternal", + /* 00DA */ "GetTypes", + /* 00DB */ "GetTypesImplementingInterface", + /* 00DC */ "GetUtcOffset", + /* 00DD */ "GetValue", + /* 00DE */ "GetVersion", + /* 00DF */ "GloballySynchronizedAttribute", + /* 00E0 */ "Guid", + /* 00E1 */ "Hash", + /* 00E2 */ "Hashtable", + /* 00E3 */ "HashtableEnumerator", + /* 00E4 */ "HexToChar", + /* 00E5 */ "Hour", + /* 00E6 */ "IAsyncResult", + /* 00E7 */ "ICloneable", + /* 00E8 */ "ICollection", + /* 00E9 */ "IComparable", + /* 00EA */ "IComparer", + /* 00EB */ "ICustomFormatter", + /* 00EC */ "IDictionary", + /* 00ED */ "IDisposable", + /* 00EE */ "IEEERemainder", + /* 00EF */ "IEnumerable", + /* 00F0 */ "IEnumerator", + /* 00F1 */ "IEqualityComparer", + /* 00F2 */ "IEventListener", + /* 00F3 */ "IEventProcessor", + /* 00F4 */ "IFormatProvider", + /* 00F5 */ "IFormattable", + /* 00F6 */ "IList", + /* 00F7 */ "ILog", + /* 00F8 */ "IOException", + /* 00F9 */ "IOExceptionErrorCode", + /* 00FA */ "IReflect", + /* 00FB */ "Increment", + /* 00FC */ "IndexOf", + /* 00FD */ "IndexOfAny", + /* 00FE */ "IndexOutOfRangeException", + /* 00FF */ "Initialize", + /* 0100 */ "InitializeArray", + /* 0101 */ "InitializeForEventSource", + /* 0102 */ "InitializeHashTable", + /* 0103 */ "Insert", + /* 0104 */ "InsertGroupSeperators", + /* 0105 */ "InsertValueIntoArray", + /* 0106 */ "Install", + /* 0107 */ "Int16", + /* 0108 */ "Int32", + /* 0109 */ "Int64", + /* 010A */ "Int64BitsToDouble", + /* 010B */ "IntPtr", + /* 010C */ "Interlocked", + /* 010D */ "Intern", + /* 010E */ "InvalidCastException", + /* 010F */ "InvalidOperationException", + /* 0110 */ "Invoke", + /* 0111 */ "InvokeMember", + /* 0112 */ "IsDaylightSavingTime", + /* 0113 */ "IsEmulator", + /* 0114 */ "IsInfinity", + /* 0115 */ "IsInstanceOfType", + /* 0116 */ "IsInterned", + /* 0117 */ "IsNaN", + /* 0118 */ "IsNegativeInfinity", + /* 0119 */ "IsPositiveInfinity", + /* 011A */ "IsSubclassOf", + /* 011B */ "IsTransparentProxy", + /* 011C */ "IsTypeLoaded", + /* 011D */ "Join", + /* 011E */ "Key", + /* 011F */ "KeyCollection", + /* 0120 */ "LastIndexOf", + /* 0121 */ "LastIndexOfAny", + /* 0122 */ "Load", + /* 0123 */ "LoadInternal", + /* 0124 */ "Log", + /* 0125 */ "Log10", + /* 0126 */ "MakeRoom", + /* 0127 */ "ManualResetEvent", + /* 0128 */ "MarshalByRefObject", + /* 0129 */ "Math", + /* 012A */ "Max", + /* 012B */ "MaxValue", + /* 012C */ "MemberInfo", + /* 012D */ "MemberTypes", + /* 012E */ "MemberwiseClone", + /* 012F */ "Message", + /* 0130 */ "MetadataSize", + /* 0131 */ "MethodBase", + /* 0132 */ "MethodDef", + /* 0133 */ "MethodDefElements", + /* 0134 */ "MethodInfo", + /* 0135 */ "MethodRef", + /* 0136 */ "MethodRefElements", + /* 0137 */ "Microsoft.SPOT", + /* 0138 */ "Microsoft.SPOT.Hardware", + /* 0139 */ "Microsoft.SPOT.Messaging", + /* 013A */ "Microsoft.SPOT.Touch", + /* 013B */ "Milliseconds", + /* 013C */ "Min", + /* 013D */ "MinValue", + /* 013E */ "Minute", + /* 013F */ "Monitor", + /* 0140 */ "Month", + /* 0141 */ "MoveNext", + /* 0142 */ "MulticastDelegate", + /* 0143 */ "Native_Resources", + /* 0144 */ "Negate", + /* 0145 */ "NewGuid", + /* 0146 */ "Next", + /* 0147 */ "NextBytes", + /* 0148 */ "NextDouble", + /* 0149 */ "NotImplementedException", + /* 014A */ "NotSupportedException", + /* 014B */ "NullReferenceException", + /* 014C */ "Number", + /* 014D */ "NumberFormatInfo", + /* 014E */ "Object", + /* 014F */ "ObjectDisposedException", + /* 0150 */ "OnEvent", + /* 0151 */ "OutOfMemoryException", + /* 0152 */ "Parse", + /* 0153 */ "ParseAssemblyName", + /* 0154 */ "ParseCertificate", + /* 0155 */ "ParseNextChar", + /* 0156 */ "ParseQuoteString", + /* 0157 */ "ParseRepeatPattern", + /* 0158 */ "ParseTypeName", + /* 0159 */ "Peek", + /* 015A */ "Piezo", + /* 015B */ "Pop", + /* 015C */ "PostProcessFloat", + /* 015D */ "PostProcessInteger", + /* 015E */ "Pow", + /* 015F */ "Print", + /* 0160 */ "PriorityLevel", + /* 0161 */ "ProcessEvent", + /* 0162 */ "ProcessorArchitecture", + /* 0163 */ "PropertyInfo", + /* 0164 */ "Push", + /* 0165 */ "PushBackIntoRecoverList", + /* 0166 */ "Queue", + /* 0167 */ "Raise", + /* 0168 */ "RamSize", + /* 0169 */ "Random", + /* 016A */ "RangeBias", + /* 016B */ "ReRegisterForFinalize", + /* 016C */ "Read", + /* 016D */ "ReadByte", + /* 016E */ "Recover", + /* 016F */ "RecoverOrCreate", + /* 0170 */ "ReferenceEquals", + /* 0171 */ "Reflection", + /* 0172 */ "Rehash", + /* 0173 */ "RemotedException", + /* 0174 */ "RemotingServices", + /* 0175 */ "Remove", + /* 0176 */ "RemoveAt", + /* 0177 */ "Replace", + /* 0178 */ "ReplaceAllInChunk", + /* 0179 */ "ReplaceDecimalSeperator", + /* 017A */ "ReplaceInPlaceAtChunk", + /* 017B */ "ReplaceNegativeSign", + /* 017C */ "Reply", + /* 017D */ "ReplyRaw", + /* 017E */ "Reset", + /* 017F */ "ResourceManager", + /* 0180 */ "ResourceUtility", + /* 0181 */ "Resources", + /* 0182 */ "ResourcesData", + /* 0183 */ "ResourcesElements", + /* 0184 */ "ResourcesFiles", + /* 0185 */ "ResourcesFilesElements", + /* 0186 */ "Resume", + /* 0187 */ "RomSize", + /* 0188 */ "Round", + /* 0189 */ "RunClassConstructor", + /* 018A */ "RuntimeArgumentHandle", + /* 018B */ "RuntimeConstructorInfo", + /* 018C */ "RuntimeFieldHandle", + /* 018D */ "RuntimeFieldInfo", + /* 018E */ "RuntimeHelpers", + /* 018F */ "RuntimeMethodHandle", + /* 0190 */ "RuntimeMethodInfo", + /* 0191 */ "RuntimeType", + /* 0192 */ "RuntimeTypeHandle", + /* 0193 */ "SByte", + /* 0194 */ "SZArrayEnumerator", + /* 0195 */ "Scale", + /* 0196 */ "Second", + /* 0197 */ "Seek", + /* 0198 */ "SeekOrigin", + /* 0199 */ "SendMessage", + /* 019A */ "SendMessageRaw", + /* 019B */ "SerializationFlags", + /* 019C */ "SerializationHintsAttribute", + /* 019D */ "Serialize", + /* 019E */ "Set", + /* 019F */ "SetCapacity", + /* 01A0 */ "SetCurrentUICulture", + /* 01A1 */ "SetLength", + /* 01A2 */ "SetLocalTime", + /* 01A3 */ "SetValue", + /* 01A4 */ "Sign", + /* 01A5 */ "Signatures", + /* 01A6 */ "Sin", + /* 01A7 */ "Single", + /* 01A8 */ "Sinh", + /* 01A9 */ "Sleep", + /* 01AA */ "Source", + /* 01AB */ "SourceID", + /* 01AC */ "SpecifyKind", + /* 01AD */ "Split", + /* 01AE */ "Sqrt", + /* 01AF */ "Stack", + /* 01B0 */ "StandardBias", + /* 01B1 */ "StandardDate", + /* 01B2 */ "StandardName", + /* 01B3 */ "Start", + /* 01B4 */ "StartsWith", + /* 01B5 */ "StaticFields", + /* 01B6 */ "Stream", + /* 01B7 */ "String", + /* 01B8 */ "StringBuilder", + /* 01B9 */ "StringResources", + /* 01BA */ "Strings", + /* 01BB */ "Substring", + /* 01BC */ "Subtract", + /* 01BD */ "SuppressFinalize", + /* 01BE */ "Suspend", + /* 01BF */ "System", + /* 01C0 */ "System.Collections", + /* 01C1 */ "System.Collections.ICollection.get_Count", + /* 01C2 */ "System.Collections.IList.Add", + /* 01C3 */ "System.Collections.IList.Clear", + /* 01C4 */ "System.Collections.IList.Contains", + /* 01C5 */ "System.Collections.IList.IndexOf", + /* 01C6 */ "System.Collections.IList.Insert", + /* 01C7 */ "System.Collections.IList.Remove", + /* 01C8 */ "System.Collections.IList.RemoveAt", + /* 01C9 */ "System.Collections.IList.get_Item", + /* 01CA */ "System.Collections.IList.set_Item", + /* 01CB */ "System.ComponentModel", + /* 01CC */ "System.Diagnostics", + /* 01CD */ "System.Globalization", + /* 01CE */ "System.Globalization.Resources", + /* 01CF */ "System.IO", + /* 01D0 */ "System.Reflection", + /* 01D1 */ "System.Resources", + /* 01D2 */ "System.Runtime.CompilerServices", + /* 01D3 */ "System.Runtime.Remoting", + /* 01D4 */ "System.Runtime.Versioning", + /* 01D5 */ "System.Security.Cryptography.X509Certificates", + /* 01D6 */ "System.Text", + /* 01D7 */ "System.Threading", + /* 01D8 */ "SystemException", + /* 01D9 */ "SystemID", + /* 01DA */ "SystemInfo", + /* 01DB */ "SystemTime", + /* 01DC */ "Tan", + /* 01DD */ "Tanh", + /* 01DE */ "Target", + /* 01DF */ "TargetFrameworkAttribute", + /* 01E0 */ "Thread", + /* 01E1 */ "ThreadAbortException", + /* 01E2 */ "ThreadPriority", + /* 01E3 */ "ThreadStart", + /* 01E4 */ "ThreadState", + /* 01E5 */ "Time", + /* 01E6 */ "TimeEvents", + /* 01E7 */ "TimeSpan", + /* 01E8 */ "TimeStamp", + /* 01E9 */ "TimeZone", + /* 01EA */ "TimeZoneId", + /* 01EB */ "TimeZoneInformation", + /* 01EC */ "Timer", + /* 01ED */ "TimerCallback", + /* 01EE */ "Timestamp", + /* 01EF */ "ToArray", + /* 01F0 */ "ToBase64String", + /* 01F1 */ "ToBoolean", + /* 01F2 */ "ToByte", + /* 01F3 */ "ToByteArray", + /* 01F4 */ "ToChar", + /* 01F5 */ "ToCharArray", + /* 01F6 */ "ToDouble", + /* 01F7 */ "ToInt16", + /* 01F8 */ "ToInt32", + /* 01F9 */ "ToInt64", + /* 01FA */ "ToLocalTime", + /* 01FB */ "ToLower", + /* 01FC */ "ToSByte", + /* 01FD */ "ToSingle", + /* 01FE */ "ToString", + /* 01FF */ "ToUInt16", + /* 0200 */ "ToUInt32", + /* 0201 */ "ToUInt64", + /* 0202 */ "ToUniversalTime", + /* 0203 */ "ToUpper", + /* 0204 */ "TouchEvent", + /* 0205 */ "TouchGesture", + /* 0206 */ "TouchGestureEventArgs", + /* 0207 */ "TouchGestureEventHandler", + /* 0208 */ "TouchInput", + /* 0209 */ "TouchInputFlags", + /* 020A */ "TouchMessages", + /* 020B */ "TouchScreenEventArgs", + /* 020C */ "TouchScreenEventHandler", + /* 020D */ "Touches", + /* 020E */ "Trace", + /* 020F */ "Trim", + /* 0210 */ "TrimEnd", + /* 0211 */ "TrimStart", + /* 0212 */ "TrueString", + /* 0213 */ "Truncate", + /* 0214 */ "TryParse", + /* 0215 */ "TrySZIndexOf", + /* 0216 */ "Type", + /* 0217 */ "TypeCode", + /* 0218 */ "TypeDef", + /* 0219 */ "TypeDefElements", + /* 021A */ "TypeRef", + /* 021B */ "TypeRefElements", + /* 021C */ "TypeSpec", + /* 021D */ "TypeSpecElements", + /* 021E */ "UInt16", + /* 021F */ "UInt32", + /* 0220 */ "UInt64", + /* 0221 */ "UTF8Decoder", + /* 0222 */ "UTF8Encoding", + /* 0223 */ "UnknownTypeException", + /* 0224 */ "Unload", + /* 0225 */ "Utility", + /* 0226 */ "ValidateFormat", + /* 0227 */ "Value", + /* 0228 */ "ValueCollection", + /* 0229 */ "ValueType", + /* 022A */ "Version", + /* 022B */ "Void", + /* 022C */ "WaitAll", + /* 022D */ "WaitAny", + /* 022E */ "WaitForPendingFinalizers", + /* 022F */ "WaitHandle", + /* 0230 */ "WaitMultiple", + /* 0231 */ "WaitOne", + /* 0232 */ "WeakDelegate", + /* 0233 */ "WeakReference", + /* 0234 */ "Write", + /* 0235 */ "WriteByte", + /* 0236 */ "X", + /* 0237 */ "X509Certificate", + /* 0238 */ "Y", + /* 0239 */ "Year", + /* 023A */ "Zero", + /* 023B */ "_Build", + /* 023C */ "_Major", + /* 023D */ "_Minor", + /* 023E */ "_Revision", + /* 023F */ "_array", + /* 0240 */ "_arrayLength", + /* 0241 */ "_assembly", + /* 0242 */ "_buckets", + /* 0243 */ "_count", + /* 0244 */ "_endIndex", + /* 0245 */ "_frameworkDisplayName", + /* 0246 */ "_frameworkName", + /* 0247 */ "_growthFactor", + /* 0248 */ "_head", + /* 0249 */ "_index", + /* 024A */ "_items", + /* 024B */ "_loadFactor", + /* 024C */ "_maxLoadFactor", + /* 024D */ "_message", + /* 024E */ "_numberOfBuckets", + /* 024F */ "_random", + /* 0250 */ "_size", + /* 0251 */ "_startIndex", + /* 0252 */ "_tail", + /* 0253 */ "abbreviatedDayNames", + /* 0254 */ "abbreviatedMonthNames", + /* 0255 */ "amDesignator", + /* 0256 */ "dateSeparator", + /* 0257 */ "dateTimeInfo", + /* 0258 */ "dayNames", + /* 0259 */ "fullDateTimePattern", + /* 025A */ "generalLongTimePattern", + /* 025B */ "generalShortTimePattern", + /* 025C */ "get_AMDesignator", + /* 025D */ "get_AbbreviatedDayNames", + /* 025E */ "get_AbbreviatedMonthNames", + /* 025F */ "get_Angle", + /* 0260 */ "get_Assembly", + /* 0261 */ "get_AssemblyQualifiedName", + /* 0262 */ "get_BaseType", + /* 0263 */ "get_Build", + /* 0264 */ "get_CanRead", + /* 0265 */ "get_CanSeek", + /* 0266 */ "get_CanTimeout", + /* 0267 */ "get_CanWrite", + /* 0268 */ "get_Capacity", + /* 0269 */ "get_Chars", + /* 026A */ "get_Count", + /* 026B */ "get_Current", + /* 026C */ "get_CurrentDomain", + /* 026D */ "get_CurrentInfo", + /* 026E */ "get_CurrentThread", + /* 026F */ "get_CurrentTimeZone", + /* 0270 */ "get_CurrentUICulture", + /* 0271 */ "get_CurrentUICultureInternal", + /* 0272 */ "get_Date", + /* 0273 */ "get_DateSeparator", + /* 0274 */ "get_DateTimeFormat", + /* 0275 */ "get_Day", + /* 0276 */ "get_DayNames", + /* 0277 */ "get_DayOfWeek", + /* 0278 */ "get_DayOfYear", + /* 0279 */ "get_DaylightName", + /* 027A */ "get_Days", + /* 027B */ "get_DeclaringType", + /* 027C */ "get_Delta", + /* 027D */ "get_End", + /* 027E */ "get_ErrorCode", + /* 027F */ "get_FieldType", + /* 0280 */ "get_Flags", + /* 0281 */ "get_FrameworkDisplayName", + /* 0282 */ "get_FrameworkName", + /* 0283 */ "get_FriendlyName", + /* 0284 */ "get_FullDateTimePattern", + /* 0285 */ "get_FullName", + /* 0286 */ "get_GeneralLongTimePattern", + /* 0287 */ "get_GeneralShortTimePattern", + /* 0288 */ "get_GrowthFactor", + /* 0289 */ "get_Hour", + /* 028A */ "get_Hours", + /* 028B */ "get_Id", + /* 028C */ "get_InnerException", + /* 028D */ "get_IsAbstract", + /* 028E */ "get_IsAlive", + /* 028F */ "get_IsArray", + /* 0290 */ "get_IsAttached", + /* 0291 */ "get_IsBigEndian", + /* 0292 */ "get_IsClass", + /* 0293 */ "get_IsEnum", + /* 0294 */ "get_IsFinal", + /* 0295 */ "get_IsFixedSize", + /* 0296 */ "get_IsInterface", + /* 0297 */ "get_IsLittleEndian", + /* 0298 */ "get_IsNotPublic", + /* 0299 */ "get_IsPublic", + /* 029A */ "get_IsReadOnly", + /* 029B */ "get_IsSerializable", + /* 029C */ "get_IsStatic", + /* 029D */ "get_IsSynchronized", + /* 029E */ "get_IsValid", + /* 029F */ "get_IsValueType", + /* 02A0 */ "get_IsVirtual", + /* 02A1 */ "get_Issuer", + /* 02A2 */ "get_Item", + /* 02A3 */ "get_Keys", + /* 02A4 */ "get_Kind", + /* 02A5 */ "get_LastExpiration", + /* 02A6 */ "get_Length", + /* 02A7 */ "get_LongDatePattern", + /* 02A8 */ "get_LongTimePattern", + /* 02A9 */ "get_Major", + /* 02AA */ "get_ManagedThreadId", + /* 02AB */ "get_MaxCapacity", + /* 02AC */ "get_MaxLoadFactor", + /* 02AD */ "get_MemberType", + /* 02AE */ "get_Message", + /* 02AF */ "get_Method", + /* 02B0 */ "get_Millisecond", + /* 02B1 */ "get_Milliseconds", + /* 02B2 */ "get_Minor", + /* 02B3 */ "get_Minute", + /* 02B4 */ "get_Minutes", + /* 02B5 */ "get_Model", + /* 02B6 */ "get_Month", + /* 02B7 */ "get_MonthDayPattern", + /* 02B8 */ "get_MonthNames", + /* 02B9 */ "get_Name", + /* 02BA */ "get_NegativeSign", + /* 02BB */ "get_Now", + /* 02BC */ "get_NumberDecimalSeparator", + /* 02BD */ "get_NumberFormat", + /* 02BE */ "get_NumberGroupSeparator", + /* 02BF */ "get_NumberGroupSizes", + /* 02C0 */ "get_OEM", + /* 02C1 */ "get_OEMString", + /* 02C2 */ "get_OffsetToStringData", + /* 02C3 */ "get_PMDesignator", + /* 02C4 */ "get_ParamName", + /* 02C5 */ "get_Parent", + /* 02C6 */ "get_Payload", + /* 02C7 */ "get_PayloadRaw", + /* 02C8 */ "get_Position", + /* 02C9 */ "get_PositiveSign", + /* 02CA */ "get_Priority", + /* 02CB */ "get_PropertyName", + /* 02CC */ "get_PropertyType", + /* 02CD */ "get_RFC1123Pattern", + /* 02CE */ "get_ReadTimeout", + /* 02CF */ "get_ResourceManager", + /* 02D0 */ "get_ReturnType", + /* 02D1 */ "get_Revision", + /* 02D2 */ "get_SKU", + /* 02D3 */ "get_Second", + /* 02D4 */ "get_Seconds", + /* 02D5 */ "get_Selector", + /* 02D6 */ "get_ShortDatePattern", + /* 02D7 */ "get_ShortTimePattern", + /* 02D8 */ "get_SortableDateTimePattern", + /* 02D9 */ "get_StackTrace", + /* 02DA */ "get_StandardName", + /* 02DB */ "get_Start", + /* 02DC */ "get_Subject", + /* 02DD */ "get_SyncRoot", + /* 02DE */ "get_Target", + /* 02DF */ "get_ThreadState", + /* 02E0 */ "get_Ticks", + /* 02E1 */ "get_TimeOfDay", + /* 02E2 */ "get_TimeSeparator", + /* 02E3 */ "get_Today", + /* 02E4 */ "get_UTF8", + /* 02E5 */ "get_UniversalSortableDateTimePattern", + /* 02E6 */ "get_UseRFC4648Encoding", + /* 02E7 */ "get_UtcNow", + /* 02E8 */ "get_Values", + /* 02E9 */ "get_Version", + /* 02EA */ "get_WriteTimeout", + /* 02EB */ "get_Year", + /* 02EC */ "get_YearMonthPattern", + /* 02ED */ "ht", + /* 02EE */ "index", + /* 02EF */ "key", + /* 02F0 */ "longDatePattern", + /* 02F1 */ "longTimePattern", + /* 02F2 */ "m_AppDomain", + /* 02F3 */ "m_ChunkChars", + /* 02F4 */ "m_ChunkLength", + /* 02F5 */ "m_ChunkOffset", + /* 02F6 */ "m_ChunkPrevious", + /* 02F7 */ "m_Delegate", + /* 02F8 */ "m_HResult", + /* 02F9 */ "m_Id", + /* 02FA */ "m_MaxCapacity", + /* 02FB */ "m_Priority", + /* 02FC */ "m_Thread", + /* 02FD */ "m_appDomain", + /* 02FE */ "m_assembly", + /* 02FF */ "m_baseAssembly", + /* 0300 */ "m_baseName", + /* 0301 */ "m_callback", + /* 0302 */ "m_certificate", + /* 0303 */ "m_cultureInfo", + /* 0304 */ "m_cultureName", + /* 0305 */ "m_data", + /* 0306 */ "m_delta", + /* 0307 */ "m_effectiveDate", + /* 0308 */ "m_end", + /* 0309 */ "m_expirationDate", + /* 030A */ "m_flags", + /* 030B */ "m_friendlyName", + /* 030C */ "m_handle", + /* 030D */ "m_hash", + /* 030E */ "m_id", + /* 030F */ "m_innerException", + /* 0310 */ "m_issuer", + /* 0311 */ "m_message", + /* 0312 */ "m_name", + /* 0313 */ "m_paramName", + /* 0314 */ "m_parent", + /* 0315 */ "m_password", + /* 0316 */ "m_payload", + /* 0317 */ "m_rand", + /* 0318 */ "m_refs", + /* 0319 */ "m_resourceFileId", + /* 031A */ "m_rm", + /* 031B */ "m_rmFallback", + /* 031C */ "m_selector", + /* 031D */ "m_seq", + /* 031E */ "m_sessionHandle", + /* 031F */ "m_size", + /* 0320 */ "m_source", + /* 0321 */ "m_stackTrace", + /* 0322 */ "m_start", + /* 0323 */ "m_state", + /* 0324 */ "m_subject", + /* 0325 */ "m_ticks", + /* 0326 */ "m_ticksOffset", + /* 0327 */ "m_timer", + /* 0328 */ "m_type", + /* 0329 */ "m_value", + /* 032A */ "manager", + /* 032B */ "monthDayPattern", + /* 032C */ "monthNames", + /* 032D */ "mscorlib", + /* 032E */ "negativeSign", + /* 032F */ "next", + /* 0330 */ "numInfo", + /* 0331 */ "numberDecimalSeparator", + /* 0332 */ "numberGroupSeparator", + /* 0333 */ "numberGroupSizes", + /* 0334 */ "op_Addition", + /* 0335 */ "op_Equality", + /* 0336 */ "op_GreaterThan", + /* 0337 */ "op_GreaterThanOrEqual", + /* 0338 */ "op_Inequality", + /* 0339 */ "op_LessThan", + /* 033A */ "op_LessThanOrEqual", + /* 033B */ "op_Subtraction", + /* 033C */ "op_UnaryNegation", + /* 033D */ "op_UnaryPlus", + /* 033E */ "pmDesignator", + /* 033F */ "positiveSign", + /* 0340 */ "propertyName", + /* 0341 */ "returnType", + /* 0342 */ "s_ewr", + /* 0343 */ "s_rgbBase64Decode", + /* 0344 */ "s_rgchBase64Encoding", + /* 0345 */ "s_rgchBase64EncodingDefault", + /* 0346 */ "s_rgchBase64EncodingRFC4648", + /* 0347 */ "set_Capacity", + /* 0348 */ "set_CurrentUICultureInternal", + /* 0349 */ "set_FrameworkDisplayName", + /* 034A */ "set_GrowthFactor", + /* 034B */ "set_Item", + /* 034C */ "set_Length", + /* 034D */ "set_MaxLoadFactor", + /* 034E */ "set_Position", + /* 034F */ "set_Priority", + /* 0350 */ "set_ReadTimeout", + /* 0351 */ "set_Target", + /* 0352 */ "set_UseRFC4648Encoding", + /* 0353 */ "set_WriteTimeout", + /* 0354 */ "shortDatePattern", + /* 0355 */ "shortTimePattern", + /* 0356 */ "temp", + /* 0357 */ "ticksAtOrigin", + /* 0358 */ "timeSeparator", + /* 0359 */ "value", + /* 035A */ "value__", + /* 035B */ "yearMonthPattern", + } + .Select((value, index) => new {value, index = (ushort) (0xFFFF - index)}) + .ToDictionary(item => item.value, item => item.index, StringComparer.Ordinal); + } +} diff --git a/source/MetadataProcessor.Core/nanoAssemblyBuilder.cs b/source/MetadataProcessor.Core/nanoAssemblyBuilder.cs new file mode 100644 index 00000000..22be290e --- /dev/null +++ b/source/MetadataProcessor.Core/nanoAssemblyBuilder.cs @@ -0,0 +1,113 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Main metadata transformation class - builds .NET nanoFramework assembly + /// from full .NET Framework assembly metadata represented in Mono.Cecil format. + /// + public sealed class nanoAssemblyBuilder + { + private readonly nanoTablesContext _tablesContext; + + /// + /// Creates new instance of object. + /// + /// Original assembly metadata in Mono.Cecil format. + /// List of full type names with explicit ordering. + /// Custom string literals sorter for UTs using only. + /// + /// If contains true each type/method/field should contains one attribute of each type. + /// + public nanoAssemblyBuilder( + AssemblyDefinition assemblyDefinition, + List explicitTypesOrder = null, + ICustomStringSorter stringSorter = null, + bool applyAttributesCompression = false) + { + _tablesContext = new nanoTablesContext( + assemblyDefinition, explicitTypesOrder, stringSorter, applyAttributesCompression); + } + + /// + /// Writes all .NET nanoFramework metadata into output stream. + /// + /// Binary writer with correct endianness. + public void Write( + nanoBinaryWriter binaryWriter) + { + var header = new nanoAssemblyDefinition(_tablesContext); + header.Write(binaryWriter, true); + + foreach (var table in GetTables(_tablesContext)) + { + var tableBegin = (binaryWriter.BaseStream.Position + 3) & 0xFFFFFFFC; + table.Write(binaryWriter); + + var padding = (4 - ((binaryWriter.BaseStream.Position - tableBegin) % 4)) % 4; + binaryWriter.WriteBytes(new byte[padding]); + + header.UpdateTableOffset(binaryWriter, tableBegin, padding); + } + + binaryWriter.BaseStream.Seek(0, SeekOrigin.Begin); + header.Write(binaryWriter, false); + } + + public void Write( + XmlWriter xmlWriter) + { + var pdbxWriter = new nanoPdbxFileWriter(_tablesContext); + pdbxWriter.Write(xmlWriter); + } + + private static IEnumerable GetTables( + nanoTablesContext context) + { + yield return context.AssemblyReferenceTable; + + yield return context.TypeReferencesTable; + + yield return context.FieldReferencesTable; + + yield return context.MethodReferencesTable; + + yield return context.TypeDefinitionTable; + + yield return context.FieldsTable; + + yield return context.MethodDefinitionTable; + + yield return context.AttributesTable; + + yield return context.TypeSpecificationsTable; + + yield return context.ResourcesTable; + + yield return context.ResourceDataTable; + + context.ByteCodeTable.UpdateStringTable(); + context.StringTable.GetOrCreateStringId( + context.AssemblyDefinition.Name.Name); + + yield return context.StringTable; + + yield return context.SignaturesTable; + + yield return context.ByteCodeTable; + + yield return context.ResourceFileTable; + + yield return nanoEmptyTable.Instance; + } + } +} diff --git a/source/MetadataProcessor.Core/nanoAssemblyDefinition.cs b/source/MetadataProcessor.Core/nanoAssemblyDefinition.cs new file mode 100644 index 00000000..0272f3ad --- /dev/null +++ b/source/MetadataProcessor.Core/nanoAssemblyDefinition.cs @@ -0,0 +1,186 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// Original work from Oleg Rakhmatulin. +// See LICENSE file in the project root for full license information. +// + +using System.IO; + +namespace nanoFramework.Tools.MetadataProcessor +{ + /// + /// Encapsulates logic for assembly definition (header) writing. + /// + public sealed class nanoAssemblyDefinition + { + /// + /// nanoFramework assembly marker V1. + /// + private const string c_NFAssemblyMarker_v1 = "NFMRK1"; + + /// + /// Position of Assembly CRC32 in the PE file. + /// + private const int c_AssemblyCrc32Position = 0x0C; + + /// + /// Position of the header CRC32 in the PE file. + /// + private const int c_HeaderCrc32Position = 0x08; + + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + private readonly nanoTablesContext _context; + + /// + /// Offset for current table address writing. + /// + private long _tablesOffset; + + /// + /// Offset for current table padding writing. + /// + private long _paddingsOffset; + + /// + /// Creates new instance of object. + /// + /// + /// Assembly tables context - contains all tables used for building target assembly. + /// + public nanoAssemblyDefinition( + nanoTablesContext context) + { + _context = context; + } + + /// + /// Writes header information into output stream (w/o CRC and table offsets/paddings). + /// + /// Binary writer with correct endianness. + /// If true no assembly name will be written. + public void Write( + nanoBinaryWriter writer, + bool isPreAllocationCall) + { + // this replicates the original struct CLR_RECORD_ASSEMBLY + + writer.WriteString(c_NFAssemblyMarker_v1); + + // header CRC32 + writer.WriteUInt32(0); + + // assembly CRC32 + writer.WriteUInt32(0); + + // current builds are for little endian targets only + // keeping this here for now, just for compatibility + writer.WriteUInt32(0); + + // native methods CRC32 + writer.WriteUInt32(writer.IsBigEndian ? _context.NativeMethodsCrc.Current : 0x00); + + // the existing MDP seems to have a bug because it's adding an extra byte at this place in the struct + // right between the NativeMethodsChecksum and PatchEntryOffset fields. + //// need this here to pad the structure in order to have a PE exactly as the one being generated now + //writer.WriteByte(0); + + // Native methods offset + writer.WriteUInt32(0xFFFFFFFF); + + writer.WriteVersion(_context.AssemblyDefinition.Name.Version); + + writer.WriteUInt16(isPreAllocationCall + ? (ushort) 0x0000 + : _context.StringTable.GetOrCreateStringId(_context.AssemblyDefinition.Name.Name)); + writer.WriteUInt16(1); // String table version + + //For every table, a number of bytes that were padded to the end of the table + //to align to unsigned long. Each table starts at a unsigned long boundary, and ends + //at a unsigned long boundary. Some of these tables will, by construction, have + //no padding, and all will have values in the range [0-3]. This isn't the most + //compact form to hold this information, but it only costs 16 bytes/assembly. + //Trying to only align some of the tables is just much more hassle than it's worth. + //And, of course, this field also has to be unsigned long-aligned. + if (isPreAllocationCall) + { + _tablesOffset = writer.BaseStream.Position; + for (var i = 0; i < 16; ++i) + { + writer.WriteUInt32(0); + } + + writer.WriteUInt32(0); // Number of patched methods + + _paddingsOffset = writer.BaseStream.Position; + for (var i = 0; i < 16; ++i) + { + writer.WriteByte(0); + } + } + else + { + // order matters! + // need to compute Assembly CRC32 before header CRC32 + + // set writer position at Assembly CRC32 position + writer.BaseStream.Seek(c_AssemblyCrc32Position, SeekOrigin.Begin); + + var assemblyCrc32 = ComputeCrc32( + writer.BaseStream, + _paddingsOffset, + writer.BaseStream.Length - _paddingsOffset); + writer.WriteUInt32(assemblyCrc32); + + // set writer position at Header CRC32 position + writer.BaseStream.Seek(c_HeaderCrc32Position, SeekOrigin.Begin); + + var headerCrc32 = ComputeCrc32( + writer.BaseStream, + 0, + _paddingsOffset); + writer.WriteUInt32(headerCrc32); + } + } + + /// + /// Updates tables offset value and padding value for current table and + /// advance writing position for next method call (filling tables info). + /// + /// Binary writer. + /// Table beginning address (offset). + /// Table padding value. + public void UpdateTableOffset( + nanoBinaryWriter writer, + long tableBegin, + long padding) + { + writer.BaseStream.Seek(_tablesOffset, SeekOrigin.Begin); + writer.WriteUInt32((uint)tableBegin); + _tablesOffset += sizeof(int); + + writer.BaseStream.Seek(_paddingsOffset, SeekOrigin.Begin); + writer.WriteByte((byte)padding); + _paddingsOffset += sizeof(byte); + + writer.BaseStream.Seek(0, SeekOrigin.End); + } + + private static uint ComputeCrc32( + Stream outputStream, + long startOffset, + long size) + { + var currentPosition = outputStream.Position; + outputStream.Seek(startOffset, SeekOrigin.Begin); + + var buffer = new byte[size]; + outputStream.Read(buffer, 0, buffer.Length); + + outputStream.Seek(currentPosition, SeekOrigin.Begin); + + return Crc32.Compute(buffer); + } + } +} diff --git a/source/MetadataProcessor.Core/packages.config b/source/MetadataProcessor.Core/packages.config new file mode 100644 index 00000000..778a66e9 --- /dev/null +++ b/source/MetadataProcessor.Core/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/source/nanoFramework.Tools.MetadataProcessor.sln b/source/nanoFramework.Tools.MetadataProcessor.sln index 6eecaffd..e8016217 100644 --- a/source/nanoFramework.Tools.MetadataProcessor.sln +++ b/source/nanoFramework.Tools.MetadataProcessor.sln @@ -1,207 +1,34 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.2027 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MetaDataProcessor", "MetaDataProcessor", "{FCCC9596-0809-4BB4-ACC2-3615EEC264C7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetadataProcessor.Core", "MetadataProcessor.Core\MetadataProcessor.Core.csproj", "{E32F7D15-2499-440C-8026-4D5EE1C5EC3A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\nf-interpreter\src\CLR\Core\Core.vcxproj", "{89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CorLib", "..\nf-interpreter\src\CLR\CorLib\CorLib.vcxproj", "{58E950CC-2FF6-423C-B006-A70A19272F20}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Diagnostics", "..\nf-interpreter\src\CLR\Diagnostics\Diagnostics.vcxproj", "{A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tools.Lib.Parser", "Tools.Parser\Parser.vcxproj", "{AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Serialization", "..\nf-interpreter\src\CLR\Core\Serialization\Serialization.vcxproj", "{16BF6131-A3B8-4B97-B867-E45669FB48BD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPC", "..\nf-interpreter\src\CLR\Core\RPC\RPC.vcxproj", "{ED4C887A-EC09-465B-B5D9-075450ADC52D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Messaging", "..\nf-interpreter\src\CLR\Messaging\Messaging.vcxproj", "{131001E3-0201-451F-A87B-951D1C5C3EEE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WireProtocol", "..\nf-interpreter\src\CLR\WireProtocol\WireProtocol.vcxproj", "{2337C4A4-3AB4-4014-9C29-9EBE32F4510E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hardware", "..\nf-interpreter\src\CLR\Core\Hardware\Hardware.vcxproj", "{5D50772E-DAC8-407D-972F-37DEB4450B72}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tools.Lib.CorHelper", "Tools.CorHelper\CorHelper.vcxproj", "{079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InterruptHandler", "..\nf-interpreter\src\CLR\Core\InterruptHandler\InterruptHandler.vcxproj", "{D32EE397-7E49-452D-AC95-AFCB3C962E3D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tools.MetaDataProcessor", "Tools.MetaDataProcessor\MetaDataProcessor.vcxproj", "{80209A7E-B9F0-4143-BCD1-B1891236A3CF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetadataProcessor.Console", "MetadataProcessor.Console\MetadataProcessor.Console.csproj", "{A9E02E14-7321-4B12-8AB5-9A0408ED8FD0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|Any CPU.Build.0 = Debug|Win32 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.ActiveCfg = Debug|x64 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.Build.0 = Debug|x64 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.ActiveCfg = Debug|Win32 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.Build.0 = Debug|Win32 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|Any CPU.ActiveCfg = Release|Win32 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|Any CPU.Build.0 = Release|Win32 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.ActiveCfg = Release|x64 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.Build.0 = Release|x64 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.ActiveCfg = Release|Win32 - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.Build.0 = Release|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|Any CPU.Build.0 = Debug|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.ActiveCfg = Debug|x64 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.Build.0 = Debug|x64 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.ActiveCfg = Debug|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.Build.0 = Debug|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|Any CPU.ActiveCfg = Release|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|Any CPU.Build.0 = Release|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.ActiveCfg = Release|x64 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.Build.0 = Release|x64 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.ActiveCfg = Release|Win32 - {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.Build.0 = Release|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|Any CPU.Build.0 = Debug|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.ActiveCfg = Debug|x64 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.Build.0 = Debug|x64 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.ActiveCfg = Debug|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.Build.0 = Debug|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|Any CPU.ActiveCfg = Release|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|Any CPU.Build.0 = Release|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.ActiveCfg = Release|x64 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.Build.0 = Release|x64 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.ActiveCfg = Release|Win32 - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.Build.0 = Release|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|Any CPU.Build.0 = Debug|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x64.ActiveCfg = Debug|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x64.Build.0 = Debug|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x86.ActiveCfg = Debug|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Debug|x86.Build.0 = Debug|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|Any CPU.ActiveCfg = Release|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|Any CPU.Build.0 = Release|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x64.ActiveCfg = Release|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x64.Build.0 = Release|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x86.ActiveCfg = Release|Win32 - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC}.Release|x86.Build.0 = Release|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|Any CPU.Build.0 = Debug|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.ActiveCfg = Debug|x64 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.Build.0 = Debug|x64 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.ActiveCfg = Debug|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.Build.0 = Debug|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|Any CPU.ActiveCfg = Release|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|Any CPU.Build.0 = Release|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.ActiveCfg = Release|x64 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.Build.0 = Release|x64 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.ActiveCfg = Release|Win32 - {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.Build.0 = Release|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|Any CPU.Build.0 = Debug|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.ActiveCfg = Debug|x64 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.Build.0 = Debug|x64 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.ActiveCfg = Debug|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.Build.0 = Debug|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|Any CPU.ActiveCfg = Release|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|Any CPU.Build.0 = Release|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.ActiveCfg = Release|x64 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.Build.0 = Release|x64 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.ActiveCfg = Release|Win32 - {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.Build.0 = Release|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|Any CPU.Build.0 = Debug|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.ActiveCfg = Debug|x64 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.Build.0 = Debug|x64 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.ActiveCfg = Debug|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.Build.0 = Debug|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|Any CPU.ActiveCfg = Release|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|Any CPU.Build.0 = Release|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.ActiveCfg = Release|x64 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.Build.0 = Release|x64 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.ActiveCfg = Release|Win32 - {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.Build.0 = Release|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|Any CPU.Build.0 = Debug|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.ActiveCfg = Debug|x64 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.Build.0 = Debug|x64 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.ActiveCfg = Debug|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.Build.0 = Debug|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|Any CPU.ActiveCfg = Release|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|Any CPU.Build.0 = Release|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.ActiveCfg = Release|x64 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.Build.0 = Release|x64 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.ActiveCfg = Release|Win32 - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.Build.0 = Release|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|Any CPU.Build.0 = Debug|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.ActiveCfg = Debug|x64 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.Build.0 = Debug|x64 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.ActiveCfg = Debug|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.Build.0 = Debug|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|Any CPU.ActiveCfg = Release|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|Any CPU.Build.0 = Release|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.ActiveCfg = Release|x64 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.Build.0 = Release|x64 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.ActiveCfg = Release|Win32 - {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.Build.0 = Release|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|Any CPU.Build.0 = Debug|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x64.ActiveCfg = Debug|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x64.Build.0 = Debug|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x86.ActiveCfg = Debug|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Debug|x86.Build.0 = Debug|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|Any CPU.ActiveCfg = Release|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|Any CPU.Build.0 = Release|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x64.ActiveCfg = Release|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x64.Build.0 = Release|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x86.ActiveCfg = Release|Win32 - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11}.Release|x86.Build.0 = Release|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|Any CPU.Build.0 = Debug|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.ActiveCfg = Debug|x64 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.Build.0 = Debug|x64 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.ActiveCfg = Debug|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.Build.0 = Debug|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|Any CPU.ActiveCfg = Release|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|Any CPU.Build.0 = Release|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.ActiveCfg = Release|x64 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.Build.0 = Release|x64 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.ActiveCfg = Release|Win32 - {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.Build.0 = Release|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|Any CPU.Build.0 = Debug|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x64.ActiveCfg = Debug|x64 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x64.Build.0 = Debug|x64 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x86.ActiveCfg = Debug|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Debug|x86.Build.0 = Debug|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|Any CPU.ActiveCfg = Release|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|Any CPU.Build.0 = Release|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x64.ActiveCfg = Release|x64 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x64.Build.0 = Release|x64 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x86.ActiveCfg = Release|Win32 - {80209A7E-B9F0-4143-BCD1-B1891236A3CF}.Release|x86.Build.0 = Release|Win32 + {E32F7D15-2499-440C-8026-4D5EE1C5EC3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E32F7D15-2499-440C-8026-4D5EE1C5EC3A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E32F7D15-2499-440C-8026-4D5EE1C5EC3A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E32F7D15-2499-440C-8026-4D5EE1C5EC3A}.Release|Any CPU.Build.0 = Release|Any CPU + {A9E02E14-7321-4B12-8AB5-9A0408ED8FD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9E02E14-7321-4B12-8AB5-9A0408ED8FD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9E02E14-7321-4B12-8AB5-9A0408ED8FD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9E02E14-7321-4B12-8AB5-9A0408ED8FD0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {58E950CC-2FF6-423C-B006-A70A19272F20} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {AB1ED6AC-5C7F-49CD-A84B-4B7362D355BC} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {16BF6131-A3B8-4B97-B867-E45669FB48BD} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {ED4C887A-EC09-465B-B5D9-075450ADC52D} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {131001E3-0201-451F-A87B-951D1C5C3EEE} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {2337C4A4-3AB4-4014-9C29-9EBE32F4510E} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {5D50772E-DAC8-407D-972F-37DEB4450B72} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {079E1BC1-3B21-46E8-B1BA-AEDB68CCDC11} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {D32EE397-7E49-452D-AC95-AFCB3C962E3D} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - {80209A7E-B9F0-4143-BCD1-B1891236A3CF} = {FCCC9596-0809-4BB4-ACC2-3615EEC264C7} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {5DF99A8C-CA3C-451A-ABC1-4D862154708B} + SolutionGuid = {31412224-888D-40FC-AE73-2FF5468E59CD} + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = MFMetaDataProcessor.Core\MFMetaDataProcessor.Core.csproj EndGlobalSection EndGlobal diff --git a/source/version.json b/source/version.json index ca7341a5..80b78f94 100644 --- a/source/version.json +++ b/source/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "1.15", + "version": "2.0", "assemblyVersion": { "precision": "build" },

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 + +extern struct BlockStorageDevice Device_BlockStorage; +extern struct MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig; +extern IBlockStorageDevice STM32Flash_BlockStorageInterface; + +void BlockStorage_AddDevices() +{ + BlockStorageList_AddDevice( (BlockStorageDevice*)&Device_BlockStorage, &STM32Flash_BlockStorageInterface, &Device_BlockStorageConfig, false); +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_BlockStorage.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_BlockStorage.h new file mode 100644 index 00000000..aa50b1b7 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_BlockStorage.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#ifndef _TARGETPAL_BLOCKSTORAGE_H_ +#define _TARGETPAL_BLOCKSTORAGE_H_ 1 + +// this device has 1 block storage devices +#define TARGET_BLOCKSTORAGE_COUNT 1 + +#endif //_TARGETPAL_BLOCKSTORAGE_H_ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.c new file mode 100644 index 00000000..c70f5865 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.c @@ -0,0 +1,31 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include +#include "target_board.h" +#include "target_common.h" +#include + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { true }, // HAL_DRIVER_CONFIG_HEADER Header; + + 1, //ConvertCOM_DebugHandle(1), + 0, //ConvertCOM_DebugHandle(0), + 921600, + 0, // STDIO = COM2 or COM1 + + { RAM1_MEMORY_StartAddress, RAM1_MEMORY_Size }, + { FLASH1_MEMORY_StartAddress, FLASH1_MEMORY_Size } +}; + +HAL_TARGET_CONFIGURATION g_TargetConfiguration; + +// this target uses DFU for updates +uint32_t GetTargetCapabilities() +{ + return TargetCapabilities_DfuUpdate; +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.h.in b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.h.in new file mode 100644 index 00000000..419f9f35 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_common.h.in @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +////////////////////////////////////////////////////////////////////////////// +// This file was automatically generated by a tool. // +// Any changes you make here will be overwritten when it's generated again. // +////////////////////////////////////////////////////////////////////////////// + +#ifndef _TARGET_COMMON_H_ +#define _TARGET_COMMON_H_ + +#include + +///////////////////////////////////////////////////////////////////////////////////////// +// The following addresses and sizes should be filled in according to the SoC data-sheet +// they also must be coherent with what's in the linker file for nanoBooter and nanoCLR + +// RAM base address +#define RAM1_MEMORY_StartAddress ((uint32_t)0x20000000) +// RAM size +#define RAM1_MEMORY_Size ((uint32_t)0x00020000) + +// FLASH base address +#define FLASH1_MEMORY_StartAddress ((uint32_t)0x08000000) +// FLASH size +#define FLASH1_MEMORY_Size ((uint32_t)0x00080000) + +///////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////// +#define TARGETNAMESTRING "@CHIBIOS_BOARD@" +#define PLATFORMNAMESTRING "STM32F4" +/////////////////////////////////////////////// + +#endif /* _TARGET_COMMON_H_ */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_system_devices_dac_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_system_devices_dac_config.cpp new file mode 100644 index 00000000..88a70347 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_system_devices_dac_config.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include + +const NF_PAL_DAC_PORT_PIN_CHANNEL DacPortPinConfig[] = { + + // DAC1, channel 1, GPIO port A, pin 4 + {1, 1, GPIOA, 4}, + +}; + +const int DacChannelCount = ARRAYSIZE(DacPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_adc_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_adc_config.cpp new file mode 100644 index 00000000..9fd10764 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_adc_config.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_adc_native_target.h" + + +const NF_PAL_ADC_PORT_PIN_CHANNEL AdcPortPinConfig[] = { + + // ADC1 + {1, GPIOA, 0, ADC_CHANNEL_IN0}, + {1, GPIOA, 1, ADC_CHANNEL_IN1}, + {1, GPIOA, 4, ADC_CHANNEL_IN4}, + + // these are the internal sources, available only at ADC1 + {1, NULL, 0, ADC_CHANNEL_SENSOR}, + {1, NULL, 0, ADC_CHANNEL_VREFINT}, + {1, NULL, 0, ADC_CHANNEL_VBAT}, +}; + +const int AdcChannelCount = ARRAYSIZE(AdcPortPinConfig); diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_i2c_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_i2c_config.cpp new file mode 100644 index 00000000..2a60a22f --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_i2c_config.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_i2c_native_target.h" + +////////// +// I2C1 // +////////// + +// pin configuration for I2C1 +// port for SCL pin is: GPIOB +// port for SDA pin is: GPIOB +// SCL pin: is GPIOB_8 +// SDA pin: is GPIOB_9 +// GPIO alternate pin function is 4 (see alternate function mapping table in device datasheet) +I2C_CONFIG_PINS(1, GPIOB, GPIOB, 8, 9, 4) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.cpp new file mode 100644 index 00000000..ef8c9b10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "target_windows_devices_serialcommunication_config.h" +#include "win_dev_serial_native_target.h" + +/////////// +// UART1 // +/////////// + +// pin configuration for UART1 +// port: GPIOA +// TX pin: is GPIOA_9 +// RX pin: is GPIOA_10 +// GPIO alternate pin function is 7 (see "Table 9. Alternate function mapping" in STM32F411xC and STM32F411xE datasheet) +UART_CONFIG_PINS(1, GPIOA, GPIOA, 9, 10, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_TxBuffer[UART1_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart1_RxBuffer[UART1_RX_SIZE]; + +// initialization for UART1 +UART_INIT(1, UART1_TX_SIZE, UART1_RX_SIZE) + +// un-initialization for UART1 +UART_UNINIT(1) + + +/////////// +// UART2 // +/////////// + +// pin configuration for UART2 +// port: GPIOA +// TX pin: is GPIOA_2 +// RX pin: is GPIOA_3 +// GPIO alternate pin function is 7 (see "Table 9. Alternate function mapping" in STM32F411xC and STM32F411xE datasheet) +UART_CONFIG_PINS(2, GPIOA, GPIOA, 2, 3, 7) + +// buffers +// buffers that are R/W by DMA are recommended to be aligned with 32 bytes cache page size boundary +// because of issues with cache coherency and DMA (this is particularly important with Cortex-M7 because of cache) +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_TxBuffer[UART2_TX_SIZE]; +#if defined(__GNUC__) +__attribute__((aligned (32))) +#endif +uint8_t Uart2_RxBuffer[UART2_RX_SIZE]; + +// initialization for UART2 +UART_INIT(2, UART2_TX_SIZE, UART2_RX_SIZE) + +// un-initialization for UART2 +UART_UNINIT(2) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.h new file mode 100644 index 00000000..dc1de238 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_serialcommunication_config.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + + +/////////// +// UART1 // +/////////// + +// enable USART1 +#define NF_SERIAL_COMM_STM32_UART_USE_USART1 TRUE + +// buffers size +// tx buffer size: 256 bytes +#define UART1_TX_SIZE 256 +// rx buffer size: 256 bytes +#define UART1_RX_SIZE 256 + + +/////////// +// UART2 // +/////////// + +// enable USART2 +#define NF_SERIAL_COMM_STM32_UART_USE_USART2 TRUE + +// buffers size +// tx buffer size: 1024 bytes +#define UART2_TX_SIZE 1024 +// rx buffer size: 1024 bytes +#define UART2_RX_SIZE 1024 diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_spi_config.cpp b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_spi_config.cpp new file mode 100644 index 00000000..ef2d3a10 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/I2M_OXYGEN_NF/target_windows_devices_spi_config.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include "win_dev_spi_native.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS BLANK ON PURPOSE BECAUSE THIS TARGET DOESN'T REQUIRE THIS SPECIFIC CONFIGURATION // +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/CMakeLists.txt new file mode 100644 index 00000000..e49d468a --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/CMakeLists.txt @@ -0,0 +1,213 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +# add header files with common OS definitions and board definitions specific for each image +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/target_board.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/nanoCLR/target_board.h" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/target_common.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/target_common.h" @ONLY) + +set(NANOBOOTER_PROJECT_NAME "nanoBooter") +set(NANOCLR_PROJECT_NAME "nanoCLR") + +find_package(BuildUtils REQUIRED) +find_package(CHIBIOS REQUIRED) +find_package(ChibiOSnfOverlay REQUIRED) +find_package(WireProtocol REQUIRED) + +# packages for nanoFramework libraries +####################################### +# mandatory +find_package(NF_CoreCLR REQUIRED) + +####################################### +# optional + +# ChibiOS contrib repo +if(CHIBIOS_CONTRIB_REQUIRED) + find_package(ChibiOS-Contrib REQUIRED) +endif() + +# nF feature: debugger +if(NF_FEATURE_DEBUGGER) + find_package(NF_Debugger REQUIRED) + find_package(NF_Diagnostics REQUIRED) +endif() + +# nF feature: networking +if(USE_NETWORKING_OPTION) + find_package(CHIBIOS_LWIP REQUIRED) + find_package(NF_NETWORKING REQUIRED) +endif() + +# nF feature: filesystem +if(USE_FILESYSTEM_OPTION) + find_package(CHIBIOS_FATFS REQUIRED) +endif() + +####################################### + +add_subdirectory("common") +add_subdirectory("nanoBooter") +add_subdirectory("nanoCLR") + +####################### +# nanoBooter executable + +add_executable( + # executables for project, project sources + ${NANOBOOTER_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + "${CMAKE_CURRENT_SOURCE_DIR}/target_BlockStorage.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOBOOTER_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOBOOTER_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOBOOTER_SOURCES} + + ${CHIBIOS_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} +) + +####################### +# nanoCLR executable + +add_executable( + # executables for project, project sources + ${NANOCLR_PROJECT_NAME}.elf + + "${CMAKE_CURRENT_SOURCE_DIR}/target_common.c" + + # need to add configuration manager to allow get/store configuration blocks + "${PROJECT_SOURCE_DIR}/src/HAL/nanoHAL_ConfigurationManager_stubs.c" + + ${COMMON_PROJECT_SOURCES} + ${NANOCLR_PROJECT_SOURCES} + + ${TARGET_CMSIS_COMMON_SOURCES} + ${TARGET_CMSIS_NANOCLR_SOURCES} + + ${TARGET_CHIBIOS_COMMON_SOURCES} + ${TARGET_CHIBIOS_NANOCLR_SOURCES} + + ${CHIBIOS_SOURCES} + ${CHIBIOS_CONTRIB_SOURCES} + ${ChibiOSnfOverlay_SOURCES} + + ${WireProtocol_SOURCES} + + # sources for nanoFramework libraries + ${NF_CoreCLR_SOURCES} + ${NF_Debugger_SOURCES} + ${NF_Diagnostics_SOURCES} + + # sources for nanoFramework Network LWIP and Sockets + "${CHIBIOS_LWIP_SOURCES}" + ${NF_Networking_SOURCES} + + # sources for nanoFramework APIs + ${TARGET_NANO_APIS_SOURCES} +) + +# add dependency from ChibiOS (this is required to make sure the ChibiOS repo is downloaded before the build starts) +add_dependencies(${NANOBOOTER_PROJECT_NAME}.elf ChibiOS) +add_dependencies(${NANOCLR_PROJECT_NAME}.elf ChibiOS) + +# include common directories +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common + ${PROJECT_SOURCE_DIR}/src/CLR/Core + ${PROJECT_SOURCE_DIR}/src/CLR/Include + ${PROJECT_SOURCE_DIR}/src/HAL/Include + ${PROJECT_SOURCE_DIR}/src/PAL/Include + + ${WireProtocol_INCLUDE_DIRS} + ${CHIBIOS_INCLUDE_DIRS} + ${ChibiOSnfOverlay_INCLUDE_DIRS} + ${CHIBIOS_CONTRIB_INCLUDE_DIRS} + + ${TARGET_CMSIS_COMMON_INCLUDE_DIRS} + ${TARGET_CHIBIOS_COMMON_INCLUDE_DIRS} +) + +# include directories for nanoBooter +target_include_directories(${NANOBOOTER_PROJECT_NAME}.elf PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}/nanoBooter" + ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter + + ${TARGET_CMSIS_NANOBOOTER_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOBOOTER_INCLUDE_DIRS} +) + +# include directories for nanoCLR +target_include_directories(${NANOCLR_PROJECT_NAME}.elf PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/nanoCLR + ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR + + ${TARGET_CMSIS_NANOCLR_INCLUDE_DIRS} + ${TARGET_CHIBIOS_NANOCLR_INCLUDE_DIRS} + + # directories for nanoFramework libraries + ${NF_CoreCLR_INCLUDE_DIRS} + ${NF_Debugger_INCLUDE_DIRS} + ${NF_Diagnostics_INCLUDE_DIRS} + + # includes for nanoFramework APIs + ${TARGET_NANO_APIS_INCLUDES} + + # includes for ChibiOS LwIP + ${CHIBIOS_LWIP_INCLUDE_DIRS} + + # incudes for Networking + ${NF_Networking_INCLUDE_DIRS} +) + +# set compiler options +nf_set_compiler_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_options(${NANOCLR_PROJECT_NAME}.elf) + +# set compiler definitions +nf_set_compiler_definitions(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_compiler_definitions(${NANOCLR_PROJECT_NAME}.elf) + +# set linker files +if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F412xG_booter-DEBUG.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F412xG_CLR-DEBUG.ld) +else() + nf_set_linker_file(${NANOBOOTER_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoBooter/STM32F412xG_booter.ld) + nf_set_linker_file(${NANOCLR_PROJECT_NAME}.elf ${CMAKE_CURRENT_SOURCE_DIR}/nanoCLR/STM32F412xG_CLR.ld) +endif() + +# set linker options +nf_set_linker_options(${NANOBOOTER_PROJECT_NAME}.elf) +nf_set_linker_options(${NANOCLR_PROJECT_NAME}.elf) + +# add other linker flags +########################################################### +# the sizes of CRT heap and ChibiOS stacks are defined here +set_property(TARGET ${NANOBOOTER_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400,--defsym=__crt_heap_size__=0x1000") +set_property(TARGET ${NANOCLR_PROJECT_NAME}.elf APPEND_STRING PROPERTY LINK_FLAGS ",--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x800,--defsym=__crt_heap_size__=0x2800") + +# generate output files +nf_generate_build_output_files(${NANOBOOTER_PROJECT_NAME}.elf) +nf_generate_build_output_files(${NANOCLR_PROJECT_NAME}.elf) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/README.md new file mode 100644 index 00000000..e1c771eb --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/README.md @@ -0,0 +1,25 @@ +## ST of the shelve board ## + +The board used in this community contribution is the NUCLEO144_F412ZG board from ST. The board can be purchased from various sources and should be about 20 euros. Further information on the Nucleo144 boards can be found in the user manuals UM1727 or UM1974 on the ST side (www.st.com). + +Some basic information abstracted from ST: + +• STM32F412ZGT6 100MHz Cortex-M4F core microcontroller with 1MB Flash memory, 256KB SRAM +• Adaptive real-time accelerator (ART Accelerator™) allowing 0-wait state execution from Flash memory +• Full access to all GPIO with ST Zio connector (Arduino Uno v3 connectivity support) +• ST morpho extension pin headers for access to all GPIO +• ST-LINK/V2-1 debugger/programmer with SWD connector +• Up to 17 serial communication interfaces: USART, IrDA, I²C, SPI, LIN, CAN, USB, I²S, SDIO +• Flexible board power supply +• USB OTG or FS Device with micro-AB connector +• True random number generator +• CRC calculation unit +• RTC with subsecond accuracy and hardware calendar +• 96-bit unique ID +• 3 x LEDs: Power LED, USB communication, User LED +• User and Reset pushbuttons +• 32.768 KHz crystal oscillator + +Since the board has two MicroUSB connectors so you can use one for flashing the nanoFramework firmware and use for debugging purposes on the ST Link side and the other for a connection that can be used against VS to be recognized as a nanoFramework device to run your C# managed application. + + diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.c new file mode 100644 index 00000000..aece76d4 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.c @@ -0,0 +1,266 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include "hal.h" +#include "stm32_gpio.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB1(STM32_GPIO_EN_MASK); + rccEnableAHB1(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.h new file mode 100644 index 00000000..d8297458 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/board.h @@ -0,0 +1,1846 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#ifndef BOARD_H +#define BOARD_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* + * Setup for STMicroelectronics STM32 Nucleo144-F412ZG board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_NUCLEO144_F412ZG_NF +#define BOARD_NAME "STMicroelectronics STM32 Nucleo144-F412ZG" + +/* + * Board oscillators-related settings. + * NOTE: LSE is fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 32768U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +#define STM32_HSE_BYPASS + +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 300U + +/* + * MCU type as defined in the ST header. + */ +#define STM32F412Zx + +/* + * IO pins assignments. + */ +#define GPIOA_ZIO_D32 0U +#define GPIOA_TIM2_CH1 0U +#define GPIOA_PIN1 1U +#define GPIOA_ZIO_A8 2U +#define GPIOA_ADC1_IN2 2U +#define GPIOA_ARD_A0 3U +#define GPIOA_ADC1_IN3 3U +#define GPIOA_ZIO_D24 4U +#define GPIOA_SPI3_NSS 4U +#define GPIOA_ARD_D13 5U +#define GPIOA_SPI1_SCK 5U +#define GPIOA_ARD_D12 6U +#define GPIOA_SPI1_MISO 6U +#define GPIOA_ARD_D11 7U +#define GPIOA_SPI1_MOSI 7U +#define GPIOA_ZIO_D71 7U +#define GPIOA_USB_SOF 8U +#define GPIOA_USB_VBUS 9U +#define GPIOA_USB_ID 10U +#define GPIOA_USB_DM 11U +#define GPIOA_USB_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_ZIO_D20 15U +#define GPIOA_I2S3_WS 15U + +#define GPIOB_ZIO_D33 0U +#define GPIOB_TIM3_CH3 0U +#define GPIOB_LED1 0U +#define GPIOB_ZIO_A6 1U +#define GPIOB_ADC1_IN9 1U +#define GPIOB_ZIO_D27 2U +#define GPIOB_QUADSPI_CLK 2U +#define GPIOB_ZIO_D23 3U +#define GPIOB_I2S3_CK 3U +#define GPIOB_ZIO_D25 4U +#define GPIOB_SPI3_MISO 4U +#define GPIOB_ZIO_D22 5U +#define GPIOB_I2S3_SD 5U +#define GPIOB_ZIO_D26 6U +#define GPIOB_QUADSPI_BK1_NCS 6U +#define GPIOB_LED2 7U +#define GPIOB_ARD_D15 8U +#define GPIOB_I2C1_SCL 8U +#define GPIOB_ARD_D14 9U +#define GPIOB_I2C1_SDA 9U +#define GPIOB_ZIO_D36 10U +#define GPIOB_TIM2_CH3 10U +#define GPIOB_ZIO_D35 11U +#define GPIOB_TIM2_CH4 11U +#define GPIOB_ZIO_D19 12U +#define GPIOB_I2S2_WS 12U +#define GPIOB_ZIO_D18 13U +#define GPIOB_I2S2_CK 13U +#define GPIOB_LED3 14U +#define GPIOB_ZIO_D17 15U +#define GPIOB_I2S2_SD 15U + +#define GPIOC_ARD_A1 0U +#define GPIOC_ADC1_IN10 0U +#define GPIOC_ARD_A3 1U +#define GPIOC_ADC1_IN11 1U +#define GPIOC_ZIO_A7 2U +#define GPIOC_ADC1_IN12 2U +#define GPIOC_ARD_A2 3U +#define GPIOC_ADC1_IN13 3U +#define GPIOC_ARD_A4 4U +#define GPIOC_ADC1_IN14 4U +#define GPIOC_ARD_A5 5U +#define GPIOC_ADC1_IN15 5U +#define GPIOC_ZIO_D16 6U +#define GPIOC_I2S2_MCK 6U +#define GPIOC_ZIO_D21 7U +#define GPIOC_I2S3_MCK 7U +#define GPIOC_ZIO_D43 8U +#define GPIOC_SDMMC_D0 8U +#define GPIOC_ZIO_D44 9U +#define GPIOC_SDMMC_D1 9U +#define GPIOC_ZIO_D45 10U +#define GPIOC_SDMMC_D2 10U +#define GPIOC_ZIO_D46 11U +#define GPIOC_SDMMC_D3 11U +#define GPIOC_ZIO_D47 12U +#define GPIOC_SDMMC_CK 12U +#define GPIOC_BUTTON 13U +#define GPIOC_OSC32_IN 14U +#define GPIOC_OSC32_OUT 15U + +#define GPIOD_ZIO_D67 0U +#define GPIOD_CAN1_RX 0U +#define GPIOD_ZIO_D66 1U +#define GPIOD_CAN1_TX 1U +#define GPIOD_ZIO_D48 2U +#define GPIOD_SDMMC_CMD 2U +#define GPIOD_ZIO_D55 3U +#define GPIOD_USART2_CTS 3U +#define GPIOD_ZIO_D54 4U +#define GPIOD_USART2_RTS 4U +#define GPIOD_ZIO_D53 5U +#define GPIOD_USART2_TX 5U +#define GPIOD_ZIO_D52 6U +#define GPIOD_USART2_RX 6U +#define GPIOD_ZIO_D51 7U +#define GPIOD_USART2_SCLK 7U +#define GPIOD_USART3_RX 8U +#define GPIOD_STLK_RX 8U +#define GPIOD_USART3_TX 9U +#define GPIOD_STLK_TX 9U +#define GPIOD_PIN10 10U +#define GPIOD_ZIO_D30 11U +#define GPIOD_QUADSPI_BK1_IO0 11U +#define GPIOD_ZIO_D29 12U +#define GPIOD_QUADSPI_BK1_IO1 12U +#define GPIOD_ZIO_D28 13U +#define GPIOD_QUADSPI_BK1_IO3 13U +#define GPIOD_ARD_D10 14U +#define GPIOD_SPI1_NSS 14U +#define GPIOD_ARD_D9 15U +#define GPIOD_TIM4_CH4 15U + +#define GPIOE_ZIO_D34 0U +#define GPIOE_TIM4_ETR 0U +#define GPIOE_PIN1 1U +#define GPIOE_ZIO_D31 2U +#define GPIOE_ZIO_D56 2U +#define GPIOE_QUADSPI_BK1_IO2 2U +#define GPIOE_ZIO_D60 3U +#define GPIOE_SAI1_SD_B 3U +#define GPIOE_ZIO_D57 4U +#define GPIOE_SAI1_FS_A 4U +#define GPIOE_ZIO_D58 5U +#define GPIOE_SAI1_SCK_A 5U +#define GPIOE_ZIO_D59 6U +#define GPIOE_SAI1_SD_A 6U +#define GPIOE_ZIO_D41 7U +#define GPIOE_TIM1_ETR 7U +#define GPIOE_ZIO_D42 8U +#define GPIOE_TIM1_CH1N 8U +#define GPIOE_ARD_D6 9U +#define GPIOE_TIM1_CH1 9U +#define GPIOE_ZIO_D40 10U +#define GPIOE_TIM1_CH2N 10U +#define GPIOE_ARD_D5 11U +#define GPIOE_TIM1_CH2 11U +#define GPIOE_ZIO_D39 12U +#define GPIOE_TIM1_CH3N 12U +#define GPIOE_ARD_D3 13U +#define GPIOE_TIM1_CH3 13U +#define GPIOE_ZIO_D38 14U +#define GPIOE_ZIO_D37 15U +#define GPIOE_TIM1_BKIN1 15U + +#define GPIOF_ZIO_D68 0U +#define GPIOF_I2C2_SDA 0U +#define GPIOF_ZIO_D69 1U +#define GPIOF_I2C2_SCL 1U +#define GPIOF_ZIO_D70 2U +#define GPIOF_I2C2_SMBA 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_ZIO_D62 7U +#define GPIOF_SAI1_MCLK_B 7U +#define GPIOF_ZIO_D61 8U +#define GPIOF_SAI1_SCK_B 8U +#define GPIOF_ZIO_D63 9U +#define GPIOF_SAI1_FS_B 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_ARD_D8 12U +#define GPIOF_ARD_D7 13U +#define GPIOF_ARD_D4 14U +#define GPIOF_ARD_D2 15U + +#define GPIOG_ZIO_D65 0U +#define GPIOG_ZIO_D64 1U +#define GPIOG_ZIO_D49 2U +#define GPIOG_ZIO_D50 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_USB_GPIO_OUT 6U +#define GPIOG_USB_GPIO_IN 7U +#define GPIOG_PIN8 8U +#define GPIOG_ARD_D0 9U +#define GPIOG_USART6_RX 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_ARD_D1 14U +#define GPIOG_USART6_TX 14U +#define GPIOG_PIN15 15U + +#define GPIOH_OSC_IN 0U +#define GPIOH_OSC_OUT 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +#define GPIOI_PIN0 0U +#define GPIOI_PIN1 1U +#define GPIOI_PIN2 2U +#define GPIOI_PIN3 3U +#define GPIOI_PIN4 4U +#define GPIOI_PIN5 5U +#define GPIOI_PIN6 6U +#define GPIOI_PIN7 7U +#define GPIOI_PIN8 8U +#define GPIOI_PIN9 9U +#define GPIOI_PIN10 10U +#define GPIOI_PIN11 11U +#define GPIOI_PIN12 12U +#define GPIOI_PIN13 13U +#define GPIOI_PIN14 14U +#define GPIOI_PIN15 15U + +#define GPIOJ_PIN0 0U +#define GPIOJ_PIN1 1U +#define GPIOJ_PIN2 2U +#define GPIOJ_PIN3 3U +#define GPIOJ_PIN4 4U +#define GPIOJ_PIN5 5U +#define GPIOJ_PIN6 6U +#define GPIOJ_PIN7 7U +#define GPIOJ_PIN8 8U +#define GPIOJ_PIN9 9U +#define GPIOJ_PIN10 10U +#define GPIOJ_PIN11 11U +#define GPIOJ_PIN12 12U +#define GPIOJ_PIN13 13U +#define GPIOJ_PIN14 14U +#define GPIOJ_PIN15 15U + +#define GPIOK_PIN0 0U +#define GPIOK_PIN1 1U +#define GPIOK_PIN2 2U +#define GPIOK_PIN3 3U +#define GPIOK_PIN4 4U +#define GPIOK_PIN5 5U +#define GPIOK_PIN6 6U +#define GPIOK_PIN7 7U +#define GPIOK_PIN8 8U +#define GPIOK_PIN9 9U +#define GPIOK_PIN10 10U +#define GPIOK_PIN11 11U +#define GPIOK_PIN12 12U +#define GPIOK_PIN13 13U +#define GPIOK_PIN14 14U +#define GPIOK_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_ZIO_D32 PAL_LINE(GPIOA, 0U) +#define LINE_TIM2_CH1 PAL_LINE(GPIOA, 0U) +#define LINE_ZIO_A8 PAL_LINE(GPIOA, 2U) +#define LINE_ADC1_IN2 PAL_LINE(GPIOA, 2U) +#define LINE_ARD_A0 PAL_LINE(GPIOA, 3U) +#define LINE_ADC1_IN3 PAL_LINE(GPIOA, 3U) +#define LINE_ZIO_D24 PAL_LINE(GPIOA, 4U) +#define LINE_SPI3_NSS PAL_LINE(GPIOA, 4U) +#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U) +#define LINE_SPI1_SCK PAL_LINE(GPIOA, 5U) +#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U) +#define LINE_SPI1_MISO PAL_LINE(GPIOA, 6U) +#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U) +#define LINE_SPI1_MOSI PAL_LINE(GPIOA, 7U) +#define LINE_ZIO_D71 PAL_LINE(GPIOA, 7U) +#define LINE_USB_SOF PAL_LINE(GPIOA, 8U) +#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U) +#define LINE_USB_ID PAL_LINE(GPIOA, 10U) +#define LINE_USB_DM PAL_LINE(GPIOA, 11U) +#define LINE_USB_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) +#define LINE_ZIO_D20 PAL_LINE(GPIOA, 15U) +#define LINE_I2S3_WS PAL_LINE(GPIOA, 15U) +#define LINE_ZIO_D33 PAL_LINE(GPIOB, 0U) +#define LINE_TIM3_CH3 PAL_LINE(GPIOB, 0U) +#define LINE_LED1 PAL_LINE(GPIOB, 0U) +#define LINE_ZIO_A6 PAL_LINE(GPIOB, 1U) +#define LINE_ADC1_IN9 PAL_LINE(GPIOB, 1U) +#define LINE_ZIO_D27 PAL_LINE(GPIOB, 2U) +#define LINE_QUADSPI_CLK PAL_LINE(GPIOB, 2U) +#define LINE_ZIO_D23 PAL_LINE(GPIOB, 3U) +#define LINE_I2S3_CK PAL_LINE(GPIOB, 3U) +#define LINE_ZIO_D25 PAL_LINE(GPIOB, 4U) +#define LINE_SPI3_MISO PAL_LINE(GPIOB, 4U) +#define LINE_ZIO_D22 PAL_LINE(GPIOB, 5U) +#define LINE_I2S3_SD PAL_LINE(GPIOB, 5U) +#define LINE_ZIO_D26 PAL_LINE(GPIOB, 6U) +#define LINE_QUADSPI_BK1_NCS PAL_LINE(GPIOB, 6U) +#define LINE_LED2 PAL_LINE(GPIOB, 7U) +#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U) +#define LINE_I2C1_SCL PAL_LINE(GPIOB, 8U) +#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U) +#define LINE_I2C1_SDA PAL_LINE(GPIOB, 9U) +#define LINE_ZIO_D36 PAL_LINE(GPIOB, 10U) +#define LINE_TIM2_CH3 PAL_LINE(GPIOB, 10U) +#define LINE_ZIO_D35 PAL_LINE(GPIOB, 11U) +#define LINE_TIM2_CH4 PAL_LINE(GPIOB, 11U) +#define LINE_ZIO_D19 PAL_LINE(GPIOB, 12U) +#define LINE_I2S2_WS PAL_LINE(GPIOB, 12U) +#define LINE_ZIO_D18 PAL_LINE(GPIOB, 13U) +#define LINE_I2S2_CK PAL_LINE(GPIOB, 13U) +#define LINE_LED3 PAL_LINE(GPIOB, 14U) +#define LINE_ZIO_D17 PAL_LINE(GPIOB, 15U) +#define LINE_I2S2_SD PAL_LINE(GPIOB, 15U) +#define LINE_ARD_A1 PAL_LINE(GPIOC, 0U) +#define LINE_ADC1_IN10 PAL_LINE(GPIOC, 0U) +#define LINE_ARD_A3 PAL_LINE(GPIOC, 1U) +#define LINE_ADC1_IN11 PAL_LINE(GPIOC, 1U) +#define LINE_ZIO_A7 PAL_LINE(GPIOC, 2U) +#define LINE_ADC1_IN12 PAL_LINE(GPIOC, 2U) +#define LINE_ARD_A2 PAL_LINE(GPIOC, 3U) +#define LINE_ADC1_IN13 PAL_LINE(GPIOC, 3U) +#define LINE_ARD_A4 PAL_LINE(GPIOC, 4U) +#define LINE_ADC1_IN14 PAL_LINE(GPIOC, 4U) +#define LINE_ARD_A5 PAL_LINE(GPIOC, 5U) +#define LINE_ADC1_IN15 PAL_LINE(GPIOC, 5U) +#define LINE_ZIO_D16 PAL_LINE(GPIOC, 6U) +#define LINE_I2S2_MCK PAL_LINE(GPIOC, 6U) +#define LINE_ZIO_D21 PAL_LINE(GPIOC, 7U) +#define LINE_I2S3_MCK PAL_LINE(GPIOC, 7U) +#define LINE_ZIO_D43 PAL_LINE(GPIOC, 8U) +#define LINE_SDMMC_D0 PAL_LINE(GPIOC, 8U) +#define LINE_ZIO_D44 PAL_LINE(GPIOC, 9U) +#define LINE_SDMMC_D1 PAL_LINE(GPIOC, 9U) +#define LINE_ZIO_D45 PAL_LINE(GPIOC, 10U) +#define LINE_SDMMC_D2 PAL_LINE(GPIOC, 10U) +#define LINE_ZIO_D46 PAL_LINE(GPIOC, 11U) +#define LINE_SDMMC_D3 PAL_LINE(GPIOC, 11U) +#define LINE_ZIO_D47 PAL_LINE(GPIOC, 12U) +#define LINE_SDMMC_CK PAL_LINE(GPIOC, 12U) +#define LINE_BUTTON PAL_LINE(GPIOC, 13U) +#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) +#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) +#define LINE_ZIO_D67 PAL_LINE(GPIOD, 0U) +#define LINE_CAN1_RX PAL_LINE(GPIOD, 0U) +#define LINE_ZIO_D66 PAL_LINE(GPIOD, 1U) +#define LINE_CAN1_TX PAL_LINE(GPIOD, 1U) +#define LINE_ZIO_D48 PAL_LINE(GPIOD, 2U) +#define LINE_SDMMC_CMD PAL_LINE(GPIOD, 2U) +#define LINE_ZIO_D55 PAL_LINE(GPIOD, 3U) +#define LINE_USART2_CTS PAL_LINE(GPIOD, 3U) +#define LINE_ZIO_D54 PAL_LINE(GPIOD, 4U) +#define LINE_USART2_RTS PAL_LINE(GPIOD, 4U) +#define LINE_ZIO_D53 PAL_LINE(GPIOD, 5U) +#define LINE_USART2_TX PAL_LINE(GPIOD, 5U) +#define LINE_ZIO_D52 PAL_LINE(GPIOD, 6U) +#define LINE_USART2_RX PAL_LINE(GPIOD, 6U) +#define LINE_ZIO_D51 PAL_LINE(GPIOD, 7U) +#define LINE_USART2_SCLK PAL_LINE(GPIOD, 7U) +#define LINE_USART3_RX PAL_LINE(GPIOD, 8U) +#define LINE_STLK_RX PAL_LINE(GPIOD, 8U) +#define LINE_USART3_TX PAL_LINE(GPIOD, 9U) +#define LINE_STLK_TX PAL_LINE(GPIOD, 9U) +#define LINE_ZIO_D30 PAL_LINE(GPIOD, 11U) +#define LINE_QUADSPI_BK1_IO0 PAL_LINE(GPIOD, 11U) +#define LINE_ZIO_D29 PAL_LINE(GPIOD, 12U) +#define LINE_QUADSPI_BK1_IO1 PAL_LINE(GPIOD, 12U) +#define LINE_ZIO_D28 PAL_LINE(GPIOD, 13U) +#define LINE_QUADSPI_BK1_IO3 PAL_LINE(GPIOD, 13U) +#define LINE_ARD_D10 PAL_LINE(GPIOD, 14U) +#define LINE_SPI1_NSS PAL_LINE(GPIOD, 14U) +#define LINE_ARD_D9 PAL_LINE(GPIOD, 15U) +#define LINE_TIM4_CH4 PAL_LINE(GPIOD, 15U) +#define LINE_ZIO_D34 PAL_LINE(GPIOE, 0U) +#define LINE_TIM4_ETR PAL_LINE(GPIOE, 0U) +#define LINE_ZIO_D31 PAL_LINE(GPIOE, 2U) +#define LINE_ZIO_D56 PAL_LINE(GPIOE, 2U) +#define LINE_QUADSPI_BK1_IO2 PAL_LINE(GPIOE, 2U) +#define LINE_ZIO_D60 PAL_LINE(GPIOE, 3U) +#define LINE_SAI1_SD_B PAL_LINE(GPIOE, 3U) +#define LINE_ZIO_D57 PAL_LINE(GPIOE, 4U) +#define LINE_SAI1_FS_A PAL_LINE(GPIOE, 4U) +#define LINE_ZIO_D58 PAL_LINE(GPIOE, 5U) +#define LINE_SAI1_SCK_A PAL_LINE(GPIOE, 5U) +#define LINE_ZIO_D59 PAL_LINE(GPIOE, 6U) +#define LINE_SAI1_SD_A PAL_LINE(GPIOE, 6U) +#define LINE_ZIO_D41 PAL_LINE(GPIOE, 7U) +#define LINE_TIM1_ETR PAL_LINE(GPIOE, 7U) +#define LINE_ZIO_D42 PAL_LINE(GPIOE, 8U) +#define LINE_TIM1_CH1N PAL_LINE(GPIOE, 8U) +#define LINE_ARD_D6 PAL_LINE(GPIOE, 9U) +#define LINE_TIM1_CH1 PAL_LINE(GPIOE, 9U) +#define LINE_ZIO_D40 PAL_LINE(GPIOE, 10U) +#define LINE_TIM1_CH2N PAL_LINE(GPIOE, 10U) +#define LINE_ARD_D5 PAL_LINE(GPIOE, 11U) +#define LINE_TIM1_CH2 PAL_LINE(GPIOE, 11U) +#define LINE_ZIO_D39 PAL_LINE(GPIOE, 12U) +#define LINE_TIM1_CH3N PAL_LINE(GPIOE, 12U) +#define LINE_ARD_D3 PAL_LINE(GPIOE, 13U) +#define LINE_TIM1_CH3 PAL_LINE(GPIOE, 13U) +#define LINE_ZIO_D38 PAL_LINE(GPIOE, 14U) +#define LINE_ZIO_D37 PAL_LINE(GPIOE, 15U) +#define LINE_TIM1_BKIN1 PAL_LINE(GPIOE, 15U) +#define LINE_ZIO_D68 PAL_LINE(GPIOF, 0U) +#define LINE_I2C2_SDA PAL_LINE(GPIOF, 0U) +#define LINE_ZIO_D69 PAL_LINE(GPIOF, 1U) +#define LINE_I2C2_SCL PAL_LINE(GPIOF, 1U) +#define LINE_ZIO_D70 PAL_LINE(GPIOF, 2U) +#define LINE_I2C2_SMBA PAL_LINE(GPIOF, 2U) +#define LINE_ZIO_D62 PAL_LINE(GPIOF, 7U) +#define LINE_SAI1_MCLK_B PAL_LINE(GPIOF, 7U) +#define LINE_ZIO_D61 PAL_LINE(GPIOF, 8U) +#define LINE_SAI1_SCK_B PAL_LINE(GPIOF, 8U) +#define LINE_ZIO_D63 PAL_LINE(GPIOF, 9U) +#define LINE_SAI1_FS_B PAL_LINE(GPIOF, 9U) +#define LINE_ARD_D8 PAL_LINE(GPIOF, 12U) +#define LINE_ARD_D7 PAL_LINE(GPIOF, 13U) +#define LINE_ARD_D4 PAL_LINE(GPIOF, 14U) +#define LINE_ARD_D2 PAL_LINE(GPIOF, 15U) +#define LINE_ZIO_D65 PAL_LINE(GPIOG, 0U) +#define LINE_ZIO_D64 PAL_LINE(GPIOG, 1U) +#define LINE_ZIO_D49 PAL_LINE(GPIOG, 2U) +#define LINE_ZIO_D50 PAL_LINE(GPIOG, 3U) +#define LINE_USB_GPIO_OUT PAL_LINE(GPIOG, 6U) +#define LINE_USB_GPIO_IN PAL_LINE(GPIOG, 7U) +#define LINE_ARD_D0 PAL_LINE(GPIOG, 9U) +#define LINE_USART6_RX PAL_LINE(GPIOG, 9U) +#define LINE_ARD_D1 PAL_LINE(GPIOG, 14U) +#define LINE_USART6_TX PAL_LINE(GPIOG, 14U) +#define LINE_OSC_IN PAL_LINE(GPIOH, 0U) +#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - ZIO_D32 TIM2_CH1 (input pullup). + * PA1 - PIN1 (input pullup). + * PA2 - ZIO_A8 ADC1_IN2 (input pullup). + * PA3 - ARD_A0 ADC1_IN3 (input pullup). + * PA4 - ZIO_D24 SPI3_NSS (input pullup). + * PA5 - ARD_D13 SPI1_SCK (input pullup). + * PA6 - ARD_D12 SPI1_MISO (input pullup). + * PA7 - ARD_D11 SPI1_MOSI ZIO_D71 (input pullup). + * PA8 - USB_SOF (alternate 10). + * PA9 - USB_VBUS (analog). + * PA10 - USB_ID (alternate 10). + * PA11 - USB_DM (alternate 10). + * PA12 - USB_DP (alternate 10). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - ZIO_D20 I2S3_WS (alternate 6). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ZIO_D32) | \ + PIN_MODE_INPUT(GPIOA_PIN1) | \ + PIN_MODE_INPUT(GPIOA_ZIO_A8) | \ + PIN_MODE_INPUT(GPIOA_ARD_A0) | \ + PIN_MODE_INPUT(GPIOA_ZIO_D24) | \ + PIN_MODE_INPUT(GPIOA_ARD_D13) | \ + PIN_MODE_INPUT(GPIOA_ARD_D12) | \ + PIN_MODE_INPUT(GPIOA_ARD_D11) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_SOF) | \ + PIN_MODE_ANALOG(GPIOA_USB_VBUS) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_ID) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_ALTERNATE(GPIOA_ZIO_D20)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D32) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ZIO_A8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D24) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D13) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_SOF) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_VBUS) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_ID) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_ZIO_D20)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ZIO_D32) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOA_ZIO_A8) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \ + PIN_OSPEED_HIGH(GPIOA_ZIO_D24) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D13) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \ + PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \ + PIN_OSPEED_HIGH(GPIOA_USB_SOF) | \ + PIN_OSPEED_HIGH(GPIOA_USB_VBUS) | \ + PIN_OSPEED_HIGH(GPIOA_USB_ID) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DM) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_HIGH(GPIOA_ZIO_D20)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ZIO_D32) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOA_ZIO_A8) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \ + PIN_PUPDR_PULLUP(GPIOA_ZIO_D24) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D13) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D12) | \ + PIN_PUPDR_PULLUP(GPIOA_ARD_D11) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_SOF) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_VBUS) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_ID) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ + PIN_PUPDR_FLOATING(GPIOA_SWDIO) | \ + PIN_PUPDR_FLOATING(GPIOA_SWCLK) | \ + PIN_PUPDR_FLOATING(GPIOA_ZIO_D20)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ZIO_D32) | \ + PIN_ODR_HIGH(GPIOA_PIN1) | \ + PIN_ODR_HIGH(GPIOA_ZIO_A8) | \ + PIN_ODR_HIGH(GPIOA_ARD_A0) | \ + PIN_ODR_HIGH(GPIOA_ZIO_D24) | \ + PIN_ODR_HIGH(GPIOA_ARD_D13) | \ + PIN_ODR_HIGH(GPIOA_ARD_D12) | \ + PIN_ODR_HIGH(GPIOA_ARD_D11) | \ + PIN_ODR_HIGH(GPIOA_USB_SOF) | \ + PIN_ODR_HIGH(GPIOA_USB_VBUS) | \ + PIN_ODR_HIGH(GPIOA_USB_ID) | \ + PIN_ODR_HIGH(GPIOA_USB_DM) | \ + PIN_ODR_HIGH(GPIOA_USB_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_ZIO_D20)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ZIO_D32, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOA_ZIO_A8, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \ + PIN_AFIO_AF(GPIOA_ZIO_D24, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D13, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \ + PIN_AFIO_AF(GPIOA_ARD_D11, 0U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_USB_SOF, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_VBUS, 0U) | \ + PIN_AFIO_AF(GPIOA_USB_ID, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_DM, 10U) | \ + PIN_AFIO_AF(GPIOA_USB_DP, 10U) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \ + PIN_AFIO_AF(GPIOA_ZIO_D20, 6U)) + +/* + * GPIOB setup: + * + * PB0 - ZIO_D33 TIM3_CH3 LED1 (output pushpull maximum). + * PB1 - ZIO_A6 ADC1_IN9 (input pullup). + * PB2 - ZIO_D27 QUADSPI_CLK (input pullup). + * PB3 - ZIO_D23 I2S3_CK (input pullup). + * PB4 - ZIO_D25 SPI3_MISO (input pullup). + * PB5 - ZIO_D22 I2S3_SD (input pullup). + * PB6 - ZIO_D26 QUADSPI_BK1_NCS (input pullup). + * PB7 - LED2 (output pushpull maximum). + * PB8 - ARD_D15 I2C1_SCL (input pullup). + * PB9 - ARD_D14 I2C1_SDA (input pullup). + * PB10 - ZIO_D36 TIM2_CH3 (input pullup). + * PB11 - ZIO_D35 TIM2_CH4 (input pullup). + * PB12 - ZIO_D19 I2S2_WS (input pullup). + * PB13 - ZIO_D18 I2S2_CK (input pullup). + * PB14 - LED3 (output pushpull maximum). + * PB15 - ZIO_D17 I2S2_SD (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_OUTPUT(GPIOB_ZIO_D33) | \ + PIN_MODE_INPUT(GPIOB_ZIO_A6) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D27) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D23) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D25) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D22) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D26) | \ + PIN_MODE_OUTPUT(GPIOB_LED2) | \ + PIN_MODE_ALTERNATE(GPIOB_ARD_D15) | \ + PIN_MODE_ALTERNATE(GPIOB_ARD_D14) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D36) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D35) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D19) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D18) | \ + PIN_MODE_OUTPUT(GPIOB_LED3) | \ + PIN_MODE_INPUT(GPIOB_ZIO_D17)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D33) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_A6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D27) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D23) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D25) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D22) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D26) | \ + PIN_OTYPE_PUSHPULL(GPIOB_LED2) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_ARD_D15) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_ARD_D14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D36) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D35) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D19) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D18) | \ + PIN_OTYPE_PUSHPULL(GPIOB_LED3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_ZIO_D17)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ZIO_D33) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_A6) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D27) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D23) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D25) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D22) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D26) | \ + PIN_OSPEED_HIGH(GPIOB_LED2) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D15) | \ + PIN_OSPEED_HIGH(GPIOB_ARD_D14) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D36) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D35) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D19) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D18) | \ + PIN_OSPEED_HIGH(GPIOB_LED3) | \ + PIN_OSPEED_HIGH(GPIOB_ZIO_D17)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_ZIO_D33) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_A6) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D27) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D23) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D25) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D22) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D26) | \ + PIN_PUPDR_FLOATING(GPIOB_LED2) | \ + PIN_PUPDR_FLOATING(GPIOB_ARD_D15) | \ + PIN_PUPDR_FLOATING(GPIOB_ARD_D14) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D36) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D35) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D19) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D18) | \ + PIN_PUPDR_FLOATING(GPIOB_LED3) | \ + PIN_PUPDR_PULLUP(GPIOB_ZIO_D17)) +#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_ZIO_D33) | \ + PIN_ODR_HIGH(GPIOB_ZIO_A6) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D27) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D23) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D25) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D22) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D26) | \ + PIN_ODR_LOW(GPIOB_LED2) | \ + PIN_ODR_LOW(GPIOB_ARD_D15) | \ + PIN_ODR_LOW(GPIOB_ARD_D14) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D36) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D35) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D19) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D18) | \ + PIN_ODR_LOW(GPIOB_LED3) | \ + PIN_ODR_HIGH(GPIOB_ZIO_D17)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ZIO_D33, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_A6, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D27, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D23, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D25, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D22, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D26, 0U) | \ + PIN_AFIO_AF(GPIOB_LED2, 0U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 4U) | \ + PIN_AFIO_AF(GPIOB_ARD_D14, 4U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D36, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D35, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D19, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D18, 0U) | \ + PIN_AFIO_AF(GPIOB_LED3, 0U) | \ + PIN_AFIO_AF(GPIOB_ZIO_D17, 0U)) + +/* + * GPIOC setup: + * + * PC0 - ARD_A1 ADC1_IN10 (input pullup). + * PC1 - ARD_A3 ADC1_IN11 (input pullup). + * PC2 - ZIO_A7 ADC1_IN12 (input pullup). + * PC3 - ARD_A2 ADC1_IN13 (input pullup). + * PC4 - ARD_A4 ADC1_IN14 (input pullup). + * PC5 - ARD_A5 ADC1_IN15 (input pullup). + * PC6 - ZIO_D16 I2S2_MCK (input pullup). + * PC7 - ZIO_D21 I2S3_MCK (input pullup). + * PC8 - ZIO_D43 SDMMC_D0 (input pullup). + * PC9 - ZIO_D44 SDMMC_D1 (input pullup). + * PC10 - ZIO_D45 SDMMC_D2 (input pullup). + * PC11 - ZIO_D46 SDMMC_D3 (input pullup). + * PC12 - ZIO_D47 SDMMC_CK (input pullup). + * PC13 - BUTTON (input floating). + * PC14 - OSC32_IN (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ARD_A1) | \ + PIN_MODE_INPUT(GPIOC_ARD_A3) | \ + PIN_MODE_INPUT(GPIOC_ZIO_A7) | \ + PIN_MODE_INPUT(GPIOC_ARD_A2) | \ + PIN_MODE_INPUT(GPIOC_ARD_A4) | \ + PIN_MODE_INPUT(GPIOC_ARD_A5) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D16) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D21) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D43) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D44) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D45) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D46) | \ + PIN_MODE_INPUT(GPIOC_ZIO_D47) | \ + PIN_MODE_INPUT(GPIOC_BUTTON) | \ + PIN_MODE_INPUT(GPIOC_OSC32_IN) | \ + PIN_MODE_INPUT(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_A7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D16) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D21) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D43) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D44) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D45) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D46) | \ + PIN_OTYPE_PUSHPULL(GPIOC_ZIO_D47) | \ + PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A1) | \ + PIN_OSPEED_VERYLOW(GPIOC_ARD_A3) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_A7) | \ + PIN_OSPEED_HIGH(GPIOC_ARD_A2) | \ + PIN_OSPEED_VERYLOW(GPIOC_ARD_A4) | \ + PIN_OSPEED_VERYLOW(GPIOC_ARD_A5) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D16) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D21) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D43) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D44) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D45) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D46) | \ + PIN_OSPEED_HIGH(GPIOC_ZIO_D47) | \ + PIN_OSPEED_HIGH(GPIOC_BUTTON) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \ + PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A1) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A3) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_A7) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A2) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A4) | \ + PIN_PUPDR_PULLUP(GPIOC_ARD_A5) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D16) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D21) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D43) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D44) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D45) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D46) | \ + PIN_PUPDR_PULLUP(GPIOC_ZIO_D47) | \ + PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \ + PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A1) | \ + PIN_ODR_HIGH(GPIOC_ARD_A3) | \ + PIN_ODR_HIGH(GPIOC_ZIO_A7) | \ + PIN_ODR_HIGH(GPIOC_ARD_A2) | \ + PIN_ODR_HIGH(GPIOC_ARD_A4) | \ + PIN_ODR_HIGH(GPIOC_ARD_A5) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D16) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D21) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D43) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D44) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D45) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D46) | \ + PIN_ODR_HIGH(GPIOC_ZIO_D47) | \ + PIN_ODR_HIGH(GPIOC_BUTTON) | \ + PIN_ODR_HIGH(GPIOC_OSC32_IN) | \ + PIN_ODR_HIGH(GPIOC_OSC32_OUT)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A1, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A3, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_A7, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A2, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \ + PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D16, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D21, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_ZIO_D43, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D44, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D45, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D46, 0U) | \ + PIN_AFIO_AF(GPIOC_ZIO_D47, 0U) | \ + PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \ + PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) + +/* + * GPIOD setup: + * + * PD0 - ZIO_D67 CAN1_RX (input pullup). + * PD1 - ZIO_D66 CAN1_TX (input pullup). + * PD2 - ZIO_D48 SDMMC_CMD (input pullup). + * PD3 - ZIO_D55 USART2_CTS (input pullup). + * PD4 - ZIO_D54 USART2_RTS (input pullup). + * PD5 - ZIO_D53 USART2_TX (input pullup). + * PD6 - ZIO_D52 USART2_RX (input pullup). + * PD7 - ZIO_D51 USART2_SCLK (input pullup). + * PD8 - USART3_RX STLK_RX (alternate 7). + * PD9 - USART3_TX STLK_TX (alternate 7). + * PD10 - PIN10 (input pullup). + * PD11 - ZIO_D30 QUADSPI_BK1_IO0 (input pullup). + * PD12 - ZIO_D29 QUADSPI_BK1_IO1 (input pullup). + * PD13 - ZIO_D28 QUADSPI_BK1_IO3 (input pullup). + * PD14 - ARD_D10 SPI1_NSS (input pullup). + * PD15 - ARD_D9 TIM4_CH4 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_ZIO_D67) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D66) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D48) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D55) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D54) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D53) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D52) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D51) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_RX) | \ + PIN_MODE_ALTERNATE(GPIOD_USART3_TX) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D30) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D29) | \ + PIN_MODE_INPUT(GPIOD_ZIO_D28) | \ + PIN_MODE_INPUT(GPIOD_ARD_D10) | \ + PIN_MODE_INPUT(GPIOD_ARD_D9)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D67) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D66) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D48) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D55) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D54) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D53) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D52) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D51) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_RX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_USART3_TX) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D30) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D29) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ZIO_D28) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ARD_D10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_ARD_D9)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_ZIO_D67) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D66) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D48) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D55) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D54) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D53) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D52) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D51) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_RX) | \ + PIN_OSPEED_HIGH(GPIOD_USART3_TX) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D30) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D29) | \ + PIN_OSPEED_HIGH(GPIOD_ZIO_D28) | \ + PIN_OSPEED_HIGH(GPIOD_ARD_D10) | \ + PIN_OSPEED_HIGH(GPIOD_ARD_D9)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_ZIO_D67) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D66) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D48) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D55) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D54) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D53) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D52) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D51) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_RX) | \ + PIN_PUPDR_FLOATING(GPIOD_USART3_TX) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D30) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D29) | \ + PIN_PUPDR_PULLUP(GPIOD_ZIO_D28) | \ + PIN_PUPDR_PULLUP(GPIOD_ARD_D10) | \ + PIN_PUPDR_PULLUP(GPIOD_ARD_D9)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_ZIO_D67) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D66) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D48) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D55) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D54) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D53) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D52) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D51) | \ + PIN_ODR_HIGH(GPIOD_USART3_RX) | \ + PIN_ODR_HIGH(GPIOD_USART3_TX) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D30) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D29) | \ + PIN_ODR_HIGH(GPIOD_ZIO_D28) | \ + PIN_ODR_HIGH(GPIOD_ARD_D10) | \ + PIN_ODR_HIGH(GPIOD_ARD_D9)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_ZIO_D67, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D66, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D48, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D55, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D54, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D53, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D52, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D51, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_USART3_RX, 7U) | \ + PIN_AFIO_AF(GPIOD_USART3_TX, 7U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D30, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D29, 0U) | \ + PIN_AFIO_AF(GPIOD_ZIO_D28, 0U) | \ + PIN_AFIO_AF(GPIOD_ARD_D10, 0U) | \ + PIN_AFIO_AF(GPIOD_ARD_D9, 0U)) + +/* + * GPIOE setup: + * + * PE0 - ZIO_D34 TIM4_ETR (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - ZIO_D31 ZIO_D56 QUADSPI_BK1_IO2(input pullup). + * PE3 - ZIO_D60 SAI1_SD_B (input pullup). + * PE4 - ZIO_D57 SAI1_FS_A (input pullup). + * PE5 - ZIO_D58 SAI1_SCK_A (input pullup). + * PE6 - ZIO_D59 SAI1_SD_A (input pullup). + * PE7 - ZIO_D41 TIM1_ETR (input pullup). + * PE8 - ZIO_D42 TIM1_CH1N (input pullup). + * PE9 - ARD_D6 TIM1_CH1 (input pullup). + * PE10 - ZIO_D40 TIM1_CH2N (input pullup). + * PE11 - ARD_D5 TIM1_CH2 (input pullup). + * PE12 - ZIO_D39 TIM1_CH3N (input pullup). + * PE13 - ARD_D3 TIM1_CH3 (input pullup). + * PE14 - ZIO_D38 (input pullup). + * PE15 - ZIO_D37 TIM1_BKIN1 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_ZIO_D34) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D31) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D60) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D57) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D58) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D59) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D41) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D42) | \ + PIN_MODE_INPUT(GPIOE_ARD_D6) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D40) | \ + PIN_MODE_INPUT(GPIOE_ARD_D5) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D39) | \ + PIN_MODE_INPUT(GPIOE_ARD_D3) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D38) | \ + PIN_MODE_INPUT(GPIOE_ZIO_D37)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D34) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D31) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D60) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D57) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D58) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D59) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D41) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D42) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D40) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D39) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ARD_D3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D38) | \ + PIN_OTYPE_PUSHPULL(GPIOE_ZIO_D37)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_ZIO_D34) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D31) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D60) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D57) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D58) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D59) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D41) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D42) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D6) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D40) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D5) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D39) | \ + PIN_OSPEED_HIGH(GPIOE_ARD_D3) | \ + PIN_OSPEED_VERYLOW(GPIOE_ZIO_D38) | \ + PIN_OSPEED_HIGH(GPIOE_ZIO_D37)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_ZIO_D34) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D31) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D60) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D57) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D58) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D59) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D41) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D42) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D6) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D40) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D5) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D39) | \ + PIN_PUPDR_PULLUP(GPIOE_ARD_D3) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D38) | \ + PIN_PUPDR_PULLUP(GPIOE_ZIO_D37)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_ZIO_D34) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D31) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D60) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D57) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D58) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D59) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D41) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D42) | \ + PIN_ODR_HIGH(GPIOE_ARD_D6) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D40) | \ + PIN_ODR_HIGH(GPIOE_ARD_D5) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D39) | \ + PIN_ODR_HIGH(GPIOE_ARD_D3) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D38) | \ + PIN_ODR_HIGH(GPIOE_ZIO_D37)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_ZIO_D34, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D31, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D60, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D57, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D58, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D59, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D41, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_ZIO_D42, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D6, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D40, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D5, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D39, 0U) | \ + PIN_AFIO_AF(GPIOE_ARD_D3, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D38, 0U) | \ + PIN_AFIO_AF(GPIOE_ZIO_D37, 0U)) + +/* + * GPIOF setup: + * + * PF0 - ZIO_D68 I2C2_SDA (input pullup). + * PF1 - ZIO_D69 I2C2_SCL (input pullup). + * PF2 - ZIO_D70 I2C2_SMBA (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - ZIO_D62 SAI1_MCLK_B (input pullup). + * PF8 - ZIO_D61 SAI1_SCK_B (input pullup). + * PF9 - ZIO_D63 SAI1_FS_B (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - ARD_D8 (input pullup). + * PF13 - ARD_D7 (input pullup). + * PF14 - ARD_D4 (input pullup). + * PF15 - ARD_D2 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_ZIO_D68) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D69) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D70) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D62) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D61) | \ + PIN_MODE_INPUT(GPIOF_ZIO_D63) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_ARD_D8) | \ + PIN_MODE_INPUT(GPIOF_ARD_D7) | \ + PIN_MODE_INPUT(GPIOF_ARD_D4) | \ + PIN_MODE_INPUT(GPIOF_ARD_D2)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D68) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D69) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D70) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D62) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D61) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ZIO_D63) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_ARD_D2)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_ZIO_D68) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D69) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D70) | \ + PIN_OSPEED_HIGH(GPIOF_PIN3) | \ + PIN_OSPEED_HIGH(GPIOF_PIN4) | \ + PIN_OSPEED_HIGH(GPIOF_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D62) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D61) | \ + PIN_OSPEED_HIGH(GPIOF_ZIO_D63) | \ + PIN_OSPEED_HIGH(GPIOF_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D8) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D7) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D4) | \ + PIN_OSPEED_VERYLOW(GPIOF_ARD_D2)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_ZIO_D68) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D69) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D70) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D62) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D61) | \ + PIN_PUPDR_PULLUP(GPIOF_ZIO_D63) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D8) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D7) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D4) | \ + PIN_PUPDR_PULLUP(GPIOF_ARD_D2)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_ZIO_D68) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D69) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D70) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D62) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D61) | \ + PIN_ODR_HIGH(GPIOF_ZIO_D63) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_ARD_D8) | \ + PIN_ODR_HIGH(GPIOF_ARD_D7) | \ + PIN_ODR_HIGH(GPIOF_ARD_D4) | \ + PIN_ODR_HIGH(GPIOF_ARD_D2)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_ZIO_D68, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D69, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D70, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D62, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_ZIO_D61, 0U) | \ + PIN_AFIO_AF(GPIOF_ZIO_D63, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D8, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D7, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D4, 0U) | \ + PIN_AFIO_AF(GPIOF_ARD_D2, 0U)) + +/* + * GPIOG setup: + * + * PG0 - ZIO_D65 (input pullup). + * PG1 - ZIO_D64 (input pullup). + * PG2 - ZIO_D49 (input pullup). + * PG3 - ZIO_D50 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - USB_GPIO_OUT (output pushpull maximum). + * PG7 - USB_GPIO_IN (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - ARD_D0 USART6_RX (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - ARD_D1 USART6_TX (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_ZIO_D65) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D64) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D49) | \ + PIN_MODE_INPUT(GPIOG_ZIO_D50) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_OUTPUT(GPIOG_USB_GPIO_OUT) | \ + PIN_MODE_INPUT(GPIOG_USB_GPIO_IN) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_ARD_D0) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_ARD_D1) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D65) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D64) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D49) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ZIO_D50) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_USB_GPIO_OUT) |\ + PIN_OTYPE_PUSHPULL(GPIOG_USB_GPIO_IN) |\ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ARD_D0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_ARD_D1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_ZIO_D65) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D64) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D49) | \ + PIN_OSPEED_VERYLOW(GPIOG_ZIO_D50) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \ + PIN_OSPEED_HIGH(GPIOG_USB_GPIO_OUT) | \ + PIN_OSPEED_HIGH(GPIOG_USB_GPIO_IN) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \ + PIN_OSPEED_HIGH(GPIOG_ARD_D0) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \ + PIN_OSPEED_HIGH(GPIOG_ARD_D1) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_ZIO_D65) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D64) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D49) | \ + PIN_PUPDR_PULLUP(GPIOG_ZIO_D50) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_USB_GPIO_OUT) | \ + PIN_PUPDR_PULLUP(GPIOG_USB_GPIO_IN) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_ARD_D0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_ARD_D1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_ZIO_D65) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D64) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D49) | \ + PIN_ODR_HIGH(GPIOG_ZIO_D50) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_USB_GPIO_OUT) | \ + PIN_ODR_HIGH(GPIOG_USB_GPIO_IN) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_ARD_D0) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_ARD_D1) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_ZIO_D65, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D64, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D49, 0U) | \ + PIN_AFIO_AF(GPIOG_ZIO_D50, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOG_USB_GPIO_OUT, 0U) | \ + PIN_AFIO_AF(GPIOG_USB_GPIO_IN, 0U)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOG_ARD_D0, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOG_ARD_D1, 0U) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0U)) + +/* + * GPIOH setup: + * + * PH0 - OSC_IN (input floating). + * PH1 - OSC_OUT (input floating). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \ + PIN_MODE_INPUT(GPIOH_OSC_OUT) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \ + PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \ + PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \ + PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \ + PIN_ODR_HIGH(GPIOH_OSC_OUT) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \ + PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0U)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0U)) + +/* + * GPIOI setup: + * + * PI0 - PIN0 (input pullup). + * PI1 - PIN1 (input pullup). + * PI2 - PIN2 (input pullup). + * PI3 - PIN3 (input pullup). + * PI4 - PIN4 (input pullup). + * PI5 - PIN5 (input pullup). + * PI6 - PIN6 (input pullup). + * PI7 - PIN7 (input pullup). + * PI8 - PIN8 (input pullup). + * PI9 - PIN9 (input pullup). + * PI10 - PIN10 (input pullup). + * PI11 - PIN11 (input pullup). + * PI12 - PIN12 (input pullup). + * PI13 - PIN13 (input pullup). + * PI14 - PIN14 (input pullup). + * PI15 - PIN15 (input pullup). + */ +#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \ + PIN_MODE_INPUT(GPIOI_PIN1) | \ + PIN_MODE_INPUT(GPIOI_PIN2) | \ + PIN_MODE_INPUT(GPIOI_PIN3) | \ + PIN_MODE_INPUT(GPIOI_PIN4) | \ + PIN_MODE_INPUT(GPIOI_PIN5) | \ + PIN_MODE_INPUT(GPIOI_PIN6) | \ + PIN_MODE_INPUT(GPIOI_PIN7) | \ + PIN_MODE_INPUT(GPIOI_PIN8) | \ + PIN_MODE_INPUT(GPIOI_PIN9) | \ + PIN_MODE_INPUT(GPIOI_PIN10) | \ + PIN_MODE_INPUT(GPIOI_PIN11) | \ + PIN_MODE_INPUT(GPIOI_PIN12) | \ + PIN_MODE_INPUT(GPIOI_PIN13) | \ + PIN_MODE_INPUT(GPIOI_PIN14) | \ + PIN_MODE_INPUT(GPIOI_PIN15)) +#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOI_PIN15)) +#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOI_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOI_PIN15)) +#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOI_PIN15)) +#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \ + PIN_ODR_HIGH(GPIOI_PIN1) | \ + PIN_ODR_HIGH(GPIOI_PIN2) | \ + PIN_ODR_HIGH(GPIOI_PIN3) | \ + PIN_ODR_HIGH(GPIOI_PIN4) | \ + PIN_ODR_HIGH(GPIOI_PIN5) | \ + PIN_ODR_HIGH(GPIOI_PIN6) | \ + PIN_ODR_HIGH(GPIOI_PIN7) | \ + PIN_ODR_HIGH(GPIOI_PIN8) | \ + PIN_ODR_HIGH(GPIOI_PIN9) | \ + PIN_ODR_HIGH(GPIOI_PIN10) | \ + PIN_ODR_HIGH(GPIOI_PIN11) | \ + PIN_ODR_HIGH(GPIOI_PIN12) | \ + PIN_ODR_HIGH(GPIOI_PIN13) | \ + PIN_ODR_HIGH(GPIOI_PIN14) | \ + PIN_ODR_HIGH(GPIOI_PIN15)) +#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN7, 0U)) +#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOI_PIN15, 0U)) + +/* + * GPIOJ setup: + * + * PJ0 - PIN0 (input pullup). + * PJ1 - PIN1 (input pullup). + * PJ2 - PIN2 (input pullup). + * PJ3 - PIN3 (input pullup). + * PJ4 - PIN4 (input pullup). + * PJ5 - PIN5 (input pullup). + * PJ6 - PIN6 (input pullup). + * PJ7 - PIN7 (input pullup). + * PJ8 - PIN8 (input pullup). + * PJ9 - PIN9 (input pullup). + * PJ10 - PIN10 (input pullup). + * PJ11 - PIN11 (input pullup). + * PJ12 - PIN12 (input pullup). + * PJ13 - PIN13 (input pullup). + * PJ14 - PIN14 (input pullup). + * PJ15 - PIN15 (input pullup). + */ +#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \ + PIN_MODE_INPUT(GPIOJ_PIN1) | \ + PIN_MODE_INPUT(GPIOJ_PIN2) | \ + PIN_MODE_INPUT(GPIOJ_PIN3) | \ + PIN_MODE_INPUT(GPIOJ_PIN4) | \ + PIN_MODE_INPUT(GPIOJ_PIN5) | \ + PIN_MODE_INPUT(GPIOJ_PIN6) | \ + PIN_MODE_INPUT(GPIOJ_PIN7) | \ + PIN_MODE_INPUT(GPIOJ_PIN8) | \ + PIN_MODE_INPUT(GPIOJ_PIN9) | \ + PIN_MODE_INPUT(GPIOJ_PIN10) | \ + PIN_MODE_INPUT(GPIOJ_PIN11) | \ + PIN_MODE_INPUT(GPIOJ_PIN12) | \ + PIN_MODE_INPUT(GPIOJ_PIN13) | \ + PIN_MODE_INPUT(GPIOJ_PIN14) | \ + PIN_MODE_INPUT(GPIOJ_PIN15)) +#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOJ_PIN15)) +#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOJ_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOJ_PIN15)) +#define VAL_GPIOJ_PUPDR (PIN_PUPDR_PULLUP(GPIOJ_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOJ_PIN15)) +#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \ + PIN_ODR_HIGH(GPIOJ_PIN1) | \ + PIN_ODR_HIGH(GPIOJ_PIN2) | \ + PIN_ODR_HIGH(GPIOJ_PIN3) | \ + PIN_ODR_HIGH(GPIOJ_PIN4) | \ + PIN_ODR_HIGH(GPIOJ_PIN5) | \ + PIN_ODR_HIGH(GPIOJ_PIN6) | \ + PIN_ODR_HIGH(GPIOJ_PIN7) | \ + PIN_ODR_HIGH(GPIOJ_PIN8) | \ + PIN_ODR_HIGH(GPIOJ_PIN9) | \ + PIN_ODR_HIGH(GPIOJ_PIN10) | \ + PIN_ODR_HIGH(GPIOJ_PIN11) | \ + PIN_ODR_HIGH(GPIOJ_PIN12) | \ + PIN_ODR_HIGH(GPIOJ_PIN13) | \ + PIN_ODR_HIGH(GPIOJ_PIN14) | \ + PIN_ODR_HIGH(GPIOJ_PIN15)) +#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN7, 0U)) +#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOJ_PIN15, 0U)) + +/* + * GPIOK setup: + * + * PK0 - PIN0 (input pullup). + * PK1 - PIN1 (input pullup). + * PK2 - PIN2 (input pullup). + * PK3 - PIN3 (input pullup). + * PK4 - PIN4 (input pullup). + * PK5 - PIN5 (input pullup). + * PK6 - PIN6 (input pullup). + * PK7 - PIN7 (input pullup). + * PK8 - PIN8 (input pullup). + * PK9 - PIN9 (input pullup). + * PK10 - PIN10 (input pullup). + * PK11 - PIN11 (input pullup). + * PK12 - PIN12 (input pullup). + * PK13 - PIN13 (input pullup). + * PK14 - PIN14 (input pullup). + * PK15 - PIN15 (input pullup). + */ +#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \ + PIN_MODE_INPUT(GPIOK_PIN1) | \ + PIN_MODE_INPUT(GPIOK_PIN2) | \ + PIN_MODE_INPUT(GPIOK_PIN3) | \ + PIN_MODE_INPUT(GPIOK_PIN4) | \ + PIN_MODE_INPUT(GPIOK_PIN5) | \ + PIN_MODE_INPUT(GPIOK_PIN6) | \ + PIN_MODE_INPUT(GPIOK_PIN7) | \ + PIN_MODE_INPUT(GPIOK_PIN8) | \ + PIN_MODE_INPUT(GPIOK_PIN9) | \ + PIN_MODE_INPUT(GPIOK_PIN10) | \ + PIN_MODE_INPUT(GPIOK_PIN11) | \ + PIN_MODE_INPUT(GPIOK_PIN12) | \ + PIN_MODE_INPUT(GPIOK_PIN13) | \ + PIN_MODE_INPUT(GPIOK_PIN14) | \ + PIN_MODE_INPUT(GPIOK_PIN15)) +#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOK_PIN15)) +#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOK_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOK_PIN15)) +#define VAL_GPIOK_PUPDR (PIN_PUPDR_PULLUP(GPIOK_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOK_PIN15)) +#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \ + PIN_ODR_HIGH(GPIOK_PIN1) | \ + PIN_ODR_HIGH(GPIOK_PIN2) | \ + PIN_ODR_HIGH(GPIOK_PIN3) | \ + PIN_ODR_HIGH(GPIOK_PIN4) | \ + PIN_ODR_HIGH(GPIOK_PIN5) | \ + PIN_ODR_HIGH(GPIOK_PIN6) | \ + PIN_ODR_HIGH(GPIOK_PIN7) | \ + PIN_ODR_HIGH(GPIOK_PIN8) | \ + PIN_ODR_HIGH(GPIOK_PIN9) | \ + PIN_ODR_HIGH(GPIOK_PIN10) | \ + PIN_ODR_HIGH(GPIOK_PIN11) | \ + PIN_ODR_HIGH(GPIOK_PIN12) | \ + PIN_ODR_HIGH(GPIOK_PIN13) | \ + PIN_ODR_HIGH(GPIOK_PIN14) | \ + PIN_ODR_HIGH(GPIOK_PIN15)) +#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN7, 0U)) +#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOK_PIN15, 0U)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/CMakeLists.txt b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/CMakeLists.txt new file mode 100644 index 00000000..aa7f1d54 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2017 The nanoFramework project contributors +# See LICENSE file in the project root for full license information. +# + +# append common source files +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/usbcfg.c") +list(APPEND COMMON_PROJECT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Device_BlockStorage$<$,$>:-DEBUG>.c") + +# make var global +set(COMMON_PROJECT_SOURCES ${COMMON_PROJECT_SOURCES} CACHE INTERNAL "make global") diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage-DEBUG.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage-DEBUG.c new file mode 100644 index 00000000..f1b9ab35 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage-DEBUG.c @@ -0,0 +1,96 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 32kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 0x08008000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08020000 nanoCLR +}; + +// 256kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 2 } // 0x08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x8000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 1, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08040000, // start address for block region + 3, // total number of blocks in this region + 0x40000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage.c new file mode 100644 index 00000000..e8f18706 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/Device_BlockStorage.c @@ -0,0 +1,96 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include + +// 32kB blocks +const BlockRange BlockRange1[] = +{ + { BlockRange_BLOCKTYPE_BOOTSTRAP , 0, 0 }, // 0x08000000 nanoBooter + { BlockRange_BLOCKTYPE_CODE , 1, 3 } // 0x08008000 nanoCLR +}; + +//128kB block +const BlockRange BlockRange2[] = +{ + { BlockRange_BLOCKTYPE_CODE , 0, 0 } // 0x08020000 nanoCLR +}; + +// 256kB blocks +const BlockRange BlockRange3[] = +{ + { BlockRange_BLOCKTYPE_DEPLOYMENT, 0, 2 } // 0x08040000 deployment +}; + +const BlockRegionInfo BlockRegions[] = +{ + { + (0), // no attributes for this region + 0x08000000, // start address for block region + 4, // total number of blocks in this region + 0x8000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange1), + BlockRange1, + }, + + { + (0), // no attributes for this region + 0x08020000, // start address for block region + 1, // total number of blocks in this region + 0x20000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange2), + BlockRange2, + }, + + { + (0), // no attributes for this region + 0x08040000, // start address for block region + 3, // total number of blocks in this region + 0x40000, // total number of bytes per block + ARRAYSIZE_CONST_EXPR(BlockRange3), + BlockRange3, + }, + +}; + +const DeviceBlockInfo Device_BlockInfo = +{ + (MediaAttribute_SupportsXIP), + 2, // UINT32 BytesPerSector + ARRAYSIZE_CONST_EXPR(BlockRegions), // UINT32 NumRegions; + (BlockRegionInfo*)BlockRegions, // const BlockRegionInfo* pRegions; +}; + +MEMORY_MAPPED_NOR_BLOCK_CONFIG Device_BlockStorageConfig = +{ + { // BLOCK_CONFIG + { + 0, // GPIO_PIN Pin; + false, // BOOL ActiveState; + }, + + (DeviceBlockInfo*)&Device_BlockInfo, // BlockDeviceinfo + }, + + { // CPU_MEMORY_CONFIG + 0, // UINT8 CPU_MEMORY_CONFIG::ChipSelect; + true, // UINT8 CPU_MEMORY_CONFIG::ReadOnly; + 0, // UINT32 CPU_MEMORY_CONFIG::WaitStates; + 0, // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts; + 16, // UINT32 CPU_MEMORY_CONFIG::BitWidth; + 0x08000000, // UINT32 CPU_MEMORY_CONFIG::BaseAddress; + 0x00100000, // UINT32 CPU_MEMORY_CONFIG::SizeInBytes; + 0, // UINT8 CPU_MEMORY_CONFIG::XREADYEnable + 0, // UINT8 CPU_MEMORY_CONFIG::ByteSignalsForRead + 0, // UINT8 CPU_MEMORY_CONFIG::ExternalBufferEnable + }, + + 0, // UINT32 ChipProtection; + 0, // UINT32 ManufacturerCode; + 0, // UINT32 DeviceCode; +}; + +BlockStorageDevice Device_BlockStorage; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.c b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.c new file mode 100644 index 00000000..11e6d6bd --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.c @@ -0,0 +1,454 @@ +// +// Copyright (c) 2017..2018 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD2. + */ +#define USBD2_DATA_REQUEST_EP 1 +#define USBD2_DATA_AVAILABLE_EP 1 +#define USBD2_INTERRUPT_REQUEST_EP 2 + +// address for device unique ID +// valid for STM32F4 series +#define DEVICE_ID1 (0x1FFF7A10) +#define DEVICE_ID2 (0x1FFF7A14) +#define DEVICE_ID3 (0x1FFF7A18) + +// // size of string serial is 36 = 2 + 5x2 + 26 from silicon unique ID precedeed of string "NANO_" and descriptor codes +// #define USB_SIZ_STRING_SERIAL 36 + +//////////////////////////////////////////////// +// vendor +#define USB_STRING_VENDOR L"STMicroelectronics" +//////////////////////////////////////////////// + +// structure for USB Vendor with Unicode string +typedef struct usb_string_vendor +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_VENDOR)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_vendor; + + +///////////////////////////////////////////////////////////////////////// +// device description +#define USB_STRING_DEVICE_DESCRIPTION L"nanoFramework Virtual COM Port" +///////////////////////////////////////////////////////////////////////// + +// structure for USB device descriptor with Unicode string +typedef struct usb_string_device_description +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_DEVICE_DESCRIPTION)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_device_description; + + +///////////////////////////////////////////////////////////////////////// +// device serial number +// this will produce a string with NANO_ prefix followed +// by the hexadecimal representation of the silicon unique ID of the CPU +#define USB_STRING_SERIAL_NUMBER L"NANO_xxxxxxxxxxx" +///////////////////////////////////////////////////////////////////////// +#define INDEX_OF_WCHAR_FOR_UNIQUE_ID 5 + +// structure for USB serial number descriptor with Unicode string +typedef struct usb_string_serial_number +{ + uint8_t bLength; + uint8_t bDescriptorType; + wchar_t bPropertyData[sizeof(USB_STRING_SERIAL_NUMBER)/sizeof(wchar_t) - 1]; // that's the 'w_char' string length less 1 because we are not storing the terminator (according to the USB spec) + +}usb_string_serial_number; + + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[] = { + USB_DESC_DEVICE (0x0200, /* bcdUSB (2.0). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(0x0043, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD2_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + + +// Vendor string +static const usb_string_vendor usb_vendor = { + sizeof(usb_vendor), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_VENDOR +}; + + +// Device Description string +static const usb_string_device_description usb_device_description = { + sizeof(usb_device_description), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_DEVICE_DESCRIPTION +}; + + +// Serial Number string. +static usb_string_serial_number usb_serial_number = { + sizeof(usb_serial_number), + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), + USB_STRING_SERIAL_NUMBER +}; + + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof usb_vendor, (uint8_t*)(&usb_vendor)}, + {sizeof usb_device_description, (uint8_t*)(&usb_device_description)}, + {sizeof usb_serial_number, (uint8_t*)(&usb_serial_number)}, +}; + + +// Convert Hex 32Bits value into char +// value: value to convert +// pbuf: pointer to the buffer +// len: buffer length +void IntToUnicode(uint32_t value , uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for( idx = 0; idx < len; idx ++) + { + if( ((value >> 28)) < 0xA ) + { + pbuf[ 2* idx] = (value >> 28) + '0'; + } + else + { + pbuf[2* idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2* idx + 1] = 0; + } +} + +// Create the serial number string descriptor +void Get_SerialNum(uint8_t* pbuf) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t*)DEVICE_ID1; + deviceserial1 = *(uint32_t*)DEVICE_ID2; + deviceserial2 = *(uint32_t*)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) + { + IntToUnicode(deviceserial0, pbuf, 8); + pbuf += 16; + IntToUnicode(deviceserial1, pbuf, 4); + } +} + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + { + if(dindex == 3) + { + // request is for serial number + // get it from the silicon unique ID + Get_SerialNum((uint8_t*)&usb_serial_number.bPropertyData[INDEX_OF_WCHAR_FOR_UNIQUE_ID]); + } + + return &vcom_strings[dindex]; + } + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + if (usbp->state == USB_ACTIVE) { + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD2_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD2_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + } + else if (usbp->state == USB_SELECTED) { + usbDisableEndpointsI(usbp); + } + + chSysUnlockFromISR(); + return; + case USB_EVENT_RESET: + /* Falls into.*/ + case USB_EVENT_UNCONFIGURED: + /* Falls into.*/ + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduSuspendHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduWakeupHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handling messages not implemented in the default handler nor in the + * SerialUSB handler. + */ +static bool requests_hook(USBDriver *usbp) { + + if (((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE) && + (usbp->setup[1] == USB_REQ_SET_INTERFACE)) { + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + } + return sduRequestsHook(usbp); +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + requests_hook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD2_DATA_REQUEST_EP, + USBD2_DATA_AVAILABLE_EP, + USBD2_INTERRUPT_REQUEST_EP +}; diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.h b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.h new file mode 100644 index 00000000..72960028 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/common/usbcfg.h @@ -0,0 +1,16 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) 2006..2015 Giovanni Di Sirio. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef USBCFG_H +#define USBCFG_H + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* USBCFG_H */ + +/** @} */ diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/README.md b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/README.md new file mode 100644 index 00000000..e0453b7b --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/README.md @@ -0,0 +1,7 @@ +## Managed code helpers + +This folder contains helper classes to make developers life easier when coding for this target board. + +* [Adc](ST_NUCLEO144_F412ZG_NF.Adc.cs) +* [Gpio](ST_NUCLEO144_F412ZG_NF.Gpio.cs) +* [LEDs](ST_NUCLEO144_F412ZG_NF.LEDs.cs) diff --git a/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Adc.cs b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Adc.cs new file mode 100644 index 00000000..594d5203 --- /dev/null +++ b/source/native/nf-interpreter/targets-community/CMSIS-OS/ChibiOS/ST_NUCLEO144_F412ZG_NF/managed_helpers/ST_NUCLEO144_F412ZG_NF.Adc.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Targets.ST_NUCLEO144_F412ZG_NF +{ + ///

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Ús`M4jAE@(OCi!u3*Glj5h@Eu%`F&dV!e* zy@yx^2OPO`FcAU4!!T#O?5#vYRT6RpAn-#$W&q+Mol#jDNnj8o$cCVMw~?0=fOCIt zLSsY-aPPiQ+pm+r^r@HzYU#HP9t48_$fAUP+cMe7ctC96s;mMsZm`^I5XBQzRtt-b zX)~50cAN_8h*|WKLAQ`h$QY|Cgd6)27$l8QKs6b72LVn4{jDhS=9cQ3h&+2j=;y&v zqtDOZK=+oNc)DT}+Q0Z3FIR0w(~MPkwd@D9O=~kE&hW55fA+nG=Aq({g z-VX*94MrAZY>tkLk3{m$zYwu> zHS)jOfRbf|fHM}LVCr1t(==2JsZ2tVhCVVD5);YIM~$^P0%xeB=Om{g zlVR78fpgMPBg+CZY@uEuCmGR^;|0jL2jzh%u7Hfb^NPs$g{VW(k%2;B3%u*V5`h;C zxpFa$fturZ%h`v;Bn=YJqx9$b@X=O+(^o5m?}TF)QLMz(b~P|S0Klop-DA{=5$M35 z7|!{jVmL5ig3vT3DaZ+hnGq<;C#_hPOuu^u{r)*Z3_)XaKI&?-V0H5(7VA#H7m6|j z1Y@y4LK4@v{ed7y2mG*hHNIK1Q~-i=r~bmF(>rka#5UZ%b^zf-uT#mGxKhv^8#YKX zUK{q{SII!H!t54@6!Z2T$pib_u%P>< z@p)Xiei~*33?kq#5dx8n%r4-%$vK$Zx=61(BcwjNdfY}pkOPtu1Muc`9T|KqvXVt0 zP?$q3FveBbQmm^^B0z{iSb!}_hX*+Q=Xa=m90&viph#~f+N4QuOA#HHA!`4*BwR=u zJR)!{QzXeq2L52QER0mtP-bi4DC?nzBt*V}0aEt-h8Vgw z#mSs>#EXTzMnKYlGY~(m5AYTuvjMhiHu!%p3i5Gq3_j-Drz*yx7xEhh2pE_V2yq0j z1{nbXL3bD0J3EAUf|m9cqNTMoAxn`I_Xts5P6$4E6t0Vx!A)9Cphopm$&d|Z;r)3s zJT3|KFcc-bb|ZcMQsn8+Mlq*<>d!>2{&dvnPDQou6jbOMpu$ieWrlhvH!wt{!8DZX zOhrEb2vcSwec1|haoK8S6hV(rw01L+xFq>PU~3(0ei$lhNhn zqS3($59dun=TVXdnPjjv=R`n2UR=ZmL>^x7_@974UrrO9KXiH~Ghj5u8K*_cP$BEsuL!Hi+2JMHA$aX6+uUiT=-( zM2vtWLM72!f6}9uhKXa3oE%Jk{svFTKuQP*DoY6jD$>y0kVpEk2+z7J1z^ZY5686= zJFrwo3BS#mj>QrZSVTZzxpzOpT%1HeuzD%JTel1+j&8@*^Lugj&@V8%ycfZ~R!B*B z03UBFp#TZj3a}tRu(7`>EE1X$5O9Q{wJo&`XdZ*V;WPHy6^%PwxFNY4mE|0{Ad z1O&V`P?jHt;=Eua#=E1oCIR)eDQKV(AL)Ud#0NOB?Hd&Mx#7K+r%<-8Sz-b@#;c-6 zMg!iTOW+Oxf$u13q>^JwC&}m`Jprdx)llt9Qk3TLBVvr~MM0P#s z;0FzU@b+&o;M?DfKm-J$5aYoHC)^2{BMW(rfEht6F@jcR1Z~ZzCG@JRtw3Hz0@8wf z5PJFuT$e6|CmCU)-aKS2T8UoLs7N5{@9mAMRqIenGND0}kdrP(wazpYO`3uP(!mk( zig+Y1k1%;zgeb@$e1ak#tEu3zf-)i{6pFax0X3+n>}9%v#!sXvW(T#SU+084|{rAN^J z2?$DlnF9}P8MuDC8Yn8p#}ikPE2odAVDlu`a6qAJg zzC*&U!Df;M8`dnx*IzEd<@1Mdi`c`Bvwy+l!YzbfRj5f6q*W) zf|gu+faQRlIXH}%1BDnEI7h(I*+N(g;I#tYRbVh+R$xlr--H0&uvwJ7vd83w%%0aPM?kVS#yx~%g;b~C^3X`yr%C^G<6=DRB7&N>LOQ94+($$ zg2%TnAU{5s05KoEz3l=J3`Q1;whl#u!GM9_zlZ4de*gi$VNgpj5b$>5t2bQEoFfal zUSXGzc=YsH7uq^SK+xFIC;$OR7BUdzgg-#&nIo`TFb{U5nL?&7MAKo?Oi?j_mpAfP ztU;BUK03%iI}|3No(wu#LJD5o3{_za>{Z9$uG%QrsEvS~_E^|xj)JAiP}nJrg5$Um z2puOW1ZdRBYY|=JA8``ejvW@&pmX&`;nMXeAem63WQYzK(r-lnDkd5rcE)UaO)B!P zpT~n4n&>|Htq@s=nzMAl$@m2z5DhLo!qI|*y8#?qFu*$jZ1@ZW998(K?78sz!NJUd zjvwmJkQ_K6S|qGJK|pX6Z_18~wht4}q4=j+@R%qK$F(F^vUBlz-&s+J@mOsFfe8W- z^bVhZCNWJ!5D=LCXB^JSDdV7l4xSM8j`MfIlOPv733kJiP!Bu~aYy7sZ#)ciMRcG$ zO!oajOkgzDjT((jqr~yu=<#s)eJ38$WZKNzhpU$1tCfpz;miSI1p9IG+-?}3-3ecg z*N^unUG54eXH%ijD0en;cIWNB8)Ur3g6HS3VJBB>^6F&F#0Xdt@PgkR0s&4-=A8u> z4{JEO-GM26U*175y+y3S(UQEq39b?tTroO>>t^R*MQp>`k=TV0gTUR5Ea2;BhewaS zgjVY%B{AshDJ3TG2x)Pis4FKx$PPqNUMTu{OK6lLI>He}8No;hcEYKjzef2zcRask zi9DkJPseKD88NGJ^5B7_uVLdLY{4Od=(#@`e{>wNGNSG+^>keuz^(GQ$SwC56mk!q zwFy+c=hS&}C`8MpHHA`TujPmt5E!Ho0Nfj)0NXK&i2rgE5d4T7QwFNepM#J76gY`X z!;^mhN0N%jR+)%;{Tb*WsoOb!5xN#F!TYbj#q-6h(KCNJ+NaJzy_O!Tlr@F6=(!{Z zN|{{*l7z^l?{w)J%4aV`)nr3tPMe0r{eK|d-WZwW5Nd1k(9_dKK=48+CNvmX$N(@n zgeXJ0CpwA@e-H%z3kcp3BM_A~`Y0?G_P^`LD?*n(A>V-0kbBTW%;0HHr;u|XL>IQU zprL^@TvaLZvJ#N{H~>Ke1g1+C!g%@&RGuRbnLwKBt~1K#E+ub18C_(YPvs|}T1f{{ z{q zgB}ZF z`xHY^c?|vKN6}wGGNF*bB>oJFHqV5ohBWL~EhTWuM)%eOC{bV_n20w+RfO?^q(R3R zH580fMa%?!!Gm2kn2aPcth7Kk#6R*OR^W^H$Nq?a@<3=n8}rBy$)P^DdvGV#i;czh z5n?zsUIoWVqWS)`9bq@j@WbMzSigJ;zFhGIP9NWcYZngU^0Dm%1b@NL)r45aJtV~4 zhmX%41c$f@%}Th188<%VIs}|G=;dQiM(QEN1~A2EM!=rj!_!8{9^~jj4j;ZvAYo=n zbe|-IJ%PX-8v+g*Cd3HLNH*N&0wiwcaPYK%12GSdFW|*Vu3*FkPdTda*|So-cvd8Y z7N-&rbhf0^JPRNe@EE;a1wuLVV82_aD~iMehwC`~<62bvd!ql2Eee$kh-GP_Ym5d; zr8E&d$pGNKh>?#)%}zNyIECnUHOaG9GWuqs;rRpviFEEUy(Tf5oCP_UgjjU#*@wD` zhUk+eu$Iuk8%Zs^RGNZ%jadkupofr^>qL1jr6qVupuvmN`MNU^$qZzqgwTM;M{FFt zCC0#8hVILWBUn`t57j0hoTN#(60u%6c_hflBYm6<&D)7+RGEZw0)+hKBx`-V1xEYs z_HE=6fW*w1jhI6_k?3+8DUp6?Y$_2V3x#?F|0-NM$Oc5R|DW-HV+4a>@LxbMFu*|Y z2Cv_~7FYpyLKevbZi~(}3tQ3H+$iiC)YsRcqP&h9xe+8&$k#DI z;=+Z5s+lM=yMeH|+IVq>^f|{7@U8)~f<^*_dNTBy)1pkl8Zz2CI?p{1>d45+%cFsw z=Wfll1Pt^#G!c+A^7{!i=sh2+={+@P=qMTk<;O8ldJJ!iY2+Wnn@j?$N5@dKX$HL1 zWpQ`eV*0M>Xx+R+sEg07xj2rX|8r%$5Oxk!P(vOkm%uD-&Jy^oSc(ENs{Al-q&)FQ za?}H%@oYj=fM^gPq=tCI>-awWAuWaLq<@`M4RMEbWz=tb@c61Jep<2|->g`Mr3>fa z&)C zM2mwa7la)Eu3^ZPif*%!(_@Y!FeRhswShY}CNSe22jh#la^ozF%r4@V4M_xI1I}Jn zuqXCmVSSZA<1*X`7+4zcw&?r!&1h>%Lm{z%{H#E{eOZRAG(WUAr_sp3yO&i6At2~$ z&4tBEGU{k0KzSoK39n=(;hD-b zlxWXJ?ziN%!+1-(0JS%7;y!8kEHwfN&1tAo*T)k@x(-rfVLxFk9Q4HDK3^W5iq;Sbq7=f!Mj=;H7VUECXptij(u!Q=h=_e3$? z5*v6aEEM(#Y=DcGas^|S1Pwx-K~qZ;>gs9<2uhKimWagA`|!AM5_fiN1xgCY*wRt6 z=~oo18K6^f5_$;;Dy7sBOO(l7awt4zh$H9Ha=cDBhSzy#@uK()UXyXYskuP(`aIs2 zpTeu+Bk0ZEhYzJ>fGOt@xMd2gmB+w;oES36<2A`^libil;_P{Vn+tjECOma?Mc@QO z+5f^Xb$0aMUVdYA! zT>1sptyv6f^UFB3_g9?S{SzV{IN(vB0}`Tr5gg!vJEY%jZOChLS}-vIJ9`tD-@c4n zyi-8BpM!_EPQmq?=W&aUEEBF9oh5_63S-ktFuTnQjMs$cm=*AIysdbLB*krduesG# z*g2aE0ZTSSak)wnw?k(T@b$MrV`DA`-ZrADb%8;Y;A8*WH+b3q zN&tfAoQh09z|Bp#G7(1L&B@c=z$-GY7lp_0vgj!K z3J;+-e;;0!9LC#%(|8|u5q=vc!^G?|$p8xi3<3a)8^Xe%3B8sF#|$uY;CKSwfe@`Z5bGeuVQI~PaY>K` z?w+?1@z@jZ2U^MCD^Zdgf}9i|yzMJSP6n}{cyGLa*MOd9W#}d_U`CJ`dk=elU5``0 zZ$V{H0Ny#flP1?i8-Zw#1kr2>ErkAu+oDV0$q0EA63Z$g=@2|jmcT$3p{jbQm^>2= zidw{4wb4f&J$|$zeCc_I&j|`P(K$_%4bf`>4v6L3VCr$%A$S{d%)}A|uxS8|u zh`_^Vs3h)jHKVaI$kUsIx<6La9J)%zegz*(xdZZPwB;W}Ti!uDD?W~AG{?DUi4bs> za+-X~3WU#=!eg0{$Pt%7o16+76x2{SSsx`EH`3e+A*Ypx1Y&7XzIO$A*wk3|NgBMs zz`NH15PV>HAZ#Cg%0eWOz)axZ#y@!bFCY-5EB=EPZ&(_<;TVEX>jTfbg;rNgCv&CE$^t2kx9Xh5!>nxyD*#9XW>b=?l=RJeepwO=u}O_(_h0?{pbd z-24{r)6U^V4(Vua2iD9LTo0f=YCE2$9m0$J)5Hia;We>@XE_Jan|qL6dj#(bFW_Cw zd3deXhOO*a1dftGmZUl=ly#A=KL`EpUO-F|5_A_36PZEMU>eevtrS8(%Ws(@0LVZ$ zzjoFv6i(Ge@fVYkzeEd#D|L~(TpL+SHITJj1KBGyQ1GQT@>cP2BC=PiA^$5a_4bjte z1}IxK1qHJW;6>W-!EZzD=~t27x=dNW{Y zpoa{zD<~8gfge%`3{qkPhz*c&(1;^OkQ(L#&y)MGRdzhg)wN+RH37!bYKYpp7a>a-{ubwa~4oi?~q=@cLW|_QPawm%zYdh!oPLC!s@q z269#PQMhYAu|oo*8#fR+V>U{)rl3qw2cg5H;QpV{a2Yie{)WAafp{=zV-Ot*E9Rm(1;!4K6b0F*Ho&+4 zJr3T6d?Xq{r-c{)y=&0lhiAP{NfL0s!!`i`xJ+3m$pZ!gE>*^D(W@$ok(CmM5HDv~ zoIZ-jHl+25qL-gNkE&_&(W$0S=%$E}(WA*5jz!V&)##5pj;E;y@tW)Xw_HWlcK#*w_@BUSU2)ir9*HMoU0D`RRq-B*g5G6MOiOMQSQc*&(hALu|6_BW= zj1;X2NYGS7vbHiZ_0?$*EuTCAsk#%8JegjvqkvQ$d8AI1Mb>0xq-!f8jc9(Zz6Nsj zG?A@GU}8w%F+~g6`UEa|6On63U^AV*8y)ke86bE1EZE8@!1ourprz#m1m^_r)GeWn zH>1?>b|iVR;YxxxODAvT{+Sp|BxG@3R~zv}yR*Z*kP_ubQs5pEqy34>`;!OvMRdeH zB!qgw@$^1?BP)i}np)UDdOY@ymPX*#-3T?dz}f|iu;PnFSh|SEe0;lZB`zG>gOel= z{`zS(g1m0wNtiPtBis@B#0zfjW@NnAh2SDyz~e@xckOQoU5_)eV_@$j3M}Gb$B~DY z+&2BPVCcMk$f3knx!DQH46abbI|}?fvjM)(vVg;wxnBZ@H2Vhs!j)scW9!D%IQq+Gl==DNrG-86 z6!pN6KzI%Ol`uzKnNum(ZSl7_AwH(U7zk?dki`k-ir_xrfk`u^*k$JA|U8 zMJK)>Fc^;~@*_~HD2GNFCDdu^BK3@}T1r5VW>& z_F*+D83nK7n~@RM*CA*BVU!unL6edWGQ<=RC_V;W(BmSW zTHR@anwZ~E;P)*mf__F@!XdmWxPtdpX82e`QlZui?<=n1P0=}YB=1FI+;;SGr=yIk z@ZYQlOR13v8?S&GqIWskQ;Dv5196EcnXy<%Z?2d)17%-rBF$cclp8m3Q%VJP!=>Ty znFJg^mmp0y9uC7L;7mv7;o@|EEF4CSgYB?UxI3IK=upwo`twn67(!$-k!*a&*< zXrhgy;5jqHKUpqOY$;s|#(L5!nOWkyB`dIO-U58JY86QX z0)vHfaAfZvII({#e%`PM4i@JS9qx{B0)xj-JP{P)MBe@?Zd+ayss?e}a;`GW<;NVI zxTy)R6I>HQhc910iA&dxd=LM_8PpYjVhq?iMT7yvlF;LhEf0toQB0M|UQxl7W+ z)eLT)w}fV?&!5-Q6l_OpT@v!s?xDRd77dk;iS>wzk>KMqd>G(zY)>&juPsOn!0s)p zvGv<8ae~0L(&qtQo7p2*Mh{(MCXzJJLM^cZzoF8&Lwes`TMzLYzeo1oy-3`@7wH$y zqV)PzRM1?l+V&TkcO698uiKHm`6o2)+>8EQG}pEsK;P_jXpx_aZiQ*&{fT+nIth%R z<)`0Ks%c07p@-se3J4f31_!xuxHCr#1$Q=(W7~z6G?I|@m(Wd4tordEsE^r8?Dq`% zXr6QTuHKx}=uAI|ruZFbiuwbs;oI;b`Y6iJEJyS#IYdbj7|6(?p1yk;uXnlFqrlA? z@qunA%8Etz(|RF}fO8Grd}0NnFk?}|5qCtUA50j7HvaG1AQ15Qv_`F5yj?F$OA4i5VE< zUD-9fE;xst%p<6c{1rWE2kT=9fEwVarxjcSfM3{ z154)PO9=_A86yFkZ9Cz6(+pcye~B-bEW_H>Ye*g}#~1Tv%Ay9j^mN%N|Nre6noIto#e z9f;Cwe{?k^A~DJVNwIEt-B(5PvyW!(D`E*GQ!CP7b>%R&e!T>LY+R4yKmCFV4}Uzn zVu^e?Lm^13lUPByj21k}``b^_NBwnPoJ*nkSx)r45qL_2V+IO}=zJcKRVd_u@HXOm zJ3C~o+km`Ti_xGt8y&KS=#eD}K=<3P5w%atMA@=+s8TgR6G@7+&&A-+t77u>xJB-BZMs;440gfItEtpB%^Yw8Q8xKZ(|a zt;lj;j%>Fti4pvYmiU8s%4k`51@9^d1j=vF5611$&*Nq8arz;DLr212c$a++4-d|Q z8Bs7_8EKSHHbjd4RD8JaE9~idDrqA@RvRT`yv?gOlCH`{J?Z44d0(P;=2v(*Z4G+$ zm!WUkN_6PVM~~iO^bsI*>CQ+0oRxU_X*{2?l)nE0dfhVg=r5$#k<=l>?bTg~PVIT< zGFVKnSxFva6<*F=jW>(ep?l_1^vM}${+yF z6Y>mdYBGft_PW}1RF%fV(fl-)PgcOOwac+qUKXn*Bw@E}FMNzm@$=es!WzMvm8-CF z`3fvqw1AkwY#3iVfh*_sV&9I9@NhIn>|<}lk#~-Y_8~8QkEFm|AuX7*0yzwr+n(Je zkIuB-*1;Giw=Tf^&SfDmi1QBaI+zO}z_kdumG?hi5Af3KLxQ$Sy2p^x)RDDIq*T6tG3e&>z=jPS; zZNp0Z{LMP-`sO>7d-|i-$eN^qfzU>-T|yHj6DGr1OB+3IjzBpXd}XmHcHnsjdFoQs z_<5o2ra4}mz6xA0#`DuxfRKj-4*5brPw|gGqeOcK+7%7)i~y!UWePft%m@fFP`30d zlq>5AI}<5GCE+@91gs~EquTX%lDmJRCSeEO)m}la|3;Jq{)~p`{dk&o2EBQg!JUoz zOK;$1;U)BDpCHD&kAUEJR6im+h@m+idmNRgRwGzvEK=nO2()#PXD|~mHba@y9b|?3 zAUi2c2q@}%^^_QVpTGhb2>zXTB+57VX9t0S;NQ3Z0)qbjSAPS+TLJ|xSo-Y6Ga;ae zOPX^WfoRvDRT!;YkD##*b#{)eO+Ed>tV? z8OniELYLg9vidYhbnuLaq&B+86NM!D$fHYK9i8H8=p0X;nLKwF>BDXsJ(3eibE*sD zIlaD*F8nj1?_KmBo@^~-z)z*=zLW-9CDqX?p^grEPv>||w9@Cb(sRu++GwQrWhv_; z=eIw>4NfX|9fIBX39ug`j+imZXy?Kg^xhg79Xud9dx2!j83RL@Zr_41Pb(DVM4`Ai z5oP76LieD8f>`9{MxwYV7A^Hzc=Es=Yo|}dwt3UBngDXucu53Yx`Kxej@Yz%HNN@s zE396z5-W%iEL<=b3+GM4&zslc&aI31Yug5xTs{mhGWaLqZg~926|r&mkeGB|=!kre zQ#c0A!rsYPXlUx;YXe93+hp99@+_Nyltk}Jg2GJ zF9L#>t+2X&oB&`Me*a-Tw*IgY`#1lHO1}WSylsap1zog?X`q?=N2-uh;KkW00)duD0G^xTT-m>uXTI*FFly-0Ighl=3e zh3-e4>1WWDbxvr4`hr0q_bi@e9>dd={b-8$6Xjt)p(=uV9}=Uu_$5N8Ng`QM5_RP4 za`gxZuHQtCr4dqsT#yzQK#n1sY_ton1t1U^zbNTwu!!j(0EpNCkN+nl;Qofp3V1Pr z>k#xj?-8~RdFS9&Kd%+=_Thh*GiOH7P|x)UO6X$6;lAr#*k3t=Ak*vgqgNv7&s`|c zpN%G>$H`)f@Rb-1j|Jj*6}Atrb5G)Z^?8&9tw)aAa%8%!MtR^bXo@|A&J6PYrNjnm zEHF@e8*c~c1OFkLmtfJ~v7kujzICo_;#tKbqc8pTS#zujsY?!&T`y zdQ9i~=g86c@yyjN6FiL?SyY0u|-SG*ZyfRDefhberZG;x97t)sj;9ig#)* zTtcwD1HM_c3agea!;-~|F@OGiESNtR3+Bzl%xRNw{O}GK6UD!DY8Re_xFEpCl0309 z5@S8-?>$0sVI;CL!Vnbb02lJ=+|HakBzt(>f+xM!>)stWxtR-@gKnOdLX;p!B{Beb z5I{I^u@k#1aC0+)r>8LodTd3m<1$!)s2TInX>2T# z4{=d&Rn|m?iY{8TW{`x`MVmD_yXs10t^E!es`{v*d6hU?3J&6*!)CSw8t(5vHOrfu>8_nN?1O%r@Dx5`6{sr_ET_!1fj)34ex>63JBWX9vLN=o^{1>4K zYWbx#csx%Ysmd~_nq-J{y%``{h8*jg$av_EwMuq+ttbR=Q|3;=^{ zKm-8)y;#VHe_;ZKa7QEVqRKDidWBrZoB@C(0t14Obi|#GSQ@l5BWOZHV-3*~qH-0* zD9B1ekcT}SuAV^%7c4C;McmduQDitDwe$m~k+J$qk-v4WoLlV~6yXpY{2=LsheykizDByKehc0dyxWJ>E+9brP=pa{P5?*X(J)Vn>LuXL0ppWw5?M)shILYzNboNvO)>MZ>Htw=VIOrXcM_ScB| z8w6i!~~r}3J` z3z7#c6GWxTxG0HeE0MPkYwIcnAjnIPhp&SrY%Ux}#2s@&%W5QS-;ILlU!Y!VDw4)4 zz;`_9`6aS=5wI66kBQ=^?#7F}eaQD;gKUr0DDvNoCIW(<0#gjM(uL~_r0aj5?mOdk zg$cR|2+AM*g6_0~0weJIO&_;q#1JB>hAQ2Yd zalikJfk2TAUO^ZP2JipFj~Ng?4F&=F46Z=*Zj>5oe5_K1h5VQPSL@4MX zZ#>s&BrVH9Fw&C{HcS?mh!LFEH-OR48*pLQW>{Q0fcq|H1iF?8@UXyr_gi@2WdT38 z+qiY*D0Y0i3R~t*$9L+QIJa;aELW^Uwy^~s+1$k%VgdSET9`ybLrooua`I4DQNdI_ zUCf-Khwr~x1CuK!aPr_*Vd3$4XCbOfB9RpBj@*<08$jA0*ZB4=JS0#A+rUoD0lb-+3gZJI_u)cH*Yi3Tyvgx{* zKiv?E=g+~H%NJw+mLE`a|32C--$1T10ji`X+6ho|wWi~}w-3-zhm`Gq;f}O2!pW>$U6oK!@Ay8)qkhRB(>2nCx+9u(%HH|PPJ)pU?fOs-+#G$avNwA4*8g|Z#B3w#e-t_XUnA3PElTeHi2A5KXiqzV zX9ef+y3z=5YD|SAgF!d3g4TpxsCx7>YNNKIFK#~p!3u=U9*-0yX;e;{f~;8#1h&Yu zxq%peJ95BL=<2FR-^(syR|Eva3fOl4H{XDPK*R|C7YP1&EC2zoI1T~%PC&3!Z+G2FwU}$AE*28VF@;s!EYd(jdUqRse#~+Z^{_jl@6qAaD92yj{Ew8FH%d zmly@l=@MwX^AozC96%#!C^TI`b@Ud}MVnA~e-oM$j^SmQCGgB2cpE`ZARKt=jaQXs z=tw_?`q-U#oqY-~qffwbwIVD?ZiGpwph06Q@`UX}Paq(WDAY_;6A+Xtl9pe;MOY)K zKX4Ki6Q-hHdNSUMY2xi@k_F_Y-!Ppg+Wv|q!dP{p_++pI0B^~_-x4tJW2XIYMyZn| zAo(zqjGYJHXGuV>;esM>+0Z{%!2k_@{v8>AKb_aqG-(Ts-s}jL+?X(V1Pi zd3HC+bGvc*)L%HVb2D~tUWcE)n1d~oC*#h>Ex0msA>z+m!2@GcEHKc=OalWf zUbql*XU~C#sv6{_WuT_0ggMivVJ;cf_Fp!^+Uyc;-#m%X`?h2o0f>9#jEF#*d~trr zjQ2%Wf-maJVo_faM@%G5$S(L8L$`!`MK z=_CeFnTiqul%li{LU*Ohqtx)ylXhWEV< z@Ugsx6$YA^qdftOrW;_%f;m{Sa2~!~x(J5|2%3X}(Q9OmYz1w!NvNZf7(otc`e&xM zh1{2r@3-K(q#W$UrSXV7d-U|hNZGs%AL3(4CJ-2;C*a|hjqsT^4awiLq)bJ>mk)|o zd?Rc{H>&8PKzAm(tqBP73y`^F4GPo^QKc{maihn>PV93y%#%Td=P#%vul_9WAgZ4H zMABdt0l{X}MeadI2C;$C8+hMLthe1BA6jhDS8^Raxo6OtxCa$sThNlQ1Fz!`qV(cY zgwN(R0%??K84wW61MKL!+%?4$Z)@apsj|*mJb%$CY#oZ?2>vgLM*=hW@0fwX`~R*} zFob1+NK4S${?*rDaD9MNkhvRj7cqiPZgA4pf))-jCLm}aR#23kj3@U!V1MN_9$A@@ z?jj)A#*APou<{2KbC#BvINVf6LgRr85F|$BjmutS0K!43It1;2$6`oQ+D& zDJWIbN6(gRLN%bq>o-w6eF@rCrs4$|<7@K3uOzhaR?!gewC18uV-{Y}b6oWDHP@ym zhVV*yBHk0o^r;%4mr%cl=;liX3j%fUbo?Z|8l#0usY$5ca~R0VL*0(U$ezA}Jk5NXw0h_xfa)2ij#gp_p(A8* zjTZ|E2<}}x2|s%iVgQzKw=;tM?elQ5x(FW^I_G7H2fj9Nvb~OTM|a@YHH)xq?o1ee z`yI~AUWl+$=ix(ocj2@t_+ri+tXQ@j>({Nv?3uHnte^<-v12hoQ2{dy^|4^)G#uN% z6HYe9xOw>yuAbe2MDo^|3I2!*vO_X~LQbqVGNL??9_@*orXuUM5ngbmp*(ue`5UO7xL7l8N;yDgw z^yjdfE`>_h-%uH`4INn=9)ApZzF(pE!6wv4A0Sz9jifIDNhi(KUO#;7^uXI%YxL$_ zLVMDF)IRki>%#;QE0db_4EVQDCr?vQ62YX#o(Yh z3PGDEq2=D6=uD&w)J_cIsR=rA4x=vd5ZbaX;c1B(UNzX`MXfE`^R5$}I)yj67x6ab z912Xofz|Xeu;m>CvGFM2XfV>Jqe5B@$s?rbx$#IF zB8IwAN_atR;yD3AorDH*M=K+JxI8k3NTZshKsQN`9s&~H!)}n%NA5TcWYOQq8>)b( z+!q>wZ=ZJ#y-4Gk@L_p(9l7nb&M=svBz~yRX;c`%N41!w=u%=gmLht0jxDea&jr-Sb1orJKl6HV`@-y&|Sn zt-Aopi`N47Zs6?H*S_~qa*d46!VEp8CTP21gesF;sPps^Z7aT{zuVPJY_%Q;k4DDQ z4QN!Kh3E8ny#y-76Q|&n6&W%CLFMAFP)m%XiGUz=m;^jWjfA!O7-U^phvrAS(U7o{ zKIalSxNRs6`+-=(E_7sH#Xy5Ifey{pS0TiH{V>pIhZjXx(GtH0Pl*-uChkN3!@bDc zJsY9gW04_4bBll=Z{`yEKU|PbK$Q~ciYLJy=xDG0JJ*1v!T$n*5MnII17-lC#X`QZ z;SY|%+mLtfIF3LRX3Rh!s!;U$Q_HjG0wd_|8EkGsAkf+*tPwOZBd9GyYV7J-;<&FZbet}0YXPY*nVOG z-45ufBN;%tsjJ2WJvGL7*K`XXt8NMnQuA+q1KZi+uvH!n-|^xoRMJK*p?|ri0pe!N z0Undyi;ssR{jCJ88OYV2hu24mbu`wa+SLWu#1-K7pYcc+R}(c%QPe}+5DDBHG8V2w z#=(8a7=+TXjkIMK8DsV+1q2Kk0k0vW;Z5fs(DPZN6wyW?&_;&-nBL2cG2Ln0qvv9V zj7NhM=~I#)nL{M$^`qhW>3J@PT`jAHECQ+aYu8CW)gbe){V*QQ)t4oZL154|UI#s5 zT4<#AhmVk_=VWkFN0&7IZDb}!AU*Xl^7G>n8R>`A)Q2c8NkU?BC^AVa=H$j9HSGyZ zub#weT}`Z3QNTK){gLJt2zPeIiuv=gXx@AQ2$n5dhOfT*3d@%-hnlJ?#Kp!zV%%70 zs!YJt$&)a{KnKSU{E0^aE-<@t5W)8>(NdL!H(kYO;nHErzQ~RDMEpZrq{p}+E9oA| zi2KM%@fQp~J<$(YBo(q#9?am7IhwZdjr<1#ewlg*b!4RqKg$5)cq`EF2+? zK#o9_8VQH_Qpmma4Vt2M;$7W&GWHv&Pv4HB$6L{yaR%?m$>FIlF@gsKI^O87u|R9u zG4x~|#jCW#=n312imR&;vs49-6h@&`Ng37Zy2zSJbKK63fZ!U^L)?i)c?%73SsHMN zu_&^T;|O>gkr+M+gMXv}?;s2U!hbV?!J7aC|1biMEF5f$F6xHdOF+=m^XzXR;5Y&f zJ8s}oWtGK<4)KNO?HjN^a|j_fIkK<sO%V|Ur&L&Xh}1E-O7bqy>GN5WQd1Rl~P z&r#AunCHL$x7qZ%2b`(KQed@QQQVXceK;jUySV9St_<~R@SxYrO@MO%B7ZMHEretCC8% zJ4_1kV^z^1IT_Eyw9zW7kMLn~Fd9A{N7c2Eci#u4*@?(Wk4AZEIx5REQCppZ`uYOY z)Z`L9tU-5IJ+Zhh6lBEVkJU@?jkYF!AT|+hVopHdf|UdU3yBslqTgxdiWS5NRtkW? zI|wSuN`gd?CU!7EUIE(bDws2EG7j(jiHzL~Rr&OHb0UzNcpuMOvhkuV6Yrko;aOu6 zDsqESlog1)^ali1#7?5z$%$YN1X3k!Ft(hap{bL`>_xyvhZ+^y&X$x_J z?9b~79TX6to5=2(8FaF3r{SIq7E)M%xRo0aM@Cvb$qLnKridL$xiNAS_G>hD;e_u@|V9@M6Pi@JM}LK`uusqy^Z`0=e}L3)mf?W) zQ#hIOJYrwbdWtGrjJAcYK|lb&F-{+rSJ0HgZ#N7Yb9ie5i)3gSl@G2*M?AS3+& zngB-RD1FpX=a&))ZYTgTj{C>r6qo*wYoL@MP)#t1d{k!F8HfF}!#wulV`@sX=QuN4 zH2?iKqfP~)KKKaVs_Eds<7$W;E3@3#pmoe-)M$_eJgJG_o*avBEyy531JGSjfacO{ zROBY1GB26SWR&Nopfo21^%eQ(Xk=8o(}kAu0{9%=j~AS#;u$kb_%lM@K7I;I2?TTH z9l?SHSh8pdmM>k7#gqpN7A}GV?~{R^0o2A#ARvr^mih#k8|h-Y&15{gW+A*U9ztVr z0ftym$S`~wa%4pP;N1?JP6s38A$j`iuECPg#D3q0cOBr4)JKY=Q z#Sy5jj7MW#GTNFm(A|-PK7s%SNW%xJaJQp`OfUtv&mYFi>z2XAL?0H^$985WSTK7A z)~;TOO`A4iJpn*$!}|4Dzj_r`FIj|lw{AhHhXrE(j$MoZ|C2EFi#Vdh*fn z2xKryWspcWwnwh@ET)@=i=_2OsQv%eG=sZ^3u33vLzdkf%1Rgb5uC5{+4)iSWlc0k zov{OQrp`p)X$GmhJltBe3RlM)Ab+9->IoLrWP`CIv~XeAQv`#@acbd2Ti?T{(iRgg`Vk5D2C8x-rqzz{2V;Or_Oc=+`|75G)) zpxQ2sKpE9UHpsvvGJ>(7N}ux8KpCsBMb*zh`D)Nur#6+)d5h${Su~V1X196I{_7hw}~^xFl1euQ$Ny zmAr}T^>KpBqsu4a_(~0&Tr?4f%!lLH#3$gPriL^f6EqoGDl^44((+8LQTWOZAU=k) zFAYhry$8=p=14KLM#dCtbnbkcRImV*r_LaF{wnyYnIMG^uU2mgYP6>)^C;#y&P9xs zGXhE7qsJJbk&f8R=v=PjfJ*zth%ucGUrj6c4%0^FcoQ^G$4i5iR7QdbMhPD^Gx&_q zqfXRTKK(UlStEO_F%nH2;i+MUYm^vXk55E_rUjBs?9lLw>dQ*<2cO`uffdd^siA;Q zBSD~pRBD3xe8;@^v3~~G8kCA`l8p{0XU>?_ydhH^Tu3kXK&1=Z=x{2&to+t|P zM@d)+wWt@ofBF$G5kR);7$fkPzuCu(5K$Pt)0j#5E;B3vwuuyU3?e%$pcf^RZ}nHVyZ?3o+Q9jXMN{ zo|bg9k|i`%$Dz3<9?i9JXsDK#htX)Li&sV!YHdtKXKOYcpU3r;;9h?joxcoyt$Apx zCbOaB@ws#apTGVr7T8Y46fHGaOwzg7u*7Z%`^wX2bT^(yiyNy7~t5IS6+OkgYy66l2$2%C!?sZBj^ffh2l_KDVL)Nw@K zBzxQ*V~h)rYbry?$B_-zP*OCRPD26Zqd%Y94IV3OFKZH?pUpHh{`MzH4Gjt<1LkC^hhmS8vYcH>OFx|^CpmOtU*`wE_9{+fP1C;DN9aJ4xgknIm~+S zJMN}`hyK71k^b2%+?+86w~R(0K~DpfhOFxhob8iLQN;j~Kmdo27m|+tiHNJmke3{a z=EhQVb~P(N&^Jg%KpT*z#=;050KxxjDqs*GP=SGJ8ySK0RQg{aP=+b%=}<-|lJN+n ziLne-R^Lo%P+yITDrrYhgu=W`q{f88@6;i9eD(qU;6pn+doBh}66rD$fP;Ucz}cA; z-W+Y3rf8!h)+#g5PC?jYbKG{aAs86pguNb4*y`dRZ;C{UQ?R$7Ja`P zWy?0BY050LOqzmrbvm64J;kUnICnL=XRkuD^;|R?IHHe0&@~Y< z1}(}@+Jp_VAGLGmGIymy!SnM97h0iA%;6no7 zhop!fnwjI{DO2#7tu4NDa>1Ti^YE3eBffK<3#Eeiu3*^1o}%0Ey- z$1i4mqy8SO!Tr7}-03VKm}HT1H;*Z{K_L>9AL z3m42KV9i%-83AF*vZYwEbgA;LVC~8kSjB62mCT^{@@3?I^f_YmZIMoC7ev|UJDFfS zX)?S?+cU`KWCo<}Q6}ggZHC?nG7f#s?4xO3>ZYfNh3y?~A_&mhOz8JW5kq)AiwfNW7snp9|Mhq^7> z0B?Cg7=xU*cOk`T5vnX_ql1pspksp)Qoyd~UspcW6@T*+(jDiahS8#hG_Q+Myo1Yj zeLFM~3~ERx8^qDIZIw@py?mgptV~UM_R9WhI&cf~>`NvZH0!hX2{jHLG?#`ps^{)-S#FTCr?MA-c&k2 z!G|Ew#|qj`R#8HbisU_#ihNev5~sL+!pH`HGeR6TwZZ`-bL`VK#W7|;g$UEK(~ zC+OoBbwm6zULRjFDt*aHoc;R|`2KSU3#U3_o~sMy&YX@#3+H3jteKcIXEx@`mxM+0 zF@NDa%$_?NGiT2vJ8*%mjWx_ojA1j`6w~acV7jdp<~rJ7^*mQ>UOEe}ZdryOKHPze zhkruIty4&k^Fnb}Fv|17P*)O-`qCIQRV1LUG!8W-ai}gyKuLBKGUEIY3~coiP0=~lh{1pnoB=O-v?i{|mxPIr;IP$j9B_CF2d53kk(ncKe9kDG znmYz(W{tt+8RK!;as+N^k3_7NI?GOWNZ@alnUM{xP(%>G7hmyQk?8ijiCe#Zj-Ye@ zAT!nvjrGOo?rx^f%8No(@5BEAf`6S|^|DYU3Ap(ID;P2Xibqr(j#Q{18w3dCW#Q0Q z19?xNG%=Qzg-SDHvH}^iu(Sw8lm@AB;Yjwn2H($j;mEXUIB#fyFo&6lUAPSRgET5U z4EGKmK*a3%h_!S;ioPWZ1PF-Ov2;NNwOgaL3+gSVGNRil6R6gk(P^dU7d2ds zm`r3ca}mNE9Z?{1ARs^)h@|k1PvC2}00BDoh+|aFU{o%q)8?5?Mc>;WK_(L^*z*T` zNdJ?y%u%LpiWWLrv(^-}nz*3Md>WGZuu~?QDdXUG5CFR9$Zdvneyiy$t1YsqB@5Ke z$Y#XRjnKh#Ep*aq>dIn+soZCUDn^@D(oX3I-zGia>}DaKQXpT?iuoF&Ud$~vJ&mZH*Pv5{N zZ*Iq1&#uFZ>z82bvbk6{Z#q`ZnU2MDdRJQ;Seu%_kpMJ*?o5_p9;M4-tfU-RvScyK zH3y3qEyT(d%duqfLM&gl1S`0GE!n{eN}l%!1a02lX!!aEBoppfEu#6yH zLuuDafbJe)thDjyCZp@5v}>Cr<7vu#1(cYS1;LNX?8ox;XaaKi%o`~0>UkdvwF$~k zlJY;QhV!GeanpV}^1q^UCdLA{J(0b39rDOn8wnt7WSfnwE2RX6=&{<; zV~F!pba2Vm05_Z|8J!Gq)kYg`W)tD1GXZg$nkdsXLW8z38Z-@A=S`4f#lZCKH&A9_ z^7DcJ8?V6k`(22>bPzeh2pY=J)76T8`m4MwRDj_A00t=wRP6^IM*Sfl7Z7;39FhqH zf+5PFVg&b?VLxQLGXVklY9J=>2mZB&del@`qP(n_(jWs#(ZNXbzJcJcKEn|QN8He- zma>|LH0xt0oAP6A+T^rs0ygB_dva0f>(RLc@^s;+wckM?5`D59c4}O?^Z|nFl{j z*9JK@uDJ6lA697zGWPzBKga9fGHG5sX`;+}TTf?;epFr2fbx0pDl0$$>0uL{wV7Hn zXPhDYxcw&0gWG)=Eiy*xpiRSE8Id{i2{rB;O*%Oi-i#vgk7}Tf`d+4Z&!Fb?W`5Tm z8Ob!G5XAju>gLMiu&uxErN%5o{PtIHYP=!$t0RjMs#DDxeQE>*Z9BA4TGSJuicB1k z%lnfx*%|Ra60bj4~e*KoOh=}boLsaP`8 z9%~j%$Hpadv4SjM8BLC#&vUy@ok|d}!90SKlw$s<|zB6 zHQ_=^(76PVg)?2Tc$yPF+_(Mc;ETqIWy%@9Sj3 zufBr87oNwRr?;ZgaT?V`7co8om8g3R#&DJm$u<44$c_({yU(i0!0@t z;Ac%^oEoNyNIG97^`FdE8%WT�P$c5#R#t77@Q%kMe^K6*oeUPO922=0-qBQloYw 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%0APRHCu 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

WC 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 jF7^1Q|LsxAaFd@81&mw*>z0mcai5&9*xl diff --git a/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.command.1.tlog b/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/CL.command.1.tlog deleted file mode 100644 index 79d1ac8f3e6a3d6d5a24c48b1ccf4667d74f69a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13344 zcmeI2+iu!G5J2a-QvV_1J?ZVC6;dC#nV=esFoYzsiV#T}B$^_iYLbs{duDAg5NK%? z1xpzrUv_qOc4oXj*{t{1&(BhkyhKu!nzZFuI#Q(65Kj&%2mE~Q>S(p4AY~4{9!gVM z)RmBj`~pgmyLPx!X|!k^$`RTH(a!Or^+NQje7xGF5a=^KU^k~h(x(5&Y z-_~-u?^q|7*pGXOW33T$+xe%KHQKqa8c)RGJKsw#Rv#aWl1se(7kiq$7TMMwLhJ_a z+{Io)-pN}edZ)d0$Wi6L`UvSkeb&hRN40qT=oaUB-4yjXxzHzeBj04i@r6UnT{0D4 zPZ^1NcOgURQ?Hs+nNb>W&2t_hpYl_QY6j@W*Sn-`nR1$cty4+QWxvQ%s5<>v7C-k? z=Y%|ekk@E;$aa;y>pN1BkH~I0-pd=#seXrNTcb_jwC3`M(yDxQttz~c)5P-@Bc_Bs zZB?gz97mP$qmnBb6Yp3ia*6(sR+mnGPAM-xIA4>A37*cDc%KzQ?t|6^#)p!- zPUd_$b5xnL+~}`Kh6(Y(i6 zOyE`t_Sg|IurMsD+DHgRfbAq_E;GK9 z{Cs~(B2UuFK{9FNSuPTCca~Ik+!q`hpywHQL_Z zUCW-;0pm5}*L98lq*UISij-17go-6c zsc;gLiZDVw_fae%jp1JdX-1a#Kw9(sRpwvwwSehG>*u0&0$pzj`5BUlAEV0ZYw62D zCE2)QD(nQQOTG}T8gz-MX;t;Z9m!X&jwf7@cd@t1b!1~8ujuJg!;~F4he6e;a-u{! z_U??`{81j9k}0n^%Mqf=DMw8ODwkF2G&hnpctGii2h97bFK%VqiT7kc?_O@ZEgPlr z3twpM?y&~Sp_i)5Gco`&}ec5v*p{}q|=U8g6#6CW$aoO5hI9Sc?mhdq2{aA!RKWd0g3PGmtt zR^(T~=tTCWdV%LyxGlNI9z0#Re=V~~JAAe7br%gv9}qo*u8jthF=qN!>NO%v12=dZ z^tC^sy44NL#j1$kH^ES50p&6Oa!#=$FRf1OLw=g-TUJ`FIFJdJwF&=$XT*KRbJbrS z?IpS&H_E@tA3NT2?Oz`6W$M2?&N=;G9@Sh0hym4qHDF#{tI$C?Dw(l-!1maN4&d0K cw_#m}?)%ueTiq+DdnvuF=V?N$M~m(3UoWY|<^TWy diff --git a/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.write.1.tlog b/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib-link.write.1.tlog deleted file mode 100644 index 114a122ac4d52b597986002a85a4b8a410c67e1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638 zcmdUwNe;p=3`PGMiKD;*cI*;LnL3~j3{pie!r6i6ASyTjQczSmah>}0CvhJ4t5#a5 z(^^|K+NhOhR4CPiaY@VQ6y11X4je$?eN$5EiS=& zGOg*mFn>h`Po~RPp+?$f1sf)uUm9UQ4tyoj;ZT2gaUVP_iqMzfiPi z_c|TXITmeG&T$4$9nN1xuh$7*p}A(!P-cN>4_y@vlPPBPE!8<9rj`?Y2=%oYsKy$h n+;1x4XKgM}qab(6D!Fh6oC3)nlK0(U)!kOpW4~+7%WJGpi-_^v diff --git a/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib.command.1.tlog b/source/Tools.Parser/Debug/Tools.Lib.Parser.tlog/Lib.command.1.tlog deleted file mode 100644 index ff69c4df49273cc44b404d18a0720a792879434f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2086 zcmdUw%}&EG5QOK9#5+{Ix0T@5o82@4nkH3#T9BgVMR<1Lvk{e33JM1#SCM6Vy=za# zyW{t_qt;rgQ>I5XdQdCNtWc^M^O7%Tw8g8DQ9^V5OgmMqt+3a8C9}@=EhA^`PSLgI zcpL0BcITJSTTaRt8y~;s1j|V;1J618T0Q9%|5!05{Kpp5v0$}u*ud8c?i|k{^Vfi} zCksllBDo4id$QMP56`i1n^MO)cxqpN6{B7UY=!Q17Y)kXBiewjiUyNo%;{UI=ZG-1 zRPfI0YjZ+%s~at_wIE(<3XA`vj-gH$FjH`5%8eQS9vnQX4XD1}38(b#W-a|tcRsCC zO~CDTaW$UNCVzelLQKEC9p}0n#*NX)vHsunYJB9mc7&1R>Nt$JR8!&lrTiYQ|CDPV DeJU~* diff --git a/source/Tools.CorHelper/CorHelper-vs2019.vcproj b/source/native/Tools.CorHelper/CorHelper-vs2019.vcproj similarity index 100% rename from source/Tools.CorHelper/CorHelper-vs2019.vcproj rename to source/native/Tools.CorHelper/CorHelper-vs2019.vcproj diff --git a/source/Tools.CorHelper/CorHelper-vs2019.vcxproj b/source/native/Tools.CorHelper/CorHelper-vs2019.vcxproj similarity index 90% rename from source/Tools.CorHelper/CorHelper-vs2019.vcxproj rename to source/native/Tools.CorHelper/CorHelper-vs2019.vcxproj index c7b9081d..01842e23 100644 --- a/source/Tools.CorHelper/CorHelper-vs2019.vcxproj +++ b/source/native/Tools.CorHelper/CorHelper-vs2019.vcxproj @@ -62,7 +62,7 @@ Disabled - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -80,7 +80,7 @@ MaxSpeed OnlyExplicitInline true - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDLL diff --git a/source/Tools.CorHelper/CorHelper-vs2019.vcxproj.filters b/source/native/Tools.CorHelper/CorHelper-vs2019.vcxproj.filters similarity index 100% rename from source/Tools.CorHelper/CorHelper-vs2019.vcxproj.filters rename to source/native/Tools.CorHelper/CorHelper-vs2019.vcxproj.filters diff --git a/source/Tools.CorHelper/CorHelper.vcproj b/source/native/Tools.CorHelper/CorHelper.vcproj similarity index 100% rename from source/Tools.CorHelper/CorHelper.vcproj rename to source/native/Tools.CorHelper/CorHelper.vcproj diff --git a/source/Tools.CorHelper/CorHelper.vcxproj b/source/native/Tools.CorHelper/CorHelper.vcxproj similarity index 90% rename from source/Tools.CorHelper/CorHelper.vcxproj rename to source/native/Tools.CorHelper/CorHelper.vcxproj index 4c1e41f8..60676b47 100644 --- a/source/Tools.CorHelper/CorHelper.vcxproj +++ b/source/native/Tools.CorHelper/CorHelper.vcxproj @@ -62,7 +62,7 @@ Disabled - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -80,7 +80,7 @@ MaxSpeed OnlyExplicitInline true - ..\Tools.MetaDataProcessor;..\Tools.Parser;..\..\nf-interpreter\src\CLR\CorLib;..\..\nf-interpreter\targets\os\win32\Include;..\..\nf-interpreter\src\PAL\Include;..\..\nf-interpreter\src\HAL\Include;..\..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) + ..\Tools.MetaDataProcessor;..\Tools.Parser;..\nf-interpreter\src\CLR\CorLib;..\nf-interpreter\targets\os\win32\Include;..\nf-interpreter\src\PAL\Include;..\nf-interpreter\src\HAL\Include;..\nf-interpreter\src\CLR\Include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true MultiThreadedDLL diff --git a/source/Tools.CorHelper/CorHelper.vcxproj.filters b/source/native/Tools.CorHelper/CorHelper.vcxproj.filters similarity index 100% rename from source/Tools.CorHelper/CorHelper.vcxproj.filters rename to source/native/Tools.CorHelper/CorHelper.vcxproj.filters diff --git a/source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.command.1.tlog b/source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.command.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..5e317af6b13b369debd9c09e9e49fda4d32d90a2 GIT binary patch literal 2958 zcmeH{TWi}u5QWckq5mQ1J?`zH#n6Y^mSj=IGO`q>!L%4BX$)>^Y?mhe@om4^m15@x z4Fu{3BX(DFJ3DiBcmDkTtWZsj6f04ou1d9#dWy759D1Z9=h4UVT+j4E6YVi4Xd9qz;@r;a zZcYzH_Q@?LU)$UJ1QouoJR$qSSq;-_ud}r3MvT;D?JG&iuBG5nNXB9g>xMl5F>~_} zq@LdBH5&V~eM)!>4gDE>EkKyC&Tm9a;c^DfMWy|OPXOwQeaGx} z$tyXp?qWo2u)&vq@ja@H93%ERhe)|T61DkmJ)igWfd+iGsXlPoM&x&Mhtaj=wquk?%h{T++QXOBv@xkqkG53l>Wb@iMxZ?o>Y_^ylZy7>R@ R;y>t?yDq*RUHsuL`4_y{q=Nte literal 0 HcmV?d00001 diff --git a/source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.read.1.tlog b/source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.read.1.tlog similarity index 96% rename from source/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.read.1.tlog rename to source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/CL.read.1.tlog index bfd3ebd59b643f6e6b682a552d76ced3109289f4..994a84b8fe3939e9be527aa24eb4ab2840da7545 100644 GIT binary patch delta 153 zcmdmYiE-U!#tAW;ehiKbAq<`jVUrs(R5#YJF`@Qp0rbpC_;My@aQV# delta 66 zcmZ2?nQ`AG#tAW#zhx*)-p9nZamEiuC_88Jl2nVy1WOdAvukXHFKiHw;_p61?fHPBD4IABa2N zDZ!%#QypNcp%bVUXZh|gHog3o?j3=no Mk&VGRref3h0;;@xTmS$7 literal 0 HcmV?d00001 diff --git a/source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib-link.write.1.tlog b/source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib-link.write.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..60824f5b6c1e044cacb5eb713e8a909eb50e1c75 GIT binary patch literal 536 zcmd6k!485j5Jcx};-|m|c%woAtzamq2jZ9b?dsbm7!IC|X`1csOt;h7*YmDQJI$)q zYE+|1j;xbcM&7dmrxUDEg-W)?OlJ*Xd+L$Zlg%kkoUCd+jN9sxvZYs44sQI0dZ160 z?v_Ny>oqqQ+|U7j4|320#=j|z{Lnn{x_xwRwfT|KwP)sbhf^NMiZrila`}j^wfBLE NxUVzFnTBDe{|yunPdESo literal 0 HcmV?d00001 diff --git a/source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib.command.1.tlog b/source/native/Tools.CorHelper/Debug/Tools.Li.079E1BC1.tlog/Lib.command.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..b7dffefb1dd3f0cc5bb05de0448bc5414f6f17f4 GIT binary patch literal 634 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